前回の投稿でAWXのProjects自動同期方法を調べたのですが、その中で一つ気になることが出てきました。 それは 「AWXではAnsible GalaxyのRoleはどのように参照されるのか」 という点です。

CLIで使うAnsibleでは ansible-galaxy install コマンドで外部Role(Galaxyに公開されているRoleや特定リポジトリのRole)をPlaybookから参照/実行できます。参照するRoleを指定する方法の1つに、参照情報を記載したYAMLファイルを読み込む方法があります。その際のコマンドは ansible-galaxy install -r [参照ファイルパス] です。AWXでも同じように参照されるのか、確認してみました。

マニュアルを読む

Ansible TowerでAnsible Galaxyを使う方法はUser Guideに書かれています。AWXも同じ方法です。それによると、<project-top-level-directory>/roles/requirements.yml ファイルを見つけると自動的に ansible-galaxy installコマンドが実行されるようです。

[https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#ansible-galaxy-support:embed:cite]

なるほど、CLI版とほぼ同じでansible-galaxy installコマンドを使って、参照するファイルの名前や保存先は指定されていると。そして実行タイミングはProject Update(プロジェクトの同期)の最後。じゃあ特段気にすることはないな、と思っていたのですが…。

実際に確認

前回の調査で知ったのですが、Project Update自体もAWXの Internal Job となっています。(正式用語かわかりませんがプログラム内のコメントでは Internal Job と記載されていたのでここでもそう呼びます)

そして、Internal JobもPlaybookを参照して実行されるようで、Project Updateは project_update.yml というPlaybookを参照しています。このPlaybookはawx_taskコンテナの/var/lib/awx/venv/awx/lib/python3.6/site-packages/awx/playbooks/project_update.ymlにあります。project_update.ymlの中身を見ると、

  • name: Update source tree if necessary
  • name: Install content with ansible-galaxy command if necessary

という2つのtasksで構成されていることが分かります。前者がAWX上で指定したSCMの更新で、後者がrequirements.ymlで指定した外部Roleの更新なんですね。実際に後者のタスクでcommand: ansible-galaxy installの記述があるので、マニュアルで書かれていた内容はこのPlaybookで実現しているようです。

外部Role更新タスクの実行条件として when: roles_enabled|booltags: install_roles がありました。変数roles_enabledSettings -> Jobs -> Enable Role Download のON/OFFで決まるようです。tagsのほうはInternal Job実行時に install_roles が付いていれば実行されるタスクのようですが、ここは未確認です(理由は後述)。

ということで、実際にroles/requirements.ymlを配置したリポジトリを用意してProjectsで指定、更新してみたのがこちら。

外部Roleの更新タスクが実行されてないですね…。SCMと同期したファイルの格納場所(awx_taskコンテナの/var/lib/awx/projects配下)を確認しても、リポジトリ内のPlaybookやRoleは同期されていますが、外部Roleは見当たりません。おかしい。

-p ./roles/オプションで出力先まで指定しているのに。awx_taskコンテナ全体を調べても外部Roleと思われるディレクトリ/ファイルは見つかりませんでした。やはり外部Roleの更新タスクが実行されていないようです。

Project Updateで外部Roleが更新されない理由

とここで、上記のProject Update実行結果をよく見たところ、Job Tagsに install_roles が含まれていませんでした。tagsの実行条件に該当していないようです。なぜ install_roles が付与されていないのか、ソースを追ってみたところ「Job Typeが Check の場合は install_roles が付与されない」≒「Job Typeが Run の場合に install_roles が付与される」ようです。

「じゃあJob Typeを Run で実行すればいい」と思ったのですが、Project UpdateをRunで実行する方法がわかりませんでした…。色々試したのですがCheckで実行されてしまいました。ソースも追ってみたのですが分からず仕舞いです。ここが上述した未確認事項の理由で、課題として残っています。

この件をTwitter上でぼそっと呟いたところ、ある御方(RHの中の人)が拾ってくれてIssueを上げてくれたのです!(自分で上げろ)。しかもその方と、他のRH中の人(ウェビナーお世話になっています)がやり取りされており、理由を教えていただきました。(教えてもらったというより勝手に見ただけ)

簡潔にいうと「仕様です」です。

上記やり取り中のワードをお借りすると「外部RoleはSCMリポジトリの外にあるから」です。自分なりの解釈をすると、「Project UpdateはあくまでProjectsで指定したSCMの更新をするだけで、外部Roleは対象外」ですかね。解釈が合っているかは怪しいですが、仕様となっちゃあ手が出せませんね。Issueのほうも同じような回答がされていました。

「じゃあマニュアルで書いてあること(At the end of a Project update,〜)って仕様と違うじゃん!」って思ったのですが、自分が触っているのはAWXなので何も言えません。

というわけで、Project Update時には外部Roleは更新されないようです。

JT実行して外部Roleを取得

もうここまで来たら、実際に外部Roleを引っ張ってくるとこを目にするまで引けません。

どうやらJT実行時に外部Roleを取ってくるようです。awx_taskコンテナの/var/lib/awx/projects配下にSCMのリポジトリが同期されているので、JTを実行してこちらを確認します。JT実行後に当該パスを確認したのがこちら。

いませんね…。roles配下はrequirements.ymlだけです。

本当の外部Roleの出力先

これも教えてもらった情報なのですが、JT実行時は /tmp 配下に一時ディレクトリが作成され、そこにPlaybookなど実行用ファイル一式配置されて実行されるようです。たしかに、JT実行時に /tmp ディレクトリを監視していると一瞬ディレクトリが現れて消えていっていました。

すぐ消えてしまうので何らかの方法でディレクトリを参照すればよいのですが、ちょうどこの作業をしているタイミングで「Ansible界の赤いきんぎょ」こと、よこちさんの「つまずきながら進める Ansible」という素敵な配信がありました(このエントリーを見ている方には説明不要ですかね)。

この配信の中で、Ansibleの Playbook Debugger というものの使い方の説明がありました。ansible-playbookコマンド実行中にデバッグできる素敵な機能です。この機能を使ったPlaybookをAWXで実行すると、ジョブがランニング状態のままとなるようです。

普段なら避けるべき事象だと思いますが、今回はこの「ジョブがランニング状態のままとなる」というのが /tmp 配下の一時ディレクトリを確認するのに都合がよかったので使ってみました。案の定、一時ディレクトリが消えずに残っていました。

一時ディレクトリを確認したところ、無事に外部Role(今回はgeerlingguy.java)が格納されていました!なるほど、外部Roleは/var/lib/awx/projects配下には配置されず直接一時ディレクトリに出力されるのですね。

まとめ

  • Project Updateしても外部Roleは取得されない
  • 外部RoleはJT実行に取得される
  • 外部Roleの出力先はawx_taskコンテナの /tmp/一時ディレクトリ 配下

さいごに

AWX、奥が深いですね。奥が深すぎて本命であるAnsibleのPlaybook作成の手が止まってしまいがちです。

この一連の調査で思ったことなんですが、/var/lib/awx/projectsディレクトリは何のためにあるんだ…。疑問は増えるばかり、謎は深まるばかりです。