allow implicit host to be grouped (#26614)

* allow implicit host to be grouped

also optimized patternmatching

fixes #24156

* resolved a great crime
This commit is contained in:
Brian Coca 2017-07-11 15:51:39 -04:00 committed by GitHub
parent d173217833
commit 661b2c5beb

View file

@ -290,27 +290,20 @@ class InventoryManager(object):
self._inventory = InventoryData() self._inventory = InventoryData()
self.parse_sources(cache=False) self.parse_sources(cache=False)
def _match(self, string, pattern_str): def _match_list(self, items, pattern_str):
try: # compile patterns
if pattern_str.startswith('~'):
return re.search(pattern_str[1:], string)
else:
return fnmatch.fnmatch(string, pattern_str)
except Exception as e:
raise AnsibleError('invalid host pattern (%s): %s' % (pattern_str, str(e)))
def _match_list(self, items, item_attr, pattern_str):
results = []
try: try:
if not pattern_str.startswith('~'): if not pattern_str.startswith('~'):
pattern = re.compile(fnmatch.translate(pattern_str)) pattern = re.compile(fnmatch.translate(pattern_str))
else: else:
pattern = re.compile(pattern_str[1:]) pattern = re.compile(pattern_str[1:])
except Exception: except Exception:
raise AnsibleError('invalid host list pattern: %s' % pattern_str) raise AnsibleError('Invalid host list pattern: %s' % pattern_str)
# apply patterns
results = []
for item in items: for item in items:
if pattern.match(getattr(item, item_attr)): if pattern.match(item):
results.append(item) results.append(item)
return results return results
@ -383,12 +376,11 @@ class InventoryManager(object):
else: else:
that = self._match_one_pattern(p) that = self._match_one_pattern(p)
if p.startswith("!"): if p.startswith("!"):
hosts = [h for h in hosts if h not in that] hosts = [h for h in hosts if h not in frozenset(that)]
elif p.startswith("&"): elif p.startswith("&"):
hosts = [h for h in hosts if h in that] hosts = [h for h in hosts if h in frozenset(that)]
else: else:
to_append = [h for h in that if h.name not in [y.name for y in hosts]] hosts.extend([h for h in that if h.name not in frozenset([y.name for y in hosts])])
hosts.extend(to_append)
return hosts return hosts
def _match_one_pattern(self, pattern): def _match_one_pattern(self, pattern):
@ -513,33 +505,25 @@ class InventoryManager(object):
""" """
results = [] results = []
# check if pattern matches group
def __append_host_to_results(host): matching_groups = self._match_list(self._inventory.groups, pattern)
if host.name not in results: if matching_groups:
if not host.implicit: for groupname in matching_groups:
results.append(host) results.extend(self._inventory.groups[groupname].get_hosts())
matched = False
for group in self._inventory.groups.values():
if self._match(to_text(group.name), pattern):
matched = True
for host in group.get_hosts():
__append_host_to_results(host)
else: else:
matching_hosts = self._match_list(group.get_hosts(), 'name', pattern) # pattern might match host
matching_hosts = self._match_list(self._inventory.hosts, pattern)
if matching_hosts: if matching_hosts:
matched = True for hostname in matching_hosts:
for host in matching_hosts: results.append(self._inventory.hosts[hostname])
__append_host_to_results(host)
if not results and pattern in C.LOCALHOST: if not results and pattern in C.LOCALHOST:
# get_host autocreates implicit when needed # get_host autocreates implicit when needed
implicit = self._inventory.get_host(pattern) implicit = self._inventory.get_host(pattern)
if implicit: if implicit:
results.append(implicit) results.append(implicit)
matched = True
if not matched: if not results:
display.warning("Could not match supplied host pattern, ignoring: %s" % pattern) display.warning("Could not match supplied host pattern, ignoring: %s" % pattern)
return results return results