Sequence query fix (#83758)

Co-authored-by: flowerysong <junk+github@flowerysong.com>
pull/84322/head
James Ramsaran 1 week ago committed by GitHub
parent c734ac2125
commit e14f9fe725
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,2 @@
bugfixes:
- sequence lookup - sequence query/lookups without positional arguments now return a valid list if their kwargs comprise a valid sequence expression (https://github.com/ansible/ansible/issues/82921).

@ -171,6 +171,12 @@ class LookupModule(LookupBase):
setattr(self, f, self.get_option(f))
def sanity_check(self):
"""
Returns True if options comprise a valid sequence expression
Raises AnsibleError if options are an invalid expression
Returns false if options are valid but result in an empty sequence - these cases do not raise exceptions
in order to maintain historic behavior
"""
if self.count is None and self.end is None:
raise AnsibleError("must specify count or end in with_sequence")
elif self.count is not None and self.end is not None:
@ -180,17 +186,18 @@ class LookupModule(LookupBase):
if self.count != 0:
self.end = self.start + self.count * self.stride - 1
else:
self.start = 0
self.end = 0
self.stride = 0
del self.count
return False
if self.stride > 0 and self.end < self.start:
raise AnsibleError("to count backwards make stride negative")
if self.stride < 0 and self.end > self.start:
raise AnsibleError("to count forward don't make stride negative")
if self.stride == 0:
return False
if self.format.count('%') != 1:
raise AnsibleError("bad formatting string: %s" % self.format)
return True
def generate_sequence(self):
if self.stride >= 0:
adjust = 1
@ -210,6 +217,10 @@ class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):
results = []
if kwargs and not terms:
# All of the necessary arguments can be provided as keywords, but we still need something to loop over
terms = ['']
for term in terms:
try:
# set defaults/global
@ -223,10 +234,9 @@ class LookupModule(LookupBase):
raise AnsibleError("unknown error parsing with_sequence arguments: %r. Error was: %s" % (term, e))
self.set_fields()
self.sanity_check()
if self.stride != 0:
if self.sanity_check():
results.extend(self.generate_sequence())
except AnsibleError:
raise
except Exception as e:

@ -196,3 +196,32 @@
- ansible_failed_result.msg == expected
vars:
expected: "bad formatting string: d"
# Tests for lookup()/plugin() jinja invocation:
# Many of these tests check edge case behaviors that are only possible when invoking query/lookup sequence through jinja.
# While they aren't particularly intuitive, these tests ensure playbooks that could be relying on these behaviors don't
# break in future
- name: Test lookup with keyword args only
assert:
that:
- query("ansible.builtin.sequence", count=5, start=10) == ["10", "11", "12", "13", "14"]
- name: Test that multiple positional args produces concatenated sequence
assert:
that:
- query("ansible.builtin.sequence", "count=5 start=1", "count=3 start=10 stride=2") == ["1", "2", "3", "4", "5", "10", "12", "14"]
- name: Test that keyword arguments are applied to all positional expressions
assert:
that:
- query("ansible.builtin.sequence", "count=5 start=0", "count=5 start=20", stride=2) == ["0", "2", "4", "6", "8", "20", "22", "24", "26", "28"]
- name: Test that keyword arguments do not overwrite parameters present in positional expressions
assert:
that:
- query("ansible.builtin.sequence", "count=5 start=0", "count=5", start=20) == ["0", "1", "2", "3", "4", "20", "21", "22", "23", "24"]
- name: Test that call with no arguments produces an empty list
assert:
that:
- query("ansible.builtin.sequence") == []

Loading…
Cancel
Save