Add export host option for inventory-manage script
The export host option allows users to export their existing host information for import into a third party system. The output is 'pivoted', so that the key is the host/container name, and the values are the group memberships and hostvar information. Some top level networking information, such as load balancer IP addresses, as well as provider networks, are also provided. Test scaffolding was added to ensure the export does what is intended. The tox inventory environment was modified to do coverage testing of both the dynamic_inventory.py and manage_inventory.py files. The coverage data is erased between runs, since combined output lead to incorrect results for dynamic_inventory.py. Change-Id: I2caa5a0c070b12a74ac26334c63ac8d0de704042
This commit is contained in:
parent
8255414408
commit
18c9e1faee
@ -142,6 +142,19 @@ Use the host's name as an argument.
|
|||||||
|
|
||||||
.. _`dynamic inventory functionality`: http://docs.ansible.com/ansible/intro_dynamic_inventory.html
|
.. _`dynamic inventory functionality`: http://docs.ansible.com/ansible/intro_dynamic_inventory.html
|
||||||
|
|
||||||
|
Exporting Host Information
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Information on a per-host basis can be obtained with the ``--export/-e``
|
||||||
|
parameter.
|
||||||
|
|
||||||
|
This JSON output has two top-level keys: ``hosts`` and ``all``.
|
||||||
|
|
||||||
|
``hosts`` contains a map of a host's name to its variable and group data.
|
||||||
|
|
||||||
|
``all`` contains global network information such as the load balancer IPs and
|
||||||
|
provider network metadata.
|
||||||
|
|
||||||
The lxc_hosts Group
|
The lxc_hosts Group
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- An export flag has been added to the ``inventory-manage.py`` script. This
|
||||||
|
flag allows exporting of host and network information from an
|
||||||
|
OpenStack-Ansible inventory for import into another system, or an
|
||||||
|
alternate view of the existing data. See the developer docs for more details.
|
@ -143,6 +143,14 @@ def args():
|
|||||||
default=False
|
default=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
exclusive_action.add_argument(
|
||||||
|
'-e',
|
||||||
|
'--export',
|
||||||
|
help='Export group and variable information per host in JSON.',
|
||||||
|
action='store_true',
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
|
||||||
return vars(parser.parse_args())
|
return vars(parser.parse_args())
|
||||||
|
|
||||||
|
|
||||||
@ -296,6 +304,38 @@ def print_inventory(inventory, sort_key):
|
|||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def export_host_info(inventory):
|
||||||
|
"""Pivot variable information to be a per-host dict
|
||||||
|
|
||||||
|
This command is meant for exporting an existing inventory's information.
|
||||||
|
The exported data re-arranges variable data so that the keys are the host,
|
||||||
|
and the values are hostvars and groups.
|
||||||
|
|
||||||
|
Two top level keys are present: 'hosts' and 'all'. 'hosts' is a dictonary
|
||||||
|
of the host information. 'all' represents global data, mostly the load
|
||||||
|
balancer and provider network values. It is taken from
|
||||||
|
inventory['all']['vars'].
|
||||||
|
"""
|
||||||
|
export_info = {'hosts': {}}
|
||||||
|
host_info = export_info['hosts']
|
||||||
|
|
||||||
|
export_info['all'] = inventory['all']['vars']
|
||||||
|
|
||||||
|
for host, hostvars in inventory['_meta']['hostvars'].items():
|
||||||
|
host_info[host] = {}
|
||||||
|
host_info[host]['hostvars'] = hostvars
|
||||||
|
|
||||||
|
for group_name, group_info in inventory.items():
|
||||||
|
if group_name in ('_meta', 'all'):
|
||||||
|
continue
|
||||||
|
for host in group_info['hosts']:
|
||||||
|
if 'groups' not in host_info[host]:
|
||||||
|
host_info[host]['groups'] = []
|
||||||
|
host_info[host]['groups'].append(group_name)
|
||||||
|
|
||||||
|
return export_info
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Run the main application."""
|
"""Run the main application."""
|
||||||
# Parse user args
|
# Parse user args
|
||||||
@ -318,6 +358,8 @@ def main():
|
|||||||
# Containers in the first column, groups for each container on the right
|
# Containers in the first column, groups for each container on the right
|
||||||
elif user_args['list_containers'] is True:
|
elif user_args['list_containers'] is True:
|
||||||
print(print_containers_per_group(inventory))
|
print(print_containers_per_group(inventory))
|
||||||
|
elif user_args['export'] is True:
|
||||||
|
print(json.dumps(export_host_info(inventory), indent=2))
|
||||||
else:
|
else:
|
||||||
recursive_dict_removal(inventory, user_args['remove_item'])
|
recursive_dict_removal(inventory, user_args['remove_item'])
|
||||||
with open(environment_file, 'wb') as f_handle:
|
with open(environment_file, 'wb') as f_handle:
|
||||||
|
53
tests/test_manage.py
Normal file
53
tests/test_manage.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
from os import path
|
||||||
|
import sys
|
||||||
|
import test_inventory
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
MANAGE_DIR = path.join(os.getcwd(), 'scripts')
|
||||||
|
|
||||||
|
sys.path.append(MANAGE_DIR)
|
||||||
|
|
||||||
|
import manage_inventory as mi
|
||||||
|
|
||||||
|
|
||||||
|
class TestExportFunction(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.inv = test_inventory.get_inventory()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
test_inventory.cleanup()
|
||||||
|
|
||||||
|
def test_host_is_present(self):
|
||||||
|
host_inv = mi.export_host_info(self.inv)['hosts']
|
||||||
|
self.assertIn('aio1', host_inv.keys())
|
||||||
|
|
||||||
|
def test_groups_added(self):
|
||||||
|
host_inv = mi.export_host_info(self.inv)['hosts']
|
||||||
|
self.assertIn('groups', host_inv['aio1'].keys())
|
||||||
|
|
||||||
|
def test_variables_added(self):
|
||||||
|
host_inv = mi.export_host_info(self.inv)['hosts']
|
||||||
|
self.assertIn('hostvars', host_inv['aio1'].keys())
|
||||||
|
|
||||||
|
def test_number_of_hosts(self):
|
||||||
|
host_inv = mi.export_host_info(self.inv)['hosts']
|
||||||
|
|
||||||
|
self.assertEqual(len(self.inv['_meta']['hostvars']),
|
||||||
|
len(host_inv))
|
||||||
|
|
||||||
|
def test_all_information_added(self):
|
||||||
|
all_info = mi.export_host_info(self.inv)['all']
|
||||||
|
self.assertIn('provider_networks', all_info)
|
||||||
|
|
||||||
|
def test_all_lb_information(self):
|
||||||
|
all_info = mi.export_host_info(self.inv)['all']
|
||||||
|
inv_all = self.inv['all']['vars']
|
||||||
|
self.assertEqual(inv_all['internal_lb_vip_address'],
|
||||||
|
all_info['internal_lb_vip_address'])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
4
tox.ini
4
tox.ini
@ -140,7 +140,6 @@ commands =
|
|||||||
-e 'force_containers_destroy=yes' \
|
-e 'force_containers_destroy=yes' \
|
||||||
{toxinidir}/playbooks/setup-everything.yml
|
{toxinidir}/playbooks/setup-everything.yml
|
||||||
|
|
||||||
|
|
||||||
[testenv:inventory]
|
[testenv:inventory]
|
||||||
# Use a fixed seed since some inventory tests rely on specific ordering
|
# Use a fixed seed since some inventory tests rely on specific ordering
|
||||||
setenv =
|
setenv =
|
||||||
@ -150,6 +149,9 @@ commands =
|
|||||||
coverage erase
|
coverage erase
|
||||||
coverage run {toxinidir}/tests/test_inventory.py
|
coverage run {toxinidir}/tests/test_inventory.py
|
||||||
coverage report --show-missing --include={toxinidir}/playbooks/inventory/*
|
coverage report --show-missing --include={toxinidir}/playbooks/inventory/*
|
||||||
|
coverage erase
|
||||||
|
coverage run {toxinidir}/tests/test_manage.py
|
||||||
|
coverage report --show-missing --include={toxinidir}/scripts/*
|
||||||
|
|
||||||
|
|
||||||
[testenv:linters]
|
[testenv:linters]
|
||||||
|
Loading…
Reference in New Issue
Block a user