diff --git a/Dockerfile b/Dockerfile index 5abbc01..37cce14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ ARG GO_IMAGE=docker.io/golang:1.16.4-buster -ARG RELEASE_IMAGE=ubuntu:focal +ARG FROM=ubuntu:20.04 FROM ${GO_IMAGE} as builder SHELL [ "/bin/bash", "-cex" ] @@ -12,11 +12,25 @@ RUN make get-modules ARG MAKE_TARGET=build RUN make ${MAKE_TARGET} -FROM ${RELEASE_IMAGE} as release + + +FROM ${FROM} as release + +LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ + org.opencontainers.image.url='https://airshipit.org' \ + org.opencontainers.image.documentation='https://docs.airshipit.org/kubernetes-entrypoint' \ + org.opencontainers.image.source='https://opendev.org/airship/kubernetes-entrypoint' \ + org.opencontainers.image.vendor='The Airship Authors' \ + org.opencontainers.image.licenses='Apache-2.0' + +ENV DEBIAN_FRONTEND noninteractive +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + COPY --from=builder /usr/src/kubernetes-entrypoint/bin/kubernetes-entrypoint /usr/local/bin/kubernetes-entrypoint -RUN apt-get update -RUN apt-get install -y --no-install-recommends coreutils +RUN apt update \ + && apt install -y --no-install-recommends coreutils USER 65534 ENTRYPOINT [ "/usr/local/bin/kubernetes-entrypoint" ] diff --git a/Makefile b/Makefile index fe7a66d..4478aa1 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,14 @@ docker-image: --build-arg GO_IMAGE=$(DOCKER_BASE_IMAGE) \ --build-arg RELEASE_IMAGE=$(DOCKER_RELEASE_IMAGE) +check-docker: + @if [ -z $$(which docker) ]; then \ + echo "Missing \`docker\` client which is required for development"; \ + exit 2; \ + fi + +images: check-docker docker-image + .PHONY: docker-image-unit-tests docker-image-unit-tests: DOCKER_MAKE_TARGET = unit-tests docker-image-unit-tests: DOCKER_TARGET_STAGE = builder diff --git a/image_tags.py b/image_tags.py new file mode 100755 index 0000000..be28669 --- /dev/null +++ b/image_tags.py @@ -0,0 +1,126 @@ +#!/usr/bin/python3 +# Copyright 2018 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import os +import sys + +LOG = logging.getLogger(__name__) + +LOG_FORMAT = '%(asctime)s %(levelname)-8s %(name)s:%(filename)s:%(lineno)3d:%(funcName)s %(message)s' # noqa + + +class TagGenExeception(Exception): + pass + + +def read_config(stream, env): + config = {} + try: + config['tags'] = json.load(stream) + except ValueError: + LOG.exception('Failed to decode JSON from input stream') + config['tags'] = {} + + LOG.debug('Configuration after reading stream: %s', config) + + config['context'] = { + 'branch': env.get('BRANCH'), + 'change': env.get('CHANGE'), + 'commit': env.get('COMMIT'), + 'ps': env.get('PATCHSET'), + } + + LOG.info('Final configuration: %s', config) + + return config + + +def build_tags(config): + tags = config.get('tags', {}).get('static', []) + LOG.debug('Dynamic tags: %s', tags) + tags.extend(build_dynamic_tags(config)) + LOG.info('All tags: %s', tags) + return tags + + +def build_dynamic_tags(config): + dynamic_tags = [] + + dynamic_tags.extend(_build_branch_tag(config)) + dynamic_tags.extend(_build_commit_tag(config)) + dynamic_tags.extend(_build_ps_tag(config)) + + return dynamic_tags + + +def _build_branch_tag(config): + if _valid_dg(config, 'branch'): + return [config['context']['branch']] + else: + return [] + + +def _build_commit_tag(config): + if _valid_dg(config, 'commit'): + return [config['context']['commit']] + else: + return [] + + +def _build_ps_tag(config): + if _valid_dg(config, 'patch_set', 'change') and _valid_dg( + config, 'patch_set', 'ps'): + return [ + '%s-%s' % (config['context']['change'], config['context']['ps']) + ] + else: + return [] + + +def _valid_dg(config, dynamic_tag, context_name=None): + if context_name is None: + context_name = dynamic_tag + + if config.get('tags', {}).get('dynamic', {}).get(dynamic_tag): + if config.get('context', {}).get(context_name): + return True + else: + raise TagGenExeception('Dynamic tag "%s" requested, but "%s"' + ' not found in context' % (dynamic_tag, + context_name)) + else: + return False + + +def main(): + config = read_config(sys.stdin, os.environ) + tags = build_tags(config) + + for tag in tags: + print(tag) + + +if __name__ == '__main__': + logging.basicConfig(format=LOG_FORMAT, level=logging.WARNING) + try: + main() + except TagGenExeception: + LOG.exception('Failed to generate tags') + sys.exit(1) + except Exception: + LOG.exception('Unexpected exception') + sys.exit(2) diff --git a/playbooks/docker-image-build.yaml b/playbooks/docker-image-build.yaml new file mode 100644 index 0000000..23bd723 --- /dev/null +++ b/playbooks/docker-image-build.yaml @@ -0,0 +1,125 @@ +# Copyright 2018 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- hosts: primary + roles: + - bindep + - ensure-docker + - ensure-python + - ensure-pip + + tasks: + - include_vars: vars.yaml + + - name: Debug tag generation inputs + block: + - debug: + var: publish + - debug: + var: distro + - debug: + var: tags + - debug: + var: zuul + - debug: + msg: "{{ tags | to_json }}" + + - name: Determine tags + shell: echo '{{ tags | to_json }}' | python3 {{ zuul.project.src_dir }}/image_tags.py + environment: + BRANCH: "{{ zuul.branch | default('') }}" + CHANGE: "{{ zuul.change | default('') }}" + COMMIT: "{{ zuul.newrev | default('') }}" + PATCHSET: "{{ zuul.patchset | default('') }}" + register: image_tags + + - name: Debug computed tags + debug: + var: image_tags + + - name: Install Docker python module for ansible docker login + block: + - pip: + name: docker + version: 4.4.4 + executable: pip3 + become: True + + - name: Install tox python module for ansible docker login + block: + - pip: + name: tox + version: 3.28.0 + executable: pip3 + become: True + + + - name: Build images + when: not publish + shell: | + set -x + make images + args: + chdir: "{{ zuul.project.src_dir }}" + executable: /bin/bash + become: True + + + + - name: Make images + when: not publish + block: + - make: + chdir: "{{ zuul.project.src_dir }}" + target: images + params: + DISTRO: "{{ distro }}" + IMAGE_TAG: "{{ item }}" + with_items: "{{ image_tags.stdout_lines }}" + + - shell: "docker images" + register: docker_images + + - debug: + var: docker_images + + become: True + + - name: Publish images + block: + - docker_login: + username: "{{ airship_armada_go_quay_creds.username }}" + password: "{{ airship_armada_go_quay_creds.password }}" + registry_url: "https://quay.io/api/v1/" + + - make: + chdir: "{{ zuul.project.src_dir }}" + target: images + params: + DOCKER_REGISTRY: "quay.io" + IMAGE_PREFIX: "airshipit" + DISTRO: "{{ distro }}" + IMAGE_TAG: "{{ item }}" + COMMIT: "{{ zuul.newrev | default('') }}" + PUSH_IMAGE: "true" + with_items: "{{ image_tags.stdout_lines }}" + + - shell: "docker images" + register: docker_images + + - debug: + var: docker_images + + when: publish + become: True diff --git a/playbooks/vars.yaml b/playbooks/vars.yaml new file mode 100644 index 0000000..c89b798 --- /dev/null +++ b/playbooks/vars.yaml @@ -0,0 +1,19 @@ +# Copyright 2017 The Openstack-Helm Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +docker_daemon: + group: zuul + registry-mirrors: + - "http://{{ zuul_site_mirror_fqdn }}:8082/" + storage-driver: overlay2 diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index 5ab4684..c36cd05 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -14,7 +14,65 @@ name: airship-kubernetes-entrypoint-lint-unit pre-run: playbooks/airship-kubernetes-entrypoint-deploy-docker.yaml run: playbooks/airship-kubernetes-entrypoint-lint-unit.yaml - nodeset: airship-kubernetes-entrypoint-single-node + nodeset: airship-kubernetes-entrypoint-single-node-focal + +- job: + name: airship-kubernetes-entrypoint-docker-build-gate-ubuntu_focal + timeout: 3600 + run: playbooks/docker-image-build.yaml + nodeset: airship-kubernetes-entrypoint-single-node-focal + vars: + publish: false + distro: ubuntu_focal + tags: + dynamic: + patch_set: true + + +- job: + name: airship-kubernetes-entrypoint-docker-publish-ubuntu_focal + timeout: 3600 + run: playbooks/docker-image-build.yaml + nodeset: airship-kubernetes-entrypoint-single-node-focal + secrets: + - airship_kubernetes_entrypoint_quay_creds + vars: + publish: true + distro: ubuntu_focal + tags: + dynamic: + branch: true + commit: true + static: + - latest + + +- secret: + name: airship_kubernetes_entrypoint_quay_creds + data: + username: !encrypted/pkcs1-oaep + - HXlskpNADDS4ySqBPLKRTZQ/Ti8bvGuSOOx09Qt74MGewp30XMg3+0tyGJPFvlAQ6xTD+ + y1Gv/mf6X1/PabyA6ceASqs0CMs3lZ13NvTkgbo04lEogVqkrh5OaHLdPhu/4O4HHJ+lK + uYXk2dqarknT7RSVF/VJqv0Q4whBexSUEOkPc5dRw8rLwPw+Um4Cs7ktLRhCk3Czmr4Gp + NT2rCLPkySUQ9novI7UNNABXkZS57e+nFmu0AkCPLBfm6NYlKPWsBXBCemc/K7sR3duoe + h8kk0M2pe0+TvYfkfaq6zqBQJ7dK8VbdGpRlKScfNtS8XxDIqqEWibC0Q4gPY3f8PGnC0 + 72bMIXvGxwDY+IEcgoZtTVT3ENXgwe6ZsG2+bXUMYe3C/D7AYY2v/Z5Tk94blZkxno/3r + ABNOVUZ4NqOG7jwqxW7mPTFrjGFk6zWaBT19P9SgC0NB9IOWun/Y9BTUlaJQJXrrbiAy8 + CiGpefhPh8WpUAD0t4lzPNncmojhUwxUCQPPpfDd377QoullvlNupOynZnIACgUOYMit8 + 60yYnJGh6+Fge28X69hbR+kQQoSCwQVV8HZ8+sGq6GNGxA2x6kz6fbhmIubomOobJJUyK + l+b5t4LK6GuTM4C++EcZwGVmPoCcOdI9ymmh0B37QJK6p/YQUgIUP8DCPngQtg= + password: !encrypted/pkcs1-oaep + - EB8J3+d+e1fMv+er9ioQc/rU9v6N3vFh+iCfRY2Kt0HsvAQ5hS8VmnPy0goaq7YA6pbls + DRnRooA4pbAQtqz8imRF+CepFUyLjjZYW1JvDiGcE8JmQWl8wNV2Q9qZ4NvzrINMs6xYX + 3sWBl23gG37BrgH9igajXipSMa1eRbHPdk12gt2Ky2ownGbJna7I2BvqwnH3sRZ58uhwu + e6SAkur9qM0guEXVG+cfg9FIwMsJ5/r985bvZ1JTktsglME5kEC8bkgIed7gq+E70jYfl + Cz9VHXEqQkBu4ZlSMvWPdH1C7vuZuafN9gKkFf0t+fhV8RmoVGrWcdCvkaO0TQb2QkFGT + Q5BvU1OdhZ3kKa8Kwd0z3mJjLk8xC3hCVe/B0HolHi7ISWfUopMNGakmrlSZJLVSrbCfK + DkAg6AOabrNkg/nJszv8ImL5BBFELBDfNKjBZCZOOR0blNFbzgHyh39pSTE/1t6j3uW/i + KR10eP8QkQiRoSTfbxhTxRxXUofLPBdsu1FSs/Cx9nv527urVN0e0dh15IZ2VAofxUTwF + /PyCh5RtrZtpJqi5BBGUPSPSWoqP9L+FkY2ZZLad0KqTC8FYMIC+p9bfO+t7RNyJSVzxx + +8/nuoWfSPgBJpd6Og1KGs2n9tt5adOLALZoj96hz8zYKHrqDdWMPWOVmDSycY= + - job: name: airship-kubernetes-entrypoint-upload-git-mirror diff --git a/zuul.d/nodesets.yaml b/zuul.d/nodesets.yaml index 23a1f3c..5b75781 100644 --- a/zuul.d/nodesets.yaml +++ b/zuul.d/nodesets.yaml @@ -15,3 +15,9 @@ nodes: - name: primary label: ubuntu-bionic + +- nodeset: + name: airship-kubernetes-entrypoint-single-node-focal + nodes: + - name: primary + label: ubuntu-focal diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml index 2e2ffc8..edde05c 100644 --- a/zuul.d/projects.yaml +++ b/zuul.d/projects.yaml @@ -14,9 +14,12 @@ check: jobs: - airship-kubernetes-entrypoint-lint-unit + - airship-kubernetes-entrypoint-docker-build-gate-ubuntu_focal gate: jobs: - airship-kubernetes-entrypoint-lint-unit + - airship-kubernetes-entrypoint-docker-build-gate-ubuntu_focal post: jobs: - airship-kubernetes-entrypoint-upload-git-mirror + - airship-kubernetes-entrypoint-docker-publish-ubuntu_focal \ No newline at end of file