diff --git a/kube/config/templates/5xx-rate.tmpl b/kube/config/templates/5xx-rate.tmpl index 2b0af89..22ab929 100644 --- a/kube/config/templates/5xx-rate.tmpl +++ b/kube/config/templates/5xx-rate.tmpl @@ -45,3 +45,6 @@ spec: {{if .Sensitivity}} sensitivity: {{.Sensitivity}} {{end}} + {{range $key, $value := .CustomLabels}} + {{$key}}: {{$value}} + {{end}} diff --git a/kube/config/templates/replicas-availability-deployment.tmpl b/kube/config/templates/replicas-availability-deployment.tmpl index baff7b5..3b12f43 100644 --- a/kube/config/templates/replicas-availability-deployment.tmpl +++ b/kube/config/templates/replicas-availability-deployment.tmpl @@ -37,3 +37,6 @@ spec: {{if .Sensitivity}} sensitivity: {{.Sensitivity}} {{end}} + {{range $key, $value := .CustomLabels}} + {{$key}}: {{$value}} + {{end}} diff --git a/pkg/templates/deployment.go b/pkg/templates/deployment.go index f045a9f..b2331c3 100644 --- a/pkg/templates/deployment.go +++ b/pkg/templates/deployment.go @@ -31,6 +31,7 @@ type templateParameterDeployment struct { Criticality string Sensitivity string Deployment *apps.Deployment + CustomLabels map[string]string } // CreateFromDeployment @@ -68,12 +69,18 @@ func (a *PrometheusRuleTemplateManager) CreateFromDeployment(deployment *apps.De prometheusRules := map[string]*monitoringv1.PrometheusRule{} annotations := params.Deployment.GetAnnotations() + params.CustomLabels = extractCustomLabels(annotations) for k, v := range annotations { if !strings.HasPrefix(k, heimPrefix) { continue } + // Skip label-* annotations as they are not templates + if strings.HasPrefix(k, labelPrefix) { + continue + } + templateName := strings.TrimLeft(k, fmt.Sprintf("%s/", heimPrefix)) logger.Infow("template selected", "template", templateName) template, ok := a.templates[templateName] diff --git a/pkg/templates/deployment_test.go b/pkg/templates/deployment_test.go index c0bb42f..045b617 100644 --- a/pkg/templates/deployment_test.go +++ b/pkg/templates/deployment_test.go @@ -24,6 +24,32 @@ var ( environmentAnnotation: "testing", criticalityAnnotation: "low", sensitivityAnnotation: "public", + priorityAnnotation: "p1", + "com.uswitch.heimdall/replicas-availability-deployment": "1", + }, + OwnerReferences: []metav1.OwnerReference{}, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: new(int32), + Selector: &metav1.LabelSelector{}, + }, + } + + testDeploymentMultiLabel = &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testAppMulti", + Namespace: "testNamespace", + Labels: map[string]string{ + "app": "testAppMulti", + }, + Annotations: map[string]string{ + ownerAnnotation: "testDeploymentOwner", + environmentAnnotation: "testing", + criticalityAnnotation: "low", + sensitivityAnnotation: "public", + "com.uswitch.heimdall/label-priority": "p3", + "com.uswitch.heimdall/label-channel": "testing", + "com.uswitch.heimdall/label-team": "platform", "com.uswitch.heimdall/replicas-availability-deployment": "1", }, OwnerReferences: []metav1.OwnerReference{}, @@ -51,4 +77,23 @@ kube_deployment_spec_replicas{namespace="testNamespace", deployment="testApp"} < assert.Assert(t, is.Len(promrules, 1)) assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Expr.StrVal, expr) assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["owner"], "testDeploymentOwner") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["environment"], "testing") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["criticality"], "low") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["sensitivity"], "public") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["priority"], "p1") +} + +func TestDeploymentMultipleCustomLabels(t *testing.T) { + log.Setup(log.DEBUG_LEVEL) + + client := fake.NewSimpleClientset() + + template, err := NewPrometheusRuleTemplateManager("../../kube/config/templates", client) + + promrules, err := template.CreateFromDeployment(testDeploymentMultiLabel, "testNamespace") + assert.Assert(t, is.Nil(err)) + assert.Assert(t, is.Len(promrules, 1)) + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["priority"], "p3") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["channel"], "testing") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["team"], "platform") } diff --git a/pkg/templates/ingress.go b/pkg/templates/ingress.go index 0848ca7..da8c846 100644 --- a/pkg/templates/ingress.go +++ b/pkg/templates/ingress.go @@ -29,6 +29,7 @@ type templateParameterIngress struct { Criticality string Sensitivity string BackendService string + CustomLabels map[string]string } // CreateFromIngress @@ -50,12 +51,18 @@ func (a *PrometheusRuleTemplateManager) CreateFromIngress(ingress *networkingv1. prometheusRules := map[string]*monitoringv1.PrometheusRule{} annotations := ingress.GetAnnotations() + params.CustomLabels = extractCustomLabels(annotations) for k, v := range annotations { if !strings.HasPrefix(k, heimPrefix) { continue } + // Skip label-* annotations as they are not templates + if strings.HasPrefix(k, labelPrefix) { + continue + } + templateName := strings.TrimLeft(k, fmt.Sprintf("%s/", heimPrefix)) template, ok := a.templates[templateName] if !ok { diff --git a/pkg/templates/ingress_test.go b/pkg/templates/ingress_test.go index 67df99f..ee50720 100644 --- a/pkg/templates/ingress_test.go +++ b/pkg/templates/ingress_test.go @@ -74,6 +74,7 @@ var ( environmentAnnotation: "testing", criticalityAnnotation: "low", sensitivityAnnotation: "public", + priorityAnnotation: "p1", }, }, Spec: networkingv1.IngressSpec{ @@ -119,6 +120,33 @@ var ( }, }, } + + testIngressMultiLabel = &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testMultiLabel", + Namespace: "testNamespace", + Annotations: map[string]string{ + "com.uswitch.heimdall/5xx-rate": "0.001", + ownerAnnotation: "testIngressOwner", + environmentAnnotation: "testing", + criticalityAnnotation: "low", + sensitivityAnnotation: "public", + "com.uswitch.heimdall/label-priority": "p2", + "com.uswitch.heimdall/label-channel": "testing", + "com.uswitch.heimdall/label-region": "eu-west-1", + }, + }, + Spec: networkingv1.IngressSpec{ + DefaultBackend: &networkingv1.IngressBackend{ + Service: &networkingv1.IngressServiceBackend{ + Name: "testService", + Port: networkingv1.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }, + } ) func TestIngressAnnotationsDefaultBackend(t *testing.T) { @@ -147,6 +175,10 @@ func TestIngressAnnotationsDefaultBackend(t *testing.T) { assert.Assert(t, is.Len(promrules, 1)) assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Expr.StrVal, expr) assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["owner"], "testIngressOwner") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["environment"], "testing") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["criticality"], "low") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["sensitivity"], "public") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["priority"], "p1") } func TestIngressAnnotationsRuleBackend(t *testing.T) { @@ -186,3 +218,19 @@ func TestNamesMatch(t *testing.T) { service = checkNamesMatch(services) assert.Equal(t, "", service) } + +func TestIngressMultipleCustomLabels(t *testing.T) { + log.Setup(log.DEBUG_LEVEL) + + client := fake.NewSimpleClientset(testService, testDeployment, testReplicaset, testPod) + + template, err := NewPrometheusRuleTemplateManager("../../kube/config/templates", client) + + promrules, err := template.CreateFromIngress(testIngressMultiLabel) + assert.Assert(t, is.Nil(err)) + assert.Assert(t, is.Len(promrules, 1)) + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["priority"], "p2") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["channel"], "testing") + assert.Equal(t, promrules[0].Spec.Groups[0].Rules[0].Labels["region"], "eu-west-1") +} + diff --git a/pkg/templates/promrules.go b/pkg/templates/promrules.go index 854b139..ec7f2f9 100644 --- a/pkg/templates/promrules.go +++ b/pkg/templates/promrules.go @@ -14,13 +14,17 @@ import ( corev1 "k8s.io/client-go/kubernetes/typed/core/v1" ) -var heimPrefix = "com.uswitch.heimdall" +var ( + heimPrefix = "com.uswitch.heimdall" + labelPrefix = "com.uswitch.heimdall/label-" +) const ( ownerAnnotation = "service.rvu.co.uk/owner" environmentAnnotation = "service.rvu.co.uk/environment" criticalityAnnotation = "service.rvu.co.uk/criticality" sensitivityAnnotation = "service.rvu.co.uk/sensitivity" + priorityAnnotation = "com.uswitch.heimdall/label-priority" ) // ClientSetI @@ -79,3 +83,17 @@ func collectPrometheusRules(prometheusRules map[string]*monitoringv1.PrometheusR return ret } + +// com.uswitch.heimdall/label-priority: p3 -> map["priority"] = "p3" +func extractCustomLabels(annotations map[string]string) map[string]string { + customLabels := make(map[string]string) + + for k, v := range annotations { + if strings.HasPrefix(k, labelPrefix) { + labelName := strings.TrimPrefix(k, labelPrefix) + customLabels[labelName] = v + } + } + + return customLabels +}