From e2f147bcec8d5e44f2aa4f73d86f9959e6eb8f2e Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Mon, 13 Feb 2023 12:07:10 -0500 Subject: [PATCH] ansible-inventory, add --limit option (#79596) * ansible-inventory, add --limit option * also graph * optimize the when not providing limit * added tests and clog * avoid empty groups, fix tests * i swear there as an ignore_errors there already!!?!?!? * Fix stdout test fallback Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> * simpler approach using subset against inventory directly * tyupose * renamed funciton to what it actuall does got yaml in line with others about removing empty groups * have graph ignore limts, also note same for --host * fixed typo long line * better test * cause hosvars are not a thing --------- Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com> Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> --- changelogs/fragments/ainv_limit.yml | 2 + lib/ansible/cli/inventory.py | 52 +++++++++++-------- .../targets/ansible-inventory/tasks/main.yml | 22 ++++++++ 3 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 changelogs/fragments/ainv_limit.yml diff --git a/changelogs/fragments/ainv_limit.yml b/changelogs/fragments/ainv_limit.yml new file mode 100644 index 00000000000..feb27fcfaf1 --- /dev/null +++ b/changelogs/fragments/ainv_limit.yml @@ -0,0 +1,2 @@ +minor_changes: + - ansible-inventory now supports the limit command line options. diff --git a/lib/ansible/cli/inventory.py b/lib/ansible/cli/inventory.py index e8ed75e4636..b8154a6d8a4 100755 --- a/lib/ansible/cli/inventory.py +++ b/lib/ansible/cli/inventory.py @@ -72,7 +72,6 @@ class InventoryCLI(CLI): opt_help.add_runtask_options(self.parser) # remove unused default options - self.parser.add_argument('-l', '--limit', help=argparse.SUPPRESS, action=opt_help.UnrecognizedArgument, nargs='?') self.parser.add_argument('--list-hosts', help=argparse.SUPPRESS, action=opt_help.UnrecognizedArgument) self.parser.add_argument('args', metavar='host|group', nargs='?') @@ -80,9 +79,10 @@ class InventoryCLI(CLI): # Actions action_group = self.parser.add_argument_group("Actions", "One of following must be used on invocation, ONLY ONE!") action_group.add_argument("--list", action="store_true", default=False, dest='list', help='Output all hosts info, works as inventory script') - action_group.add_argument("--host", action="store", default=None, dest='host', help='Output specific host info, works as inventory script') + action_group.add_argument("--host", action="store", default=None, dest='host', + help='Output specific host info, works as inventory script. It will ignore limit') action_group.add_argument("--graph", action="store_true", default=False, dest='graph', - help='create inventory graph, if supplying pattern it must be a valid group name') + help='create inventory graph, if supplying pattern it must be a valid group name. It will ignore limit') self.parser.add_argument_group(action_group) # graph @@ -144,17 +144,22 @@ class InventoryCLI(CLI): # FIXME: should we template first? results = self.dump(myvars) - elif context.CLIARGS['graph']: - results = self.inventory_graph() - elif context.CLIARGS['list']: - top = self._get_group('all') - if context.CLIARGS['yaml']: - results = self.yaml_inventory(top) - elif context.CLIARGS['toml']: - results = self.toml_inventory(top) - else: - results = self.json_inventory(top) - results = self.dump(results) + else: + if context.CLIARGS['subset']: + # not doing single host, set limit in general if given + self.inventory.subset(context.CLIARGS['subset']) + + if context.CLIARGS['graph']: + results = self.inventory_graph() + elif context.CLIARGS['list']: + top = self._get_group('all') + if context.CLIARGS['yaml']: + results = self.yaml_inventory(top) + elif context.CLIARGS['toml']: + results = self.toml_inventory(top) + else: + results = self.json_inventory(top) + results = self.dump(results) if results: outfile = context.CLIARGS['output_file'] @@ -249,7 +254,7 @@ class InventoryCLI(CLI): return dump @staticmethod - def _remove_empty(dump): + def _remove_empty_keys(dump): # remove empty keys for x in ('hosts', 'vars', 'children'): if x in dump and not dump[x]: @@ -302,7 +307,7 @@ class InventoryCLI(CLI): results = {} results[group.name] = {} if group.name != 'all': - results[group.name]['hosts'] = [h.name for h in group.hosts] + results[group.name]['hosts'] = [h.name for h in self.inventory.get_hosts(group.name)] results[group.name]['children'] = [] for subgroup in group.child_groups: results[group.name]['children'].append(subgroup.name) @@ -312,7 +317,8 @@ class InventoryCLI(CLI): if context.CLIARGS['export']: results[group.name]['vars'] = self._get_group_variables(group) - self._remove_empty(results[group.name]) + self._remove_empty_keys(results[group.name]) + # remove empty groups if not results[group.name]: del results[group.name] @@ -349,7 +355,7 @@ class InventoryCLI(CLI): # hosts for group results[group.name]['hosts'] = {} if group.name != 'all': - for h in group.hosts: + for h in self.inventory.get_hosts(group.name): myvars = {} if h.name not in seen: # avoid defining host vars more than once seen.append(h.name) @@ -361,7 +367,10 @@ class InventoryCLI(CLI): if gvars: results[group.name]['vars'] = gvars - self._remove_empty(results[group.name]) + self._remove_empty_keys(results[group.name]) + # remove empty groups + if not results[group.name]: + del results[group.name] return results @@ -384,7 +393,7 @@ class InventoryCLI(CLI): results.update(format_group(subgroup)) if group.name != 'all': - for host in group.hosts: + for host in self.inventory.get_hosts(group.name): if host.name not in seen: seen.add(host.name) host_vars = self._get_host_variables(host=host) @@ -398,7 +407,8 @@ class InventoryCLI(CLI): if context.CLIARGS['export']: results[group.name]['vars'] = self._get_group_variables(group) - self._remove_empty(results[group.name]) + self._remove_empty_keys(results[group.name]) + # remove empty groups if not results[group.name]: del results[group.name] diff --git a/test/integration/targets/ansible-inventory/tasks/main.yml b/test/integration/targets/ansible-inventory/tasks/main.yml index 84ac2c3cf5b..9dabc48d647 100644 --- a/test/integration/targets/ansible-inventory/tasks/main.yml +++ b/test/integration/targets/ansible-inventory/tasks/main.yml @@ -145,3 +145,25 @@ loop_control: loop_var: toml_package when: toml_package is not contains 'tomllib' or (toml_package is contains 'tomllib' and ansible_facts.python.version_info >= [3, 11]) + +- name: check baseline + command: ansible-inventory -i '{{ role_path }}/files/valid_sample.yml' --list + register: limited + +- name: ensure empty host list + assert: + that: + - "'something' in inv['_meta']['hostvars']" + vars: + inv: '{{ limited.stdout|from_json}}' + +- name: check that limit removes host + command: ansible-inventory -i '{{ role_path }}/files/valid_sample.yml' --limit '!something' --list + register: limited + +- name: ensure empty host list + assert: + that: + - "'something' not in inv['_meta']['hostvars']" + vars: + inv: '{{ limited.stdout|from_json}}'