Sfoglia il codice sorgente

[Opencost-Core] Parse CloudCostProperty (#2461)

* Add parsing for CloudCostProperty to opencost-core

Signed-off-by: Matt Bolt <mbolt35@gmail.com>

* fix parsing to use lcase

Signed-off-by: Matt Bolt <mbolt35@gmail.com>

* Remove unused function

Signed-off-by: Matt Bolt <mbolt35@gmail.com>

---------

Signed-off-by: Matt Bolt <mbolt35@gmail.com>
Matt Bolt 2 anni fa
parent
commit
2dcd33bb3b
2 ha cambiato i file con 63 aggiunte e 28 eliminazioni
  1. 61 0
      core/pkg/opencost/cloudcostprops.go
  2. 2 28
      pkg/cloudcost/queryservice_helper.go

+ 61 - 0
core/pkg/opencost/cloudcostprops.go

@@ -1,11 +1,29 @@
 package opencost
 
 import (
+	"fmt"
 	"strings"
 
 	"github.com/opencost/opencost/core/pkg/log"
+	"github.com/opencost/opencost/core/pkg/util/promutil"
 )
 
+type CloudCostProperty string
+
+// IsLabel returns true if the allocation property has a label prefix
+func (apt *CloudCostProperty) IsLabel() bool {
+	return strings.HasPrefix(string(*apt), "label:")
+}
+
+// GetLabel returns the label string associated with the label property if it exists.
+// Otherwise, empty string is returned.
+func (apt *CloudCostProperty) GetLabel() string {
+	if apt.IsLabel() {
+		return strings.TrimSpace(strings.TrimPrefix(string(*apt), "label:"))
+	}
+	return ""
+}
+
 const (
 	CloudCostInvoiceEntityIDProp string = "invoiceEntityID"
 	CloudCostAccountIDProp       string = "accountID"
@@ -16,6 +34,49 @@ const (
 	CloudCostLabelProp           string = "label"
 )
 
+func ParseCloudProperties(props []string) ([]CloudCostProperty, error) {
+	properties := []CloudCostProperty{}
+	added := make(map[CloudCostProperty]struct{})
+
+	for _, prop := range props {
+		property, err := ParseCloudCostProperty(prop)
+		if err != nil {
+			return nil, fmt.Errorf("Failed to parse property: %w", err)
+		}
+
+		if _, ok := added[property]; !ok {
+			added[property] = struct{}{}
+			properties = append(properties, property)
+		}
+	}
+
+	return properties, nil
+}
+
+func ParseCloudCostProperty(text string) (CloudCostProperty, error) {
+	switch strings.TrimSpace(strings.ToLower(text)) {
+	case "invoiceentityid":
+		return CloudCostProperty(CloudCostInvoiceEntityIDProp), nil
+	case "accountid":
+		return CloudCostProperty(CloudCostAccountIDProp), nil
+	case "provider":
+		return CloudCostProperty(CloudCostProviderProp), nil
+	case "providerid":
+		return CloudCostProperty(CloudCostProviderIDProp), nil
+	case "category":
+		return CloudCostProperty(CloudCostCategoryProp), nil
+	case "service":
+		return CloudCostProperty(CloudCostServiceProp), nil
+	}
+
+	if strings.HasPrefix(text, "label:") {
+		label := promutil.SanitizeLabelName(strings.TrimSpace(strings.TrimPrefix(text, "label:")))
+		return CloudCostProperty(fmt.Sprintf("label:%s", label)), nil
+	}
+
+	return "", fmt.Errorf("invalid cloud cost property: %s", text)
+}
+
 const (
 	// CloudCostClusterManagementCategory describes CloudCost representing Hosted Kubernetes Fees
 	CloudCostClusterManagementCategory string = "Cluster Management"

+ 2 - 28
pkg/cloudcost/queryservice_helper.go

@@ -4,13 +4,11 @@ import (
 	"encoding/csv"
 	"fmt"
 	"net/http"
-	"strings"
 
 	"github.com/opencost/opencost/core/pkg/filter"
 	"github.com/opencost/opencost/core/pkg/filter/cloudcost"
 	"github.com/opencost/opencost/core/pkg/opencost"
 	"github.com/opencost/opencost/core/pkg/util/httputil"
-	"github.com/opencost/opencost/core/pkg/util/promutil"
 )
 
 func ParseCloudCostRequest(qp httputil.QueryParams) (*QueryRequest, error) {
@@ -31,11 +29,11 @@ func ParseCloudCostRequest(qp httputil.QueryParams) (*QueryRequest, error) {
 	aggregateByRaw := qp.GetList("aggregate", ",")
 	var aggregateBy []string
 	for _, aggBy := range aggregateByRaw {
-		prop, err := ParseCloudCostProperty(aggBy)
+		prop, err := opencost.ParseCloudCostProperty(aggBy)
 		if err != nil {
 			return nil, fmt.Errorf("error parsing aggregate by %v", err)
 		}
-		aggregateBy = append(aggregateBy, prop)
+		aggregateBy = append(aggregateBy, string(prop))
 	}
 
 	// if we're aggregating by nothing (aka `item` on the frontend) then aggregate by all
@@ -66,30 +64,6 @@ func ParseCloudCostRequest(qp httputil.QueryParams) (*QueryRequest, error) {
 	return opts, nil
 }
 
-func ParseCloudCostProperty(text string) (string, error) {
-	switch strings.TrimSpace(strings.ToLower(text)) {
-	case strings.ToLower(opencost.CloudCostInvoiceEntityIDProp):
-		return opencost.CloudCostInvoiceEntityIDProp, nil
-	case strings.ToLower(opencost.CloudCostAccountIDProp):
-		return opencost.CloudCostAccountIDProp, nil
-	case strings.ToLower(opencost.CloudCostProviderProp):
-		return opencost.CloudCostProviderProp, nil
-	case strings.ToLower(opencost.CloudCostProviderIDProp):
-		return opencost.CloudCostProviderIDProp, nil
-	case strings.ToLower(opencost.CloudCostCategoryProp):
-		return opencost.CloudCostCategoryProp, nil
-	case strings.ToLower(opencost.CloudCostServiceProp):
-		return opencost.CloudCostServiceProp, nil
-	}
-
-	if strings.HasPrefix(text, "label:") {
-		label := promutil.SanitizeLabelName(strings.TrimSpace(strings.TrimPrefix(text, "label:")))
-		return fmt.Sprintf("label:%s", label), nil
-	}
-
-	return "", fmt.Errorf("invalid cloud cost property: %s", text)
-}
-
 func parseCloudCostViewRequest(qp httputil.QueryParams) (*ViewQueryRequest, error) {
 	qr, err := ParseCloudCostRequest(qp)
 	if err != nil {