diff --git a/doc/source/container-roles.rst b/doc/source/container-roles.rst index 8d16c7c24..dd4ce5784 100644 --- a/doc/source/container-roles.rst +++ b/doc/source/container-roles.rst @@ -10,6 +10,7 @@ Container Roles .. zuul:autorole:: ensure-openshift .. zuul:autorole:: ensure-podman .. zuul:autorole:: ensure-skopeo +.. zuul:autorole:: ensure-quay-repo .. zuul:autorole:: pause-buildset-registry .. zuul:autorole:: promote-container-image .. zuul:autorole:: promote-docker-image diff --git a/roles/ensure-quay-repo/README.rst b/roles/ensure-quay-repo/README.rst new file mode 100644 index 000000000..5db7ea907 --- /dev/null +++ b/roles/ensure-quay-repo/README.rst @@ -0,0 +1,52 @@ +This role primarily exists to create a new public repository in quay. +This role can be used to create private repos as well, but repos are +created by default in quay if you simply push to them. + +Users of this role will need to generate an application token with +`create repository` permissions. Additional permissions are not +necessary. + +When invoking this role you should set no_log: true on the +`include_role` task to prevent disclosure of your token. + +** Role Variables ** + +.. zuul:rolevar:: container_registry_credentials + :type: dict + + Required. This is expected to be a Zuul secret in dictionary form. + For convenience this is in the same format as the + ``container_registry_credentials`` variable used by the other container + roles. Specify an ``api_token`` which is issued from an application + assigned to an organisation. See ``__ + + Example: + + .. code-block:: yaml + + container_registry_credentials: + quay.io: + api_token: 'abcd1234' + +.. zuul:rolevar:: container_images + :type: list + + Required. A list of dictionaries. This provides info about the image + repositories to be created in a quay registry. For convenience this + is in the same format as the ``container_images`` variable used by other + container roles. Specify a ``registry`` (this should match up with your + credentials to locate the api token), ``namespace``, ``repo_shortname``, + ``repo_description``, ``visibility``, and ``api_url`` attributes. + + By default visibility will be ``public`` and ``api_url`` will be + ``https://{{ registry }}``. + + Example: + + .. code-block:: yaml + + container_images: + - registry: quay.io + namespace: myquayorg + repo_shortname: myimage + repo_description: The best container image diff --git a/roles/ensure-quay-repo/tasks/create.yaml b/roles/ensure-quay-repo/tasks/create.yaml new file mode 100644 index 000000000..00f475860 --- /dev/null +++ b/roles/ensure-quay-repo/tasks/create.yaml @@ -0,0 +1,49 @@ +- name: Set quay_root_url + set_fact: + quay_root_url: "https://{{ zj_image.registry }}" + when: zj_image.api_url is not defined + +- name: Alias api_url + set_fact: + quay_root_url: "{{ zj_image.api_url }}" + when: zj_image.api_url is defined + +- name: Set quay_repo_visibility + set_fact: + quay_repo_visibility: "public" + when: zj_image.visibility is not defined + +- name: Alias visibility + set_fact: + quay_repo_visibility: "{{ zj_image.visibility }}" + when: zj_image.visibility is defined + +- name: Create the repo in quay + no_log: true + uri: + url: "{{ quay_root_url }}/api/v1/repository" + method: POST + body_format: json + body: + namespace: "{{ zj_image.namespace }}" + repository: "{{ zj_image.repo_shortname}}" + description: "{{ zj_image.repo_description }}" + visibility: "{{ quay_repo_visibility }}" + headers: + Content-Type: application/json + Authorization: "Bearer {{ container_registry_credentials[zj_image.registry].api_token }}" + status_code: + - 201 + # 400 is returned when the repo already exists. + # We double check this below. + - 400 + register: quay_repo_create + delay: 5 + retries: 3 + +- name: Fail if repo doesn't exist and we got a 400 status code + when: + - quay_repo_create.status == 400 + - "'error_message' not in quay_repo_create.json or ('error_message' in quay_repo_create.json and quay_repo_create.json.error_message != 'Repository already exists')" + fail: + msg: "Could not create {{ quay_root_url }}/{{ zj_image.namespace }}/{{ zj_image.repo_shortname }}" diff --git a/roles/ensure-quay-repo/tasks/main.yaml b/roles/ensure-quay-repo/tasks/main.yaml new file mode 100644 index 000000000..5da52871d --- /dev/null +++ b/roles/ensure-quay-repo/tasks/main.yaml @@ -0,0 +1,25 @@ +- 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: Create repository in quay registry + loop: "{{ container_images }}" + loop_control: + loop_var: zj_image + include_tasks: create.yaml