From 777230be591b57e7bda69b9133543e8151def957 Mon Sep 17 00:00:00 2001 From: Paul Belanger Date: Thu, 12 Nov 2020 15:30:03 -0500 Subject: [PATCH] Create upload-container-image role This new role will be used to replace our upload-docker-image role in the future. Change-Id: I0e2b0cca6575255520aa6d4d48a12128ab5f46cc Signed-off-by: Paul Belanger --- doc/source/container-roles.rst | 1 + roles/build-container-image/tasks/build.yaml | 6 ++-- roles/upload-container-image/README.rst | 13 +++++++++ .../upload-container-image/defaults/main.yaml | 2 ++ roles/upload-container-image/tasks/main.yaml | 15 ++++++++++ roles/upload-container-image/tasks/push.yaml | 21 ++++++++++++++ ...est-build-container-image-release-pre.yaml | 28 +++++++++++++++++++ .../test-build-container-image-release.yaml | 11 +++++++- zuul-tests.d/container-roles-jobs.yaml | 27 ++++++++++++++++++ 9 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 roles/upload-container-image/README.rst create mode 100644 roles/upload-container-image/defaults/main.yaml create mode 100644 roles/upload-container-image/tasks/main.yaml create mode 100644 roles/upload-container-image/tasks/push.yaml diff --git a/doc/source/container-roles.rst b/doc/source/container-roles.rst index 2da315798..7267c0a1b 100644 --- a/doc/source/container-roles.rst +++ b/doc/source/container-roles.rst @@ -14,6 +14,7 @@ Container Roles .. zuul:autorole:: pull-from-intermediate-registry .. zuul:autorole:: push-to-intermediate-registry .. zuul:autorole:: run-buildset-registry +.. zuul:autorole:: upload-container-image .. zuul:autorole:: upload-docker-image .. zuul:autorole:: use-buildset-registry .. zuul:autorole:: use-docker-mirror diff --git a/roles/build-container-image/tasks/build.yaml b/roles/build-container-image/tasks/build.yaml index 3261be4b9..36dcbc6df 100644 --- a/roles/build-container-image/tasks/build.yaml +++ b/roles/build-container-image/tasks/build.yaml @@ -30,6 +30,8 @@ containerfile: "{{ zj_image.container_filename|default(container_filename)|default('') }}" - name: Build a container image + vars: + tag_prefix: "{{ ('change_' + zuul.change) if (zuul.change is defined) else zuul.pipeline }}_" command: >- {{ container_command }} build {{ zj_image.path | default('.') }} {% if containerfile %}-f {{ containerfile }}{% endif %} {% if zj_image.target | default(false) -%} @@ -42,8 +44,8 @@ --build-arg "ZUUL_SIBLINGS={{ zj_image.siblings | join(' ') }}" {% endif -%} {% for tag in zj_image.tags | default(['latest']) -%} - --tag {{ zj_image.repository }}:change_{{ zuul.change }}_{{ tag }} - --tag {{ zj_image.repository }}:{{ tag }} + --tag {{ zj_image.repository }}:{{ tag_prefix }}{{ tag }} + --tag {{ zj_image.repository }}:{{ tag }} {% endfor -%} args: chdir: "{{ zuul_work_dir }}/{{ zj_image.context }}" diff --git a/roles/upload-container-image/README.rst b/roles/upload-container-image/README.rst new file mode 100644 index 000000000..0e81c3cbc --- /dev/null +++ b/roles/upload-container-image/README.rst @@ -0,0 +1,13 @@ +Upload one or more container images. + +.. include:: ../../roles/build-container-image/common.rst + +.. zuul:rolevar:: upload_container_image_promote + :type: bool + :default: true + + If ``true`` (the default), then this role will upload the image(s) + to the container registry with special tags designed for use by the + promote-container-image role. Set to ``false`` to use + this role to directly upload images with the final tag (e.g., as + part of an un-gated release job). diff --git a/roles/upload-container-image/defaults/main.yaml b/roles/upload-container-image/defaults/main.yaml new file mode 100644 index 000000000..55f75a686 --- /dev/null +++ b/roles/upload-container-image/defaults/main.yaml @@ -0,0 +1,2 @@ +zuul_work_dir: "{{ zuul.project.src_dir }}" +upload_container_image_promote: true diff --git a/roles/upload-container-image/tasks/main.yaml b/roles/upload-container-image/tasks/main.yaml new file mode 100644 index 000000000..8faa20d03 --- /dev/null +++ b/roles/upload-container-image/tasks/main.yaml @@ -0,0 +1,15 @@ +- name: Verify repository names + when: | + container_registry_credentials is defined + and zj_image.registry not in container_registry_credentials + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + fail: + msg: "{{ zj_image.registry }} credentials not found" + +- name: Upload image to container registry + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + include_tasks: push.yaml diff --git a/roles/upload-container-image/tasks/push.yaml b/roles/upload-container-image/tasks/push.yaml new file mode 100644 index 000000000..fb3156ddc --- /dev/null +++ b/roles/upload-container-image/tasks/push.yaml @@ -0,0 +1,21 @@ +- name: Log in to registry + command: "{{ container_command }} login -u {{ container_registry_credentials[zj_image.registry].username }} -p {{ container_registry_credentials[zj_image.registry].password }} {{ zj_image.registry }}" + no_log: true + +- name: Publish images + block: + - name: Upload tag to registry + vars: + promote_tag_prefix: "{{ ('change_' + zuul.change) if (zuul.change is defined) else zuul.pipeline }}_" + command: "{{ container_command }} push {{ zj_image.repository }}:{{ upload_container_image_promote | ternary(promote_tag_prefix, '') }}{{ zj_image_tag }}" + loop: "{{ zj_image.tags | default(['latest']) }}" + loop_control: + loop_var: zj_image_tag + register: result + until: result.rc == 0 + retries: 3 + delay: 30 + + always: + - name: Log out of registry + command: "{{ container_command }} logout {{ zj_image.registry }}" diff --git a/test-playbooks/container/test-build-container-image-release-pre.yaml b/test-playbooks/container/test-build-container-image-release-pre.yaml index 4e1cb54c4..5aa88bc04 100644 --- a/test-playbooks/container/test-build-container-image-release-pre.yaml +++ b/test-playbooks/container/test-build-container-image-release-pre.yaml @@ -8,6 +8,34 @@ username: zuul password: testpassword repository: testrepo + container_registry_credentials: + 127.0.0.1:5200: + username: zuul + password: testpassword + repository: testrepo + + - name: Install container system + include_role: + name: "ensure-{{ container_command }}" + + - name: Enable insecure registries + block: + - name: Create podman configration directory + become: true + file: + state: directory + path: /etc/containers + mode: 0755 + + - name: Setup insecure registries + become: true + copy: + dest: /etc/containers/registries.conf + content: | + [registries.insecure] + registries = ['127.0.0.1:5200'] + mode: 0644 + when: container_command == 'podman' - name: Set up a publication registry to stand in for Docker Hub import_tasks: ../../util-tasks/run-docker-registry.yaml diff --git a/test-playbooks/container/test-build-container-image-release.yaml b/test-playbooks/container/test-build-container-image-release.yaml index d7ba8ef43..ab22a39b6 100644 --- a/test-playbooks/container/test-build-container-image-release.yaml +++ b/test-playbooks/container/test-build-container-image-release.yaml @@ -1,5 +1,6 @@ - hosts: all vars: + upload_container_image_promote: false upload_docker_image_promote: false _arch_docker_images: - context: test-playbooks/container/docker @@ -12,7 +13,12 @@ repository: "testrepo" # This is what the Zuul repo uses to tag its releases: tags: "{{ zuul.tag is defined | ternary([zuul.get('tag', '').split('.')[0], '.'.join(zuul.get('tag', '').split('.')[:2]), zuul.get('tag', '')], ['latest']) }}" - container_images: "{{ docker_images }}" + container_images: + - context: test-playbooks/container/docker + registry: 127.0.0.1:5200 + repository: 127.0.0.1:5200/testrepo + # This is what the Zuul repo uses to tag its releases: + tags: "{{ zuul.tag is defined | ternary([zuul.get('tag', '').split('.')[0], '.'.join(zuul.get('tag', '').split('.')[:2]), zuul.get('tag', '')], ['latest']) }}" tasks: - name: Save zuul variables set_fact: @@ -40,3 +46,6 @@ vars: zuul: "{{ new_zuul }}" docker_images: "{{ multiarch | ternary(_arch_docker_images, _normal_docker_images) }}" + + - name: "Show local container images for debugging" + command: "{{ container_command }} image ls" diff --git a/zuul-tests.d/container-roles-jobs.yaml b/zuul-tests.d/container-roles-jobs.yaml index fc141bb9b..2b171718f 100644 --- a/zuul-tests.d/container-roles-jobs.yaml +++ b/zuul-tests.d/container-roles-jobs.yaml @@ -71,6 +71,31 @@ - name: ubuntu-focal-arm64 label: ubuntu-focal-arm64 +- job: + name: zuul-jobs-test-build-container-image-release + description: | + Test building a container image in a release pipeline. + + This job tests changes to the build-container-image role, + simulating its use within a tag-based release pipeline. It is + not meant to be used directly but rather run on changes to roles + in the zuul-jobs repo. + files: + - roles/ensure-podman/.* + - roles/ensure-package-repositories/.* + - roles/build-container-image/.* + - roles/upload-container-image/.* + - test-playbooks/container/.* + pre-run: test-playbooks/container/test-build-container-image-release-pre.yaml + run: test-playbooks/container/test-build-container-image-release.yaml + vars: + container_command: podman + multiarch: false + nodeset: + nodes: + - name: builder + label: ubuntu-bionic + - job: name: zuul-jobs-test-build-docker-image-release description: | @@ -84,6 +109,7 @@ - roles/ensure-docker/.* - roles/ensure-package-repositories/.* - roles/build-docker-image/.* + - roles/upload-docker-image/.* - test-playbooks/container/.* pre-run: test-playbooks/container/test-build-container-image-release-pre.yaml run: test-playbooks/container/test-build-container-image-release.yaml @@ -400,6 +426,7 @@ - zuul-jobs-test-ensure-docker-ubuntu-xenial - zuul-jobs-test-ensure-docker-ubuntu-bionic-arm64 - zuul-jobs-test-ensure-docker-ubuntu-focal-arm64 + - zuul-jobs-test-build-container-image-release - zuul-jobs-test-build-docker-image-release - zuul-jobs-test-build-docker-image-release-multiarch - zuul-jobs-test-registry-docker