cloudcostmatcher.go 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package opencost
  2. import (
  3. "fmt"
  4. "github.com/opencost/opencost/core/pkg/filter/ast"
  5. ccfilter "github.com/opencost/opencost/core/pkg/filter/cloudcost"
  6. "github.com/opencost/opencost/core/pkg/filter/matcher"
  7. "github.com/opencost/opencost/core/pkg/filter/transform"
  8. )
  9. // CloudCostMatcher is a matcher implementation for CloudCost instances,
  10. // compiled using the matcher.MatchCompiler for cloud costs.
  11. type CloudCostMatcher matcher.Matcher[*CloudCost]
  12. // NewCloudCostMatchCompiler creates a new instance of a
  13. // matcher.MatchCompiler[*CloudCost] which can be used to compile filter.Filter
  14. // ASTs into matcher.Matcher[*CloudCost] implementations.
  15. //
  16. // If storage interfaces every support querying natively by alias (e.g. if a
  17. // data store contained a "product" attribute on an CloudCost row), that should
  18. // be handled by a purpose-built AST compiler.
  19. func NewCloudCostMatchCompiler() *matcher.MatchCompiler[*CloudCost] {
  20. passes := []transform.CompilerPass{}
  21. passes = append(passes,
  22. transform.UnallocatedReplacementPass(),
  23. )
  24. return matcher.NewMatchCompiler(
  25. cloudCostFieldMap,
  26. cloudCostSliceFieldMap,
  27. cloudCostMapFieldMap,
  28. passes...,
  29. )
  30. }
  31. // Maps fields from a cloud cost to a string value based on an identifier
  32. func cloudCostFieldMap(cc *CloudCost, identifier ast.Identifier) (string, error) {
  33. if cc == nil {
  34. return "", fmt.Errorf("cannot map to nil cloud cost")
  35. }
  36. if cc.Properties == nil {
  37. return "", fmt.Errorf("cannot map to nil properties")
  38. }
  39. if identifier.Field == nil {
  40. return "", fmt.Errorf("cannot map field from identifier with nil field")
  41. }
  42. switch ccfilter.CloudCostField(identifier.Field.Name) {
  43. case ccfilter.FieldInvoiceEntityID:
  44. return cc.Properties.InvoiceEntityID, nil
  45. case ccfilter.FieldInvoiceEntityName:
  46. return cc.Properties.InvoiceEntityName, nil
  47. case ccfilter.FieldAccountID:
  48. return cc.Properties.AccountID, nil
  49. case ccfilter.FieldAccountName:
  50. return cc.Properties.AccountName, nil
  51. case ccfilter.FieldRegionID:
  52. return cc.Properties.RegionID, nil
  53. case ccfilter.FieldAvailabilityZone:
  54. return cc.Properties.AvailabilityZone, nil
  55. case ccfilter.FieldProvider:
  56. return cc.Properties.Provider, nil
  57. case ccfilter.FieldProviderID:
  58. return cc.Properties.ProviderID, nil
  59. case ccfilter.FieldCategory:
  60. return cc.Properties.Category, nil
  61. case ccfilter.FieldService:
  62. return cc.Properties.Service, nil
  63. case ccfilter.FieldLabel:
  64. return cc.Properties.Labels[identifier.Key], nil
  65. }
  66. return "", fmt.Errorf("Failed to find string identifier on CloudCost: %s", identifier.Field.Name)
  67. }
  68. // Maps slice fields from an asset to a []string value based on an identifier
  69. func cloudCostSliceFieldMap(cc *CloudCost, identifier ast.Identifier) ([]string, error) {
  70. return nil, fmt.Errorf("Cloud Cost have no slice fields")
  71. }
  72. // Maps map fields from a cloud cost to a map[string]string value based on an identifier
  73. func cloudCostMapFieldMap(cc *CloudCost, identifier ast.Identifier) (map[string]string, error) {
  74. switch ccfilter.CloudCostField(identifier.Field.Name) {
  75. case ccfilter.FieldLabel:
  76. return cc.Properties.Labels, nil
  77. }
  78. return nil, fmt.Errorf("Failed to find map[string]string identifier on CloudCost: %s", identifier.Field.Name)
  79. }