レッドハットの杉村です。Ansible のテクニカルサポートをしています。毎月1つは何か書くことを目標にしています。5月があっという間に去ってしまいまして、5月34日(6月3日) ということにさせてください。
これまで2回に分けまして、Ansible で扱う変数について紹介しました。
これまではコマンドラインから ansible-playbook を実行する例を見てきましたが、Ansible automation controller ではもう少々複雑な変数の受け渡しができます。2つの方法について紹介していきます。
Ansible Automation Platform 2.2 (Ansible automation controller 4.2.0) を利用した例で説明していきます。
set_stats
ワークフロージョブテンプレートを定義して、複数のプレイブックの実行の間で処理結果を次のプレイブックに引き継ぎたいことがあると思います。
簡単すぎる例で恐縮ですが、このようなワークフローを考えてみます。文字列を引き継ぎたいということだけの例なので、内容の妥当性についてはここでは気にしないでください。
ジョブテンプレートA
- パスワード文字列を外部変数として受け取る
- 管理対象にパスワードを設定する
- パスワード文字列を次のジョブテンプレートで使えるようにする
---
- hosts: all
gather_facts: false
vars:
service_account: ansible
tasks:
- name: store a password for further use
set_stats:
data:
service_account_password: "{{ password_string }}"
aggregate: false
- name: change a password for a service account
user:
name: "{{ service_account }}"
state: present
password: "{{ password_string | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}"
become: true
set_stats: では aggregate: false を指定しました。これを指定しない場合はデフォルトの true となり、呼び出した数だけ文字列が連結されてしまいます。
ジョブテンプレートB
- ジョブテンプレートAからパスワード文字列を受け取る
- 管理対象にアクセスしてhostnameコマンドを実行する
---
- hosts: all
gather_facts: false
vars:
ansible_user: ansible
ansible_password: "{{ service_account_password }}"
tasks:
- name: run something
command: hostname
register: result
- name: debug
debug:
var: result
ワークフロー
ワークフローでは survey を定義して、実行時に入力を受け付けるようにしました。

実行結果
ワークフロージョブテンプレートを起動すると入力を求められるので適当に入れます。

無事実行されました。

このときそれぞれのジョブテンプレートの結果を見ると、1つ目のジョブテンプレートで set_stats で格納された変数 service_account_password の値が Artifacts として保存されて、2つ目のジョブテンプレートの外部変数として渡っていることがわかります。


入力した文字列は隠したいということはあるでしょうが、ここでは本題ではありません。
ここでは set_stats モジュールで Artifacts として保存されて、外部変数に渡っていくということを示したかったです。
set_fact
先ほどの例では、ジョブテンプレートで生成した変数を次のジョブテンプレートに外部変数として渡せることがわかりました。
もしこれが100台あった場合を考えてみます。今回の例では単純な1つの変数でしたが、100台別々に設定したいということになると、外部変数として100台分のデータをリストにして作成し、後段のジョブテンプレートでは渡ってきた100台分のうち該当するものを選択して使うという処理が必要となってしまいます。
Ansible では fact の仕組みがありまして、以前の記事までで出てきたようなインベントリに設定するホスト変数に対して動的に格納することができます。これにより、100台でも何台であってもシンプルにプレイブックを実装することができます。
先ほど set_stats で実装したものを、set_fact で書き換えてみました。今回はパスワード文字列を外から与えるのではなく、プレイブックの中でホストごとにランダムに生成しています。
ジョブテンプレートA
- パスワード文字列をランダムに生成する
- 管理対象にパスワードを設定する
- パスワード文字列を次のジョブテンプレートで使えるようにする
---
- hosts: all
gather_facts: false
vars:
service_account: ansible
tasks:
- name: generate a password
set_fact:
service_account_password: "{{ lookup('password', '/dev/null', seed=inventory_hostname) }}"
cacheable: true
- name: change a password for a service account
user:
name: "{{ service_account }}"
state: present
password: "{{ service_account_password | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}"
become: true
set_fact: では cacheable: true を指定してください。ジョブテンプレートでも Enable Fact Storage オプションを有効にすることで、プレイブックから fact データへの読み書きができるようになります。

ジョブテンプレートB
- ジョブテンプレートAからパスワード文字列を受け取る
- 管理対象にアクセスしてhostnameコマンドを実行する
---
- hosts: all
gather_facts: false
vars:
ansible_user: ansible
ansible_password: "{{ ansible_facts.service_account_password }}"
tasks:
- name: run something
command: hostname
register: result
- name: debug
debug:
var: result
外部変数から受け取るのではなく、ansible_facts から受け取ってきています。これを使うジョブテンプレートでも同様に Enable Fact Storage オプションを有効にしておいてください。
実行結果
このワークフロージョブテンプレートを2台のホストを定義したインベントリーを指定して実行してみました。

それぞれのジョブテンプレートでは入出力がありませんので、Variables や Artifacts は空です。

fact データは、インベントリーからホストをたどると見ることができます。生成した文字列がホストのそれぞれで別々に格納されていることがわかります。

終わりに
今回は Ansible の変数を複数のジョブで受け渡しする方法について紹介しました。
まとめて一つの外部変数として渡したいときは set_stats を使い、ホストごとに別々な値を設定して使いたいときは set_fact を使うことができます。
fact のデータはプレイブックの先頭で gather_facts: true と書いたときに setup モジュールが実行して情報収集された結果や、ダイナミックインベントリでクラウドサービスから API で取得した情報なども格納されます。少々使い方や設定が複雑なところもありますが、automation controller 上で使うことによって便利にお使いいただけるものと思います。
Ansible Automation Platform の試用版はこちらをご覧ください。
Happy Automation!