0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ansible 自作モジュール作成 ~その3:Change要否を判定したい人生~

Posted at

前回の記事1:Ansible 自作モジュール作成 ~その1:引数受け取りたい人生~
前回の記事2:Ansible 自作モジュール作成 ~その2:ただコマンドを実行したい人生~

振り返り

  • モジュールの雛形作った(その1)
  • 複数の引数受け取れた(その1)
  • 引数をコマンドと結合して実行した(その2)

参考

初期処理

おさらいもかねて。まずは雛形を作成(参考「前回の記事1」参照)。
テスト的に作成したコマンド実行部分(参考「前回の記事2」参照)は一度取り除いた。

mkfifo.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

# メイン処理
#-----------------------------------------------------------
def main():
    # AnsibleModuleクラス: moduleを作成
    module = AnsibleModule(

        # 引数受け取り
        argument_spec=dict(

            # 引数: data(str型,def:pong)
            data=dict(type='str', default='pong'),
        ),
        # 引数チェックを有効
        supports_check_mode=True
    )

    # 結果dict: resultを作成
    result = dict(
        # key: ping に引数で与えられたkey: data のvalueを格納
        ping=module.params['data'],
    )

    # resultの中身を key=value,の形で出力
    module.exit_json(**result)

if __name__ == '__main__':
    main()

これに変数の受け取り部分を実装。

mkfifo.py
: #(省略)
    # AnsibleModuleクラス: moduleを作成
    module = AnsibleModule(

        # 引数受け取り
        argument_spec=dict(

            # 引数: path(必須,str型)
            path=dict(required=True,type='str'),
            # 引数: owner(str型,デフォルト=root)
            owner=dict(type='str',default='root'),
            # 引数: group(str型,デフォルト=root)
            group=dict(type='str',default='root'),
            # 引数: mode(str型,デフォルト=0644)
            mode=dict(type='str',default='0644'),
        ),
        # 引数チェックを有効
        supports_check_mode=True
    )
: #(省略)

現時点ではOS版数やディストリビューションによる分岐は設けない。changed変数を設けるだけ…だけど、changedってどこに定義するんだ?AnsibleModuleクラスの外側で良いのかな?ちょっとお試しする。

sakrua.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

# メイン処理
#-----------------------------------------------------------
def main():
    # AnsibleModuleクラス: moduleを作成
    module = AnsibleModule(
        {}
    )

    changed = False  この値をTrueに変えたりする

    module.exit_json(changed=changed)

if __name__ == '__main__':
    main()
# changed = Trueの場合
$ ansible -i test_grp 192.168.56.104 -m sakura -M library -u root
192.168.56.104 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true
}

# changed = Falseの場合
$ ansible -i test_grp 192.168.56.104 -m sakura -M library -u root
192.168.56.104 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

よしよし。AnsibleModuleクラスの外側に定義するわけだ。

Changedを判定してみる

changedTrueになる条件は以下

  1. pathで与えられた名前付きパイプが存在しない
  2. pathで与えられた名前付きパイプのower:group:modeが引数どおりではない

条件1. に関してはtest -p xxxxxReturnCodeで判断できる。
条件2. に関してはstat -c %U:%G:%aの標準出力で判断できる。

ただしstat -c %aの結果は下3桁しか出ないのでstat -c 0%aで対処する。
またstdoutは改行コードまで出力されるため比較時に\nを差し込んだ。

mkfifo.py
: #(省略)
    # 変更有無を初期化(変更なし)
    changed = False

    # testコマンドでpathに名前付きパイプが存在するか確認
    rc, stdout, stderr = module.run_command("test -p " + module.params['path'])
    # 確認結果
    if ( rc != 0 ):
        # 存在しないので変更対象
        changed = True
    else:
        # 存在する場合はowner:group:modeを取得
        rc, stdout, stderr = module.run_command("stat -c %U:%G:0%a " + module.params['path'])
        # 比較。コマンド結果は最後に改行コード \n が付くことに注意
        if ( stdout != module.params['owner'] + ':' + module.params['group'] + ':' + module.params['mode'] + '\n'):
            # owner:group:modeが異なるので変更対象
            changed = True

    # 終了
    module.exit_json(changed=changed,stdout=stdout,stderr=stderr)
: #(省略)

いったんここまでで動かしてみようかな。

$ ansible -i test_grp 192.168.56.104 -m mkfifo -M library -u root -a "path=/tmp/testfifo owner=root group=root mode=0777"
192.168.56.104 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "stderr": "",
    "stderr_lines": [],
    "stdout": "",
    "stdout_lines": []
}

試しに対象サーバ上に/tmp/testfifoを作ってみる。

# /tmp/testfifo root:root:0644 で作ってみる
$ ssh root@192.168.56.104 "mkfifo /tmp/testfifo; chmod 0644 /tmp/testfifo"
$ ssh root@192.168.56.104 "ls -l /tmp/testfifo"
prw-r--r--. 1 root root 0  6月  1 01:30 2020 /tmp/testfifo
$ ansible -i test_grp 192.168.56.104 -m mkfifo -M library -u root -a "path=/tmp/testfifo owner=root group=root mode=0777"
192.168.56.104 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "stderr": "",
    "stderr_lines": [],
    "stdout": "root:root:0644\n",
    "stdout_lines": [
        "root:root:0644"
    ]
}

# /tmp/testfifo root:root:0777 にしてみる
$ ssh root@192.168.56.104 "chmod 0777 /tmp/testfifo"
$ ssh root@192.168.56.104 "ls -l /tmp/testfifo"
prwxrwxrwx. 1 root root 0  6月  1 01:30 2020 /tmp/testfifo
$ ansible -i test_grp 192.168.56.104 -m mkfifo -M library -u root -a "path=/tmp/testfifo owner=root group=root mode=0777"
192.168.56.104 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "stderr": "",
    "stderr_lines": [],
    "stdout": "root:root:0777\n",
    "stdout_lines": [
        "root:root:0777"
    ]
}

おけ。本項はここまで。次はコマンド投入編。。は内容うすくなりそうだな。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?