stringmapmatcher.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package matcher
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/opencost/opencost/pkg/filter21/ast"
  6. "github.com/opencost/opencost/pkg/log"
  7. )
  8. // StringMapMatcherFactory leverages a single MapFieldMapper[T] to generate instances of
  9. // StringMapMatcher[T].
  10. type StringMapMatcherFactory[T any] struct {
  11. fieldMapper MapFieldMapper[T]
  12. }
  13. // NewStringMapMatcherFactory creates a new StringMapMatcher factory for a given T type.
  14. func NewStringMapMatcherFactory[T any](fieldMapper MapFieldMapper[T]) *StringMapMatcherFactory[T] {
  15. return &StringMapMatcherFactory[T]{
  16. fieldMapper: fieldMapper,
  17. }
  18. }
  19. // NewStringMapMatcher creates a new StringMapMatcher using the provided op, field ident and key for comparison
  20. func (smmf *StringMapMatcherFactory[T]) NewStringMapMatcher(op ast.FilterOp, ident ast.Identifier, key string) *StringMapMatcher[T] {
  21. return &StringMapMatcher[T]{
  22. Op: op,
  23. Identifier: ident,
  24. Key: key,
  25. fieldMapper: smmf.fieldMapper,
  26. }
  27. }
  28. // // StringMapMatcher matches properties of a T instance which are map[string]string
  29. type StringMapMatcher[T any] struct {
  30. Op ast.FilterOp
  31. Identifier ast.Identifier
  32. Key string
  33. fieldMapper MapFieldMapper[T]
  34. }
  35. func (smm *StringMapMatcher[T]) String() string {
  36. return fmt.Sprintf(`(%s %s "%s")`, smm.Op, smm.Identifier.String(), smm.Key)
  37. }
  38. func (smm *StringMapMatcher[T]) Matches(that T) bool {
  39. thatMap, err := smm.fieldMapper(that, smm.Identifier)
  40. if err != nil {
  41. log.Errorf("Filter: StringMapMatcher: could not retrieve field %s: %s", smm.Identifier.String(), err.Error())
  42. return false
  43. }
  44. switch smm.Op {
  45. case ast.FilterOpContains:
  46. _, exists := thatMap[smm.Key]
  47. return exists
  48. case ast.FilterOpContainsPrefix:
  49. for k := range thatMap {
  50. if strings.HasPrefix(k, smm.Key) {
  51. return true
  52. }
  53. }
  54. return false
  55. case ast.FilterOpContainsSuffix:
  56. for k := range thatMap {
  57. if strings.HasSuffix(k, smm.Key) {
  58. return true
  59. }
  60. }
  61. return false
  62. default:
  63. log.Errorf("Filter: StringMapMatcher: Unhandled matcher op. This is a filter implementation error and requires immediate patching. Op: %s", smm.Op)
  64. return false
  65. }
  66. }