diff --git a/docs/docs/30-administration/10-configuration/11-backends/20-kubernetes.md b/docs/docs/30-administration/10-configuration/11-backends/20-kubernetes.md index c15d99edd..8ba332322 100644 --- a/docs/docs/30-administration/10-configuration/11-backends/20-kubernetes.md +++ b/docs/docs/30-administration/10-configuration/11-backends/20-kubernetes.md @@ -19,6 +19,8 @@ The following metadata labels are supported: - `woodpecker-ci.org/repo-full-name` - `woodpecker-ci.org/branch` - `woodpecker-ci.org/org-id` +- `woodpecker-ci.org/task-uuid` +- `woodpecker-ci.org/step` ## Private registries diff --git a/pipeline/backend/kubernetes/kubernetes.go b/pipeline/backend/kubernetes/kubernetes.go index 85e8804f0..596cb6d0b 100644 --- a/pipeline/backend/kubernetes/kubernetes.go +++ b/pipeline/backend/kubernetes/kubernetes.go @@ -274,7 +274,7 @@ func (e *kube) StartStep(ctx context.Context, step *types.Step, taskUUID string) } log.Trace().Str("taskUUID", taskUUID).Msgf("starting step: %s", step.Name) - _, err = startPod(ctx, e, step, options) + _, err = startPod(ctx, e, step, options, taskUUID) return err } diff --git a/pipeline/backend/kubernetes/pod.go b/pipeline/backend/kubernetes/pod.go index ebabf1f31..c99419ebd 100644 --- a/pipeline/backend/kubernetes/pod.go +++ b/pipeline/backend/kubernetes/pod.go @@ -36,11 +36,12 @@ const ( // This will be removed in the future. StepLabelLegacy = "step" StepLabel = "woodpecker-ci.org/step" + TaskUUIDLabel = "woodpecker-ci.org/task-uuid" podPrefix = "wp-" defaultFSGroup int64 = 1000 ) -func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions) (*v1.Pod, error) { +func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions, taskUUID string) (*v1.Pod, error) { var err error nsp := newNativeSecretsProcessor(config, options.Secrets) @@ -49,7 +50,7 @@ func mkPod(step *types.Step, config *config, podName, goos string, options Backe return nil, err } - meta, err := podMeta(step, config, options, podName) + meta, err := podMeta(step, config, options, podName, taskUUID) if err != nil { return nil, err } @@ -84,7 +85,7 @@ func podName(step *types.Step) (string, error) { return dnsName(podPrefix + step.UUID) } -func podMeta(step *types.Step, config *config, options BackendOptions, podName string) (meta_v1.ObjectMeta, error) { +func podMeta(step *types.Step, config *config, options BackendOptions, podName, taskUUID string) (meta_v1.ObjectMeta, error) { var err error meta := meta_v1.ObjectMeta{ Name: podName, @@ -92,7 +93,7 @@ func podMeta(step *types.Step, config *config, options BackendOptions, podName s Annotations: podAnnotations(config, options), } - meta.Labels, err = podLabels(step, config, options) + meta.Labels, err = podLabels(step, config, options, taskUUID) if err != nil { return meta, err } @@ -100,7 +101,7 @@ func podMeta(step *types.Step, config *config, options BackendOptions, podName s return meta, nil } -func podLabels(step *types.Step, config *config, options BackendOptions) (map[string]string, error) { +func podLabels(step *types.Step, config *config, options BackendOptions, taskUUID string) (map[string]string, error) { var err error labels := make(map[string]string) @@ -141,6 +142,10 @@ func podLabels(step *types.Step, config *config, options BackendOptions) (map[st return labels, err } + if len(taskUUID) > 0 { + labels[TaskUUIDLabel] = taskUUID + } + return labels, nil } @@ -598,13 +603,13 @@ func mapToEnvVars(m map[string]string) []v1.EnvVar { return ev } -func startPod(ctx context.Context, engine *kube, step *types.Step, options BackendOptions) (*v1.Pod, error) { +func startPod(ctx context.Context, engine *kube, step *types.Step, options BackendOptions, taskUUID string) (*v1.Pod, error) { podName, err := stepToPodName(step) if err != nil { return nil, err } engineConfig := engine.getConfig() - pod, err := mkPod(step, engineConfig, podName, engine.goos, options) + pod, err := mkPod(step, engineConfig, podName, engine.goos, options, taskUUID) if err != nil { return nil, err } diff --git a/pipeline/backend/kubernetes/pod_test.go b/pipeline/backend/kubernetes/pod_test.go index b06edd70b..4a9d00db7 100644 --- a/pipeline/backend/kubernetes/pod_test.go +++ b/pipeline/backend/kubernetes/pod_test.go @@ -25,6 +25,8 @@ import ( "go.woodpecker-ci.org/woodpecker/v3/pipeline/backend/types" ) +const taskUUID = "11301" + func TestPodName(t *testing.T) { name, err := podName(&types.Step{UUID: "01he8bebctabr3kgk0qj36d2me-0"}) assert.NoError(t, err) @@ -73,9 +75,10 @@ func TestPodMeta(t *testing.T) { Environment: map[string]string{"CI": "woodpecker"}, }, &config{ Namespace: "woodpecker", - }, BackendOptions{}, "wp-01he8bebctabr3kg-0") + }, BackendOptions{}, "wp-01he8bebctabr3kg-0", taskUUID) assert.NoError(t, err) assert.EqualValues(t, "wp-svc-01he8bebctabr3kg-postgres", meta.Labels[ServiceLabel]) + assert.EqualValues(t, taskUUID, meta.Labels[TaskUUIDLabel]) // Detached service meta, err = podMeta(&types.Step{ @@ -87,7 +90,7 @@ func TestPodMeta(t *testing.T) { Environment: map[string]string{"CI": "woodpecker"}, }, &config{ Namespace: "woodpecker", - }, BackendOptions{}, "wp-01he8bebctabr3kg-0") + }, BackendOptions{}, "wp-01he8bebctabr3kg-0", taskUUID) assert.NoError(t, err) assert.EqualValues(t, "wp-svc-01he8bebctabr3kg-postgres", meta.Labels[ServiceLabel]) @@ -101,7 +104,7 @@ func TestPodMeta(t *testing.T) { Environment: map[string]string{"CI": "woodpecker"}, }, &config{ Namespace: "woodpecker", - }, BackendOptions{}, "wp-01he8bebctabr3kg-0") + }, BackendOptions{}, "wp-01he8bebctabr3kg-0", taskUUID) assert.NoError(t, err) assert.EqualValues(t, "", meta.Labels[ServiceLabel]) } @@ -123,7 +126,8 @@ func TestTinyPod(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "build-via-gradle", - "woodpecker-ci.org/step": "build-via-gradle" + "woodpecker-ci.org/step": "build-via-gradle", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -185,7 +189,7 @@ func TestTinyPod(t *testing.T) { Environment: map[string]string{"CI": "woodpecker"}, }, &config{ Namespace: "woodpecker", - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) + }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -205,7 +209,8 @@ func TestFullPod(t *testing.T) { "app": "test", "part-of": "woodpecker-ci", "step": "go-test", - "woodpecker-ci.org/step": "go-test" + "woodpecker-ci.org/step": "go-test", + "woodpecker-ci.org/task-uuid": "11301" }, "annotations": { "apps.kubernetes.io/pod-index": "0", @@ -391,19 +396,22 @@ func TestFullPod(t *testing.T) { PodTolerationsAllowFromStep: true, PodNodeSelector: map[string]string{"topology.kubernetes.io/region": "eu-central-1"}, 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", - Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}}, - Resources: Resources{ - Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"}, - Limits: map[string]string{"memory": "256Mi", "cpu": "2"}, - }, - SecurityContext: &secCtx, - }) + }, + "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", + Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}}, + Resources: Resources{ + Requests: map[string]string{"memory": "128Mi", "cpu": "1000m"}, + Limits: map[string]string{"memory": "256Mi", "cpu": "2"}, + }, + SecurityContext: &secCtx, + }, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -425,7 +433,7 @@ func TestPodPrivilege(t *testing.T) { SecurityContext: SecurityContextConfig{RunAsNonRoot: globalRunAsRoot}, }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ SecurityContext: &secCtx, - }) + }, "") } // securty context is requesting user and group 101 (non-root) @@ -504,7 +512,8 @@ func TestScratchPod(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "curl-google", - "woodpecker-ci.org/step": "curl-google" + "woodpecker-ci.org/step": "curl-google", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -532,7 +541,7 @@ func TestScratchPod(t *testing.T) { Entrypoint: []string{"/usr/bin/curl", "-v", "google.com"}, }, &config{ Namespace: "woodpecker", - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) + }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -550,7 +559,8 @@ func TestSecrets(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "test-secrets", - "woodpecker-ci.org/step": "test-secrets" + "woodpecker-ci.org/step": "test-secrets", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -652,7 +662,7 @@ func TestSecrets(t *testing.T) { Target: SecretTarget{File: "~/.docker/config.json"}, }, }, - }) + }, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -670,7 +680,8 @@ func TestPodTolerations(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "toleration-test", - "woodpecker-ci.org/step": "toleration-test" + "woodpecker-ci.org/step": "toleration-test", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -711,7 +722,7 @@ func TestPodTolerations(t *testing.T) { Namespace: "woodpecker", PodTolerations: globalTolerations, PodTolerationsAllowFromStep: false, - }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}) + }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{}, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -729,7 +740,8 @@ func TestPodTolerationsAllowFromStep(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "toleration-test", - "woodpecker-ci.org/step": "toleration-test" + "woodpecker-ci.org/step": "toleration-test", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -751,7 +763,8 @@ func TestPodTolerationsAllowFromStep(t *testing.T) { "namespace": "woodpecker", "labels": { "step": "toleration-test", - "woodpecker-ci.org/step": "toleration-test" + "woodpecker-ci.org/step": "toleration-test", + "woodpecker-ci.org/task-uuid": "11301" } }, "spec": { @@ -789,7 +802,7 @@ func TestPodTolerationsAllowFromStep(t *testing.T) { PodTolerationsAllowFromStep: false, }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ Tolerations: stepTolerations, - }) + }, taskUUID) assert.NoError(t, err) podJSON, err := json.Marshal(pod) @@ -803,7 +816,7 @@ func TestPodTolerationsAllowFromStep(t *testing.T) { PodTolerationsAllowFromStep: true, }, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{ Tolerations: stepTolerations, - }) + }, taskUUID) assert.NoError(t, err) podJSON, err = json.Marshal(pod)