Ansibleのモジュールを開発してみよう

この記事は、「赤帽エンジニア Advent Calendar 2018」16日目の記事です。

こんにちは、Ansibleのテクニカルサポートエンジニアをしている、八木澤(@hiyoko_taisa)です。 Ansibleを使う上で「こんなモジュールがあったらいいのに」「このモジュールにこんな機能があればいいのに」と思うことはありませんか?

Ansibleでは、Pythonの知識があればモジュールを自作することも可能です。 ここでは、そのやり方について下記の公式ドキュメントをベースに解説します。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules.html

注: 自作モジュールの作成方法およびトラブルシュートはRed Hat Ansible Engineのサポート対象外となりますので、ご注意ください

モジュールを作る前に

1. 似たようなモジュールが存在しないか?

「モジュールを作ろう!」と意気込む前に、まず同様のモジュールが存在していないか確認しましょう。 公式ドキュメントにはAnsibleで利用可能なモジュールのリストがあります。下記を検索し、同じようなモジュールがないか見てみましょう。 https://docs.ansible.com/ansible/2.7/modules/list_of_all_modules.html#all-modules

2. Pull Requestが存在しないか?

現時点でモジュールに希望する機能がない場合でも、既にPull Requestとして機能拡張が予定されている場合があります。 下記を確認して、似たような機能を実現するPRが存在するか確認してみましょう。

もし似たようなPRが存在すれば、テストしてみてPRへのフィードバックを送ることも可能です。 これにより、そのPRがマージされるまでの期間が短くなる可能性があります。

3. Action Pluginで実現できないか?

モジュールの開発ではなく、プラグインにより望む機能が実現できる可能性があります。 プラグインの開発については、下記ページを確認してみてください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_plugins.html#developing-plugins

4. Roleで実現できないか?

既存のモジュールを組み合わせたRoleを使うことで、要望する機能が実現できる可能性があります。 Roleについては、下記ドキュメントを確認してください。 https://docs.ansible.com/ansible/2.7/user_guide/playbooks_reuse_roles.html#playbooks-reuse-roles

5. 単一のモジュールではなく、複数のモジュールを作ったほうがいいか?

複数の機能を持つ巨大なモジュールよりも、単一の機能をもつシンプルなモジュールを複数作ったほうがよい場合があります。 UNIX哲学に基づいて、一つのことをうまくやれるモジュールが望ましいです。

上記すべてにおいて、現在のAnsibleの機能では実現できない場合は、新しいモジュールを作ることを検討しましょう。

モジュールを作成する

こちらを確認しながら、新しいモジュールを作成していきます。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules_general.html#starting-a-new-module

モジュールのフォーマットについては、下記を確認してください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules_documenting.html#module-format-and-documentation

Python shebang

すべてのAnsibleモジュールはかならず #!/usr/bin/python から始まっている必要があります。

CopyrightとLicense

shebangのあとに、下記のようにCopyrightとLicenseのコメントを記載します。

#!/usr/bin/python

# Copyright: (c) 2018, Terry Jones <terry.jones@example.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

ANSIBLE_MATADATA block

shebangとcopyrightのセクションの後に、 ANSIBLE_METADATA を定義する必要があります。 下記のように metadata_version, status, supported_by を定義しましょう。

ANSIBLE_METADATA = {'metadata_version': '1.1',
                    'status': ['preview'],
                    'supported_by': 'community'}

上記で定義するフィールドの詳細については、下記を確認してください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules_documenting.html#ansible-metadata-fields

DOCUMENTATION block

Ansibleの公式ドキュメントに存在するModuleページのドキュメントは、この DOCUMENTATIONブロックから生成されます。 DOCUMENTATIONブロックはYAMLで定義されている必要があります。 ここで定義すべき内容については、下記を参照してください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules_documenting.html#documentation-fields

EXAMPLES block

DOCUMENTATIONブロックに続けて、Moduleの書式を説明するEXAMPLESブロックを定義する必要があります。 下記のように、実際のPlaybookでの使用例を記載します。

EXAMPLES = '''
- name: Ensure foo is installed
  modulename:
    name: foo
    state: present
'''

RETURN block

Moduleが返却する値の一覧を定義します。 下記を確認して、返却する値を定義してください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_modules_documenting.html#return-block

python imports

最後に、python importを記載します。 すべてのモジュールは、下記をimportする必要があります。

from module_utils.basic import AnsibleModule

下記のようなワイルドカードを使ったimportは許可されていないので注意してください。

from module_utils.basic import *

モジュールを作り込む

あとは自分が実現したい機能に応じて、Pythonで作り込んでいけばモジュールは作ることが出来ます。 GitHub上に存在する他のモジュールを参考にしながら進めるのがよいと思います。

その他

モジュールのPython3対応については、下記を確認してください。 https://docs.ansible.com/ansible/2.7/dev_guide/developing_python_3.html

最後に

Ansibleには数え切れないほどのモジュールが存在し、日々コミュニティによって開発が続けられています。 新規モジュールを作るだけではなく、既存モジュールへのPRやバグ報告などのコントリビュートは、今後のAnsibleの発展に必要不可欠です。 皆様もぜひ、一度気になるモジュールの中身を眺めてみて、どうやってモジュールが動いているのか調べてみるのもいいと思います。

モジュールをもっと深く知って、Happy Automation!

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。