🎒

GitHubActionsでPacker+Ansibleを使ってイメージを自動ビルドするアクションを作った

2021/09/17に公開

はじめに

マシンイメージの自動作成を行うPacker。便利なツールですよね。Packerを使えばコマンド1発でイメージのビルドを行えるのですが、その1発のコマンドでも自動化できたらだいぶ楽になるかなと思いGitHub ActionsでAnsibleのprovisionerに使ったPackerビルドを行う方法を書いていこうと思います。

アプローチ

GitHub Actionsでやっていくにはまずは公式の用意したワークフローを使うのが一般的だと思います。
もちろんPackerにも公式のワークフローが存在しています。
https://github.com/marketplace/actions/packer-github-actions

しかし、公式のワークフローだとProvisionarにAnsibleが使えないようです
このissueに書いてある通りansible-playbookが実行できない感じです。
https://github.com/hashicorp/packer-github-actions/issues/20
Packerのワークフローはランナー上のDockerコンテナ上で実行されるので、その中にAnsibleがインストールされてないような感じですね。

ということで、公式のワークフローではAnsibleが使えないようなので、自分でdockerのイメージとアクションを用意していく必要がありそうなので制作していきましょう!

ちなみに、自作のActionについては詳しく知りたい場合は以下の公式ドキュメントを参考にしてください。
https://docs.github.com/ja/actions/creating-actions

今回はDockerコンテナのアクションでPacker+Ansibleのアクションを作成していきます
https://docs.github.com/ja/actions/creating-actions/creating-a-docker-container-action

やり方

まずはディレクトリ構成は以下のような感じです

├── .github
│   └── workflows
│       └── packer.yml
├── Dockerfile
├── action.yml
├── entrypoint.sh
└── packer
    ├── packer.json
    └── roles

Dockerイメージの用意

まずはDockerfileを書いていきます。
やってることはdebianのベースイメージを使って、PackerとAnsiblenのインストールをしています。

インストールについてはこちらの公式ドキュメントを参考にしています。
https://learn.hashicorp.com/tutorials/packer/get-started-install-cli

https://docs.ansible.com/ansible/2.9_ja/installation_guide/intro_installation.html#debian-ansible

FROM debian:buster-slim
RUN apt update
RUN apt -y upgrade
RUN apt -y install gnupg
RUN apt -y install curl
RUN apt -y install software-properties-common

# Install Packer
RUN curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
RUN apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
RUN apt update && apt -y install packer

# Install Ansible
RUN echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
RUN apt update && apt -y install ansible

COPY "entrypoint.sh" "/entrypoint.sh"

ENTRYPOINT ["/entrypoint.sh"]

action.ymlの用意

GitHub Actionsでは自身が定義したアクションを実行したい際には、action.ymlを作成する必要があります。
やっていることとしては、inputでcommandとworking_directoryの2つの入力を受け取って、先ほど用意したDockerアクションを実行するためにrunsでDockerfileを設定しています。

action.ymlについての詳細は公式ドキュメントに詳しく書いてあります。
https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions

# action.yml
name: 'Packer Build'
description: 'Automatic build with Packer'
inputs:
  command:
    description: 'input command'
    required: true
  
  working_directory:
    description: working directory for command (defaults to root)
    required: false

runs:
  using: 'docker'
  image: 'Dockerfile'

entrypoint.shの用意

entrypoint.shは以下のようになってます。
やってることとしては、先程のaction.ymlのinputで定義したcommandとworking_directoryで得られた入力によってINPUT_COMMANDINPUT_WORKING_DIRECTORYという環境変数が生成されるため、
必須の入力項目であるcommandがなければエラーを吐いて終了。ある場合はworking_directoryで指定されたディレクトリへCDして、コマンドの実行しています。

#!/usr/bin/env bash

set -e

# fail if INPUT_COMMAND is not set
if [ -z "${INPUT_COMMAND}" ]; then
  echo "Required variable \`command\` is missing"
  exit 1
fi

if [ -n "${INPUT_WORKING_DIRECTORY}" ]; then
  cd "${INPUT_WORKING_DIRECTORY}"
fi

${INPUT_COMMAND}

workflows/packer.yml

いよいよワークフローファイルについてです
以下のような感じになっています。
uses:./にすることで先ほど作成したaction.ymlを実行するようになっています。
あとは、commandとworking_directoryで実行したいコマンドとディレクトリを指定します。
コマンドをそのまま渡す形式にしているためvalidateコマンドなどで構文チェックなども可能です。

with:
  command: packer build packer.json
  working_directory: ./packer

このワークフローだとonworkflow_dispatchになっているため手動で実行されるようになっています。
この部分はPRがマージされた時などいろいろ設定できるので好きなように変更するといいと思います。

name: Packer Build

on:
  workflow_dispatch:

jobs:
  packer:
    runs-on: ubuntu-latest
    name: packer
    
    steps:
      - uses: actions/checkout@v2

      - name: Packer Validate
        uses: ./
        with:
          command: packer validate -syntax-only packer.json
          working_directory: ./packer
      
      - name: Packer Build
        uses: ./
        with:
          command: packer build packer.json
          working_directory: ./packer

実行してみる

workflow_dispatchであればGitHubのリポジトリのタブからActionsを選択して

Select Workflowから先ほど作成したPacker Buildを選択

Run workflowで実行が可能です。

実行してこんな感じでstepの横にチェックマークがついてたら成功です。

まとめ

これでGitHub Actions上でAnsibleを使ったPackerビルドができるようになると思います。
今後は、公式のワークフローでもできるようになればいいなぁと思ってます!
あと、今回作ったコンテナ上でコマンドを実行するみたいなアクションは汎用性が高いと思うので、このコマンドをGitHub Actionsで使ってみたいけど公式でアクション作ってないなぁみたいな時は、自作も簡単にできるようになるのではと思います。

Discussion