AWXのプロジェクトを自動同期させたい

Ansible/AWXを利用していて、少し煩わしいと思ったことがあります。それは「Playbookをリポジトリに追加したら、AWXのプロジェクトの同期を手動実行しないとジョブテンプレートからそのPlaybookを選択できない」という点です。プロジェクトを同期していないと、ジョブテンプレートのPlaybook選択するプルダウンに追加したPlaybookが出てこないのです。現在の手順は以下のような感じです。

  1. 新規Playbookをリポジトリに追加
  2. プロジェクト手動同期
  3. ジョブテンプレートで新規playbookを選択

簡単な手順ではあるのですが、わざわざ「2. プロジェクト手動同期」をする度にモヤモヤーってしています。このモヤモヤを取り除きたいと思います。

f:id:nnstt1:20200517200209p:plain

(どんだけ面倒くさがりなんだ……)

やりたいこと

簡潔にいうとタイトルの通り 「AWXのプロジェクトを自動同期させたい」 です。自分の検証環境ではGitLabでPlaybookを管理しているので、具体的には以下のような流れで自動同期をしてみます。

  1. GitLabのリポジトリを更新する(Playbookの追加に限定しません)
  2. AWXになんとかして更新を通知する
  3. AWXのプロジェクトを更新させる

「AWXになんとかして更新を通知する」方法として、AWXの「Webhook」と「API」の2通り検討しました。

前提

今回使用した環境は以下です。

  • それぞれ個別のサーバに構築
  • AWX 11.0.0(Ansible 2.9.5)
  • GitLab CE 12.10.3
  • AWXのプロジェクトはGitLabと連携済み
  • GitLab Runnerは Shell Executer を登録済み

同期方法

Webhook

AWXにはWebhook経由でジョブテンプレートを実行するための設定があります。

f:id:nnstt1:20200517194250p:plain
ジョブテンプレート Webhook設定

ジョブテンプレート編集画面でENABLE WEBHOOKにチェックし、WEBHOOK SERVICEでGitLabを選択するとWEBHOOK URLWEBHOOK KEYに値が表示されます。(WEBHOOK KEYはジョブテンプレート保存後に表示)

Towerのマニュアルになりますが、詳細はこちら。 docs.ansible.com

マニュアルにある通りGitLabの設定をしたら、Webhookを使用してジョブテンプレートを実行することができます。しかし、AWXのプロジェクトをWebhookで実行することはできないようです。上記のジョブテンプレート編集画面のようなWebhookを設定する画面は見つかりませんでした。(AWXのソースを見ても無さそうです)

Webhook経由で無理やりプロジェクトを同期させる方法としては「Update Revision on Launchを有効にしたプロジェクトを使用するジョブテンプレートをWebhookで実行する」があるかと思います。AWXのプロジェクトの設定でUpdate Revision on Launchを有効にしていると、当該プロジェクトを使用するジョブテンプレートを実行するときにプロジェクトの同期も実行されます。

f:id:nnstt1:20200517201458p:plain
プロジェクトのUpdate Revision on Launch

f:id:nnstt1:20200517202423p:plain
ジョブテンプレートの実行の前にプロジェクトの同期が実行される

この機能を利用してWebhookからジョブテンプレートを実行し、間接的にプロジェクトを同期することで AWXのプロジェクトを自動同期させたい を達成可能です。ジョブテンプレートの中身は何でも良いですが、目的がプロジェクトの同期なので処理が軽めの同期用ジョブテンプレートを用意するのが良いと思います。また、Webhookはワークフローテンプレートの実行も可能なので、複数プロジェクトを一斉に同期ということも可能です。(やる機会は無さそうですが)

API

AWXではAPIが提供されており、こちらからジョブテンプレートの実行やインベントリのホスト一覧を取得などができます。その中でプロジェクトの同期も可能となっています。

docs.ansible.com

Webhookの場合はGitLab上で設定項目が存在するのですが、API呼び出す用の設定とかは無さそうなのでGitLab CIでcurlコマンド叩いてAPI呼び出します。今回は以下のような.gitlab-ci.ymlを準備しました。

job:
  script:
    - 'export AWX_TOKEN=`curl -s -u $AWX_USER:$AWX_PASSWORD -X POST http://[awx_server]/api/v2/tokens/ | jq -r .token`'
    - 'curl -X POST -H "Authorization: Bearer $AWX_TOKEN" -H "Content-Type: application/json" http://[awx_server]/api/v2/projects/[プロジェクトID]/update/'
}
  • GitLabのリポジトリ(プロジェクト)設定で変数 AWX_USERAWX_PASSWORD を定義(Settings -> CI/CD -> Variables)
  • API/api/v2/tokens/トークンを取得し、環境変数 AWX_TOKENに格納
  • AWXのURLから自動同期させたいプロジェクトのIDを目視確認
  • 上記トークンを使用して /api/v2/projects/[プロジェクトID]/update/ を叩く

上記のファイルをリポジトリに配置したり必要な変数を設定すれば、リポジトリ更新時にCIが動いてAPI経由でAWXのプロジェクト同期処理が実行されます。GitLabは特定ブランチの更新時だけWebhookと飛ばすことができるのですが、APIの場合も.gitlab-ci.ymlを使うのでブランチ毎の設定が可能です。

まとめ

Webhook または API を使用して AWXのプロジェクトを自動同期させたい という目標を達成することはできました。これで多少なりともAWXの使い勝手がよくなれば嬉しいです。今回はGitLabと連携させたのですが、GitHub Actionでもできそうなのでいずれやってみます。

また、AWXのAPIはたくさんの機能が提供されているようなので、プロジェクト同期に限らず色々おもしろいことができそうですね。

あと、Webhookという仕組みがあるんだからそっちで直接プロジェクト同期したいなぁという気持ちがあります。AWXはDjango使っているらしいので勉強がてら実装してみるのも面白そうです(意訳:だれかやって)。