LoginSignup
9
10

More than 5 years have passed since last update.

【Ansible】独自モジュール作成時の変数の呼び出し方について

Last updated at Posted at 2016-12-19

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で宣言をします。
(変数の書き方は本ページでは割愛します)

main.yml
un: "Hello"
deux: "World"

tasks/main.yml作成

次にtaskの用意です。
taskでは以下のように書きます。

main.yml
- name: get hello world
  test: # .pyを除いた実行する独自モジュール名
    un: "{{ un }}" # 独自モジュールで使用したい変数
    deux: "{{ deux }}"
  register: cinq # 独自モジュールの実行結果を格納する変数名

独自モジュール作成

では、モジュールを作成してみましょう。
libraryディレクトリに「test.py」というファイルを作成します。

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にふれていく予定なので、
また新しい学びがあったら投稿したいと思います。

ご覧いただきありがとうございました。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10