diff --git a/README.md b/README.md index 55c68f6..43cd056 100644 --- a/README.md +++ b/README.md @@ -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" ``` diff --git a/compose.yaml b/compose.yaml index c496f56..fdbf03c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -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" diff --git a/pkg/network/serve.go b/pkg/network/serve.go index 4cc3a3e..35fd025 100644 --- a/pkg/network/serve.go +++ b/pkg/network/serve.go @@ -6,6 +6,7 @@ import ( "net/http" "os" "strconv" + "strings" "time" "github.com/ovh/go-ovh/ovh" @@ -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) } } diff --git a/pkg/ovhsdk/api/cloud_project_flavor.go b/pkg/ovhsdk/api/cloud_project_flavor.go index 2acfb8b..5629718 100644 --- a/pkg/ovhsdk/api/cloud_project_flavor.go +++ b/pkg/ovhsdk/api/cloud_project_flavor.go @@ -1,6 +1,8 @@ package api import ( + "fmt" + "github.com/ovh/go-ovh/ovh" "github.com/wiremind/ovh-exporter/pkg/ovhsdk/models" ) @@ -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 diff --git a/pkg/ovhsdk/api/cloud_project_instance_billing.go b/pkg/ovhsdk/api/cloud_project_instance_billing.go index f185072..c0341ed 100644 --- a/pkg/ovhsdk/api/cloud_project_instance_billing.go +++ b/pkg/ovhsdk/api/cloud_project_instance_billing.go @@ -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 }