Просмотр исходного кода

Recognizes annotations when aggregating by owner

Signed-off-by: nickcurie <nick.curie64@gmail.com>
nickcurie 3 лет назад
Родитель
Сommit
64b7eb4f54
2 измененных файлов с 112 добавлено и 5 удалено
  1. 20 5
      pkg/kubecost/allocationprops.go
  2. 92 0
      pkg/kubecost/allocationprops_test.go

+ 20 - 5
pkg/kubecost/allocationprops.go

@@ -317,7 +317,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 			}
 		case agg == AllocationDepartmentProp:
 			labels := p.Labels
-			if labels == nil {
+			annotations := p.Annotations
+			if labels == nil && annotations == nil {
 				names = append(names, UnallocatedSuffix)
 			} else {
 				labelNames := strings.Split(labelConfig.DepartmentLabel, ",")
@@ -325,6 +326,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 					labelName = labelConfig.Sanitize(labelName)
 					if labelValue, ok := labels[labelName]; ok {
 						names = append(names, labelValue)
+					} else if annotationValue, ok := annotations[labelName]; ok {
+						names = append(names, annotationValue)
 					} else {
 						names = append(names, UnallocatedSuffix)
 					}
@@ -332,7 +335,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 			}
 		case agg == AllocationEnvironmentProp:
 			labels := p.Labels
-			if labels == nil {
+			annotations := p.Annotations
+			if labels == nil && annotations == nil {
 				names = append(names, UnallocatedSuffix)
 			} else {
 				labelNames := strings.Split(labelConfig.EnvironmentLabel, ",")
@@ -340,6 +344,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 					labelName = labelConfig.Sanitize(labelName)
 					if labelValue, ok := labels[labelName]; ok {
 						names = append(names, labelValue)
+					} else if annotationValue, ok := annotations[labelName]; ok {
+						names = append(names, annotationValue)
 					} else {
 						names = append(names, UnallocatedSuffix)
 					}
@@ -347,7 +353,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 			}
 		case agg == AllocationOwnerProp:
 			labels := p.Labels
-			if labels == nil {
+			annotations := p.Annotations
+			if labels == nil && annotations == nil {
 				names = append(names, UnallocatedSuffix)
 			} else {
 				labelNames := strings.Split(labelConfig.OwnerLabel, ",")
@@ -355,6 +362,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 					labelName = labelConfig.Sanitize(labelName)
 					if labelValue, ok := labels[labelName]; ok {
 						names = append(names, labelValue)
+					} else if annotationValue, ok := annotations[labelName]; ok {
+						names = append(names, annotationValue)
 					} else {
 						names = append(names, UnallocatedSuffix)
 					}
@@ -362,7 +371,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 			}
 		case agg == AllocationProductProp:
 			labels := p.Labels
-			if labels == nil {
+			annotations := p.Annotations
+			if labels == nil && annotations == nil {
 				names = append(names, UnallocatedSuffix)
 			} else {
 				labelNames := strings.Split(labelConfig.ProductLabel, ",")
@@ -370,6 +380,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 					labelName = labelConfig.Sanitize(labelName)
 					if labelValue, ok := labels[labelName]; ok {
 						names = append(names, labelValue)
+					} else if annotationValue, ok := annotations[labelName]; ok {
+						names = append(names, annotationValue)
 					} else {
 						names = append(names, UnallocatedSuffix)
 					}
@@ -377,7 +389,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 			}
 		case agg == AllocationTeamProp:
 			labels := p.Labels
-			if labels == nil {
+			annotations := p.Annotations
+			if labels == nil && annotations == nil {
 				names = append(names, UnallocatedSuffix)
 			} else {
 				labelNames := strings.Split(labelConfig.TeamLabel, ",")
@@ -385,6 +398,8 @@ func (p *AllocationProperties) GenerateKey(aggregateBy []string, labelConfig *La
 					labelName = labelConfig.Sanitize(labelName)
 					if labelValue, ok := labels[labelName]; ok {
 						names = append(names, labelValue)
+					} else if annotationValue, ok := annotations[labelName]; ok {
+						names = append(names, annotationValue)
 					} else {
 						names = append(names, UnallocatedSuffix)
 					}

+ 92 - 0
pkg/kubecost/allocationprops_test.go

@@ -0,0 +1,92 @@
+package kubecost
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestGenerateKey(t *testing.T) {
+
+	cases := map[string]struct {
+		aggregate       []string
+		allocationProps *AllocationProperties
+		expected        string
+	}{
+		"aggregateregate by owner without owner labels": {
+			aggregate: []string{"owner"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"app": "cost-analyzer"},
+				Annotations: map[string]string{"owner": "test owner 123"},
+			},
+			expected: "test owner 123",
+		},
+		"aggregate by owner without labels": {
+			aggregate: []string{"owner"},
+			allocationProps: &AllocationProperties{
+				Annotations: map[string]string{"owner": "test owner 123"},
+			},
+			expected: "test owner 123",
+		},
+		"aggregate by owner with owner label and annotation": {
+			aggregate: []string{"owner"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"owner": "owner-label"},
+				Annotations: map[string]string{"owner": "owner-annotation"},
+			},
+			expected: "owner-label",
+		},
+		"aggregate by environment with environment label and annotation": {
+			aggregate: []string{"environment"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"env": "environment-label"},
+				Annotations: map[string]string{"env": "environment-annotation"},
+			},
+			expected: "environment-label",
+		},
+		"aggregate by department with department label and annotation": {
+			aggregate: []string{"department"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"department": "department-label"},
+				Annotations: map[string]string{"department": "department-annotation"},
+			},
+			expected: "department-label",
+		},
+		"aggregate by team with team label and annotation": {
+			aggregate: []string{"team"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"team": "team-label"},
+				Annotations: map[string]string{"team": "team-annotation"},
+			},
+			expected: "team-label",
+		},
+		"aggregate by product with product label and annotation": {
+			aggregate: []string{"product"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"app": "product-label"},
+				Annotations: map[string]string{"app": "product-annotation"},
+			},
+			expected: "product-label",
+		},
+		"aggregate by product and owner with multiple labels and annotations": {
+			aggregate: []string{"product", "owner"},
+			allocationProps: &AllocationProperties{
+				Labels:      map[string]string{"app": "product-label", "owner": "owner-label", "team": "team-label"},
+				Annotations: map[string]string{"app": "product-annotation", "owner": "owner-annotation", "team": "team-annotation"},
+			},
+			expected: "product-label/owner-label",
+		},
+	}
+
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+
+			lc := NewLabelConfig()
+
+			result := tc.allocationProps.GenerateKey(tc.aggregate, lc)
+
+			if !reflect.DeepEqual(result, tc.expected) {
+				t.Fatalf("expected %+v; got %+v", tc.expected, result)
+			}
+		})
+	}
+}