できる限りやるべきではないと釘を刺されているけども、独自のモジュールを開発したいことはある。
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がないとエラーになる。理由はよくわからない。