Add docker image publishing
Change-Id: I6a09b73ffd0af6d2d23963b99c436b43410b1a46
This commit is contained in:
parent
4d65082663
commit
57466a94bf
61
.zuul.yaml
61
.zuul.yaml
|
@ -14,11 +14,72 @@
|
||||||
check:
|
check:
|
||||||
jobs:
|
jobs:
|
||||||
- airship-promenade-linter
|
- airship-promenade-linter
|
||||||
|
- airship-docker-build-gate
|
||||||
|
|
||||||
gate:
|
gate:
|
||||||
jobs:
|
jobs:
|
||||||
- airship-promenade-linter
|
- airship-promenade-linter
|
||||||
|
- airship-docker-build-gate
|
||||||
|
|
||||||
|
post:
|
||||||
|
jobs:
|
||||||
|
- airship-docker-build-post
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
name: airship-promenade-linter
|
name: airship-promenade-linter
|
||||||
run: tools/gate/playbooks/zuul-linter.yaml
|
run: tools/gate/playbooks/zuul-linter.yaml
|
||||||
nodeset: openstack-helm-single-node
|
nodeset: openstack-helm-single-node
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: airship-docker-build-base
|
||||||
|
run: tools/gate/playbooks/docker-image-build.yaml
|
||||||
|
nodeset: ubuntu-xenial
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: airship-docker-build-gate
|
||||||
|
parent: airship-docker-build-base
|
||||||
|
vars:
|
||||||
|
publish: false
|
||||||
|
tags:
|
||||||
|
dynamic:
|
||||||
|
patch_set: true
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: airship-docker-build-post
|
||||||
|
parent: airship-docker-build-base
|
||||||
|
secrets:
|
||||||
|
- airship_dockerhub_creds
|
||||||
|
vars:
|
||||||
|
publish: true
|
||||||
|
tags:
|
||||||
|
dynamic:
|
||||||
|
branch: true
|
||||||
|
commit: true
|
||||||
|
static:
|
||||||
|
- latest
|
||||||
|
|
||||||
|
- secret:
|
||||||
|
name: airship_dockerhub_creds
|
||||||
|
data:
|
||||||
|
username: !encrypted/pkcs1-oaep
|
||||||
|
- KIl1I3Ki2tvGCCqlRNE0BPgkJo5Fw8St5eX9gCr9TncYtnvZuusDjlbvJS5jFd4o0Coj8
|
||||||
|
4LniBnmitm+mQiaPrWvM0Op4w8fA12oFA2bF6ZG/R2ZhzDzRSC7ucpoHoNDuZWeSh2v38
|
||||||
|
/rNPTRw4wgm6p3tPHeNLelBOkE8WbN/v6Wj03pKGBQC5Z1Ua1BD2DoNZqAfH2mnxrgEs1
|
||||||
|
r7jvc3Livw3qvJVqtleRBldxN89GOlH9uU6XUdlUVUBecEv03SfgrRXU5njGa16KunyOE
|
||||||
|
cs3VdLqh65EXrrx4vc7RPOx+Ql6wshDtD6vhF4zEthEfRdYUK+6rY368b9O5WdOSHJTL5
|
||||||
|
yMQwItXYn+4AzPKPwf4dHeJmbHhXp3q7aI57WlMip71ReJNGpS2S2WekNGrPrl/5Fp/Ns
|
||||||
|
XdpEZwoq2wAVDZe9nsfSAOLICxurQVawpOrJBcCot8zCe/7xYPHVBnvktV08oTIyykMOx
|
||||||
|
LYtl7Vq/0VwI+aoMfEUPBjuzApvgRIRi0IbkzrEJvD6Y17nrJ7uGbimyYhz76g2GrCPex
|
||||||
|
mCDZ7DReoX/ECIwpsurib51O7KH4uQh3fX5yrbnuXCQzfdCrX12b5uRPWnfFDMcj6rq4+
|
||||||
|
36N7tof6O6ooTl0fbQSGHK38Smaz7lWt69WW2FjT6IfNiI7rEV3aeACtfbG6JU=
|
||||||
|
password: !encrypted/pkcs1-oaep
|
||||||
|
- PleEYq7618O5ujy1Hy3a3nT2WLjYC46PPWnGwra2KKKfvoDSB/wfwLhZ9p9M9OODb5xHJ
|
||||||
|
Me0V+7bD0xBPK9VQIpOlj1BA3PXcyX6zzVvbCSJKmILFhg81++aGBUnSDuKe+Y7qPTgjI
|
||||||
|
l5hW69LJkyHtj6WVKWGo+7Le3kjbtEMZt7lqhtdhWlWfFNWoTDfpAzvj/14yRp5xTZPFt
|
||||||
|
zWYdj2grjjDmFjUHRbdbyUnfNEI+WZeXM5U+0F7jyAEkW3yqBeQV9InM1dhwNFqpGFflk
|
||||||
|
XXIamyjhf/DpT0e7kBDd8NKvb6m+ubPUE8HG+TLEqcSN0mOxfTYWHx4okrkAXrSDhYyi5
|
||||||
|
DWj0lfrr/YE7XE5NnPfmDEgo53lx8yiFmiQ4iz4UtAhjSftUm99EOrL2vFCRawKVW+liw
|
||||||
|
9nExTVGUexLiy+DcIAShVWEVwQPtIr/HcleuO4zLfaljNS9NHBke9lHrU+QZ3AZnkd0/A
|
||||||
|
wcA8OJdGauWiAMvSLqvQEWP3xRBiZe63OATtaWQTmOxzn+9crmIf1eVhCpiNEQNTlmTNe
|
||||||
|
fB0SPYANzVkAF8+ZAmcGBt24Ivc+uSBqrqzR7lFkbDaEbBrTjddKcfbUCoul0yye+qfPj
|
||||||
|
cow63ecH56++tyGyfMKpNL5WJ2GpbCPwiB8ZwDQZv7iQD0TpinhJxAmvt5qhcs=
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
- hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: Install Docker (Debian)
|
||||||
|
block:
|
||||||
|
- apt:
|
||||||
|
name: "{{ item }}"
|
||||||
|
with_items:
|
||||||
|
- docker.io
|
||||||
|
- python-pip
|
||||||
|
when: ansible_os_family == 'Debian'
|
||||||
|
- pip:
|
||||||
|
name: docker
|
||||||
|
version: 2.7.0
|
||||||
|
become: True
|
||||||
|
|
||||||
|
- name: Debug tag generation inputs
|
||||||
|
block:
|
||||||
|
- debug:
|
||||||
|
var: publish
|
||||||
|
- debug:
|
||||||
|
var: tags
|
||||||
|
- debug:
|
||||||
|
var: zuul
|
||||||
|
- debug:
|
||||||
|
msg: "{{ tags | to_json }}"
|
||||||
|
|
||||||
|
- name: Determine tags
|
||||||
|
shell: echo '{{ tags | to_json }}' | python {{ zuul.project.src_dir }}/tools/image_tags.py
|
||||||
|
environment:
|
||||||
|
BRANCH: "{{ zuul.branch }}"
|
||||||
|
CHANGE: "{{ zuul.change }}"
|
||||||
|
COMMIT: "{{ zuul.newrev }}"
|
||||||
|
PATCHSET: "{{ zuul.patchset }}"
|
||||||
|
register: image_tags
|
||||||
|
|
||||||
|
- name: Debug computed tags
|
||||||
|
debug:
|
||||||
|
var: image_tags
|
||||||
|
|
||||||
|
- name: Build images
|
||||||
|
docker_image:
|
||||||
|
name: airshipit/promenade
|
||||||
|
dockerfile: "Dockerfile"
|
||||||
|
path: "{{ zuul.project.src_dir }}"
|
||||||
|
pull: false
|
||||||
|
tag: "{{ item }}"
|
||||||
|
with_items: "{{ image_tags.stdout_lines }}"
|
||||||
|
become: True
|
||||||
|
|
||||||
|
- name: Push to Docker Hub
|
||||||
|
block:
|
||||||
|
- command: docker login -u {{ airship_dockerhub_creds.username }} -p {{ airship_dockerhub_creds.password }}
|
||||||
|
no_log: True
|
||||||
|
- command: docker push docker.io/airshipit/promenade:{{ item }}
|
||||||
|
with_items: "{{ image_tags.stdout_lines }}"
|
||||||
|
when: publish
|
|
@ -0,0 +1,113 @@
|
||||||
|
#!/bin/python
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
LOG_FORMAT = '%(asctime)s %(levelname)-8s %(name)s:%(funcName)s [%(lineno)3d] %(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:
|
||||||
|
LOG.exception('Unexpected exception')
|
||||||
|
sys.exit(2)
|
4
tox.ini
4
tox.ini
|
@ -31,7 +31,7 @@ commands =
|
||||||
[testenv:fmt]
|
[testenv:fmt]
|
||||||
deps = yapf==0.20.0
|
deps = yapf==0.20.0
|
||||||
commands =
|
commands =
|
||||||
yapf -ir {toxinidir}/promenade {toxinidir}/tests
|
yapf -ir {toxinidir}/promenade {toxinidir}/tests {toxinidir}/tools/image_tags.py
|
||||||
|
|
||||||
[testenv:freeze]
|
[testenv:freeze]
|
||||||
deps = -r{toxinidir}/requirements-direct.txt
|
deps = -r{toxinidir}/requirements-direct.txt
|
||||||
|
@ -52,5 +52,5 @@ deps =
|
||||||
yapf==0.20.0
|
yapf==0.20.0
|
||||||
flake8==3.5.0
|
flake8==3.5.0
|
||||||
commands =
|
commands =
|
||||||
yapf -rd {toxinidir}/promenade {toxinidir}/tests
|
yapf -rd {toxinidir}/promenade {toxinidir}/tests {toxinidir}/tools/image_tags.py
|
||||||
flake8 {toxinidir}/promenade
|
flake8 {toxinidir}/promenade
|
||||||
|
|
Loading…
Reference in New Issue