From 8aaa06dd5084dc753495677040c3c2d5b01e8c3e Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Thu, 13 Aug 2015 16:32:11 +0530 Subject: [PATCH] Introduce _split_pattern to parse an "x:y:z" pattern This function takes a string like 'foo:bar[1:2]:baz[x:y]-quux' and returns a list of patterns ['foo', 'bar[1:2]', 'baz[x:y]-quux'], i.e. splits the string on colons that are not part of a range specification. --- lib/ansible/inventory/__init__.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/ansible/inventory/__init__.py b/lib/ansible/inventory/__init__.py index 8d82ac8f05..11739f3358 100644 --- a/lib/ansible/inventory/__init__.py +++ b/lib/ansible/inventory/__init__.py @@ -155,6 +155,23 @@ class Inventory(object): results.append(item) return results + def _split_pattern(self, pattern): + """ + takes e.g. "webservers[0:5]:dbservers:others" + and returns ["webservers[0:5]", "dbservers", "others"] + """ + + term = re.compile( + r'''(?: # We want to match something comprising: + [^:\[\]] # (anything other than ':', '[', or ']' + | # ...or... + \[[^\]]*\] # a single complete bracketed expression) + )* # repeated as many times as possible + ''', re.X + ) + + return [x for x in term.findall(pattern) if x] + def get_hosts(self, pattern="all"): """ find all host names matching a pattern string, taking into account any inventory restrictions or @@ -164,7 +181,7 @@ class Inventory(object): # process patterns if isinstance(pattern, list): pattern = ';'.join(pattern) - patterns = pattern.replace(";",":").split(":") + patterns = self._split_pattern(pattern.replace(";",":")) hosts = self._get_hosts(patterns) # exclude hosts not in a subset, if defined @@ -504,10 +521,10 @@ class Inventory(object): self._subset = None else: subset_pattern = subset_pattern.replace(',',':') - subset_pattern = subset_pattern.replace(";",":").split(":") + subset_patterns = self._split_pattern(subset_pattern.replace(";",":")) results = [] # allow Unix style @filename data - for x in subset_pattern: + for x in subset_patterns: if x.startswith("@"): fd = open(x[1:]) results.extend(fd.read().split("\n"))