1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
- name: test with_sequence
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=0 end=3
- name: test with_sequence backwards
set_fact: "{{ 'y' + item }}={{ item }}"
with_sequence: start=3 end=0 stride=-1
- name: verify with_sequence
assert:
that:
- "x0 == '0'"
- "x1 == '1'"
- "x2 == '2'"
- "x3 == '3'"
- "y3 == '3'"
- "y2 == '2'"
- "y1 == '1'"
- "y0 == '0'"
- name: test with_sequence not failing on count == 0
debug: msg='previously failed with backward counting error'
with_sequence: count=0
register: count_of_zero
- name: test with_sequence does 1 when start == end
debug: msg='should run once'
with_sequence: start=1 end=1
register: start_equal_end
- name: test with_sequence count 1
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: count=1
register: count_of_one
- assert:
that:
- start_equal_end is not skipped
- count_of_zero is skipped
- count_of_one is not skipped
- name: test with_sequence shortcut syntax (end)
set_fact: "{{ 'ws_z_' + item }}={{ item }}"
with_sequence: '4'
- name: test with_sequence shortcut syntax (start-end/stride)
set_fact: "{{ 'ws_z_' + item }}=stride_{{ item }}"
with_sequence: '2-6/2'
- name: test with_sequence shortcut syntax (start-end:format)
set_fact: "{{ 'ws_z_' + item }}={{ item }}"
with_sequence: '7-8:host%02d'
- name: verify with_sequence shortcut syntax
assert:
that:
- "ws_z_1 == '1'"
- "ws_z_2 == 'stride_2'"
- "ws_z_3 == '3'"
- "ws_z_4 == 'stride_4'"
- "ws_z_6 == 'stride_6'"
- "ws_z_host07 == 'host07'"
- "ws_z_host08 == 'host08'"
- block:
- name: EXPECTED FAILURE - test invalid arg
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=0 junk=3
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test invalid arg"
- ansible_failed_result.msg in [expected1, expected2]
vars:
expected1: "unrecognized arguments to with_sequence: ['junk']"
expected2: "unrecognized arguments to with_sequence: [u'junk']"
- block:
- name: EXPECTED FAILURE - test bad kv value
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=A end=3
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test bad kv value"
- ansible_failed_result.msg.startswith("Invalid type for")
- block:
- name: EXPECTED FAILURE - test bad simple form start value
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: A-4/2
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test bad simple form start value"
- ansible_failed_result.msg.startswith("Invalid type for")
- block:
- name: EXPECTED FAILURE - test bad simple form end value
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: 1-B/2
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test bad simple form end value"
- ansible_failed_result.msg.startswith("Invalid type for")
- block:
- name: EXPECTED FAILURE - test bad simple form stride value
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: 1-4/C
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test bad simple form stride value"
- ansible_failed_result.msg.startswith("Invalid type for")
- block:
- name: EXPECTED FAILURE - test no count or end
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=1
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test no count or end"
- ansible_failed_result.msg == "must specify count or end in with_sequence"
- block:
- name: EXPECTED FAILURE - test both count and end
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=1 end=4 count=2
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test both count and end"
- ansible_failed_result.msg == "can't specify both count and end in with_sequence"
- block:
- name: EXPECTED FAILURE - test count backwards message
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=4 end=1 stride=2
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test count backwards message"
- ansible_failed_result.msg == "to count backwards make stride negative"
- block:
- name: EXPECTED FAILURE - test count forward message
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=1 end=4 stride=-2
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test count forward message"
- ansible_failed_result.msg == "to count forward don't make stride negative"
- block:
- name: EXPECTED FAILURE - test bad format string message
set_fact: "{{ 'x' + item }}={{ item }}"
with_sequence: start=1 end=4 format=d
- fail:
msg: "should not get here"
rescue:
- assert:
that:
- ansible_failed_task.name == "EXPECTED FAILURE - test bad format string message"
- 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") == []
|