Skip to content

Commit e5b3610

Browse files
danpawlikevallesp
authored andcommitted
Add parse ansible argument string to variables
In some playbook, when nested Ansible is executed via shell/command module, there is a string which contains arguments to parse by the ansible-playbook binary. If nested Ansible can be removed, it would be required to parse such variables. This helper task can help to parse properly variables, that later can be read properly by tasks without using nested Ansible execution. Signed-off-by: Daniel Pawlik <[email protected]>
1 parent 9906dc1 commit e5b3610

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

roles/cifmw_helpers/README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,117 @@ execute tasks on new host.
209209
name: cifmw_helpers
210210
tasks_from: inventory_file.yml
211211
```
212+
213+
#### Parse string of arguments and convert to list of variables or list of files
214+
215+
In some playbook, when nested Ansible is executed via shell/command module,
216+
there is a string which contains arguments to parse by the ansible-playbook
217+
binary. If nested Ansible can be removed, it would be required to parse
218+
such variables. Below example how nested Ansible execution looks like,
219+
and how it could be replaced.
220+
221+
NOTE: `test.yaml` is executed on `host-1`.
222+
223+
Example:
224+
- all files are on same host which execute ansible-playbook
225+
226+
```yaml
227+
- name: Nested Ansible execution
228+
hosts: localhost
229+
tasks:
230+
- name: Run ansible-playbook
231+
vars:
232+
cmd_args: "[email protected] -e @/tmp/someotherfile.yml -e myvar=test"
233+
ansible.builtin.command: |
234+
ansible-playbook "{{ cmd_args }}" test.yaml
235+
```
236+
237+
To:
238+
239+
```yaml
240+
- name: Playbook that does not use nested Ansible - same host
241+
hosts: localhost
242+
vars:
243+
cifmw_cmd_args: "[email protected] -e @/tmp/someotherfile.yml -e myvar=test"
244+
tasks:
245+
# NOTE: The task returns fact: cifmw_cmd_args_vars and cifmw_cmd_args_files
246+
- name: Read inventory file and add it using add_host module
247+
ansible.builtin.include_role:
248+
name: cifmw_helpers
249+
tasks_from: parse_ansible_args_string.yml
250+
251+
- name: Parse only variables from cifmw_cmd_args_vars
252+
when: cifmw_cmd_args_vars is defined and cifmw_cmd_args_vars | length > 0
253+
vars:
254+
various_vars: "{{ cifmw_cmd_args_vars }}"
255+
ansible.builtin.include_role:
256+
name: cifmw_helpers
257+
tasks_from: various_vars.yml
258+
259+
- name: Read var files from cifmw_cmd_args
260+
when: cifmw_cmd_args_files is defined and cifmw_cmd_args_files | length > 0
261+
ansible.builtin.include_vars:
262+
file: "{{ files_item }}"
263+
loop: "{{ cifmw_cmd_args_files }}"
264+
loop_control:
265+
loop_var: files_item
266+
```
267+
268+
- files are located in remote host - controller
269+
270+
In alternative version, variables are available on remote host. That requires
271+
to fetch the files first to host which is executing the Ansible - include_vars
272+
reads only files that are on the host where ansible-playbook was executed.
273+
Example:
274+
275+
```yaml
276+
- name: Nested Ansible execution
277+
hosts: controller
278+
tasks:
279+
- name: Run ansible-playbook
280+
vars:
281+
cmd_args: "[email protected] -e @/tmp/someotherfile.yml -e myvar=test"
282+
ansible.builtin.command: |
283+
ansible-playbook "{{ cmd_args }}" test.yaml
284+
```
285+
286+
To:
287+
288+
```yaml
289+
- name: Playbook that does not use nested Ansible - different host
290+
hosts: controller
291+
vars:
292+
cifmw_cmd_args: "[email protected] -e @/tmp/someotherfile.yml -e myvar=test"
293+
tasks:
294+
# NOTE: The task returns fact: cifmw_cmd_args_vars and cifmw_cmd_args_files
295+
- name: Read inventory file and add it using add_host module
296+
ansible.builtin.include_role:
297+
name: cifmw_helpers
298+
tasks_from: parse_ansible_args_string.yml
299+
300+
- name: Parse only variables from cifmw_cmd_args_vars
301+
when: cifmw_cmd_args_vars is defined and cifmw_cmd_args_vars | length > 0
302+
vars:
303+
various_vars: "{{ cifmw_cmd_args_vars }}"
304+
ansible.builtin.include_role:
305+
name: cifmw_helpers
306+
tasks_from: various_vars.yml
307+
308+
- name: Fetch cifmw_cmd_args_files to executing host
309+
when: cifmw_cmd_args_files is defined and cifmw_cmd_args_files | length > 0
310+
ansible.builtin.fetch:
311+
src: "{{ files_item }}"
312+
dest: "{{ files_item }}"
313+
flat: true
314+
loop: "{{ cifmw_cmd_args_files }}"
315+
loop_control:
316+
loop_var: files_item
317+
318+
- name: Read fetched var files from cmd_args
319+
when: cifmw_cmd_args_files is defined and cifmw_cmd_args_files | length > 0
320+
ansible.builtin.include_vars:
321+
file: "{{ files_item }}"
322+
loop: "{{ cifmw_cmd_args_files }}"
323+
loop_control:
324+
loop_var: files_item
325+
```
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
# This would help to parse variables, that
3+
# are called in nested ansible execution using shell/command
4+
# module.
5+
# For example:
6+
#
7+
# cifmw_cmd_args: "[email protected] -e @/tmp/someotherfile.yml -e myvar=test"
8+
#
9+
# to:
10+
#
11+
# cifmw_cmd_args_vars: [{'myvar': 'test'}]
12+
# cifmw_cmd_args_files: ['somefile.yml', '/tmp/someotherfile.yml']
13+
#
14+
15+
- name: Split string of arguments into the lists of vars and files
16+
when: cifmw_cmd_args | length > 1
17+
ansible.builtin.set_fact:
18+
cifmw_cmd_args_vars: "{{ cifmw_cmd_args
19+
| split(' -e ')
20+
| reject('search', '@')
21+
| reject('equalto', '')
22+
| map('regex_replace', '^(.*?)=(.*)$', '{\"\\1\": \"\\2\"}')
23+
| map('from_yaml')
24+
| list
25+
}}"
26+
cifmw_cmd_args_files: "{{ cifmw_cmd_args
27+
| split('-e')
28+
| select()
29+
| map('trim')
30+
| select('match', '^@.*\\.(yml|yaml)$')
31+
| list
32+
| replace('@', '')
33+
}}"
34+
no_log: "{{ cifmw_helpers_no_log }}"

0 commit comments

Comments
 (0)