diff --git a/doc/source/jobs.rst b/doc/source/jobs.rst index 2c5c56742..6ac0cfea6 100644 --- a/doc/source/jobs.rst +++ b/doc/source/jobs.rst @@ -10,4 +10,5 @@ Jobs docker-jobs go-jobs helm-jobs + packer-jobs system-jobs diff --git a/doc/source/packer-jobs.rst b/doc/source/packer-jobs.rst new file mode 100644 index 000000000..24dfc788a --- /dev/null +++ b/doc/source/packer-jobs.rst @@ -0,0 +1,4 @@ +Packer Jobs +=========== + +.. zuul:autojob:: packer diff --git a/doc/source/packer-roles.rst b/doc/source/packer-roles.rst new file mode 100644 index 000000000..57068faef --- /dev/null +++ b/doc/source/packer-roles.rst @@ -0,0 +1,5 @@ +Packer Roles +============ + +.. zuul:autorole:: ensure-packer +.. zuul:autorole:: packer diff --git a/doc/source/roles.rst b/doc/source/roles.rst index 4139b7749..ee316b9fd 100644 --- a/doc/source/roles.rst +++ b/doc/source/roles.rst @@ -20,6 +20,7 @@ Roles js-roles kubernetes-roles launchpad-roles + packer-roles puppet-roles python-roles system-roles diff --git a/playbooks/packer/pre.yaml b/playbooks/packer/pre.yaml new file mode 100644 index 000000000..6872a4d9b --- /dev/null +++ b/playbooks/packer/pre.yaml @@ -0,0 +1,9 @@ +- hosts: all + pre_tasks: + - name: Install unzip + package: + name: unzip + become: yes + roles: + - revoke-sudo + - ensure-packer diff --git a/playbooks/packer/run.yaml b/playbooks/packer/run.yaml new file mode 100644 index 000000000..35099f199 --- /dev/null +++ b/playbooks/packer/run.yaml @@ -0,0 +1,3 @@ +- hosts: all + roles: + - packer diff --git a/roles/ensure-packer/README.rst b/roles/ensure-packer/README.rst new file mode 100644 index 000000000..e65c46b70 --- /dev/null +++ b/roles/ensure-packer/README.rst @@ -0,0 +1,24 @@ +Install packer + +**Role Variables** + +.. zuul:rolevar:: packer_install_dir + :default: {{ ansible_user_dir }}/.local/bin/ + + Directory to install packer in. + +.. zuul:rolevar:: packer_version + :default: 1.5.5 + + Version of packer to install. + Zuul will skip the installation if this matches an already installed version of packer. + +.. zuul:rolevar:: packer_os + :default: {{ ansible_system | lower }} + + OS target of package to install. + +.. zuul:rolevar:: packer_arch + :default: amd64 / 386 + + Architecture target of package to install. diff --git a/roles/ensure-packer/defaults/main.yaml b/roles/ensure-packer/defaults/main.yaml new file mode 100644 index 000000000..4c4787235 --- /dev/null +++ b/roles/ensure-packer/defaults/main.yaml @@ -0,0 +1,7 @@ +hashicorp_releases_fqdn: https://releases.hashicorp.com +packer_version: 1.5.5 +packer_install_dir: "{{ ansible_user_dir }}/.local/bin/" +packer_os: "{{ ansible_system | lower }}" +packer_arch: "{{ packer_arch_translation[ansible_architecture] }}" +packer_package: "packer_{{ packer_version }}_{{ packer_os }}_{{ packer_arch }}" +packer_executable: "{{ ansible_user_dir }}/.local/bin/packer" diff --git a/roles/ensure-packer/tasks/install-packer.yaml b/roles/ensure-packer/tasks/install-packer.yaml new file mode 100644 index 000000000..1553939a9 --- /dev/null +++ b/roles/ensure-packer/tasks/install-packer.yaml @@ -0,0 +1,59 @@ +- name: Get packer checksums + uri: + url: "{{ hashicorp_releases_fqdn }}/\ + packer/{{ packer_version }}/packer_{{ packer_version }}_SHA256SUMS" + return_content: true + register: packer_version_checksums + +- name: Set packer checksum + set_fact: + packer_checksum: "{{\ + packer_version_checksums.content |\ + regex_search( '[a-z0-9]+ ' + packer_package) |\ + regex_replace( '(?P<checksum>[a-z0-9]+) ' + packer_package, '\\g<checksum>') + }}" + +- name: Create temp directory + tempfile: + state: directory + register: packer_install_tempdir + +- name: Download packer archive + get_url: + url: "{{ hashicorp_releases_fqdn }}/\ + packer/{{ packer_version }}/{{ packer_package }}.zip" + dest: "{{ packer_install_tempdir.path }}/{{ packer_package }}.zip" + checksum: "sha256:{{ packer_checksum }}" + +- name: Create packer package directory + file: + path: "{{ packer_install_tempdir.path }}/{{ packer_package }}" + state: directory + +- name: Unarchive packer + unarchive: + src: "{{ packer_install_tempdir.path }}/{{ packer_package }}.zip" + dest: "{{ packer_install_tempdir.path }}/{{ packer_package }}" + remote_src: yes + +- name: Make sure installation directory exists + file: + path: "{{ packer_install_dir }}" + state: directory + +- name: Install packer + copy: + src: "{{ packer_install_tempdir.path }}/{{ packer_package }}/packer" + dest: "{{ packer_install_dir }}/packer" + mode: '0755' + owner: "{{ ansible_user }}" + remote_src: yes + +- name: Set packer executable fact + set_fact: + packer_executable: "{{ packer_install_dir }}/packer" + cacheable: true + +- name: Output packer version + command: "{{ packer_executable }} version" + diff --git a/roles/ensure-packer/tasks/main.yaml b/roles/ensure-packer/tasks/main.yaml new file mode 100644 index 000000000..f7945f1c2 --- /dev/null +++ b/roles/ensure-packer/tasks/main.yaml @@ -0,0 +1,11 @@ +- name: Check installed packer version + command: "{{ packer_executable }} version" + register: packer_installed_version + failed_when: false + +- name: Install packer + include_tasks: install-packer.yaml + when: + - packer_installed_version.rc != 0 or + "packer_version != (packer_installed_version.msg | \ + regex_replace(packer_version_pattern, '\\g<version>'))" diff --git a/roles/ensure-packer/vars/main.yaml b/roles/ensure-packer/vars/main.yaml new file mode 100644 index 000000000..225b63183 --- /dev/null +++ b/roles/ensure-packer/vars/main.yaml @@ -0,0 +1,7 @@ +packer_arch_translation: + amd64: amd64 + x86_64: amd64 + i386: 386 + +packer_version_pattern: ^Packer v(?P<version>\d+\.\d+\.\d+).*$ + diff --git a/roles/packer/README.rst b/roles/packer/README.rst new file mode 100644 index 000000000..91159fdbb --- /dev/null +++ b/roles/packer/README.rst @@ -0,0 +1,32 @@ +Run packer command. Assumes the appropriate version of packer has been installed. + +**Role Variables** + +.. zuul:rolevar:: packer_executable + :default: {{ ansible_user_dir }}/.local/bin/packer + + Path to packer executable to use. + +.. zuul:rolevar:: packer_command + :default: build + + Packer command to run. + Examples are "build", "validate" + +.. zuul:rolevar:: packer_template + :default: packer.json + + Packer template file to use when executing packer. + +.. zuul:rolevar:: packer_extra_args + + String of extra command line options to pass to packer. + +.. zuul:rolevar:: packer_environemnt + + Environment variables to set in packer command. + +.. zuul:rolevar:: zuul_workdir + :default: {{ zuul.project.src_dir }} + + Directory to run packer in. diff --git a/roles/packer/defaults/main.yaml b/roles/packer/defaults/main.yaml new file mode 100644 index 000000000..2312e7a00 --- /dev/null +++ b/roles/packer/defaults/main.yaml @@ -0,0 +1,6 @@ +packer_command: build +packer_executable: "{{ ansible_user_dir }}/.local/bin/packer" +packer_workdir: "{{ zuul.project.src_dir }}" +packer_template: "packer.json" +packer_extra_args: "" +packer_environment: {} diff --git a/roles/packer/tasks/main.yaml b/roles/packer/tasks/main.yaml new file mode 100644 index 000000000..242369208 --- /dev/null +++ b/roles/packer/tasks/main.yaml @@ -0,0 +1,36 @@ +- name: Require packer executable + fail: + msg: packer_executable not defined + when: packer_executable is not defined + +- name: Create packer variable tempfile + tempfile: + register: packer_variable_tempfile + when: packer_variables is defined + +- name: Create packer variables file + copy: + content: | + {{ packer_variables | to_json }} + dest: "{{ packer_variable_tempfile.path }}" + when: packer_variables is defined + no_log: true # We don't want to log this since credentials could be passed this way + +- block: + - name: Run packer + command: >- + {{ packer_executable }} + {{ packer_command }} + {% if packer_variables is defined %} + -var-file={{ packer_variable_tempfile.path }} + {% endif %} + {{ packer_extra_args }} + {{ packer_template }} + environment: "{{ packer_environment }}" + args: + chdir: "{{ packer_workdir }}" + always: + - name: Delete packer variables file + file: + state: absent + path: "{{ packer_variable_tempfile.path }}" diff --git a/test-playbooks/packer/packer.json b/test-playbooks/packer/packer.json new file mode 100644 index 000000000..1b5463678 --- /dev/null +++ b/test-playbooks/packer/packer.json @@ -0,0 +1,11 @@ +{ + "variables": { + "packer_test_file": "{{env `PACKER_TEST_FILE`}}" + }, + "builders": [{ + "type": "file", + "content": "{{user `packer_test_content`}}", + "target": "{{user `packer_test_file` }}" + }] +} + diff --git a/test-playbooks/packer/post.yaml b/test-playbooks/packer/post.yaml new file mode 100644 index 000000000..8d965f52a --- /dev/null +++ b/test-playbooks/packer/post.yaml @@ -0,0 +1,9 @@ +- hosts: all + tasks: + - name: Ensure test_variable was written to file + lineinfile: + line: "{{ packer_variables.packer_test_content | replace('\n', '') }}" + dest: "{{ packer_environment.PACKER_TEST_FILE }}" + check_mode: yes + register: test_variable_presence + failed_when: test_variable_presence.changed diff --git a/zuul-tests.d/packer-jobs.yaml b/zuul-tests.d/packer-jobs.yaml new file mode 100644 index 000000000..038853680 --- /dev/null +++ b/zuul-tests.d/packer-jobs.yaml @@ -0,0 +1,144 @@ +- job: + name: test-packer + parent: packer + description: Test packer job + post-run: test-playbooks/packer/post.yaml + tags: all-platforms + files: + - roles/ensure-packer/.* + - roles/packer/.* + - test-playbooks/packer/.* + - zuul.d/packer-jobs.yaml + vars: + packer_install_dir: '{{ ansible_user_dir }}/packer' + packer_template: test-playbooks/packer/packer.json + packer_environment: + PACKER_TEST_FILE: testfile + packer_variables: + packer_test_content: "abc\n" + +- job: + name: test-packer-centos-7 + description: Test packer job on centos-7 + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: centos-7 + label: centos-7 + +- job: + name: test-packer-centos-8 + description: Test packer job on centos-8 + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: centos-8 + label: centos-8 + +- job: + name: test-packer-debian-stretch + description: Test packer job on debian-stretch + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: debian-stretch + label: debian-stretch + +- job: + name: test-packer-fedora-30 + description: Test packer job on fedora-30 + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: fedora-30 + label: fedora-30 + +- job: + name: test-packer-gentoo-17-0-systemd + description: Test packer job on gentoo-17-0-systemd + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: gentoo-17-0-systemd + label: gentoo-17-0-systemd + +- job: + name: test-packer-opensuse-15 + description: Test packer job on opensuse-15 + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: opensuse-15 + label: opensuse-15 + +- job: + name: test-packer-opensuse-tumbleweed-nv + voting: false + description: Test packer job on opensuse-tumbleweed + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: opensuse-tumbleweed + label: opensuse-tumbleweed + +- job: + name: test-packer-ubuntu-bionic + description: Test packer job on ubuntu-bionic + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-bionic + label: ubuntu-bionic + +- job: + name: test-packer-ubuntu-bionic-plain-nv + voting: false + description: Test packer job on ubuntu-bionic-plain + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-bionic-plain + label: ubuntu-bionic-plain + +- job: + name: test-packer-ubuntu-xenial + description: Test packer job on ubuntu-xenial + parent: test-packer + tags: auto-generated + nodeset: + nodes: + - name: ubuntu-xenial + label: ubuntu-xenial + +- project: + check: + jobs: + - test-packer-centos-7 + - test-packer-centos-8 + - test-packer-debian-stretch + - test-packer-fedora-30 + - test-packer-gentoo-17-0-systemd + - test-packer-opensuse-15 + - test-packer-opensuse-tumbleweed-nv + - test-packer-ubuntu-bionic + - test-packer-ubuntu-bionic-plain-nv + - test-packer-ubuntu-xenial + gate: + jobs: + - test-packer-centos-7 + - test-packer-centos-8 + - test-packer-debian-stretch + - test-packer-fedora-30 + - test-packer-gentoo-17-0-systemd + - test-packer-opensuse-15 + - test-packer-ubuntu-bionic + - test-packer-ubuntu-xenial diff --git a/zuul.d/packer-jobs.yaml b/zuul.d/packer-jobs.yaml new file mode 100644 index 000000000..d84c42d3b --- /dev/null +++ b/zuul.d/packer-jobs.yaml @@ -0,0 +1,57 @@ +- job: + name: packer + description: | + Base job for packaer operations + + Responds to these variables: + + .. zuul:jobvar:: packer_command + :default: build + + Command to pass to packer. + + .. zuul:jobvar:: packer_variables + + Dictionary with variables to pass to packer. + + .. zuul:jobvar:: packer_extra_args + :default: "" + + String containing extra arguments to append to the packer command line. + + .. zuul:jobvar:: packer_environemnt + + Environment variables to set in packer command. + + .. zuul:jobvar:: packer_template + :default: packer.json + + Packer template json file to use. + + .. zuul:jobvar:: packer_install_dir + :default: {{ ansible_user_dir }}/packer/ + + Path to install packer in. + + .. zuul:jobvar:: packer_version + :default: 1.5.5 + + The version of packer to use. + + .. zuul:jobvar:: packer_os + :default: {{ ansible_system | lower }} + + OS to use when choosing packer version. + + .. zuul:jobvar:: packer_arch + :default: amd64 / 386 + + Architecture to use when choosing packer version + + .. zuul:jobvar:: zuul_work_dir + :default: {{ zuul.project.src_dir }} + + Path to operate in. + + pre-run: playbooks/packer/pre.yaml + run: playbooks/packer/run.yaml