Jelajahi Sumber

Merge pull request #1457 from nickcurie/nick/anno-bugfix

add aliased fields (labels, annotations) to filters
Niko Kovacevic 3 tahun lalu
induk
melakukan
831c65c364

+ 10 - 0
pkg/kubecost/allocationfilter.go

@@ -30,6 +30,7 @@ const (
 
 	FilterLabel      = "label"
 	FilterAnnotation = "annotation"
+	FilterAlias      = "alias"
 
 	FilterServices = "services"
 )
@@ -362,6 +363,15 @@ func (filter AllocationFilterCondition) Matches(a *Allocation) bool {
 		} else {
 			valueToCompare = val
 		}
+	case FilterAlias:
+		var ok bool
+		valueToCompare, ok = a.Properties.Labels[filter.Key]
+		if !ok {
+			valueToCompare, ok = a.Properties.Annotations[filter.Key]
+			if !ok {
+				toCompareMissing = true
+			}
+		}
 	case FilterServices:
 		valueToCompare = a.Properties.Services
 	default:

+ 9 - 9
pkg/util/allocationfilterutil/queryfilters.go

@@ -194,19 +194,19 @@ func AllocationFilterFromParamsV1(
 	// Label-mapped queries require a label config to be present.
 	if labelConfig != nil {
 		if raw := qp.GetList("filterDepartments", ","); len(raw) > 0 {
-			filter.Filters = append(filter.Filters, filterV1LabelMappedFromList(raw, labelConfig.DepartmentLabel))
+			filter.Filters = append(filter.Filters, filterV1LabelAliasMappedFromList(raw, labelConfig.DepartmentLabel))
 		}
 		if raw := qp.GetList("filterEnvironments", ","); len(raw) > 0 {
-			filter.Filters = append(filter.Filters, filterV1LabelMappedFromList(raw, labelConfig.EnvironmentLabel))
+			filter.Filters = append(filter.Filters, filterV1LabelAliasMappedFromList(raw, labelConfig.EnvironmentLabel))
 		}
 		if raw := qp.GetList("filterOwners", ","); len(raw) > 0 {
-			filter.Filters = append(filter.Filters, filterV1LabelMappedFromList(raw, labelConfig.OwnerLabel))
+			filter.Filters = append(filter.Filters, filterV1LabelAliasMappedFromList(raw, labelConfig.OwnerLabel))
 		}
 		if raw := qp.GetList("filterProducts", ","); len(raw) > 0 {
-			filter.Filters = append(filter.Filters, filterV1LabelMappedFromList(raw, labelConfig.ProductLabel))
+			filter.Filters = append(filter.Filters, filterV1LabelAliasMappedFromList(raw, labelConfig.ProductLabel))
 		}
 		if raw := qp.GetList("filterTeams", ","); len(raw) > 0 {
-			filter.Filters = append(filter.Filters, filterV1LabelMappedFromList(raw, labelConfig.TeamLabel))
+			filter.Filters = append(filter.Filters, filterV1LabelAliasMappedFromList(raw, labelConfig.TeamLabel))
 		}
 	} else {
 		log.Debugf("No label config is available. Not creating filters for label-mapped 'fields'.")
@@ -275,10 +275,10 @@ func filterV1SingleValueFromList(rawFilterValues []string, filterField kubecost.
 	return filter
 }
 
-// filterV1LabelMappedFromList is like filterV1SingleValueFromList but is
-// explicitly for a label because "label-mapped" filters (like filterTeams=)
+// filterV1LabelAliasMappedFromList is like filterV1SingleValueFromList but is
+// explicitly for labels and annotations because "label-mapped" filters (like filterTeams=)
 // are actually label filters with a fixed label key.
-func filterV1LabelMappedFromList(rawFilterValues []string, labelName string) kubecost.AllocationFilterOr {
+func filterV1LabelAliasMappedFromList(rawFilterValues []string, labelName string) kubecost.AllocationFilterOr {
 	filter := kubecost.AllocationFilterOr{
 		Filters: []kubecost.AllocationFilter{},
 	}
@@ -289,7 +289,7 @@ func filterV1LabelMappedFromList(rawFilterValues []string, labelName string) kub
 		filterValue, wildcard := parseWildcardEnd(filterValue)
 
 		subFilter := kubecost.AllocationFilterCondition{
-			Field: kubecost.FilterLabel,
+			Field: kubecost.FilterAlias,
 			// All v1 filters are equality comparisons
 			Op:    kubecost.FilterEquals,
 			Key:   labelName,

+ 53 - 0
pkg/util/allocationfilterutil/queryfilters_test.go

@@ -628,6 +628,58 @@ func TestFiltersFromParamsV1(t *testing.T) {
 				}),
 			},
 		},
+		{
+			name: "single owner",
+			qp: map[string]string{
+				"filterOwners": "nick",
+			},
+			shouldMatch: []kubecost.Allocation{
+				allocGenerator(kubecost.AllocationProperties{
+					Labels: kubecost.AllocationLabels{
+						"testowner": "nick",
+					},
+				}),
+				allocGenerator(kubecost.AllocationProperties{
+					Annotations: kubecost.AllocationAnnotations{
+						"testowner": "nick",
+					},
+				}),
+				allocGenerator(kubecost.AllocationProperties{
+					Labels: kubecost.AllocationLabels{
+						"testowner": "nick",
+					},
+					Annotations: kubecost.AllocationAnnotations{
+						"dontpick": "notnick",
+					},
+				}),
+				allocGenerator(kubecost.AllocationProperties{
+					Labels: kubecost.AllocationLabels{
+						"dontpick": "notnick",
+					},
+					Annotations: kubecost.AllocationAnnotations{
+						"testowner": "nick",
+					},
+				}),
+			},
+			shouldNotMatch: []kubecost.Allocation{
+				allocGenerator(kubecost.AllocationProperties{
+					Labels: kubecost.AllocationLabels{
+						"dontpick": "notnick",
+					},
+					Annotations: kubecost.AllocationAnnotations{
+						"dontpick": "notnick",
+					},
+				}),
+				allocGenerator(kubecost.AllocationProperties{
+					Labels: kubecost.AllocationLabels{
+						"testowner": "notnick",
+					},
+					Annotations: kubecost.AllocationAnnotations{
+						"testowner": "nick",
+					},
+				}),
+			},
+		},
 	}
 
 	for _, c := range cases {
@@ -642,6 +694,7 @@ func TestFiltersFromParamsV1(t *testing.T) {
 
 			labelConfig := kubecost.LabelConfig{}
 			labelConfig.DepartmentLabel = "internal-product-umbrella"
+			labelConfig.OwnerLabel = "testowner"
 
 			clustersMap := mockClusterMap{
 				m: map[string]*clusters.ClusterInfo{