ansible歴半年の新米インフラエンジニアです
はじめに
当方、とある企業でインフラエンジニアとしてansibleのroleやplaybook作成に日々勤しんでいる者です。
まだansible歴が半年ですが、やっと開発・運用に慣れてきた今日この頃。
そんな最中に舞い込んできた業務が「独自モジュール」を作って欲しいとのことでした。
ansibleには、多くのモジュールが実装されています。
(公式ホームページ参照:http://docs.ansible.com/ansible/list_of_all_modules.html )
しかし、今回の依頼は上記のような既存モジュールでは非対応の要件とのこと。
プログラミング経験は、1か月前からpythonを始めたばかりの新米。
そんな自分が本当に独自モジュール作成なんてカッコイイ仕事が出来るのか、当初は不安でした。
不安でした、が!
Ansibleのモジュールは、意外にも簡単に作成することが可能でした。
作るだけならハードルは高くありません。
しかし、独自モジュールはansibleとは分離しているものなので
ansible側で定義した変数を呼び出すやり方を知らないと、
呼び出せないストレスで苦しむ可能性があります。
長くなりましたが、ここからが本題です。
このページでは、そんなストレスに対抗すべく
初心者が躓くであろう変数の呼び出し方をご紹介します。
※どの言語でも作成可能とのことですが、今回は当方が学んでいるpythonでの書き方でご説明します。
環境
・CentOS 7.2
・Python 2.7.5
下準備
まず、独自モジュール置き場を用意します。
playbook内に「library」ディレクトリを作成します。
※ディレクトリ名は原則です、ここを違う名前にすると読み込んでくれません
今回は、実行するrole内に作成します。
role構成は以下の通りです。
ansible-test-playbook
|_test-server.yml
|_group_vars
|_host_vars
|_vars
|_inventory
|_roles
|_role_test
|_defaults
|_main.yml
|_tasks
|_main.yml
|_templates
|_library ⬅︎new!
|_test.py ⬅︎new!
下準備もできたので、次に独自モジュールを作成していきます。
簡単なシェルスリプトだけでも動きますが、
今回は「ansible側で宣言した変数をモジュール側で読み込んで実行」するやり方を中心に書いていきます。
ansibleでは一度記載した変数は呼び出せば自由に使用できますよね。
ですが、独自モジュール側ではそのまま呼び出そうとしてもうまくいきません。
そこでtaskで呼び出したい変数を指定し、独自モジュールに持っていくという工程が必要となります。
以下では、変数を独自モジュールに持っていき、実行結果をansible側に戻すまでを記載します。
defaults/main.yml作成
今回呼び出したい変数は以下のようにdefaultsで宣言をします。
(変数の書き方は本ページでは割愛します)
un: "Hello"
deux: "World"
tasks/main.yml作成
次にtaskの用意です。
taskでは以下のように書きます。
- name: get hello world
test: # .pyを除いた実行する独自モジュール名
un: "{{ un }}" # 独自モジュールで使用したい変数
deux: "{{ deux }}"
register: cinq # 独自モジュールの実行結果を格納する変数名
独自モジュール作成
では、モジュールを作成してみましょう。
libraryディレクトリに「test.py」というファイルを作成します。
#!/usr/bin/env python
# coding: utf-8
# 必要なものをインポート
import json, urllib2
from ansible.module_utils.basic import *
def main():
# varsから情報を取得するおまじないのようなものです
# この時に変数名を、taskで宣言したものと一致するように書いてください
module = AnsibleModule(
argument_spec=dict(
un=dict(required=True, type='str'),
deux=dict(required=True, type='str')
),
# no skip
supports_check_mode=True,
)
# 上記で取得した情報を格納して、モジュール内で使用できるようにする
un = module.params['un']
deux = module.params['deux']
# このモジュールで実行する内容
trois = un + deux
# 実行結果を辞書型で格納
# 後述のansible_factsが辞書型の形式で作られているので、この形は必須です
quatre = {"quatre": trois}
# 実行結果をansible側に引き渡す
module.exit_json(changed=True, ansible_facts=quatre)
if __name__ == '__main__':
main()
実行
では、準備が整いましたので上記を実行してみます。
PLAYBOOK: test-server.yml ********************************************************
1 plays in test-server.yml
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [role-test : get hello world] *******************************************
changed: [localhost] => {
"ansible_facts": {
"quatre": "HelloWorld" ⬅︎実行結果
},
"changed": true,
"invocation": {
"module_args": {
"deux": "World",
"un": "Hello"
},
"module_name": "test"
}
}
独自モジュールの実行結果がansible_factsの中に格納されているのが分かります。
では、今度はansible側で実行結果を呼び出すにはどう書けば良いか。
"{{ cinq.ansible_facts.quatre }}"
「taskの中のregisterで指定した変数名.ansible_facts.独自モジュール内で宣言した辞書型のkey」
この書き方をすればansible内で実行結果を使用できます。
これで作業は終了です。
あとがき
いかがだったでしょうか?
少しでもこのような悩みに陥った方のお役に立てれば幸いです。
今後もansibleやpythonにふれていく予定なので、
また新しい学びがあったら投稿したいと思います。
ご覧いただきありがとうございました。