![見出し画像](https://assets.st-note.com/production/uploads/images/172396397/rectangle_large_type_2_d491872a999098fb28f9ac6137f1b306.png?width=1200)
AWXのプロジェクトをCI/CDで更新する
株式会社SHIFT ITソリューション部の水谷です。
年明けバタバタしていてスタートが出遅れてしまいましたが、今年もAnsibleネタでブログを書いていこうと思います。
今回はAWX(あるいはAAP)のプロジェクトをGitLabのCI/CD機能を使って更新する方法について書いてみます。
AWXのプロジェクト同期機能
AWXやAAPを使れている方ならご存じかと思いますが、AWXやAAPにはプロジェクトの「起動時のリビジョン更新」という機能があります。
![](https://assets.st-note.com/img/1738290008-rJjQGLS51OuqHVMpFoEmIwiB.png?width=1200)
これを設定しておくと、このプロジェクトに紐づいたジョブテンプレートを実行する際に、自動的にリポジトリから最新のPlaybookを取得してくれます。
とても便利だし、間違って古いPlaybookを実行してしまうミスもなくせる素晴らしい機能のため、多くの方が使っていると思います。ただ、この機能の問題点(?)として、特に大きなプロジェクトでは更新に長い時間がかかることがある点が挙げられます。
というのも、このリビジョンの更新機能は単純にリポジトリをクローンするだけではなく、RoleやCollectionの取得も合わせて行っているためです。
例えばそのプロジェクトが、別々のリポジトリで管理されている10個のRoleを使用しており、Ansible Galaxyにある5個のCollectionをインストールする必要がある場合(少し大きめのプロジェクトならよくあるケース)など、ジョブテンプレートの起動ボタンを押してから実際にPlaybookの実行が始まるまでに数分待たされることになるでしょう。
実行時間が1時間とかの長いジョブテンプレートにとっては、この数分は微々たるものかもしれませんが、短いPlaybookを実行したいだけなのに、実行開始まで数分待たされるのはあまり嬉しくないですよね?
対策としては、まず必要なCollectionをEEに入れてしまう(カスタムEEを作成する)という方法があります。また、RoleもPlaybookと同じリポジトリで管理するという手もあります。が、これについてはRoleは再利用性を考えれば別リポジトリで管理した方が良いので、あまり良い解決方法とは言えないですね。
そこで、少し発想を変えて、(ジョブテンプレート実行のタイミングではなく)Playbookが格納されているリポジトリが更新されたタイミングでプロジェクトを更新することを考えてみました。
CI/CDによるリビジョン更新のアイディア
AWXやAAPにはREST APIがあります。ネットを検索すると、ジョブテンプレートを外部から起動する例がよく見つかりますね。AWXのAPIはとても充実しており、プロジェクトの更新を行うAPIも存在します。
https://ansible.readthedocs.io/projects/awx/en/latest/rest_api/api_ref.html
![](https://assets.st-note.com/img/1738290035-bwShNKriVX3pm6JxCqTID7L9.png?width=1200)
今回のアイディアは、リポジトリの更新をトリガーにして、このAPIをCI/CDパイプラインで呼び出すことでAWXプロジェクトも同期してしまおう、ということになります。
REST APIによるプロジェクト更新
ということで、まずはAWX側(API)を見ていきましょう。
AWXのAPIリファレンスページ を "project" で検索して見ていくと、その名前からプロジェクトの更新APIはおそらく /api/v2/projects/{id}/update/ だと目星がつきます。
![](https://assets.st-note.com/img/1738290050-WrmfdMjBItgRxZhC9D2EOVQK.png?width=1200)
{id}のところにAWX上のプロジェクト番号を入れればよさそうな感じがしますね。
さっそく実行してみたいところですが、実行のためにはトークンが必要なので、先にそれを取得します。
AWXにログインし、左メニュー「ユーザー」でユーザー一覧からトークンを発行するユーザーを選択し、「トークン」タブから「作成」をクリック。
![](https://assets.st-note.com/img/1738290057-OGX6tQ1DSa7g32CsUWnFfYvJ.png?width=1200)
「範囲」に「書き込み」を選択し、「保存」をクリックするとトークンが発行されます。
![](https://assets.st-note.com/img/1738290062-TeGvMPXLuYAnOJ7ih6Cw83Sm.png?width=1200)
トークンは1度しか表示されないので、忘れずにメモっておきます。
これがあれば、REST APIの実行が可能です。
さっそく curl コマンドで実行してみます。
curl -k -s -X POST \
-H "Authorization: Bearer lB21kpkVWBTIaQzeg6gBafXSn0pS2y" \
https://192.168.1.12:8043/api/v2/projects/6/update/
ヘッダーに "Authorization: Bearer lB21kpkVWBTIaQzeg6gBafXSn0pS2y" と、先ほど取得したトークンを書いてます。また、プロジェクトIDは6にしているのですが、これはAWXをインストールした時に自動的に作られる Demo Project に対応します。
※AWXのURLとトークンは私のテスト環境のもですので、試される場合は変更してください。
実行すると、このようにソースコントロールの更新が実行されます。
![](https://assets.st-note.com/img/1738290085-krBNmufIH1l7nRJTD3U0AZ4E.png?width=1200)
ジョブのログを見てみると、ちゃんとGitサーバーにアクセスしてプロジェクトを更新するタスクが実行されたことがわかります(実際にはリポジトリに変更がなかったため、何もしていませんが)。
![](https://assets.st-note.com/img/1738290095-rjvdAyEZD78HXxsQKkhi15oW.png?width=1200)
テストリポジトリを作成してテスト
では、GitLabに適当なプロジェクトを作って、CI/CDでAWXのプロジェクトを更新してみましょう。
![](https://assets.st-note.com/img/1738290105-UvHBgupbyMWniDVIoc1GdCN0.png?width=1200)
"RestAPITestProject" という名前でプライベートなリポジトリを作成しました。
ここにいくつかのPlaybookを含むファイルをcommit/pushしておきます。
続いてAWX側にProjectを作成します。
![](https://assets.st-note.com/img/1738290123-PgmlIcOy2GQjAMCtb0xfrk3L.png?width=1200)
「起動時のリビジョン更新」のチェックボックスは外した状態にしておきます。
また、このプロジェクトのURLが "https://192.168.1.12:8043/#/projects/8/details " となっていることから、IDが8であることがわかります。
ですので、このプロジェクトを更新する curl コマンドは以下になります。
curl -k -s -X POST \
-H "Authorization: Bearer lB21kpkVWBTIaQzeg6gBafXSn0pS2y" \
https://192.168.1.12:8043/api/v2/projects/8/update/
あとは、これを使ってシンプルな .gitlab-ci.yml を作成します。
---
stages:
- sync
sync-awx-project:
stage: sync
script:
- |-
curl -k -s -X POST \
-H "Authorization: Bearer lB21kpkVWBTIaQzeg6gBafXSn0pS2y" \
https://192.168.1.12:8043/api/v2/projects/8/update/
これを commit/push すると、パイプラインが走り、curl コマンドが実行されました。
![](https://assets.st-note.com/img/1738290135-RuoJ9IZCEAFsGmcDKrxyQbe7.png?width=1200)
AWX側をみてみると……。
![](https://assets.st-note.com/img/1738290138-D1YCryNRlvH8EWMJ9knLxpAa.png?width=1200)
プロジェクトの更新ジョブが実行され、「成功」のステータスで終了していました。
ジョブの起動とプロジェクトの更新が同時に起きたときの挙動
ここで気になる点が1つあります。
Playbookを更新して、commit/pushし、プロジェクトの更新ジョブがまさに動作しているタイミングで、そのプロジェクトから作ったジョブテンプレートを実行するとどうなるか?
これは実際にやってみたのですが、下のスクリーンショットのように、更新中のプロジェクトが紐づいているジョブテンプレートの実行は「保留中」となり、プロジェクトの更新が完了した後に実行されました。
![](https://assets.st-note.com/img/1738290153-oFhsbnVWR1lk9wBH7A3y2u6m.png?width=1200)
ちゃんとこのようなシチュエーションでも問題が起きないよう考慮されているんですね。
ただし、commit/pushしてからCI/CDで curl コマンドが実行されるまでには少し時間がかかるので、その間にジョブテンプレートを実行してしまうと古いPlaybookが実行されてしまうので、その点には注意が必要ではあります。
まとめ
プロジェクトの規模にもよりますが、「実行時の更新」は便利だから使いたいが、ジョブテンプレート起動時に待たされるのは嫌だな、と感じているAWX/AAPユーザーにとっては1つの解決策になるのではないかな、と思います。
あとは、CI/CDパイプラインをもう少し充実させて、例えば ansible-lint や moleculeでのテストがパスした時にだけプロジェクトの更新を行う、とか、マージリクエスト(プルリクエスト)のマージ時に本番用のプロジェクトを更新し、それ以外はテスト用プロジェクトを更新するようにする。特定のディレクトリ以下(Playbook等が格納されているディレクトリ以下)が更新されたときだけプロジェクトを更新する、など、いろいろ作りこんでいけば便利になるのではないかと思いますので、気になった方は試していただければと思います。
★公式ブロガー水谷の執筆記事一覧
執筆者プロフィール:水谷 裕一
大手外資系IT企業で15年間テストエンジニアとして、多数のプロジェクトでテストの自動化作業を経験。その後画像処理系ベンチャーを経てSHIFTに入社。
SHIFTグループ会社「RGA」および「システムアイ」に出向し、インフラ構築の自動化やCI/CD、コンテナ関連の業務に従事した後、2024年3月よりSHIFTのインフラサービスGに配属。
LinuxよりWindowsの方が好き。
✅IaC支援サービスのご紹介
SHIFTではTerraformやCDKを使ったクラウドインフラ構築の自動化や、Ansibleを使ったサーバOSの設定自動化や構成管理のご支援も行っております。ご依頼・ご相談は下記リンクからお願いします。
お問合せはお気軽に
✅お役立ち資料無料ダウンロード
SHIFTについて(コーポレートサイト)
SHIFTのサービスについて(サービスサイト)
SHIFTの導入事例
SHIFTの採用情報はこちら
PHOTO:UnsplashのAndras Vas