From d68e65bfdd34ee162e9c16acb25cb652b189496a Mon Sep 17 00:00:00 2001 From: Nolan Brubaker Date: Wed, 10 Aug 2016 21:14:34 -0400 Subject: [PATCH] Add an inventory config check option Previously there was no way to do a 'dry run' against a set of inventory configuration files without actually writing the full inventory structure to disk. This change adds a simple check flag to the script, allowing users to pre-validate their configurations prior to executing the Ansible playbooks. No syntax validation happens against the YAML files; rather, the dynamic_inventory.py script is executed and builds a full inventory in memory, but does not write any output. Currently, this is meant as a starting point. Further validation can build from here, but the flag is largely meant to check for known exceptions/errors early. Change-Id: Ic58566ee124c824c8bba549ade46bce5c268905a --- doc/source/developer-docs/inventory.rst | 11 +++++++++++ playbooks/inventory/dynamic_inventory.py | 10 ++++++++++ ...config_check_argument-5a1126c779e3e8f5.yaml | 7 +++++++ tests/test_inventory.py | 18 +++++++++++++++++- 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/config_check_argument-5a1126c779e3e8f5.yaml diff --git a/doc/source/developer-docs/inventory.rst b/doc/source/developer-docs/inventory.rst index a1dd261c5d..a41f1bc57b 100644 --- a/doc/source/developer-docs/inventory.rst +++ b/doc/source/developer-docs/inventory.rst @@ -101,6 +101,17 @@ The same JSON structure is printed to stdout, which is consumed by Ansible as the inventory for the playbooks. +Checking Inventory Configuration for Errors +------------------------------------------- + +Using the ``--check`` flag when running ``dynamic_inventory.py`` will run the +inventory build process and look for known errors, but not write any files to +disk. + +This check does not do YAML syntax validation, though it will fail if there +are unparseable errors. + + Inspecting and Managing the Inventory ------------------------------------- diff --git a/playbooks/inventory/dynamic_inventory.py b/playbooks/inventory/dynamic_inventory.py index 2fba5736cf..c889983abb 100755 --- a/playbooks/inventory/dynamic_inventory.py +++ b/playbooks/inventory/dynamic_inventory.py @@ -133,6 +133,12 @@ def args(arg_list): action='store_true' ) + parser.add_argument( + '--check', + help="Configuration check only, don't generate inventory", + action='store_true', + ) + return vars(parser.parse_args(arg_list)) @@ -1138,6 +1144,10 @@ def main(all_args): sort_keys=True ) + check = all_args.get('check') + if check: + return 'Configuration ok!' + # Generate a list of all hosts and their used IP addresses hostnames_ips = {} for _host, _vars in dynamic_inventory['_meta']['hostvars'].iteritems(): diff --git a/releasenotes/notes/config_check_argument-5a1126c779e3e8f5.yaml b/releasenotes/notes/config_check_argument-5a1126c779e3e8f5.yaml new file mode 100644 index 0000000000..0790240ff5 --- /dev/null +++ b/releasenotes/notes/config_check_argument-5a1126c779e3e8f5.yaml @@ -0,0 +1,7 @@ +--- +features: + - The `dynamic_inventory.py` file now takes a new argument, ``--check``, + which will run the inventory build without writing any files to the file + system. This is useful for checking to make sure your configuration does + not contain known errors prior to running Ansible commands. + diff --git a/tests/test_inventory.py b/tests/test_inventory.py index a9b0d56abc..34d28fd138 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -737,7 +737,6 @@ class TestMultipleRuns(unittest.TestCase): inventory_file_path = os.path.join(TARGET_DIR, 'openstack_inventory.json') - inv = di.get_inventory(TARGET_DIR, inventory_file_path) self.assertIsInstance(inv, dict) self.assertIn('_meta', inv) @@ -1001,5 +1000,22 @@ class TestSetUsedIPS(unittest.TestCase): di.USED_IPS = set() +class TestConfigCheckFunctional(TestConfigCheckBase): + def duplicate_ip(self): + ip = self.user_defined_config['log_hosts']['aio1'] + self.user_defined_config['log_hosts']['bogus'] = ip + + def test_checking_good_config(self): + output = di.main({'config': TARGET_DIR, 'check': True}) + self.assertEqual(output, 'Configuration ok!') + + def test_duplicated_ip(self): + self.duplicate_ip() + self.write_config() + with self.assertRaises(di.MultipleHostsWithOneIPError) as context: + di.main({'config': TARGET_DIR, 'check': True}) + self.assertEqual(context.exception.ip, '172.29.236.100') + + if __name__ == '__main__': unittest.main()