From 64d72ca1fbc8eb2b052a57a6258a21ba155b80ab Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Mon, 25 Mar 2019 11:48:47 +0100 Subject: [PATCH] Add workflow labels and annotations global vars --- docs/variables.md | 2 + workflow/controller/operator.go | 6 +++ workflow/controller/operator_test.go | 61 ++++++++++++++++++++++++++++ workflow/validate/validate.go | 9 ++++ 4 files changed, 78 insertions(+) diff --git a/docs/variables.md b/docs/variables.md index cabf49084437..98dc34c067c4 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -43,6 +43,8 @@ The following variables are made available to reference various metadata of a wo | `workflow.uid` | Workflow UID. Useful for setting ownership reference to a resource, or a unique artifact location | | `workflow.parameters.` | Input parameter to the workflow | | `workflow.outputs.parameters.` | Input artifact to the workflow | +| `workflow.annotations.` | Workflow annotations | +| `workflow.labels.` | Workflow labels | | `workflow.creationTimestamp` | Workflow creation timestamp formatted in RFC 3339 (e.g. `2018-08-23T05:42:49Z`) | | `workflow.creationTimestamp.` | Creation timestamp formatted with a [strftime](http://strftime.org) format character | diff --git a/workflow/controller/operator.go b/workflow/controller/operator.go index 417a460c7936..f2cb6e4fcaa8 100644 --- a/workflow/controller/operator.go +++ b/workflow/controller/operator.go @@ -254,6 +254,12 @@ func (woc *wfOperationCtx) setGlobalParameters() { for _, param := range woc.wf.Spec.Arguments.Parameters { woc.globalParams["workflow.parameters."+param.Name] = *param.Value } + for k, v := range woc.wf.ObjectMeta.Annotations { + woc.globalParams["workflow.annotations."+k] = v + } + for k, v := range woc.wf.ObjectMeta.Labels { + woc.globalParams["workflow.labels."+k] = v + } if woc.wf.Status.Outputs != nil { for _, param := range woc.wf.Status.Outputs.Parameters { woc.globalParams["workflow.outputs.parameters."+param.Name] = *param.Value diff --git a/workflow/controller/operator_test.go b/workflow/controller/operator_test.go index 42e43e22fa1e..b8b5b3f543e9 100644 --- a/workflow/controller/operator_test.go +++ b/workflow/controller/operator_test.go @@ -886,3 +886,64 @@ func TestExpandWithSequence(t *testing.T) { assert.Equal(t, "testuser01", items[0].Value.(string)) assert.Equal(t, "testuser0A", items[9].Value.(string)) } + +var metadataTemplate = ` +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + name: metadata-template + labels: + image: foo:bar + annotations: + k8s-webhook-handler.io/repo: "git@github.com:argoproj/argo.git" + k8s-webhook-handler.io/revision: 1e111caa1d2cc672b3b53c202b96a5f660a7e9b2 +spec: + entrypoint: foo + templates: + - name: foo + container: + image: "{{workflow.labels.image}}" + env: + - name: REPO + value: "{{workflow.annotations.k8s-webhook-handler.io/repo}}" + - name: REVISION + value: "{{workflow.annotations.k8s-webhook-handler.io/revision}}" + command: [sh, -c] + args: ["echo hello world"] +` + +func TestMetadataPassing(t *testing.T) { + controller := newController() + wfcset := controller.wfclientset.ArgoprojV1alpha1().Workflows("") + wf := unmarshalWF(metadataTemplate) + wf, err := wfcset.Create(wf) + assert.Nil(t, err) + wf, err = wfcset.Get(wf.ObjectMeta.Name, metav1.GetOptions{}) + assert.Nil(t, err) + woc := newWorkflowOperationCtx(wf, controller) + woc.operate() + assert.Equal(t, wfv1.NodeRunning, woc.wf.Status.Phase) + pods, err := controller.kubeclientset.CoreV1().Pods(wf.ObjectMeta.Namespace).List(metav1.ListOptions{}) + assert.Nil(t, err) + assert.True(t, len(pods.Items) > 0, "pod was not created successfully") + + var ( + pod = pods.Items[0] + container = pod.Spec.Containers[0] + foundRepo = false + foundRev = false + ) + for _, ev := range container.Env { + switch ev.Name { + case "REPO": + assert.Equal(t, "git@github.com:argoproj/argo.git", ev.Value) + foundRepo = true + case "REVISION": + assert.Equal(t, "1e111caa1d2cc672b3b53c202b96a5f660a7e9b2", ev.Value) + foundRev = true + } + } + assert.True(t, foundRepo) + assert.True(t, foundRev) + assert.Equal(t, "foo:bar", container.Image) +} diff --git a/workflow/validate/validate.go b/workflow/validate/validate.go index 95524577d8ea..8f5085fb466f 100644 --- a/workflow/validate/validate.go +++ b/workflow/validate/validate.go @@ -66,6 +66,14 @@ func ValidateWorkflow(wf *wfv1.Workflow, lint ...bool) error { for _, param := range ctx.wf.Spec.Arguments.Parameters { ctx.globalParams["workflow.parameters."+param.Name] = placeholderValue } + + for k := range ctx.wf.ObjectMeta.Annotations { + ctx.globalParams["workflow.annotations."+k] = placeholderValue + } + for k := range ctx.wf.ObjectMeta.Labels { + ctx.globalParams["workflow.labels."+k] = placeholderValue + } + if ctx.wf.Spec.Entrypoint == "" { return errors.New(errors.CodeBadRequest, "spec.entrypoint is required") } @@ -111,6 +119,7 @@ func (ctx *wfValidationCtx) validateTemplate(tmpl *wfv1.Template, args wfv1.Argu localParams[common.LocalVarPodName] = placeholderValue scope[common.LocalVarPodName] = placeholderValue } + _, err = common.ProcessArgs(tmpl, args, ctx.globalParams, localParams, true) if err != nil { return errors.Errorf(errors.CodeBadRequest, "templates.%s %s", tmpl.Name, err)