diff --git a/roles/promote-container-image/README.rst b/roles/promote-container-image/README.rst index dc97afd8d..29dc039d7 100644 --- a/roles/promote-container-image/README.rst +++ b/roles/promote-container-image/README.rst @@ -10,3 +10,26 @@ Promote one or more previously uploaded container images. by the upload-container-image role. Set to ``intermediate-registry`` to have this role copy an image created and pushed to an intermediate registry by the build-container-role. + In that case, the variables below provide the extra information + needed to perform the query. + +.. zuul:rolevar:: promote_container_image_api + + Only required for the ``intermediate-registry`` method. + The Zuul API endpoint to use. Example: ``https://zuul.example.org/api/tenant/{{ zuul.tenant }}`` + +.. zuul:rolevar:: promote_container_image_pipeline + + Only required for the ``intermediate-registry`` method. + The pipeline in which the previous build ran. + +.. zuul:rolevar:: promote_container_image_job + + Only required for the ``intermediate-registry`` method. + The job of the previous build. + +.. zuul:rolevar:: promote_container_image_query + :default: change={{ zuul.change }}&patchset={{ zuul.patchset }}&pipeline={{ promote_container_image_pipeline }}&job_name={{ promote_container_image_job }} + + Only required for the ``intermediate-registry`` method. + The query to use to find the build. Normally the default is used. diff --git a/roles/promote-container-image/defaults/main.yaml b/roles/promote-container-image/defaults/main.yaml index 9739eb171..deda4a500 100644 --- a/roles/promote-container-image/defaults/main.yaml +++ b/roles/promote-container-image/defaults/main.yaml @@ -1 +1,2 @@ zuul_work_dir: "{{ zuul.project.src_dir }}" +promote_container_image_query: "change={{ zuul.change }}&patchset={{ zuul.patchset }}&pipeline={{ promote_container_image_pipeline }}&job_name={{ promote_container_image_job }}" diff --git a/roles/promote-container-image/tasks/main.yaml b/roles/promote-container-image/tasks/main.yaml index aea1b0a22..19c21e2ea 100644 --- a/roles/promote-container-image/tasks/main.yaml +++ b/roles/promote-container-image/tasks/main.yaml @@ -1,8 +1,30 @@ -- name: Promote container image with tags +- 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: Verify repository permission + when: | + container_registry_credentials[zj_image.registry].repository is defined and + not zj_image.repository | regex_search(container_registry_credentials[zj_image.registry].repository) + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + fail: + msg: "{{ zj_image.repository }} not permitted by {{ container_registry_credentials[zj_image.registry].repository }}" + +- name: Promote image when: promote_container_image_method|default('tag') == 'tag' - include_tasks: promote-from-tag.yaml + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + include_tasks: promote-retag.yaml - name: Promote container image with intermediate registry when: promote_container_image_method|default('tag') == 'intermediate-registry' - fail: - msg: 'The intermediate-registry promote role is not yet complete' + include_tasks: promote-from-intermediate-registry.yaml diff --git a/roles/promote-container-image/tasks/promote-from-intermediate-registry.yaml b/roles/promote-container-image/tasks/promote-from-intermediate-registry.yaml new file mode 100644 index 000000000..93058420e --- /dev/null +++ b/roles/promote-container-image/tasks/promote-from-intermediate-registry.yaml @@ -0,0 +1,21 @@ +- name: Query Zuul API for image information + uri: + url: "{{ promote_container_image_api }}/builds?{{ promote_container_image_query }}" + register: build + +- name: Parse build response + set_fact: + build: "{{ build.json[0] }}" + +- name: Map image artifacts + set_fact: + zj_artifact_map: "{{ zj_artifact_map | default({}) | combine({zj_map_item.metadata.repository + ':' + zj_map_item.metadata.tag: zj_map_item.url}) }}" + loop_control: + loop_var: zj_map_item + loop: "{{ build | json_query(\"artifacts[?metadata.type=='container_image']\")}}" + +- name: Promote image + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + include_tasks: promote-registry.yaml diff --git a/roles/promote-container-image/tasks/promote-from-tag.yaml b/roles/promote-container-image/tasks/promote-from-tag.yaml deleted file mode 100644 index fb4a96d6c..000000000 --- a/roles/promote-container-image/tasks/promote-from-tag.yaml +++ /dev/null @@ -1,25 +0,0 @@ -- 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: Verify repository permission - when: | - container_registry_credentials[zj_image.registry].repository is defined and - not zj_image.repository | regex_search(container_registry_credentials[zj_image.registry].repository) - loop: "{{ container_images }}" - loop_control: - loop_var: zj_image - fail: - msg: "{{ zj_image.repository }} not permitted by {{ container_registry_credentials[zj_image.registry].repository }}" - -- name: Promote image - loop: "{{ container_images }}" - loop_control: - loop_var: zj_image - include_tasks: promote-retag.yaml diff --git a/roles/promote-container-image/tasks/promote-registry.yaml b/roles/promote-container-image/tasks/promote-registry.yaml new file mode 100644 index 000000000..4ca542708 --- /dev/null +++ b/roles/promote-container-image/tasks/promote-registry.yaml @@ -0,0 +1,24 @@ +- name: Log in to registry + no_log: true + command: >- + skopeo login {{ zj_image.registry }} -u {{ container_registry_credentials[zj_image.registry].username }} -p {{ container_registry_credentials[zj_image.registry].password }} + register: result + until: result.rc == 0 + retries: 3 + delay: 30 + +- name: Copy image + block: + - name: Copy image + loop: "{{ zj_image.tags | default(['latest']) }}" + loop_control: + loop_var: zj_image_tag + command: >- + skopeo --insecure-policy copy --all {{ zj_artifact_map[zj_image.repository + ':' + zj_image_tag] }} docker://{{ zj_image.repository }}:{{ zj_image_tag }} + register: result + until: result.rc == 0 + retries: 3 + delay: 30 + always: + - name: Log out of registry + command: "skopeo logout {{ zj_image.registry }}"