Ansible TowerのDynamic Inventoryを触ってみた

Ansible TowerでDynamic Inventoryを使ってインベントリーを作成した備忘録です。

# 1. Dynamic Inventoryについて

AnsibleのInventoryを動的に作成することができます。
詳細についてはGoogle先生に聞くと色々と情報が出てくるので、ここでは割愛します。

## 1-1. 公式 Ansible Dynamic Inventory

[http://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html](http://docs.ansible.com/ansible/latest/user_guide/intro_dynamic_inventory.html)

# 2. Dynamic Inventory動作確認

## 2-1. スクリプト

Dynamic Inventoryは、スクリプトを実行して情報を取得します。
ここでは動作確認用スクリプト(python)ととして以下のテンプレートを使用します。
※Dynamic Inventoryでは `--list` 引数さえ受け取ってJSONフォーマットで結果を出力できればいいのでシェルスクリプトでもPerlでも言語は問いません。

```python:dynamic_inventory.py
#!/usr/bin/python
from collections import defaultdict
import argparse
import json

def options():
    parser = argparse.ArgumentParser()
    parser.add_argument("--list", action="store_true")
    args = parser.parse_args()
    return args

def main():
    args = options()
    if(args.list):
        multi_dimension_dict = lambda: defaultdict(multi_dimension_dict)

        # インベントリー情報の処理を書いていく

if __name__ == "__main__":
    main()
```

## 2-2. Dynamic Inventoryスクリプト登録

Ansible TowerにDynamic Inventory用のスクリプトを登録する必要があります。

(1) `インベントリースクリプト` をクリックします。

![スクリーンショット 2018-05-29 23.45.11.png](https://qiita-image-store.s3.amazonaws.com/0/180118/ed16c92d-3805-22bb-f645-4e89c8516f26.png)

(2) `追加` をクリックします。

![スクリーンショット 2018-05-29 23.46.05.png](https://qiita-image-store.s3.amazonaws.com/0/180118/6c0d870e-9124-5028-9335-999cf556a153.png)

(3) 必要な項目を入力して `カスタムスクリプト` にスクリプトをコピペまたはドラッグ&ドロップして `保存` をクリックします。


![スクリーンショット 2018-05-29 23.47.02.png](https://qiita-image-store.s3.amazonaws.com/0/180118/6a59a8d6-e68c-a992-8254-8c714650a985.png)

`カスタムスクリプト` は以下のものを使用しました。

```python
#!/usr/bin/python
from collections import defaultdict
import argparse
import json

def options():
    parser = argparse.ArgumentParser()
    parser.add_argument("--list", action="store_true")
    args = parser.parse_args()
    return args

def main():
    args = options()
    if(args.list):
        multi_dimension_dict = lambda: defaultdict(multi_dimension_dict)

        inventory = multi_dimension_dict()
        inventory["group01"]["hosts"] = ["web01", "web02"]
        inventory["group01"]["vars"] = {"ansible_user": "root", "ansible_password": "secret"}
        print(json.dumps(inventory, indent=2))

if __name__ == "__main__":
    main()
```

スクリプト単体で実行すると以下のJSON形式になります。

```json
{
  "group01": {
    "hosts": [
      "web01",
      "web02"
    ],
    "vars": {
      "ansible_password": "secret",
      "ansible_user": "root"
    }
  }
}
```

|   項目  |              説明              |
|---------|--------------------------------|
| group01 | グループ名です。               |
| hosts   | 対象のホストをlistで登録します |
| vars    | `group01` のhostsに対してのvarsです   |


## 2-3. インベントリー

インベントリーを作成し `ソース(カスタムスクリプト)` を登録します。
ここでは既に作成した `TEST Inventory` に登録してみます。

(1) `ソース` をクリックします。

![スクリーンショット 2018-05-29 23.55.04.png](https://qiita-image-store.s3.amazonaws.com/0/180118/88388301-e2f5-c1e9-8097-938ebfb18f3f.png)

(2) `ソースの追加` をクリックします。

![スクリーンショット 2018-05-29 23.55.32.png](https://qiita-image-store.s3.amazonaws.com/0/180118/557fa349-5d4f-8dd2-cb10-0a5b01ad0578.png)

(3) `名前` を入力し `ソース` を `カスタムスクリプト` にして `カスタムインベントリースクリプト` に登録したスクリプトを選択し `保存` をクリックします。

![スクリーンショット 2018-05-29 23.56.32.png](https://qiita-image-store.s3.amazonaws.com/0/180118/c7479ea0-09a6-bc61-792d-78fe028d45ca.png)

## 2-4. カスタムスクリプトの実行

(1) 登録したソースの `同期プロセスの開始` をクリックします。

![スクリーンショット 2018-05-29 23.59.01.png](https://qiita-image-store.s3.amazonaws.com/0/180118/605b3f56-9378-d9ee-9839-b41fa553592d.png)

問題なく完了した場合、以下のようにホストおよびvarsが登録されていることを確認できます。

![スクリーンショット 2018-05-30 0.02.32.png](https://qiita-image-store.s3.amazonaws.com/0/180118/e6af9e62-afc1-1996-34a6-0b4cb46ffa3b.png)

![スクリーンショット 2018-05-30 0.02.38.png](https://qiita-image-store.s3.amazonaws.com/0/180118/ad48544e-7a0f-328c-f42f-48c7bf2336ca.png)

## 2-5. ホスト別でvarsを設定する場合

その場合は `_meta` を使えばホスト別で設定が可能です。
以下のスクリプトでは `web01` に `test` と言う変数に `var` という値を設定しています。

**スクリプト例**

```python
#!/usr/bin/python
from collections import defaultdict
import argparse
import json

def options():
    parser = argparse.ArgumentParser()
    parser.add_argument("--list", action="store_true")
    args = parser.parse_args()
    return args

def main():
    args = options()
    if(args.list):
        multi_dimension_dict = lambda: defaultdict(multi_dimension_dict)

        inventory = multi_dimension_dict()
        inventory["group01"]["hosts"] = ["web01", "web02"]
        inventory["group01"]["vars"] = {"ansible_user": "root", "ansible_password": "secret"}

        inventory["_meta"]["hostvars"] = {"web01": {"test": "var"}}
        print(json.dumps(inventory, indent=2))

if __name__ == "__main__":
    main()
```

# 3. 最後に

Dynamic Inventoryを使うことで動的にインベントリーの作成ができることが確認できました。
オンプレとかの場合だと、CMDBとかと連携すれば自動でホストのグループを作ったり変数設定できたりと便利そうです。
うまく使えれば、インベントリの作成自動化も効率化できますね :-)

# 参考

https://qiita.com/t_nakayama0714/items/91c2d711a397df68dddc