Tambourine作業メモ

主にスキル習得のためにやった作業のメモ。他人には基本的に無用のものです。

Ansibleで遊んでみる(4)

できる限りやるべきではないと釘を刺されているけども、独自のモジュールを開発したいことはある。

Moleculeによるロール単位の開発をしている場合、そのロールで自分で実装したモジュールが欲しい場合どうすればいいのか実験する。

ロール直下にlibraryというディレクトリを作ると、そこにあるファイルをモジュールだと判断してくれるらしい。試してみよう。

Moleculeでロールを作成する。

> mol init role mymdl
INFO     Initializing new role mymdl...
No config file found; using defaults
- Role mymdl was created successfully
INFO     Initialized role in /Users/tambara/study/ansible_study/roles/mymdl successfully.

libraryディレクトリを作り、以下の様なPythonスクリプトを置く。

library/mymdl.py

#!/usr/bin/env python

from ansible.module_utils.basic import AnsibleModule

def run_module():
    module_args = dict(
        name=dict(type='str', required=True),
        new=dict(type='bool', required=False, default=False)
    )

    result = dict(
        changed=False,
        original_message='',
        message=''
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    if module.check_mode:
        module.exit_json(**result)

    result['original_message'] = module.params['name']
    result['message'] = 'goodbye'

    if module.params['new']:
        result['changed'] = True
    
    if module.params['name'] == 'fail me':
        module.fail_json(msg='You requested this to fail', **result)
    
    module.exit_json(**result)

def main():
    run_module()

if __name__ == '__main__':
    main()

AnsibleModule.check_modeはDRY RUNさせるとtrueになるもの。

これを

---
- name: test my module
  mymdl:
    name: hello
    new: true
  register: hoge
  ignore_errors: true
- name: debug
  debug:
    msg: "{{ hoge }}"

のように定義して実行してみる。

> mol converge
(略)

PLAY [Converge] ****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [inst]

TASK [Include mymdl] ***********************************************************

TASK [mymdl : test my module] **************************************************
changed: [inst]

TASK [mymdl : debug] ***********************************************************
ok: [inst] => {
    "msg": {
        "changed": true,
        "failed": false,
        "message": "goodbye",
        "original_message": "hello"
    }
}

PLAY RECAP *********************************************************************
inst                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ちゃんと動いている。

さて、このモジュールのテストをどうするか。

テストはlibraryの下に以下の様に置く

  • library/
    • mymdl.py
    • tests/
      • __init__.py
      • test_mymdl.py

この構成で、libraryディレクトリでpytestを実行すれば良い。

test_mymdl.pyでmymdlをimportするには

import mymdl

で、OK。ただし、__init__.pyがないとエラーになる。理由はよくわからない。