package promutil import ( "fmt" "reflect" "testing" "github.com/opencost/opencost/core/pkg/util/json" ) func checkSlice(s1, s2 []string) error { if len(s1) != len(s2) { return fmt.Errorf("len(s1) [%d] != len(s2) [%d]", len(s1), len(s2)) } for i := 0; i < len(s1); i++ { if s1[i] != s2[i] { return fmt.Errorf("At Index: %d. Different Values %s (s1) != %s (s2)", i, s1[i], s2[i]) } } return nil } func TestEmptyKubeLabelsToPromLabels(t *testing.T) { labels, values := KubeLabelsToLabels(nil) if len(labels) != 0 { t.Errorf("Labels length is non-zero\n") } if len(values) != 0 { t.Errorf("Values length is non-zero\n") } labels, values = KubeLabelsToLabels(map[string]string{}) if len(labels) != 0 { t.Errorf("Labels length is non-zero\n") } if len(values) != 0 { t.Errorf("Values length is non-zero\n") } } func TestKubeLabelsToPromLabels(t *testing.T) { var expectedLabels []string = []string{ "label_app", "label_chart", "label_control_plane", "label_gatekeeper_sh_operation", "label_heritage", "label_pod_template_hash", "label_release", } var expectedValues []string = []string{ "gatekeeper", "gatekeeper", "audit-controller", "audit", "Helm", "5599859cd4", "gatekeeper", } kubeLabels := map[string]string{ "app": "gatekeeper", "chart": "gatekeeper", "control-plane": "audit-controller", "gatekeeper.sh/operation": "audit", "heritage": "Helm", "pod-template-hash": "5599859cd4", "release": "gatekeeper", } labels, values := KubePrependQualifierToLabels(kubeLabels, "label_") l2, v2 := KubeLabelsToLabels(kubeLabels) // Check to make sure we get expected labels and values returned err := checkSlice(labels, expectedLabels) if err != nil { t.Errorf("%s", err) } err = checkSlice(values, expectedValues) if err != nil { t.Errorf("%s", err) } // Check to make sure the helper function returns what the prependqualifier func // returns err = checkSlice(l2, labels) if err != nil { t.Errorf("%s", err) } err = checkSlice(v2, values) if err != nil { t.Errorf("%s", err) } } func TestKubePrependQualifierToLabelsDuplicates(t *testing.T) { // 7 expected labels/values expectedLabels := []string{ "label_app_", "label_chart", "label_control_plane", "label_gatekeeper_sh_operation", "label_heritage", "label_pod_template_hash", "label_release", } expectedValues := []string{ "gatekeeper", "gatekeeper", "audit-controller", "audit", "Helm", "5599859cd4", "gatekeeper", } // 8 input labels/values, with one duplicate label kubeLabels := map[string]string{ // app- will be sanitized to app_ "app-": "gatekeeper", "app_": "gatekeeper", "chart": "gatekeeper", "control-plane": "audit-controller", "gatekeeper.sh/operation": "audit", "heritage": "Helm", "pod-template-hash": "5599859cd4", "release": "gatekeeper", } labels, values := KubePrependQualifierToLabels(kubeLabels, "label_") // Check to make sure we get expected labels and values returned err := checkSlice(labels, expectedLabels) if err != nil { t.Errorf("%s", err) } err = checkSlice(values, expectedValues) if err != nil { t.Errorf("%s", err) } } func TestSanitizeLabels(t *testing.T) { type testCase struct { in map[string]string exp map[string]string } tcs := map[string]testCase{ "empty labels": { in: map[string]string{}, exp: map[string]string{}, }, "no op": { in: map[string]string{ "foo": "bar", "baz": "loo", }, exp: map[string]string{ "foo": "bar", "baz": "loo", }, }, "modification, no collisions": { in: map[string]string{ "foo-foo": "bar", "baz---baz": "loo", }, exp: map[string]string{ "foo_foo": "bar", "baz___baz": "loo", }, }, "modification, one collision": { in: map[string]string{ "foo-foo": "bar", "foo+foo": "bar", "baz---baz": "loo", }, exp: map[string]string{ "foo_foo": "bar", "baz___baz": "loo", }, }, "modification, all collisions": { in: map[string]string{ "foo-foo": "bar", "foo+foo": "bar", "foo_foo": "bar", }, exp: map[string]string{ "foo_foo": "bar", }, }, } for name, tc := range tcs { t.Run(name, func(t *testing.T) { act := SanitizeLabels(tc.in) if !reflect.DeepEqual(tc.exp, act) { t.Errorf("sanitizing labels failed for case %s: %+v != %+v", name, tc.exp, act) } }) } } func TestClusterInfoLabels(t *testing.T) { expected := map[string]bool{"clusterprofile": true, "errorreporting": true, "id": true, "logcollection": true, "name": true, "productanalytics": true, "provider": true, "provisioner": true, "remotereadenabled": true, "thanosenabled": true, "valuesreporting": true, "version": true} clusterInfo := `{"clusterProfile":"production","errorReporting":"true","id":"cluster-one","logCollection":"true","name":"bolt-3","productAnalytics":"true","provider":"GCP","provisioner":"GKE","remoteReadEnabled":"false","thanosEnabled":"false","valuesReporting":"true","version":"1.14+"}` var m map[string]any err := json.Unmarshal([]byte(clusterInfo), &m) if err != nil { t.Errorf("Error: %s", err) return } labels := MapToLabels(m) for k := range expected { if _, ok := labels[k]; !ok { t.Errorf("Failed to locate key: \"%s\" in labels.", k) return } } }