web-dev-qa-db-ja.com

Ansibleインベントリファイルからホストのリストを取得するにはどうすればよいですか?

Ansible Python APIを使用して、特定のインベントリファイル/グループの組み合わせからホストのリストを取得する方法はありますか?

たとえば、インベントリファイルはサービスタイプごとに分割されます。

[dev:children]
dev_a
dev_b

[dev_a]
my.Host.int.abc.com

[dev_b]
my.Host.int.xyz.com


[prod:children]
prod_a
prod_b

[prod_a]
my.Host.abc.com

[prod_b]
my.Host.xyz.com

使ってもいいですか ansible.inventory何らかの方法で特定のインベントリファイルと、処理対象のグループを渡し、一致するホストのリストを返すようにしますか?

13
MrDuk

私もしばらくこれに苦労していましたが、試行錯誤を通して解決策を見つけました。

APIの主な利点の1つは、ホスト名だけでなく変数とメタデータをプルできることです。

Python API-Ansible Documentation から開始:

#!/usr/bin/env python
#  Ansible: initialize needed objects
variable_manager = VariableManager()
loader = DataLoader()

#  Ansible: Load inventory
inventory = Inventory(
    loader = loader,
    variable_manager = variable_manager,
    Host_list = 'hosts', # Substitute your filename here
)

これにより、グループとホストを提供するメソッドとプロパティを持つInventoryインスタンスが提供されます。

さらに拡張する(およびグループクラスとホストクラスの例を提供する)ために、インベントリをグループのリストとしてシリアル化するスニペットを次に示します。各グループには、各ホストの属性のリストである「hosts」属性があります。

#/usr/bin/env python
def serialize(inventory):
    if not isinstance(inventory, Inventory):
        return dict()

    data = list()
    for group in inventory.get_groups():
        if group != 'all':
            group_data = inventory.get_group(group).serialize()

            #  Seed Host data for group
            Host_data = list()
            for Host in inventory.get_group(group).hosts:
                Host_data.append(Host.serialize())

            group_data['hosts'] = Host_data
            data.append(group_data)

    return data

#  Continuing from above
serialized_inventory = serialize(inventory)

私はこれを4つのF5 BIG-IPのラボに対して実行しました。これが結果です(トリミング):

<!-- language: lang-json -->
[{'depth': 1,
  'hosts': [{'address': u'bigip-ve-03',
             'name': u'bigip-ve-03',
             'uuid': UUID('b5e2180b-964f-41d9-9f5a-08a0d7dd133c'),
             'vars': {u'hostname': u'bigip-ve-03.local',
                      u'ip': u'10.128.1.130'}}],
  'name': 'ungrouped',
  'vars': {}},
 {'depth': 1,
  'hosts': [{'address': u'bigip-ve-01',
             'name': u'bigip-ve-01',
             'uuid': UUID('3d7daa57-9d98-4fa6-afe1-5f1e03db4107'),
             'vars': {u'hostname': u'bigip-ve-01.local',
                      u'ip': u'10.128.1.128'}},
            {'address': u'bigip-ve-02',
             'name': u'bigip-ve-02',
             'uuid': UUID('72f35cd8-6f9b-4c11-b4e0-5dc5ece30007'),
             'vars': {u'hostname': u'bigip-ve-02.local',
                      u'ip': u'10.128.1.129'}},
            {'address': u'bigip-ve-04',
             'name': u'bigip-ve-04',
             'uuid': UUID('255526d0-087e-44ae-85b1-4ce9192e03c1'),
             'vars': {}}],
  'name': u'bigip',
  'vars': {u'password': u'admin', u'username': u'admin'}}]
7
Theo

前と同じトリックを行いますが、allの代わりに、リストするグループ名を渡します。

ansible (group name here) -i (inventory file here) --list-hosts

14
nitzmahone

私のために働いた

_from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager

if __name__ == '__main__':
    inventory_file_name = 'my.inventory'
    data_loader = DataLoader()
    inventory = InventoryManager(loader = data_loader,
                             sources=[inventory_file_name])

    print(inventory.get_groups_dict()['spark-workers'])
_

inventory.get_groups_dict()は、コードに示されているようにキーとしてgroup_nameを使用してホストを取得するために使用できる辞書を返します。次のように、pipで実行できるansibleパッケージをインストールする必要があります

_pip install ansible
_
3
smishra

承認された回答以降、Ansible APIに変更が加えられました。

これは、Ansible 2.8(およびそれ以上)で動作します

ほとんどのデータにアクセスできた方法は次のとおりです。

from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager


loader = DataLoader()
# Sources can be a single path or comma separated paths
inventory = InventoryManager(loader=loader, sources='path/to/file')

# My use case was to have all:vars as the 1st level keys, and have groups as key: list pairs.
# I also don't have anything ungrouped, so there might be a slightly better solution to this.
# Your use case may be different, so you can customize this to how you need it.
x = {}
ignore = ('all', 'ungrouped')
x.update(inventory.groups['all'].serialize()['vars'])
group_dict = inventory.get_groups_dict()

for group in inventory.groups:
    if group in ignore:
        continue
    x.update({
        group: group_dict[group]
    })

例:

入力:

[all:vars]
x=hello
y=world

[group_1]
youtube
google

[group_2]
stack
overflow

出力:

{"x":"hello","y":"world","group_1":["youtube","google"],"group_2":["stack","overflow"]}

繰り返しになりますが、ユースケースは私のユースケースとは異なる場合があるため、コードを希望どおりにわずかに変更する必要があります。

1
NinjaKitty