From 64ca9a54d10da444ad0685a031f40ec6762b82c5 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <127358482+zc-devs@users.noreply.github.com> Date: Sat, 13 Apr 2024 02:30:05 +0300 Subject: [PATCH] Added step's labels and annotations --- .../backend/kubernetes/backend_options.go | 2 + .../kubernetes/backend_options_test.go | 4 + pipeline/backend/kubernetes/pod.go | 73 +++++++++++++------ pipeline/backend/kubernetes/pod_test.go | 6 +- .../frontend/yaml/linter/schema/schema.json | 13 +++- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/pipeline/backend/kubernetes/backend_options.go b/pipeline/backend/kubernetes/backend_options.go index 3b1109a2c..a1d82067e 100644 --- a/pipeline/backend/kubernetes/backend_options.go +++ b/pipeline/backend/kubernetes/backend_options.go @@ -11,6 +11,8 @@ type BackendOptions struct { Resources Resources `mapstructure:"resources"` RuntimeClassName *string `mapstructure:"runtimeClassName"` ServiceAccountName string `mapstructure:"serviceAccountName"` + Labels map[string]string `mapstructure:"labels"` + Annotations map[string]string `mapstructure:"annotations"` NodeSelector map[string]string `mapstructure:"nodeSelector"` Tolerations []Toleration `mapstructure:"tolerations"` SecurityContext *SecurityContext `mapstructure:"securityContext"` diff --git a/pipeline/backend/kubernetes/backend_options_test.go b/pipeline/backend/kubernetes/backend_options_test.go index f9c21a5fe..3d5a73f32 100644 --- a/pipeline/backend/kubernetes/backend_options_test.go +++ b/pipeline/backend/kubernetes/backend_options_test.go @@ -20,6 +20,8 @@ func Test_parseBackendOptions(t *testing.T) { "kubernetes": map[string]any{ "nodeSelector": map[string]string{"storage": "ssd"}, "serviceAccountName": "wp-svc-acc", + "labels": map[string]string{"app": "test"}, + "annotations": map[string]string{"apps.kubernetes.io/pod-index": "0"}, "tolerations": []map[string]any{ {"key": "net-port", "value": "100Mbit", "effect": TaintEffectNoSchedule}, }, @@ -49,6 +51,8 @@ func Test_parseBackendOptions(t *testing.T) { assert.Equal(t, BackendOptions{ NodeSelector: map[string]string{"storage": "ssd"}, ServiceAccountName: "wp-svc-acc", + Labels: map[string]string{"app": "test"}, + Annotations: map[string]string{"apps.kubernetes.io/pod-index": "0"}, Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}}, Resources: Resources{ Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"}, diff --git a/pipeline/backend/kubernetes/pod.go b/pipeline/backend/kubernetes/pod.go index 331efae92..aa0cf355d 100644 --- a/pipeline/backend/kubernetes/pod.go +++ b/pipeline/backend/kubernetes/pod.go @@ -76,43 +76,68 @@ func podName(step *types.Step) (string, error) { func podMeta(step *types.Step, config *config, options BackendOptions, podName string) (metav1.ObjectMeta, error) { var err error meta := metav1.ObjectMeta{ - Name: podName, - Namespace: config.Namespace, + Name: podName, + Namespace: config.Namespace, + Annotations: podAnnotations(config, options, podName), } - meta.Labels = config.PodLabels - if meta.Labels == nil { - meta.Labels = make(map[string]string, 1) - } - meta.Labels[StepLabel], err = stepLabel(step) + meta.Labels, err = podLabels(step, config, options) if err != nil { return meta, err } - if step.Type == types.StepTypeService { - meta.Labels[ServiceLabel], _ = serviceName(step) - } - - meta.Annotations = config.PodAnnotations - if meta.Annotations == nil { - meta.Annotations = make(map[string]string) - } - - securityContext := options.SecurityContext - if securityContext != nil { - key, value := apparmorAnnotation(podName, securityContext.ApparmorProfile) - if key != nil && value != nil { - meta.Annotations[*key] = *value - } - } - return meta, nil } +func podLabels(step *types.Step, config *config, options BackendOptions) (map[string]string, error) { + var err error + labels := make(map[string]string) + + if len(options.Labels) > 0 { + log.Trace().Msgf("using labels from the backend options: %v", options.Labels) + maps.Copy(labels, options.Labels) + } + if len(config.PodLabels) > 0 { + log.Trace().Msgf("using labels from the configuration: %v", config.PodLabels) + maps.Copy(labels, config.PodLabels) + } + if step.Type == types.StepTypeService { + labels[ServiceLabel], _ = serviceName(step) + } + labels[StepLabel], err = stepLabel(step) + if err != nil { + return labels, err + } + + return labels, nil +} + func stepLabel(step *types.Step) (string, error) { return toDNSName(step.Name) } +func podAnnotations(config *config, options BackendOptions, podName string) map[string]string { + annotations := make(map[string]string) + + if len(options.Annotations) > 0 { + log.Trace().Msgf("using annotations from the backend options: %v", options.Annotations) + maps.Copy(annotations, options.Annotations) + } + if len(config.PodAnnotations) > 0 { + log.Trace().Msgf("using annotations from the configuration: %v", config.PodAnnotations) + maps.Copy(annotations, config.PodAnnotations) + } + securityContext := options.SecurityContext + if securityContext != nil { + key, value := apparmorAnnotation(podName, securityContext.ApparmorProfile) + if key != nil && value != nil { + annotations[*key] = *value + } + } + + return annotations +} + func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSpec, error) { var err error spec := v1.PodSpec{ diff --git a/pipeline/backend/kubernetes/pod_test.go b/pipeline/backend/kubernetes/pod_test.go index bf4f35a41..412b30579 100644 --- a/pipeline/backend/kubernetes/pod_test.go +++ b/pipeline/backend/kubernetes/pod_test.go @@ -159,11 +159,13 @@ func TestFullPod(t *testing.T) { "creationTimestamp": null, "labels": { "app": "test", + "part-of": "woodpecker-ci", "step": "go-test" }, "annotations": { "apps.kubernetes.io/pod-index": "0", - "container.apparmor.security.beta.kubernetes.io/wp-01he8bebctabr3kgk0qj36d2me-0": "localhost/k8s-apparmor-example-deny-write" + "container.apparmor.security.beta.kubernetes.io/wp-01he8bebctabr3kgk0qj36d2me-0": "localhost/k8s-apparmor-example-deny-write", + "kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu, memory request and limit for container" } }, "spec": { @@ -334,6 +336,8 @@ func TestFullPod(t *testing.T) { PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"}, SecurityContext: SecurityContextConfig{RunAsNonRoot: false}, }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ + Labels: map[string]string{"part-of": "woodpecker-ci"}, + Annotations: map[string]string{"kubernetes.io/limit-ranger": "LimitRanger plugin set: cpu, memory request and limit for container"}, NodeSelector: map[string]string{"storage": "ssd"}, RuntimeClassName: &runtimeClass, ServiceAccountName: "wp-svc-acc", diff --git a/pipeline/frontend/yaml/linter/schema/schema.json b/pipeline/frontend/yaml/linter/schema/schema.json index 13d7af690..ee04a5a09 100644 --- a/pipeline/frontend/yaml/linter/schema/schema.json +++ b/pipeline/frontend/yaml/linter/schema/schema.json @@ -691,8 +691,17 @@ "description": "Advanced options for the kubernetes agent backends", "type": "object", "properties": { - "resources": { - "$ref": "#/definitions/step_backend_kubernetes_resources" + "labels": { + "type": "object", + "additionalProperties": { + "type": ["boolean", "string", "number"] + } + }, + "annotations": { + "type": "object", + "additionalProperties": { + "type": ["boolean", "string", "number"] + } }, "securityContext": { "$ref": "#/definitions/step_backend_kubernetes_security_context"