From 59c050232ea8933181a585bb2105fa2812b1b5ba Mon Sep 17 00:00:00 2001 From: chhsia0 Date: Thu, 5 Sep 2019 15:08:42 -0700 Subject: [PATCH] Added Task `update-image-digests`. This is intended to be a workaround for https://github.com/tektoncd/pipeline/issues/216. The `resourcesResoult` field is proposed to be removed in pipeline 0.9, where this Task will no longer work. --- update-image-digests/README.md | 86 +++++++++++++++++++ .../image-digest-updater.yaml | 37 ++++++++ .../update-image-digests.yaml | 67 +++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 update-image-digests/README.md create mode 100644 update-image-digests/image-digest-updater.yaml create mode 100644 update-image-digests/update-image-digests.yaml diff --git a/update-image-digests/README.md b/update-image-digests/README.md new file mode 100644 index 0000000000..3b5c0bb786 --- /dev/null +++ b/update-image-digests/README.md @@ -0,0 +1,86 @@ +# Update Image Digests + +This Task updates all image resources that has digests exported built by a predecessor task in the same pipeline run. + +## Install the Task + +``` +kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/master/update-image-digests/update-image-digests.yaml +``` + +## Inputs + +### Parameters + +* **pipelineTask**: The name of the task that exports image digests in the pipeline. + +## Usage + +### Authorizing the Deployment + +In order to retrieve digests and update image resources, you must first define a `ServiceAccount` +with permission to get and patch resources. + +To create a `ServiceAccount` with these permissions, you can run: + +``` +kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/master/update-image-digests/image-digest-updater.yaml +``` + +### Using the Task in a Pipeline + +The following Pipeline uses this Task to update the digest of an image resource outputted by Task +`build`, so `test` can find the correct image to run tests. +``` +apiVersion: tekton.dev/v1alpha1 +kind: Pipeline +metadata: + name: build-and-test +spec: + resources: + - name: git-source + type: git + - name: built-image + type: image + tasks: + - name: build + resources: + inputs: + - name: git-source + resource: git-source + outputs: + - name: built-image + resource: built-image + taskRef: + name: source-to-image + - name: update-digest + params: + - name: pipelineTask + value: build + runAfter: + - build + taskRef: + name: update-image-digests + - name: test + resources: + inputs: + - from: + - build + name: built-image + resource: built-image + runAfter: + - update-digest + taskRef: + name: run-test-binary +``` + +### Runtime Assumptions + +This Task relies on the following implementation details of Tekton pipeline: +* The pod running this Task has the `tekton.dev/pipelineRun` label set to the name of the + PipelineRun this pod belongs to, which is true if this Task is in a Pipeline. +* The TaskRun of the Task is created after its predecessor Task finishes. It uses the name of the + PipelineRun and the `pipelineTask` parameter to uniquely identify the predecessor's TaskRun and + gets the image digests from the status of the predecessor. +* The TaskRuns of all successor Tasks are created after this Task finishes, so the string + interpolation can find the updated digests. diff --git a/update-image-digests/image-digest-updater.yaml b/update-image-digests/image-digest-updater.yaml new file mode 100644 index 0000000000..dc4e9ac409 --- /dev/null +++ b/update-image-digests/image-digest-updater.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: image-digest-updater-account + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: image-digest-updater +rules: +- apiGroups: + - tekton.dev + resources: + - taskruns + verbs: + - list +- apiGroups: + - tekton.dev + resources: + - pipelineresources + verbs: + - get + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: image-digest-updater-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: image-digest-updater +subjects: +- kind: ServiceAccount + name: image-digest-updater-account + namespace: default diff --git a/update-image-digests/update-image-digests.yaml b/update-image-digests/update-image-digests.yaml new file mode 100644 index 0000000000..68002ebbda --- /dev/null +++ b/update-image-digests/update-image-digests.yaml @@ -0,0 +1,67 @@ +apiVersion: tekton.dev/v1alpha1 +kind: Task +metadata: + name: update-image-digests +spec: + inputs: + params: + - name: pipelineTask + type: string + description: The name of the task in the pipeline that outputs image resources + volumes: + - name: data + emptyDir: {} + stepTemplate: + image: lachlanevenson/k8s-kubectl + volumeMounts: + - name: data + mountPath: /data + steps: + - name: get-digests + command: + - sh + - -c + - >- + kubectl get taskrun.tekton.dev + --selector='tekton.dev/pipelineRun=$(PIPELINE_RUN),tekton.dev/pipelineTask=$(inputs.params.pipelineTask)' + --output='jsonpath={range ..resourcesResult[*]}{.name} {.digest}{"\n"}{end}' + > /data/digests + env: + - name: PIPELINE_RUN + valueFrom: + fieldRef: + fieldPath: metadata.labels['tekton.dev/pipelineRun'] + - name: check-digests + command: + - sh + - -c + - |- + xargs -n 2 -I {} sh -c 'egrep "^[0-9a-z.-]+ sha256:[0-9a-f]{64}$" <- + xargs -n 2 sh -c + 'kubectl get pipelineresource.tekton.dev/$1 --output=json > /data/image-$1.json' + -- < /data/digests + - name: create-patches + image: stedolan/jq + command: + - sh + - -c + - >- + xargs -n 2 sh -c + 'jq -c "{spec:{params:(.spec.params|[(.[]|select(.name!=\"digest\"))]+[{name:\"digest\",value:\"$2\"}])}}" + /data/image-$1.json > /data/patch-$1.json' + -- < /data/digests + - name: patch-image-resources + command: + - sh + - -c + - >- + xargs -n 2 sh -c + 'kubectl patch pipelineresource.tekton.dev/$1 --type=merge --patch=$(cat < /data/patch-$1.json)' + -- < /data/digests