From a307259776bf9f95b15ca39a532cd37f512f8c5e Mon Sep 17 00:00:00 2001 From: Clark Boylan Date: Mon, 8 Apr 2019 11:08:03 -0700 Subject: [PATCH] Use /etc/hosts with docker registries to handle ipv6 Docker doesn't appear to understand properly escaped ipv6 addrs in its "urls". Address this by adding /etc/hosts entries for any buildset_registry that is specified by an ip address (v4 or v6). This allows us to use a named alias instead of the ipv6 address. An example failure for posterity: "[2607:ff68:100:54:f816:3eff:fe7c:e98a]:5000/zuul/nodepool:latest" is not a valid repository/tag: invalid reference format Change-Id: Id865dc7d3382174b61f9eaa76e29b637a85f5142 --- roles/build-docker-image/tasks/push.yaml | 24 +++++++++- .../tasks/main.yaml | 47 +++++++++++++++++-- .../tasks/push-image.yaml | 43 +++++++++++++++-- .../tasks/push.yaml | 45 ++++++++++++++++-- roles/use-buildset-registry/tasks/main.yaml | 30 ++++++++++-- .../tasks/user-config.yaml | 24 +++++++++- 6 files changed, 192 insertions(+), 21 deletions(-) diff --git a/roles/build-docker-image/tasks/push.yaml b/roles/build-docker-image/tasks/push.yaml index 582849329..e37d9ea80 100644 --- a/roles/build-docker-image/tasks/push.yaml +++ b/roles/build-docker-image/tasks/push.yaml @@ -1,12 +1,32 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) + - name: Tag image for buildset registry command: >- - docker tag {{ image.repository }}:{{ image_tag }} {{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} + docker tag {{ image.repository }}:{{ image_tag }} {{ buildset_registry_alias }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} loop: "{{ image.tags | default(['latest']) }}" loop_control: loop_var: image_tag - name: Push tag to buildset registry command: >- - docker push {{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} + docker push {{ buildset_registry_alias }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} loop: "{{ image.tags | default(['latest']) }}" loop_control: loop_var: image_tag diff --git a/roles/pull-from-intermediate-registry/tasks/main.yaml b/roles/pull-from-intermediate-registry/tasks/main.yaml index 448f01cf7..cf9c6ca18 100644 --- a/roles/pull-from-intermediate-registry/tasks/main.yaml +++ b/roles/pull-from-intermediate-registry/tasks/main.yaml @@ -1,3 +1,40 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) +- name: Configure /etc/hosts for intermediate_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry$" + line: "{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry" + insertafter: EOF + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using ip + set_fact: + intermediate_registry_alias: zuul-jobs.intermediate_registry + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using name + set_fact: + intermediate_registry_alias: "{{ intermediate_registry.host }}" + when: not ( intermediate_registry.host | ipaddr ) + # This can be removed if we add this functionality to Zuul directly - name: Load information from zuul_return when: buildset_registry is not defined @@ -5,12 +42,12 @@ buildset_registry: "{{ (lookup('file', zuul.executor.work_root + '/results.json') | from_json)['buildset_registry'] }}" - name: Ensure registry cert directory exists file: - path: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/" + path: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/" state: directory - name: Write registry TLS certificate copy: content: "{{ buildset_registry.cert }}" - dest: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/ca.crt" + dest: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/ca.crt" # Update user config for intermediate and buildset registries @@ -42,9 +79,9 @@ new_config: auths: | { - "{{ intermediate_registry.host | ipwrap }}:{{ intermediate_registry.port }}": + "{{ intermediate_registry_alias }}:{{ intermediate_registry.port }}": {"auth": "{{ (intermediate_registry.username + ":" + intermediate_registry.password) | b64encode }}"}, - "{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}": + "{{ buildset_registry_alias }}:{{ buildset_registry.port }}": {"auth": "{{ (buildset_registry.username + ":" + buildset_registry.password) | b64encode }}"}, } set_fact: @@ -62,7 +99,7 @@ command: >- skopeo --insecure-policy copy {{ item.url }} - docker://{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/{{ item.metadata.repository }}:{{ item.metadata.tag }} + docker://{{ buildset_registry_alias }}:{{ buildset_registry.port }}/{{ item.metadata.repository }}:{{ item.metadata.tag }} when: "'metadata' in item and item.metadata.type | default('') == 'container_image'" loop: "{{ zuul.artifacts | default([]) }}" always: diff --git a/roles/push-to-intermediate-registry/tasks/push-image.yaml b/roles/push-to-intermediate-registry/tasks/push-image.yaml index 6e1e72d59..4009c0859 100644 --- a/roles/push-to-intermediate-registry/tasks/push-image.yaml +++ b/roles/push-to-intermediate-registry/tasks/push-image.yaml @@ -1,8 +1,45 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) +- name: Configure /etc/hosts for intermediate_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry$" + line: "{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry" + insertafter: EOF + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using ip + set_fact: + intermediate_registry_alias: zuul-jobs.intermediate_registry + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using name + set_fact: + intermediate_registry_alias: "{{ intermediate_registry.host }}" + when: not ( intermediate_registry.host | ipaddr ) + - name: Push tag to intermediate registry command: >- skopeo --insecure-policy copy - docker://{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} - docker://{{ intermediate_registry.host | ipwrap }}:{{ intermediate_registry.port}}/{{ image.repository }}:{{ zuul.build }}_{{ image_tag }} + docker://{{ buildset_registry_alias }}:{{ buildset_registry.port }}/{{ image.repository }}:{{ image_tag }} + docker://{{ intermediate_registry_alias }}:{{ intermediate_registry.port}}/{{ image.repository }}:{{ zuul.build }}_{{ image_tag }} loop: "{{ image.tags | default(['latest']) }}" loop_control: loop_var: image_tag @@ -13,7 +50,7 @@ zuul: artifacts: - name: "image_{{ image.repository }}:{{ image_tag }}" - url: "docker://{{ intermediate_registry.host | ipwrap }}:{{ intermediate_registry.port}}/{{ image.repository }}:{{ zuul.build }}_{{ image_tag}}" + url: "docker://{{ intermediate_registry_alias }}:{{ intermediate_registry.port}}/{{ image.repository }}:{{ zuul.build }}_{{ image_tag}}" metadata: type: container_image repository: "{{ image.repository }}" diff --git a/roles/push-to-intermediate-registry/tasks/push.yaml b/roles/push-to-intermediate-registry/tasks/push.yaml index 3c71df47a..3797e6b58 100644 --- a/roles/push-to-intermediate-registry/tasks/push.yaml +++ b/roles/push-to-intermediate-registry/tasks/push.yaml @@ -1,3 +1,40 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) +- name: Configure /etc/hosts for intermediate_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry$" + line: "{{ intermediate_registry.host }}\tzuul-jobs.intermediate_registry" + insertafter: EOF + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using ip + set_fact: + intermediate_registry_alias: zuul-jobs.intermediate_registry + when: intermediate_registry.host | ipaddr +- name: Set intermediate_registry alias variable when using name + set_fact: + intermediate_registry_alias: "{{ intermediate_registry.host }}" + when: not ( intermediate_registry.host | ipaddr ) + # This can be removed if we add this functionality to Zuul directly - name: Load information from zuul_return when: buildset_registry is not defined @@ -5,12 +42,12 @@ buildset_registry: "{{ (lookup('file', zuul.executor.work_root + '/results.json') | from_json)['buildset_registry'] }}" - name: Ensure registry cert directory exists file: - path: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/" + path: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/" state: directory - name: Write registry TLS certificate copy: content: "{{ buildset_registry.cert }}" - dest: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/ca.crt" + dest: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/ca.crt" # Update user config for intermediate and buildset registries - name: Ensure docker user directory exists @@ -41,9 +78,9 @@ new_config: auths: | { - "{{ intermediate_registry.host | ipwrap }}:{{ intermediate_registry.port }}": + "{{ intermediate_registry_alias }}:{{ intermediate_registry.port }}": {"auth": "{{ (intermediate_registry.username + ":" + intermediate_registry.password) | b64encode }}"}, - "{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}": + "{{ buildset_registry_alias }}:{{ buildset_registry.port }}": {"auth": "{{ (buildset_registry.username + ":" + buildset_registry.password) | b64encode }}"}, } set_fact: diff --git a/roles/use-buildset-registry/tasks/main.yaml b/roles/use-buildset-registry/tasks/main.yaml index f98820c91..97c5bb9ce 100644 --- a/roles/use-buildset-registry/tasks/main.yaml +++ b/roles/use-buildset-registry/tasks/main.yaml @@ -1,3 +1,23 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) + - name: Ensure docker directory exists become: yes file: @@ -6,23 +26,23 @@ - name: Ensure buildset registry cert directory exists become: true file: - path: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/" + path: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/" state: directory - name: Ensure proxy registry cert directory exists become: true file: - path: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.proxy_port }}/" + path: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.proxy_port }}/" state: directory - name: Write buildset registry TLS certificate become: true copy: content: "{{ buildset_registry.cert }}" - dest: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}/ca.crt" + dest: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.port }}/ca.crt" - name: Write proxy registry TLS certificate become: true copy: content: "{{ buildset_registry.cert }}" - dest: "/etc/docker/certs.d/{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.proxy_port }}/ca.crt" + dest: "/etc/docker/certs.d/{{ buildset_registry_alias }}:{{ buildset_registry.proxy_port }}/ca.crt" # Update daemon config - name: Check if docker daemon configuration exists @@ -46,7 +66,7 @@ - name: Add registry to docker daemon configuration vars: new_config: - registry-mirrors: "['https://{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port}}/', 'https://{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.proxy_port}}/']" + registry-mirrors: "['https://{{ buildset_registry_alias }}:{{ buildset_registry.port}}/', 'https://{{ buildset_registry_alias }}:{{ buildset_registry.proxy_port}}/']" set_fact: docker_config: "{{ docker_config | combine(new_config) }}" - name: Save docker daemon configuration diff --git a/roles/use-buildset-registry/tasks/user-config.yaml b/roles/use-buildset-registry/tasks/user-config.yaml index 56b2d2124..73de57c5b 100644 --- a/roles/use-buildset-registry/tasks/user-config.yaml +++ b/roles/use-buildset-registry/tasks/user-config.yaml @@ -1,3 +1,23 @@ +# Docker doesn't understand docker push [1234:5678::]:5000/image/path:tag +# so we set up /etc/hosts with a registry alias name to support ipv6 and 4. +- name: Configure /etc/hosts for buildset_registry to workaround docker not understanding ipv6 addresses + become: yes + lineinfile: + path: /etc/hosts + state: present + regex: "^{{ buildset_registry.host }}\tzuul-jobs.buildset_registry$" + line: "{{ buildset_registry.host }}\tzuul-jobs.buildset_registry" + insertafter: EOF + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using ip + set_fact: + buildset_registry_alias: zuul-jobs.buildset_registry + when: buildset_registry.host | ipaddr +- name: Set buildset_registry alias variable when using name + set_fact: + buildset_registry_alias: "{{ buildset_registry.host }}" + when: not ( buildset_registry.host | ipaddr ) + # Update user config - name: Ensure docker user directory exists file: @@ -29,9 +49,9 @@ { "https://index.docker.io/v1/": {"auth": "{{ (buildset_registry.username + ":" + buildset_registry.password) | b64encode }}"}, - "{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.port }}": + "{{ buildset_registry_alias }}:{{ buildset_registry.port }}": {"auth": "{{ (buildset_registry.username + ":" + buildset_registry.password) | b64encode }}"}, - "{{ buildset_registry.host | ipwrap }}:{{ buildset_registry.proxy_port }}": + "{{ buildset_registry_alias }}:{{ buildset_registry.proxy_port }}": {"auth": "{{ (buildset_registry.username + ":" + buildset_registry.password) | b64encode }}"} } set_fact: