mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Use ',' instead of ':' or ';' to separate host patterns
The earlier-recommended "pat1:pat2:pat3[x:y]" notation doesn't work well with IPv6 addresses, so we recommend ',' as a separator instead. We know that commas can't occur within a pattern, so we can just split on it. We still have to accept the "foo:bar" notation because it's so commonly used, but we issue a deprecation warning for it. Fixes #12296 Closes #12404 Closes #12329
This commit is contained in:
parent
3db8070aa3
commit
2405861a9e
1 changed files with 54 additions and 26 deletions
|
@ -149,23 +149,6 @@ class Inventory(object):
|
||||||
results.append(item)
|
results.append(item)
|
||||||
return results
|
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", ignore_limits_and_restrictions=False):
|
def get_hosts(self, pattern="all", ignore_limits_and_restrictions=False):
|
||||||
"""
|
"""
|
||||||
Takes a pattern or list of patterns and returns a list of matching
|
Takes a pattern or list of patterns and returns a list of matching
|
||||||
|
@ -173,14 +156,6 @@ class Inventory(object):
|
||||||
or applied subsets
|
or applied subsets
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Enumerate all hosts matching the given pattern (which may be
|
|
||||||
# either a list of patterns or a string like 'pat1:pat2').
|
|
||||||
if isinstance(pattern, list):
|
|
||||||
pattern = ':'.join(pattern)
|
|
||||||
|
|
||||||
if ';' in pattern or ',' in pattern:
|
|
||||||
display.deprecated("Use ':' instead of ',' or ';' to separate host patterns", version=2.0, removed=True)
|
|
||||||
|
|
||||||
patterns = self._split_pattern(pattern)
|
patterns = self._split_pattern(pattern)
|
||||||
hosts = self._evaluate_patterns(patterns)
|
hosts = self._evaluate_patterns(patterns)
|
||||||
|
|
||||||
|
@ -197,6 +172,59 @@ class Inventory(object):
|
||||||
|
|
||||||
return hosts
|
return hosts
|
||||||
|
|
||||||
|
def _split_pattern(self, pattern):
|
||||||
|
"""
|
||||||
|
Takes a string containing host patterns separated by commas (or a list
|
||||||
|
thereof) and returns a list of single patterns (which may not contain
|
||||||
|
commas). Whitespace is ignored.
|
||||||
|
|
||||||
|
Also accepts ':' as a separator for backwards compatibility, but it is
|
||||||
|
not recommended due to the conflict with IPv6 addresses and host ranges.
|
||||||
|
|
||||||
|
Example: 'a,b[1], c[2:3] , d' -> ['a', 'b[1]', 'c[2:3]', 'd']
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(pattern, list):
|
||||||
|
pattern = ','.join(pattern)
|
||||||
|
|
||||||
|
patterns = []
|
||||||
|
|
||||||
|
if ';' in pattern:
|
||||||
|
display.deprecated("Use ',' instead of ':' or ';' to separate host patterns", version=2.0, removed=True)
|
||||||
|
|
||||||
|
# If it's got commas in it, we'll treat it as a straightforward
|
||||||
|
# comma-separated list of patterns.
|
||||||
|
|
||||||
|
elif ',' in pattern:
|
||||||
|
patterns = re.split('\s*,\s*', pattern)
|
||||||
|
|
||||||
|
# If it doesn't, it could still be a single pattern. This accounts for
|
||||||
|
# non-separator uses of colons: IPv6 addresses and [x:y] host ranges.
|
||||||
|
|
||||||
|
else:
|
||||||
|
(base, port) = parse_address(pattern, allow_ranges=True)
|
||||||
|
if base:
|
||||||
|
patterns = [pattern]
|
||||||
|
|
||||||
|
# The only other case we accept is a ':'-separated list of patterns.
|
||||||
|
# This mishandles IPv6 addresses, and is retained only for backwards
|
||||||
|
# compatibility.
|
||||||
|
|
||||||
|
else:
|
||||||
|
patterns = re.findall(
|
||||||
|
r'''(?: # We want to match something comprising:
|
||||||
|
[^\s:\[\]] # (anything other than whitespace or ':[]'
|
||||||
|
| # ...or...
|
||||||
|
\[[^\]]*\] # a single complete bracketed expression)
|
||||||
|
)+ # occurring once or more
|
||||||
|
''', pattern, re.X
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(patterns) > 1:
|
||||||
|
display.deprecated("Use ',' instead of ':' or ';' to separate host patterns", version=2.0)
|
||||||
|
|
||||||
|
return [p.strip() for p in patterns]
|
||||||
|
|
||||||
def _evaluate_patterns(self, patterns):
|
def _evaluate_patterns(self, patterns):
|
||||||
"""
|
"""
|
||||||
Takes a list of patterns and returns a list of matching host names,
|
Takes a list of patterns and returns a list of matching host names,
|
||||||
|
@ -249,7 +277,7 @@ class Inventory(object):
|
||||||
The pattern may be:
|
The pattern may be:
|
||||||
|
|
||||||
1. A regex starting with ~, e.g. '~[abc]*'
|
1. A regex starting with ~, e.g. '~[abc]*'
|
||||||
2. A shell glob pattern with ?/*/[chars]/[!chars], e.g. 'foo'
|
2. A shell glob pattern with ?/*/[chars]/[!chars], e.g. 'foo*'
|
||||||
3. An ordinary word that matches itself only, e.g. 'foo'
|
3. An ordinary word that matches itself only, e.g. 'foo'
|
||||||
|
|
||||||
The pattern is matched using the following rules:
|
The pattern is matched using the following rules:
|
||||||
|
|
Loading…
Reference in a new issue