ksaitoの日記

日々試したことの覚え書き

ansible Moduleの作り方2

オフシャルドキュメントを参考にテスト方法と引数の取り方を試しました。

テスト

オフシャルドキュメントのチュートリアルにテスト方法とかんたんなモジュールの作り方が書かれています。

下記でテスト環境を準備します。

$ git clone git://github.com/ansible/ansible.git --recursive
$ source ansible/hacking/env-setup
$ chmod +x ansible/hacking/test-module

これでansibleの最新ソース一式をクローンしてローカルのソースでモジュールの開発とテストをする環境が準備できます。

結果を返すだけのシンプルなモジュールをpythonで書きます。

$ cat mymodule.py 
#! /usr/bin/python

import json

print json.dumps({
    "rc": 0,
    "changed": True,
})
$ 

テストします。

$ $ANSIBLE_HOME/hacking/test-module -m mymodule.py
* including generated source, if any, saving to: /home/vagrant/.ansible_module_generated
* this may offset any line numbers in tracebacks/debuggers!
***********************************
RAW OUTPUT
{"changed": true, "rc": 0}


***********************************
PARSED OUTPUT
{
    "changed": true, 
    "rc": 0
}
$ 

引数

ansibleの引数がどのように処理されている確認してみます。

先ほどのソースに、チュートリアルにある引数の処理を追加・実行して確認してみます。

 cat mymodule.py 
#! /usr/bin/python

import json
import sys

args_file = sys.argv[1]

print json.dumps({
    "rc": 0,
    "changed": True,
    "args": args_file
})
$ $ANSIBLE_HOME/hacking/test-module -m mymodule.py -a "arg1=aaa arg2=bbb"
* including generated source, if any, saving to: /home/vagrant/.ansible_module_generated
* this may offset any line numbers in tracebacks/debuggers!
***********************************
RAW OUTPUT
{"changed": true, "args": "/home/vagrant/.ansible_test_module_arguments", "rc": 0}


***********************************
PARSED OUTPUT
{
    "args": "/home/vagrant/.ansible_test_module_arguments", 
    "changed": true, 
    "rc": 0
}
$ 

引数は、-aオプションで"key1=値 key2=値..."で指定します。

sys.argv[1]に引数が書かれたファイルパスがあり、このファイルから引数を読むようです。

$ cat /home/vagrant/.ansible_test_module_arguments 
arg1=aaa arg2=bbb$

ファイルに書かれた引数は、文字列処理として取り込みます。

shlexというのをインポートして引数ごとに分解して=splitしてキーと値を取り出す。 引数を処理するヘルパーのようなものがあったほうが便利そうですが、処理としてはわかりやすい。

$ cat mymodule.py
#! /usr/bin/python

import json
import sys
import shlex

args_file = sys.argv[1]
args_data = file(args_file).read()
args = shlex.split(args_data)
for arg in args:
    if "=" in arg:
        (key, value) = arg.split("=")

print json.dumps({
    "rc": 0,
    "changed": True,
    "args": args_file,
    "key": key,
    "value": value,
})
$ 

実行するとこんな感じ(エラー処理なし、引数複数あっても最後のものしか取りません。サンプルなので)

$ $ANSIBLE_HOME/hacking/test-module -m mymodule.py -a "arg1=aaa arg2=bbb"
* including generated source, if any, saving to: /home/vagrant/.ansible_module_generated
* this may offset any line numbers in tracebacks/debuggers!
***********************************
RAW OUTPUT
{"value": "bbb", "changed": true, "key": "arg2", "args": "/home/vagrant/.ansible_test_module_arguments", "rc": 0}


***********************************
PARSED OUTPUT
{
    "args": "/home/vagrant/.ansible_test_module_arguments",
    "changed": true,
    "key": "arg2",
    "rc": 0,
    "value": "bbb"
}
$ 

ansible_facts

モジュールからansible_factsに値を渡すことができると書いてあるので試してみます。

チュートリアルによると、モジュールの戻り値のjsonansible_factsを返すと、そのあとのモジュールからansible_factsとして参照できるようになります。

モジュール

こんな感じでtestvalueという変数を定義(=json戻り値に含める)します。

$ cat library/mymodule.py
#! /usr/bin/python

import json

print json.dumps({
    "rc": 0,
    "changed": True,
    "ansible_facts" : {
        "testvalue" : "mymodule.py value",
    }
})
$ python library/mymodule.py
{"changed": true, "ansible_facts": {"testvalue": "mymodule.py value"}, "rc": 0}
$ 

モジュールとして実行

モジュールを呼び出した後続の処理では、"{{testvalue}}``で設定した変数を参照することができます。

$ cat site.yml
---
- hosts: localhost
  tasks:
    - mymodule:
    - debug: msg="{{ testvalue }}"
$ ansible-playbook -i "localhost," site.yml

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [mymodule] ****************************************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "mymodule.py value"
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0

$