概要
AWS向けのAnsible自作モジュールを公式のAWSモジュールに見習って作り方を学びたいと思います
ちなみに公式のAWSモジュールのソースコードはこちらで確認できます
自作したモジュールの置き場はplaybookと同じディレクトリ内にlibraryディレクトリに配置すれば自動的に読み込まれます
それ以外は環境変数ANSIBLE_LIBRARY
、コマンドパラメータ--module-path
、ansible.cfgのlibrary
で指定することができます
playbook.yml
library/
|-----my_lib_hoge.yml
|-----my_lib_fuga.yml
さっそくコード
以下ではアプリケーションロードバランサーの情報を取得するコードになります
細かい説明はコード内のコメントを参照ください
#!/usr/bin/env python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
module: qiita sample module
short_description: describe elb v2 by elb name
description:
- Gather facts about EC2 Elastic Load Balancers V2 in AWS
version_added: "2.4"
author:
- "comefigo"
options:
names:
description:
- List of ELB V2 names
required: True
default: null
'''
# Ansibleモジュールのおまじない
from ansible.module_utils.basic import AnsibleModule
# awsとのやりとりに便利な機能を提供してくれるutility
from ansible.module_utils.ec2 import (
boto3_conn,
boto_exception,
ec2_argument_spec,
get_aws_connection_info,
snake_dict_to_camel_dict,
camel_dict_to_snake_dict
)
def main():
# aws_access_key, aws_secret_key, ec2_url などのパラメータ定義が取得できる
fields = ec2_argument_spec()
# 取得したパラメータにnamesというパラメータ定義を追加します(dict型)
fields.update(dict(
names={'required': True, 'type': 'list'}
))
# このモジュールで必要なパラメータを引数にmoduleを生成
module = AnsibleModule(argument_spec=fields)
result = {}
try:
# aws接続用に必要なパラメータを取得
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
# 上記で取得した値でboto3クライアントを生成
elbv2 = boto3_conn(module, conn_type='client', resource='elbv2', region=region, endpoint=ec2_url, **aws_connect_kwargs)
############################################################
# boto3のクライアントを取得できたのであとは好きなように実装してください
#
# describe ELB Application Load Balancer
ret = elbv2.describe_load_balancers(Names=module.params['names'])
# 結果を追加
# キャメルケースからスネークケースに変換
result.update(camel_dict_to_snake_dict(ret))
except Exception as err:
import traceback
error_msg = boto_exception(err)
# 異常時はmodule.fail_jsonに戻り値を出力
module.fail_json(msg=error_msg, exception=traceback.format_exc())
# 正常時はmodule.exit_jsonに戻り値を出力
module.exit_json(**result)
if __name__ == '__main__':
main()
使い方
ファイル名がそのままモジュール名になります
- my_describe_elbv2:
aws_access_key: xxxxxxxxxx
aws_secret_key: xxxxxxxxxx
ec2_url: yyyyyyy
names:
- my-elb1
- my-elb2
ポイント
module_utils.ec2で提供されているAWS接続用の各種機能を使うことで簡単に実装できます
boto3のクライアントが生成された後はboto3に従って実装できますので、好き勝手に作れます
ec2_argument_spec
AWS関連のモジュールで必要なaws_access_key
、aws_secret_key
、security_token
、ec2_url
、profile
、validate_certs
、 のモジュール用のパラメータ定義が取得できるregion
boto3_conn
boto3のコネクションオブジェクトが取得できる
snake_dict_to_camel_dict、camel_dict_to_snake_dict
AWSからのJSONレスポンスのキー値はキャメルケースになっているため、pythonのコード規約に合わせてスネークケースに変換する時にcamel_dict_to_snake_dict
を使用します
また、その逆の時はsnake_dict_to_camel_dict
を使用します
required_if(サンプルコードでは未使用)
特定の条件下でパラメータを必須とする時はrequired_ifで指定します
例) stateがpresentの時にarg1とarg2を必須とする
module = AnsibleModule(argument_spec=fields,
required_if=[('state', 'present', ['arg1', 'arg2'])])
required_together(サンプルコードでは未使用)
特定のパラメータを使用する時に関連するパラメータを必須指定しなければならない時にrequired_togetherを指定します
例) arg1とarg2とarg3はセットで指定しなければならない
module = AnsibleModule(argument_spec=fields,
required_together=[['arg1', 'arg2', 'arg3']])
リトライを実装しましょう!
上記のコードにはないですが、リトライ処理は必ず実装しましょう!
理由としては、AWSのみならず共通して言えるのがAPIをコールしてなにかする系のモジュールでは、コール先がコール制限(1秒間にコールできる数)やネットワークの品質によるエラーになることが割とあります。そのたびに処理が中断されるのもつらいので、冪等性を担保しつつリトライ処理を実装しましょう!(※リトライ処理した分だけリソースが追加されないように)
いかがでしょうか
かなり簡単に実装できたのではないでしょうか?
Enjoy Asinble!!