Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Opencost-Core] Parse CloudCostProperty #2461

Merged
merged 3 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 61 additions & 0 deletions core/pkg/opencost/cloudcostprops.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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"
Expand Down
30 changes: 2 additions & 28 deletions pkg/cloudcost/queryservice_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down