Skip to content

Commit

Permalink
feat(serve): billing: handle multiple project ids (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime1907 authored Sep 23, 2024
1 parent 54895c1 commit a0c5ba5
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 47 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export OVH_ENDPOINT="ovh-eu"
export OVH_APP_KEY=""
export OVH_APP_SECRET=""
export OVH_CONSUMER_KEY=""
export OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_ID=""
export OVH_CACHE_UPDATE_INTERVAL="60"
export OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_IDS=""
export OVH_CACHE_UPDATE_INTERVAL="300"
export SERVER_PORT="8080"
```

Expand Down
4 changes: 2 additions & 2 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ services:
OVH_APP_KEY: ""
OVH_APP_SECRET: ""
OVH_CONSUMER_KEY: ""
OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_ID: ""
OVH_CACHE_UPDATE_INTERVAL: "60"
OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_IDS: ""
OVH_CACHE_UPDATE_INTERVAL: "300"
SERVER_PORT: "8080"
80 changes: 45 additions & 35 deletions pkg/network/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"os"
"strconv"
"strings"
"time"

"github.com/ovh/go-ovh/ovh"
Expand Down Expand Up @@ -56,51 +57,60 @@ func setCloudProjectInstanceBilling(projectID string, instanceID string, instanc
}).Set(amount)
}

func updateCloudProviderInstanceBilling(ovhClient *ovh.Client) {
logger.Info().Msg("updating cloud provider instance billing")
func updateCloudProviderInstanceBillingPerInstance(projectID string, instance models.InstanceSummary, flavors []models.Flavor) {
logger.Info().Msgf("updating cloud provider instance billing for instance %s", instance.ID)

flavor := api.FindFlavorByID(flavors, instance.FlavorID)
planType := "undefined"
if instance.PlanCode != nil && flavor.PlanCodes.Hourly != nil && flavor.PlanCodes.Monthly != nil {
switch {
case *instance.PlanCode == *flavor.PlanCodes.Hourly:
planType = "hourly"
case *instance.PlanCode == *flavor.PlanCodes.Monthly:
planType = "monthly"
}
}
instancePlanCode := "undefined"
if instance.PlanCode != nil {
instancePlanCode = *instance.PlanCode
}
instanceMonthlyBillingSince := time.Unix(0, 0)
instanceMonthlyBillingStatus := "undefined"
if instance.MonthlyBilling != nil {
instanceMonthlyBillingSince = instance.MonthlyBilling.Since
instanceMonthlyBillingStatus = instance.MonthlyBilling.Status
}

projectID := os.Getenv("OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_ID")
setCloudProjectInstanceBilling(projectID, instance.ID, instance.Name, planType, instancePlanCode, instanceMonthlyBillingSince, instanceMonthlyBillingStatus, 1)
}

func updateCloudProviderInstanceBillingPerProjectID(ovhClient *ovh.Client, projectID string) {
logger.Info().Msgf("updating cloud provider instance billing for project %s", projectID)

projectInstances, err := api.GetCloudProjectInstances(ovhClient, projectID)
if err != nil {
logger.Error().Err(err).Msgf("Failed to retrieve instances: %v", err)
logger.Error().Msgf("Failed to retrieve instances: %v", err)
return
}

var flavors []models.Flavor
for _, instance := range projectInstances {
if api.FindFlavorByID(flavors, instance.FlavorID) == nil {
flavor, err := api.GetCloudProjectFlavor(ovhClient, projectID, instance.FlavorID)
if err != nil {
logger.Error().Err(err).Msgf("Failed to retrieve flavor: %v", err)
} else {
flavors = append(flavors, flavor)
}
}
flavors, err := api.GetCloudProjectFlavorsPerInstances(ovhClient, projectID, projectInstances)
if err != nil {
logger.Error().Msgf("Failed to retrieve flavors: %v", err)
return
}

for _, instance := range projectInstances {
flavor := api.FindFlavorByID(flavors, instance.FlavorID)
planType := "undefined"
if instance.PlanCode != nil && flavor.PlanCodes.Hourly != nil && flavor.PlanCodes.Monthly != nil {
switch {
case *instance.PlanCode == *flavor.PlanCodes.Hourly:
planType = "hourly"
case *instance.PlanCode == *flavor.PlanCodes.Monthly:
planType = "monthly"
}
}
instancePlanCode := "undefined"
if instance.PlanCode != nil {
instancePlanCode = *instance.PlanCode
}
instanceMonthlyBillingSince := time.Unix(0, 0)
instanceMonthlyBillingStatus := "undefined"
if instance.MonthlyBilling != nil {
instanceMonthlyBillingSince = instance.MonthlyBilling.Since
instanceMonthlyBillingStatus = instance.MonthlyBilling.Status
}
updateCloudProviderInstanceBillingPerInstance(projectID, instance, flavors)
}
}

func updateCloudProviderInstanceBilling(ovhClient *ovh.Client) {
projectIDs := os.Getenv("OVH_CLOUD_PROJECT_INSTANCE_BILLING_PROJECT_IDS")

projectIDList := strings.Split(projectIDs, ",")

setCloudProjectInstanceBilling(projectID, instance.ID, instance.Name, planType, instancePlanCode, instanceMonthlyBillingSince, instanceMonthlyBillingStatus, 1)
for _, projectID := range projectIDList {
updateCloudProviderInstanceBillingPerProjectID(ovhClient, projectID)
}
}

Expand Down
22 changes: 22 additions & 0 deletions pkg/ovhsdk/api/cloud_project_flavor.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package api

import (
"fmt"

"github.com/ovh/go-ovh/ovh"
"github.com/wiremind/ovh-exporter/pkg/ovhsdk/models"
)
Expand All @@ -14,6 +16,26 @@ func FindFlavorByID(flavors []models.Flavor, flavorID string) *models.Flavor {
return nil
}

func GetCloudProjectFlavorsPerInstances(ovhClient *ovh.Client, projectID string, projectInstances []models.InstanceSummary) ([]models.Flavor, error) {
var flavors []models.Flavor
var apierr error = nil
for _, instance := range projectInstances {
if FindFlavorByID(flavors, instance.FlavorID) == nil {
flavor, err := GetCloudProjectFlavor(ovhClient, projectID, instance.FlavorID)
if err != nil {
if apierr == nil {
apierr = fmt.Errorf("Failed to retrieve flavor: %v", err)
} else {
apierr = fmt.Errorf("%s; %v", apierr, err)
}
} else {
flavors = append(flavors, flavor)
}
}
}
return flavors, apierr
}

func GetCloudProjectFlavor(client *ovh.Client, projectID string, flavorID string) (models.Flavor, error) {
var flavor models.Flavor

Expand Down
8 changes: 0 additions & 8 deletions pkg/ovhsdk/api/cloud_project_instance_billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,27 @@ import (
)

func GetCloudProjectInstances(client *ovh.Client, projectID string) ([]models.InstanceSummary, error) {
// Define the response structure for the instance billing
var instances []models.InstanceSummary

// Build the API endpoint
endpoint := "/cloud/project/" + projectID + "/instance"

// Call OVH API to get instance data
err := client.Get(endpoint, &instances)
if err != nil {
return instances, err
}

// Return the billing price for this instance
return instances, nil
}

func GetCloudProjectInstance(client *ovh.Client, projectID string, instanceID string) (models.Instance, error) {
// Define the response structure for the instance billing
var instanceData models.Instance

// Build the API endpoint
endpoint := "/cloud/project/" + projectID + "/instance/" + instanceID

// Call OVH API to get instance data
err := client.Get(endpoint, &instanceData)
if err != nil {
return instanceData, err
}

// Return the billing price for this instance
return instanceData, nil
}

0 comments on commit a0c5ba5

Please sign in to comment.