Search code examples
kubernetesreplaceyqtektonopenshift-pipelines

Tekton: yq Task gives safelyRenameFile [ERRO] Failed copying from /tmp/temp & [ERRO] open /workspace/source permission denied error


We have a Tekton pipeline and want to replace the image tags contents of our deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice-api-spring-boot
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: microservice-api-spring-boot
  template:
    metadata:
      labels:
        app: microservice-api-spring-boot
    spec:
      containers:
        - image: registry.gitlab.com/jonashackt/microservice-api-spring-boot@sha256:5d8a03755d3c45a3d79d32ab22987ef571a65517d0edbcb8e828a4e6952f9bcd
          name: microservice-api-spring-boot
          ports:
            - containerPort: 8098
      imagePullSecrets:
        - name: gitlab-container-registry

Our Tekton pipeline uses the yq Task from Tekton Hub to replace the .spec.template.spec.containers[0].image with the "$(params.IMAGE):$(params.SOURCE_REVISION)" name like this:

- name: substitute-config-image-name
  taskRef:
    name: yq
  runAfter:
    - fetch-config-repository
  workspaces:
    - name: source
      workspace: config-workspace
  params:
    - name: files
      value:
      - "./deployment/deployment.yml"
    - name: expression
      value: .spec.template.spec.containers[0].image = \"$(params.IMAGE)\":\"$(params.SOURCE_REVISION)\"

Sadly the yq Task doesn't seem to work, it produces a green Step completed successfully, but shows the following errors:

16:50:43 safelyRenameFile [ERRO] Failed copying from /tmp/temp3555913516 to /workspace/source/deployment/deployment.yml
16:50:43 safelyRenameFile [ERRO] open /workspace/source/deployment/deployment.yml: permission denied

Here's also a screenshot from our Tekton Dashboard:

enter image description here

Any idea on how to solve the error?


Solution

  • The problem seems to be related to the way how the Dockerfile of https://github.com/mikefarah/yq now handles file permissions (for example this fix among others). The 0.3 version of the Tekton yq Task uses the image https://hub.docker.com/layers/mikefarah/yq/4.16.2/images/sha256-c6ef1bc27dd9cee57fa635d9306ce43ca6805edcdab41b047905f7835c174005 which produces the error.

    One work-around to the problem could be the usage of the yq Task version 0.2 which you can apply via:

    kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/yq/0.2/yq.yaml
    

    This one uses the older docker.io/mikefarah/yq:4@sha256:34f1d11ad51dc4639fc6d8dd5ade019fe57cf6084bb6a99a2f11ea522906033b and works without the error.

    Alternatively you can simply create your own yq based Task that won't have the problem like this:

    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: replace-image-name-with-yq
    spec:
      workspaces:
        - name: source
          description: A workspace that contains the file which need to be dumped.
      params:
        - name: IMAGE_NAME
          description: The image name to substitute
        - name: FILE_PATH
          description: The file path relative to the workspace dir.
        - name: YQ_VERSION
          description: Version of https://github.com/mikefarah/yq
          default: v4.2.0
      steps:
        - name: substitute-with-yq
          image: alpine
          workingDir: $(workspaces.source.path)
          command:
            - /bin/sh
          args:
            - '-c'
            - |
              set -ex
              echo "--- Download yq & add to path"
              wget https://github.com/mikefarah/yq/releases/download/$(params.YQ_VERSION)/yq_linux_amd64 -O /usr/bin/yq &&\
                  chmod +x /usr/bin/yq
              echo "--- Run yq expression"
              yq e ".spec.template.spec.containers[0].image = \"$(params.IMAGE_NAME)\"" -i $(params.FILE_PATH)
              echo "--- Show file with replacement"
              cat $(params.FILE_PATH)
          resources: {}
    

    This custom Task simple uses the alpine image as base and installs yq using the Plain binary wget download. Also it uses yq exactly as you would do on the command line locally, which makes development of your expression so much easier!

    As a bonus it outputs the file contents so you can check the replacement results right in the Tekton pipeline!

    You need to apply it with

    kubectl apply -f tekton-ci-config/replace-image-name-with-yq.yml
    

    And should now be able to use it like this:

    - name: replace-config-image-name
      taskRef:
        name: replace-image-name-with-yq
      runAfter:
        - dump-contents
      workspaces:
        - name: source
          workspace: config-workspace
      params:
        - name: IMAGE_NAME
          value: "$(params.IMAGE):$(params.SOURCE_REVISION)"
        - name: FILE_PATH
          value: "./deployment/deployment.yml"
    

    Inside the Tekton dashboard it will look somehow like this and output the processed file:

    enter image description here