generated from vshn/go-bootstrap
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Gabriel Saratura
committed
Nov 28, 2023
1 parent
e6014af
commit 38241dc
Showing
17 changed files
with
681 additions
and
492 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package cloudscale | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1" | ||
"github.com/vshn/billing-collector-cloudservices/pkg/kubernetes" | ||
"github.com/vshn/billing-collector-cloudservices/pkg/odoo" | ||
"github.com/vshn/billing-collector-cloudservices/pkg/prom" | ||
"time" | ||
|
||
"github.com/cloudscale-ch/cloudscale-go-sdk/v2" | ||
"github.com/vshn/billing-collector-cloudservices/pkg/log" | ||
cloudscalev1 "github.com/vshn/provider-cloudscale/apis/cloudscale/v1" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
const ( | ||
organizationLabel = "appuio.io/organization" | ||
namespaceLabel = "crossplane.io/claim-namespace" | ||
) | ||
|
||
func getOdooMeteredBillingRecord(ctx context.Context, date time.Time, cloudscaleClient *cloudscale.Client, k8sclient client.Client, promClient apiv1.API, salesOrderId string) ([]odoo.OdooMeteredBillingRecord, error) { | ||
logger := log.Logger(ctx) | ||
|
||
logger.V(1).Info("fetching bucket metrics from cloudscale", "date", date) | ||
|
||
bucketMetricsRequest := cloudscale.BucketMetricsRequest{Start: date, End: date} | ||
bucketMetrics, err := cloudscaleClient.Metrics.GetBucketMetrics(ctx, &bucketMetricsRequest) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Fetch organisations in case salesOrderId is missing | ||
var nsTenants map[string]string | ||
if salesOrderId == "" { | ||
logger.V(1).Info("Sales order id is missing, fetching namespaces to get the associated org id") | ||
nsTenants, err = kubernetes.FetchNamespaceWithOrganizationMap(ctx, k8sclient) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
logger.V(1).Info("fetching buckets") | ||
|
||
buckets, err := fetchBuckets(ctx, k8sclient) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
allRecords := make([]odoo.OdooMeteredBillingRecord, 0) | ||
for _, bucketMetricsData := range bucketMetrics.Data { | ||
name := bucketMetricsData.Subject.BucketName | ||
logger = logger.WithValues("bucket", name) | ||
ns, ok := buckets[name] | ||
if !ok { | ||
logger.Info("unable to sync bucket, ObjectBucket not found") | ||
continue | ||
} | ||
if salesOrderId == "" { | ||
salesOrderId, err = prom.GetSalesOrderId(ctx, promClient, nsTenants[ns]) | ||
if err != nil { | ||
logger.Error(err, "unable to sync bucket", "namespace", ns) | ||
continue | ||
} | ||
} | ||
records, err := createOdooRecord(bucketMetricsData, salesOrderId, ns) | ||
if err != nil { | ||
logger.Error(err, "unable to sync bucket", "namespace", ns) | ||
continue | ||
} | ||
allRecords = append(allRecords, records...) | ||
logger.V(1).Info("Created Odoo records", "namespace", ns, "records", records) | ||
} | ||
|
||
return allRecords, nil | ||
} | ||
|
||
func fetchBuckets(ctx context.Context, k8sclient client.Client) (map[string]string, error) { | ||
buckets := &cloudscalev1.BucketList{} | ||
if err := k8sclient.List(ctx, buckets, client.HasLabels{namespaceLabel}); err != nil { | ||
return nil, fmt.Errorf("bucket list: %w", err) | ||
} | ||
|
||
bucketNS := map[string]string{} | ||
for _, b := range buckets.Items { | ||
bucketNS[b.GetBucketName()] = b.Labels[namespaceLabel] | ||
} | ||
return bucketNS, nil | ||
} | ||
|
||
func createOdooRecord(bucketMetricsData cloudscale.BucketMetricsData, salesOrderId, namespace string) ([]odoo.OdooMeteredBillingRecord, error) { | ||
if len(bucketMetricsData.TimeSeries) != 1 { | ||
return nil, fmt.Errorf("there must be exactly one metrics data point, found %d", len(bucketMetricsData.TimeSeries)) | ||
} | ||
|
||
storageBytesValue, err := convertUnit(units[productIdStorage], uint64(bucketMetricsData.TimeSeries[0].Usage.StorageBytes)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
trafficOutValue, err := convertUnit(units[productIdTrafficOut], uint64(bucketMetricsData.TimeSeries[0].Usage.SentBytes)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
queryRequestsValue, err := convertUnit(units[productIdQueryRequests], uint64(bucketMetricsData.TimeSeries[0].Usage.SentBytes)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
//TODO where to put zone and namespace? | ||
return []odoo.OdooMeteredBillingRecord{ | ||
{ | ||
ProductID: productIdStorage, | ||
InstanceID: bucketMetricsData.Subject.BucketName, | ||
ItemDescription: "Cloudscale ObjectStorage", | ||
ItemGroupDescription: "AppCat Cloudscale ObjectStorage", | ||
SalesOrderID: salesOrderId, | ||
UnitID: units[productIdStorage], | ||
ConsumedUnits: storageBytesValue, | ||
TimeRange: odoo.TimeRange{ | ||
From: bucketMetricsData.TimeSeries[0].Start, | ||
To: bucketMetricsData.TimeSeries[0].End, | ||
}, | ||
}, | ||
{ | ||
ProductID: productIdTrafficOut, | ||
InstanceID: bucketMetricsData.Subject.BucketName, | ||
ItemDescription: "Cloudscale ObjectStorage", | ||
ItemGroupDescription: "AppCat Cloudscale ObjectStorage", | ||
SalesOrderID: salesOrderId, | ||
UnitID: units[productIdTrafficOut], | ||
ConsumedUnits: trafficOutValue, | ||
TimeRange: odoo.TimeRange{ | ||
From: bucketMetricsData.TimeSeries[0].Start, | ||
To: bucketMetricsData.TimeSeries[0].End, | ||
}, | ||
}, | ||
{ | ||
ProductID: productIdQueryRequests, | ||
InstanceID: bucketMetricsData.Subject.BucketName, | ||
ItemDescription: "Cloudscale ObjectStorage", | ||
ItemGroupDescription: "AppCat Cloudscale ObjectStorage", | ||
SalesOrderID: salesOrderId, | ||
UnitID: units[productIdQueryRequests], | ||
ConsumedUnits: queryRequestsValue, | ||
TimeRange: odoo.TimeRange{ | ||
From: bucketMetricsData.TimeSeries[0].Start, | ||
To: bucketMetricsData.TimeSeries[0].End, | ||
}, | ||
}, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.