Ansible Automation PlatformにDynamic Inventoryが表示されない件


最近Ansibleの資格試験を準備していて、Ansible Automation Platform（以下AAPとする）には、レポジトリにある`.py`のDynamic Inventoryはなかなか表示されないことがありました。この記事ではDynamic Inventory Fileを表示させた方法を書きます。



## 環境定義と問題再現 （解決方法は一番最後に）

まずはテストするために、以下のファイルを定義しました。

### 環境定義

#### inventory

```text
[lb]
servera.lab.example.com

[web]
serverb.lab.example.com
serverc.lab.example.com
```
#### ansible.cfg

```text
[defaults]
inventory=inventory
```

#### hello_world.yml
```yaml
- name: Hello World Sample
  hosts: all
  gather_facts: no
  tasks:
    - name: Hello Message
      debug:
        msg: "Hello World!"

```

#### dynamic_inventory.py

:::note info
#! のパスは各自Python3に指定する必要があると思います
:::


```py
#!/bin python3
import json

def get_inventory():
    inventory = {
        'lb': {
            'hosts': ['servera.lab.example.com']
        },
        'web': {
            'hosts': ['serverb.lab.example.com', 'serverc.lab.example.com']
        },
        '_meta': {
            'hostvars': {}
        }
    }
    return inventory

def main():
    import sys
    if len(sys.argv) == 2 and (sys.argv[1] == '--list' or sys.argv[1] == '--host'):
        if sys.argv[1] == '--list':
            print(json.dumps(get_inventory()))
        elif sys.argv[1] == '--host':
            print(json.dumps({}))
    else:
        print("Usage: %s --list | --host <hostname>" % sys.argv[0])
        sys.exit(1)

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

#### 一部コマンドの実行結果

<details><summary>tree and ll</summary>


```bash
# tree
.
├── ansible.cfg
├── dynamic_inventory.py
├── hello_world.yml
└── inventory

# ll
total 16
-rw-rw-r--. 1 student student   31 May 26 02:39 ansible.cfg
-rw-rw-r--. 1 student student  735 May 26 02:49 dynamic_inventory.py
-rw-rw-r--. 1 student student  135 May 26 02:39 hello_world.yml
-rw-rw-r--. 1 student student   85 May 26 02:43 inventory

# ansible-playbook hello_world.yml
PLAY [Hello World Sample] *************************************************************

TASK [Hello Message] ******************************************************************
ok: [servera.lab.example.com] => {
    "msg": "Hello World!"
}
ok: [serverb.lab.example.com] => {
    "msg": "Hello World!"
}
ok: [serverc.lab.example.com] => {
    "msg": "Hello World!"
}

PLAY RECAP ****************************************************************************
servera.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverc.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


# ansible-playbook -i dynamic_inventory.py hello_world.yml


[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with script plugin: problem running
/home/student/git-repos/advanced-inventory/dynamic_inventory.py --list ([Errno 13] Permission denied: '/home/student/git-repos/advanced-inventory/dynamic_inventory.py')
[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with ini plugin: /home/student/git-
repos/advanced-inventory/dynamic_inventory.py:2: Expected key=value host variable assignment, got: json
[WARNING]: Unable to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Hello World Sample] *************************************************************

skipping: no hosts matched

PLAY RECAP ****************************************************************************

```
</details>

<details><summary>ansible-playbook hello_world.yml</summary>


```bash
$ ansible-playbook hello_world.yml
PLAY [Hello World Sample] *************************************************************

TASK [Hello Message] ******************************************************************
ok: [servera.lab.example.com] => {
    "msg": "Hello World!"
}
ok: [serverb.lab.example.com] => {
    "msg": "Hello World!"
}
ok: [serverc.lab.example.com] => {
    "msg": "Hello World!"
}

PLAY RECAP ****************************************************************************
servera.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverc.lab.example.com      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


# ansible-playbook -i dynamic_inventory.py hello_world.yml


[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with script plugin: problem running
/home/student/git-repos/advanced-inventory/dynamic_inventory.py --list ([Errno 13] Permission denied: '/home/student/git-repos/advanced-inventory/dynamic_inventory.py')
[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with ini plugin: /home/student/git-
repos/advanced-inventory/dynamic_inventory.py:2: Expected key=value host variable assignment, got: json
[WARNING]: Unable to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Hello World Sample] *************************************************************

skipping: no hosts matched

PLAY RECAP ****************************************************************************

```
</details>


<details><summary>ansible-playbook -i dynamic_inventory.py hello_world.yml</summary>


```bash

$ ansible-playbook -i dynamic_inventory.py hello_world.yml

[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with script plugin: problem running
/home/student/git-repos/advanced-inventory/dynamic_inventory.py --list ([Errno 13] Permission denied: '/home/student/git-repos/advanced-inventory/dynamic_inventory.py')
[WARNING]: * Failed to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py with ini plugin: /home/student/git-
repos/advanced-inventory/dynamic_inventory.py:2: Expected key=value host variable assignment, got: json
[WARNING]: Unable to parse /home/student/git-repos/advanced-inventory/dynamic_inventory.py as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Hello World Sample] *************************************************************

skipping: no hosts matched

PLAY RECAP ****************************************************************************

```
</details>

### 再現

この状態でAAPにおいて、Inventoryを作成して、Sourceを`Sourced from a Project`に指定しても、`Inventory file`には作成していた`dynamic_inventory.py`は表示されることがなく、`inventory`しかなかったです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457921/776cdebc-015a-c71f-445e-208b55ca8f38.png)

もちろん手動で入力してもエラーになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457921/6023c93d-73a1-fd24-3bb9-69971e5c673d.png)


## 解決方法

dynamic inventoryは実行可能なファイルでないといけないことが分かり、以下のコマンドを実行すれば無事に反映されました。

```bash
chmod +x dynamic_inventory.py

# ProjectにPushして、AAP ProjectでSyncを行います。
git add dynamic_inventory.py
git commit -m "add x to dynamic inventory"
git push
```

## 最後に

Ansible Dynamic Inventoryの知識は以前から頭に入っていましたが、実践経験が少なかったため、実際の問題に出会った際、Ansible Documentを調べていても、操作していてもpyファイルを認識されていなく、慌てていました。実際一度手で触って見れば、二度と忘れることのない解決方法でした。やはり、知識の吸収よりは、実践経験を積むのですね。