mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add YAML inventory format.
See test/yaml_hosts for an example. Hosts can be part of multiple groups. Groups can also have variables, inherited by the hosts. There is no variable scope, last variable seen wins.
This commit is contained in:
parent
54f4526160
commit
3a24aa9a70
3 changed files with 172 additions and 0 deletions
|
@ -97,6 +97,8 @@ class Inventory(object):
|
|||
results = []
|
||||
groups = dict(ungrouped=[])
|
||||
lines = file(self.inventory_file).read().split("\n")
|
||||
if "---" in lines:
|
||||
return self._parse_yaml()
|
||||
group_name = 'ungrouped'
|
||||
for item in lines:
|
||||
item = item.lstrip().rstrip()
|
||||
|
@ -154,6 +156,76 @@ class Inventory(object):
|
|||
|
||||
# *****************************************************
|
||||
|
||||
def _parse_yaml(self):
|
||||
""" Load the inventory from a yaml file.
|
||||
|
||||
returns hosts and groups"""
|
||||
data = utils.parse_yaml_from_file(self.inventory_file)
|
||||
|
||||
if type(data) != list:
|
||||
raise errors.AnsibleError("YAML inventory should be a list.")
|
||||
|
||||
hosts = []
|
||||
groups = {}
|
||||
|
||||
for item in data:
|
||||
if type(item) == dict:
|
||||
if "group" in item:
|
||||
group_name = item["group"]
|
||||
|
||||
group_vars = []
|
||||
if "vars" in item:
|
||||
group_vars = item["vars"]
|
||||
|
||||
group_hosts = []
|
||||
if "hosts" in item:
|
||||
for host in item["hosts"]:
|
||||
host_name = self._parse_yaml_host(host, group_vars)
|
||||
group_hosts.append(host_name)
|
||||
|
||||
groups[group_name] = group_hosts
|
||||
hosts.extend(group_hosts)
|
||||
|
||||
# or a host
|
||||
elif "host" in item:
|
||||
host_name = self._parse_yaml_host(item)
|
||||
hosts.append(host_name)
|
||||
else:
|
||||
host_name = self._parse_yaml_host(item)
|
||||
hosts.append(host_name)
|
||||
|
||||
# filter duplicate hosts
|
||||
output_hosts = []
|
||||
for host in hosts:
|
||||
if host not in output_hosts:
|
||||
output_hosts.append(host)
|
||||
|
||||
return output_hosts, groups
|
||||
|
||||
def _parse_yaml_host(self, item, variables=[]):
|
||||
def set_variables(host, variables):
|
||||
for variable in variables:
|
||||
if len(variable) != 1:
|
||||
raise AnsibleError("Only one item expected in %s"%(variable))
|
||||
k, v = variable.items()[0]
|
||||
self._set_variable(host, k, v)
|
||||
|
||||
if type(item) in [str, unicode]:
|
||||
set_variables(item, variables)
|
||||
return item
|
||||
elif type(item) == dict:
|
||||
if "host" in item:
|
||||
host_name = item["host"]
|
||||
set_variables(host_name, variables)
|
||||
|
||||
if "vars" in item:
|
||||
set_variables(host_name, item["vars"])
|
||||
|
||||
return host_name
|
||||
else:
|
||||
raise AnsibleError("Unknown item in inventory: %s"%(item))
|
||||
|
||||
|
||||
def _get_variables_from_script(self, host, extra_vars=None):
|
||||
''' support per system variabes from external variable scripts, see web docs '''
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class TestInventory(unittest.TestCase):
|
|||
|
||||
self.inventory_file = os.path.join(self.test_dir, 'simple_hosts')
|
||||
self.inventory_script = os.path.join(self.test_dir, 'inventory_api.py')
|
||||
self.inventory_yaml = os.path.join(self.test_dir, 'yaml_hosts')
|
||||
|
||||
os.chmod(self.inventory_script, 0755)
|
||||
|
||||
|
@ -26,6 +27,9 @@ class TestInventory(unittest.TestCase):
|
|||
def script_inventory(self):
|
||||
return Inventory( self.inventory_script )
|
||||
|
||||
def yaml_inventory(self):
|
||||
return Inventory( self.inventory_yaml )
|
||||
|
||||
def test_simple(self):
|
||||
inventory = self.simple_inventory()
|
||||
hosts = inventory.list_hosts()
|
||||
|
@ -149,6 +153,76 @@ class TestInventory(unittest.TestCase):
|
|||
|
||||
assert vars == {"hammer":True, "simple": "yes"}
|
||||
|
||||
### Tests for yaml inventory file
|
||||
|
||||
def test_yaml(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts()
|
||||
print hosts
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_all(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts('all')
|
||||
|
||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_norse(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts("norse")
|
||||
|
||||
expected_hosts=['thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_combined(self):
|
||||
inventory = self.yaml_inventory()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_restrict(self):
|
||||
inventory = self.yaml_inventory()
|
||||
|
||||
restricted_hosts = ['hera', 'poseidon', 'thor']
|
||||
expected_hosts=['zeus', 'hera', 'poseidon', 'thor', 'odin', 'loki']
|
||||
|
||||
inventory.restrict_to(restricted_hosts)
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == restricted_hosts
|
||||
|
||||
inventory.lift_restriction()
|
||||
hosts = inventory.list_hosts("norse:greek")
|
||||
|
||||
assert hosts == expected_hosts
|
||||
|
||||
def test_yaml_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('thor')
|
||||
|
||||
assert vars == {"hammer":True}
|
||||
|
||||
def test_yaml_host_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('saturn')
|
||||
|
||||
assert vars == {"moon":"titan"}
|
||||
|
||||
def test_yaml_extra_vars(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('thor', 'a=5')
|
||||
|
||||
assert vars == {"hammer":True}
|
||||
|
||||
def test_yaml_port(self):
|
||||
inventory = self.yaml_inventory()
|
||||
vars = inventory.get_variables('hera')
|
||||
|
||||
assert vars == {'ansible_ssh_port': 3000}
|
||||
|
||||
### Test Runner class method
|
||||
|
||||
def test_class_method(self):
|
||||
|
|
26
test/yaml_hosts
Normal file
26
test/yaml_hosts
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
|
||||
- jupiter
|
||||
- host: saturn
|
||||
vars:
|
||||
- moon: titan
|
||||
|
||||
- group: greek
|
||||
hosts:
|
||||
- zeus
|
||||
- hera
|
||||
- poseidon
|
||||
vars:
|
||||
- ansible_ssh_port: 3000
|
||||
|
||||
- group: norse
|
||||
hosts:
|
||||
- host: thor
|
||||
vars:
|
||||
- hammer: True
|
||||
- odin
|
||||
- loki
|
||||
|
||||
- group: multiple
|
||||
hosts:
|
||||
- saturn
|
Loading…
Reference in a new issue