diff --git a/changelogs/fragments/empty_host_pattern.yml b/changelogs/fragments/empty_host_pattern.yml new file mode 100644 index 00000000000..9727ac75065 --- /dev/null +++ b/changelogs/fragments/empty_host_pattern.yml @@ -0,0 +1,2 @@ +bugfixes: + - return empty list if host pattern is empty https://github.com/ansible/ansible/pull/37931 diff --git a/lib/ansible/inventory/manager.py b/lib/ansible/inventory/manager.py index db21af6f059..070e01170b6 100644 --- a/lib/ansible/inventory/manager.py +++ b/lib/ansible/inventory/manager.py @@ -330,49 +330,52 @@ class InventoryManager(object): or applied subsets """ + hosts = [] + # Check if pattern already computed if isinstance(pattern, list): pattern_hash = u":".join(pattern) else: pattern_hash = pattern - if not ignore_limits and self._subset: - pattern_hash += ":%s" % to_native(self._subset) + if pattern_hash: + if not ignore_limits and self._subset: + pattern_hash += u":%s" % to_text(self._subset, errors='surrogate_or_strict') - if not ignore_restrictions and self._restriction: - pattern_hash += ":%s" % to_native(self._restriction) + if not ignore_restrictions and self._restriction: + pattern_hash += u":%s" % to_text(self._restriction, errors='surrogate_or_strict') - if pattern_hash not in self._hosts_patterns_cache: + if pattern_hash not in self._hosts_patterns_cache: - patterns = split_host_pattern(pattern) - hosts = self._evaluate_patterns(patterns) + patterns = split_host_pattern(pattern) + hosts = self._evaluate_patterns(patterns) - # mainly useful for hostvars[host] access - if not ignore_limits and self._subset: - # exclude hosts not in a subset, if defined - subset = self._evaluate_patterns(self._subset) - hosts = [h for h in hosts if h in subset] + # mainly useful for hostvars[host] access + if not ignore_limits and self._subset: + # exclude hosts not in a subset, if defined + subset = self._evaluate_patterns(self._subset) + hosts = [h for h in hosts if h in subset] - if not ignore_restrictions and self._restriction: - # exclude hosts mentioned in any restriction (ex: failed hosts) - hosts = [h for h in hosts if h.name in self._restriction] - - seen = set() - self._hosts_patterns_cache[pattern_hash] = [x for x in hosts if x not in seen and not seen.add(x)] - - # sort hosts list if needed (should only happen when called from strategy) - if order in ['sorted', 'reverse_sorted']: - from operator import attrgetter - hosts = sorted(self._hosts_patterns_cache[pattern_hash][:], key=attrgetter('name'), reverse=(order == 'reverse_sorted')) - elif order == 'reverse_inventory': - hosts = sorted(self._hosts_patterns_cache[pattern_hash][:], reverse=True) - else: - hosts = self._hosts_patterns_cache[pattern_hash][:] - if order == 'shuffle': - from random import shuffle - shuffle(hosts) - elif order not in [None, 'inventory']: - AnsibleOptionsError("Invalid 'order' specified for inventory hosts: %s" % order) + if not ignore_restrictions and self._restriction: + # exclude hosts mentioned in any restriction (ex: failed hosts) + hosts = [h for h in hosts if h.name in self._restriction] + + seen = set() + self._hosts_patterns_cache[pattern_hash] = [x for x in hosts if x not in seen and not seen.add(x)] + + # sort hosts list if needed (should only happen when called from strategy) + if order in ['sorted', 'reverse_sorted']: + from operator import attrgetter + hosts = sorted(self._hosts_patterns_cache[pattern_hash][:], key=attrgetter('name'), reverse=(order == 'reverse_sorted')) + elif order == 'reverse_inventory': + hosts = sorted(self._hosts_patterns_cache[pattern_hash][:], reverse=True) + else: + hosts = self._hosts_patterns_cache[pattern_hash][:] + if order == 'shuffle': + from random import shuffle + shuffle(hosts) + elif order not in [None, 'inventory']: + AnsibleOptionsError("Invalid 'order' specified for inventory hosts: %s" % order) return hosts