Common Packer Usage

To use any provisioning script available from the common-packer repository, the calling template must appropriately reference the full path to the script. In most cases this is ‘provision/$SCRIPT’ which is now ‘common-packer/provision/$SCRIPT’

To use any of the provided templates, the template should have a symlink into the calling project’s templates directory. This is because our common-packer job scripts operate on the templates available in this directory. Any template, will also look for local customization out of the local repository’s provisioning directory via local-$TEMPLATE.yaml playbook.

Distribution specific vars are now provided in ‘common-packer/vars/$DISTRO’. Path to them as normal and they will already contain the correct strings. For a new project make sure the base_image name is available in the cloud system.

Setup packer template

This setups up a builder image for use in a project. Repeat for any other templates provided by common-packer as necessary.

# Instructions assume the working directory is the ci-management repo root
cd packer
mkdir provision templates
ln -rs common-packer/templates/builder.json templates/builder.json
cp common-packer/provision/local-builder.yaml provision/local-builder.yaml

Example template design and run

In most cases the ‘builder’ template unmodified is all that the project should need to run their code builds. If a project has a custom package that they must build into a custom builder type then design the new template with the following parameters:

  1. Execute the common-packer/provision/install-python.sh script
  2. Execute the common-packer/provision/baseline.yaml Ansible playbook
  3. Execute a local playbook
  4. Execute the system reseal Ansible role

Steps 2-4 are actually all contained inside of the local playbook. The following examples for docker template and provisioning script show how they import the existing baseline playbook into the local playbook to reduce duplication in code.

Example docker template:

{
  "variables": {
    "ansible_roles_path": ".galaxy",
    "arch": "x86_64",
    "base_image": null,
    "cloud_network": null,
    "cloud_user_data": null,
    "cloud_region": "ca-ymq-1",
    "cloud_availability_zone": "ca-ymq-2",
    "vm_use_block_storage": "false",
    "vm_volume_size": "10",
    "vm_image_disk_format": "",
    "distro": null,
    "flavor": "v1-standard-1",
    "ssh_user": null,
    "ssh_proxy_host": ""
  },
  "builders": [
    {
      "name": "vexxhost",
      "image_name": "ZZCI - {{user `distro`}} - docker - {{user `arch`}} - {{isotime \"20060102-150405.000\"}}",
      "instance_name": "{{user `distro`}}-docker-{{uuid}}",
      "source_image_name": "{{user `base_image`}}",
      "type": "openstack",
      "region": "{{user `cloud_region`}}",
      "availability_zone": "{{user `cloud_availability_zone`}}",
      "networks": [
        "{{user `cloud_network`}}"
      ],
      "user_data_file": "{{user `cloud_user_data`}}",
      "ssh_username": "{{user `ssh_user`}}",
      "ssh_proxy_host": "{{user `ssh_proxy_host`}}",
      "flavor": "{{user `flavor`}}",
      "metadata": {
        "ci_managed": "yes"
      },
      "use_blockstorage_volume": "{{user `vm_use_block_storage`}}",
      "volume_size": "{{user `vm_volume_size`}}",
      "image_disk_format": "{{user `vm_image_disk_format`}}"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "scripts": [
        "common-packer/provision/install-python.sh"
      ],
      "execute_command": "chmod +x {{ .Path }}; if [ \"$UID\" == \"0\" ]; then {{ .Vars }} '{{ .Path }}'; else {{ .Vars }} sudo -E '{{ .Path }}'; fi"
    },
    {
      "type": "shell-local",
      "command": "./common-packer/ansible-galaxy.sh {{user `ansible_roles_path`}}"
    },
    {
      "type": "ansible",
      "playbook_file": "provision/local-docker.yaml",
      "ansible_env_vars": [
        "ANSIBLE_NOCOWS=1",
        "ANSIBLE_PIPELINING=True",
        "ANSIBLE_ROLES_PATH={{user `ansible_roles_path`}}",
        "ANSIBLE_CALLBACK_WHITELIST=profile_tasks",
        "ANSIBLE_STDOUT_CALLBACK=debug"
      ]
    }
  ]
}

Example provisioning script:

---
- import_playbook: baseline.yaml

- hosts: all
  become_user: root
  become_method: sudo

  pre_tasks:
    - include_role: name=lfit.system-update

  roles:
    - {role: lfit.docker-install, mtu: 1458}

  post_tasks:
    - name: System Reseal
      script: system-reseal.sh
      become: true

Install Roles from Ansible Galaxy

Common-packer contains a script ansible-galaxy.sh which runs ansible-galaxy install -r requirements.yaml from the common-packer repo to install common-packer role dependencies. In the local ci-management/packer directory a project can provide it’s own requirements.yaml to pull in roles before running a Packer build.

Local testing of common-packer

For developers of common-packer who would like to be able to locally test from the common-packer repo, the common-packer repository already contains a symlink to itself which allows one to test the templates in the common-packer templates standalone.