|
|
@@ -0,0 +1,80 @@
|
|
|
+package kubecost
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+
|
|
|
+ "github.com/opencost/opencost/pkg/filter21/ast"
|
|
|
+ ccfilter "github.com/opencost/opencost/pkg/filter21/cloudcost"
|
|
|
+ "github.com/opencost/opencost/pkg/filter21/matcher"
|
|
|
+ "github.com/opencost/opencost/pkg/filter21/transform"
|
|
|
+)
|
|
|
+
|
|
|
+// CloudCostMatcher is a matcher implementation for CloudCost instances,
|
|
|
+// compiled using the matcher.MatchCompiler for cloud costs.
|
|
|
+type CloudCostMatcher matcher.Matcher[*CloudCost]
|
|
|
+
|
|
|
+// NewCloudCostMatchCompiler creates a new instance of a
|
|
|
+// matcher.MatchCompiler[*CloudCost] which can be used to compile filter.Filter
|
|
|
+// ASTs into matcher.Matcher[*CloudCost] implementations.
|
|
|
+//
|
|
|
+// If storage interfaces every support querying natively by alias (e.g. if a
|
|
|
+// data store contained a "product" attribute on an CloudCost row), that should
|
|
|
+// be handled by a purpose-built AST compiler.
|
|
|
+func NewCloudCostMatchCompiler() *matcher.MatchCompiler[*CloudCost] {
|
|
|
+ passes := []transform.CompilerPass{}
|
|
|
+
|
|
|
+ passes = append(passes,
|
|
|
+ transform.UnallocatedReplacementPass(),
|
|
|
+ )
|
|
|
+ return matcher.NewMatchCompiler(
|
|
|
+ cloudCostFieldMap,
|
|
|
+ cloudCostSliceFieldMap,
|
|
|
+ cloudCostMapFieldMap,
|
|
|
+ passes...,
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+// Maps fields from a cloud cost to a string value based on an identifier
|
|
|
+func cloudCostFieldMap(cc *CloudCost, identifier ast.Identifier) (string, error) {
|
|
|
+ if cc == nil {
|
|
|
+ return "", fmt.Errorf("cannot map to nil cloud cost")
|
|
|
+ }
|
|
|
+ if cc.Properties == nil {
|
|
|
+ return "", fmt.Errorf("cannot map to nil properties")
|
|
|
+ }
|
|
|
+ if identifier.Field == nil {
|
|
|
+ return "", fmt.Errorf("cannot map field from identifier with nil field")
|
|
|
+ }
|
|
|
+ switch ccfilter.CloudCostField(identifier.Field.Name) {
|
|
|
+ case ccfilter.FieldInvoiceEntity:
|
|
|
+ return cc.Properties.InvoiceEntityID, nil
|
|
|
+ case ccfilter.FieldAccount:
|
|
|
+ return cc.Properties.AccountID, nil
|
|
|
+ case ccfilter.FieldProvider:
|
|
|
+ return cc.Properties.Provider, nil
|
|
|
+ case ccfilter.FieldProviderID:
|
|
|
+ return cc.Properties.ProviderID, nil
|
|
|
+ case ccfilter.FieldCategory:
|
|
|
+ return cc.Properties.Category, nil
|
|
|
+ case ccfilter.FieldService:
|
|
|
+ return cc.Properties.Service, nil
|
|
|
+ case ccfilter.FieldLabel:
|
|
|
+ return cc.Properties.Labels[identifier.Key], nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return "", fmt.Errorf("Failed to find string identifier on CloudCost: %s", identifier.Field.Name)
|
|
|
+}
|
|
|
+
|
|
|
+// Maps slice fields from an asset to a []string value based on an identifier
|
|
|
+func cloudCostSliceFieldMap(cc *CloudCost, identifier ast.Identifier) ([]string, error) {
|
|
|
+ return nil, fmt.Errorf("Cloud Cost have no slice fields")
|
|
|
+}
|
|
|
+
|
|
|
+// Maps map fields from a cloud cost to a map[string]string value based on an identifier
|
|
|
+func cloudCostMapFieldMap(cc *CloudCost, identifier ast.Identifier) (map[string]string, error) {
|
|
|
+ switch ccfilter.CloudCostField(identifier.Field.Name) {
|
|
|
+ case ccfilter.FieldLabel:
|
|
|
+ return cc.Properties.Labels, nil
|
|
|
+ }
|
|
|
+ return nil, fmt.Errorf("Failed to find map[string]string identifier on CloudCost: %s", identifier.Field.Name)
|
|
|
+}
|