How to loop vars in ansible playbook [duplicate] - ansible

The documentation for import_tasks mentions
Any loops, conditionals and most other keywords will be applied to the included tasks, not to this statement itself.
This is exactly what I want. Unfortunately, when I attempt to make import_tasks work with a loop
- import_tasks: msg.yml
with_items:
- 1
- 2
- 3
I get the message
ERROR! You cannot use loops on 'import_tasks' statements. You should use 'include_tasks' instead.
I don't want the include_tasks behaviour, as this applies the loop to the included file, and duplicates the tasks. I specifically want to run the first task for each loop variable (as one task with the standard with_items output), then the second, and so on. How can I get this behaviour?
Specifically, consider the following:
Suppose I have the following files:
playbook.yml
---
- hosts: 192.168.33.100
gather_facts: no
tasks:
- include_tasks: msg.yml
with_items:
- 1
- 2
msg.yml
---
- name: Message 1
debug:
msg: "Message 1: {{ item }}"
- name: Message 2
debug:
msg: "Message 2: {{ item }}"
I would like the printed messages to be
Message 1: 1
Message 1: 2
Message 2: 1
Message 2: 2
However, with import_tasks I get an error, and with include_tasks I get
Message 1: 1
Message 2: 1
Message 1: 2
Message 2: 2

You can add a with_items loop taking a list to every task in the imported file, and call import_tasks with a variable which you pass to the inner with_items loop. This moves the handling of the loops to the imported file, and requires duplication of the loop on all tasks.
Given your example, this would change the files to:
playbook.yml
---
- hosts: 192.168.33.100
gather_facts: no
tasks:
- import_tasks: msg.yml
vars:
messages:
- 1
- 2
msg.yml
---
- name: Message 1
debug:
msg: "Message 1: {{ item }}"
with_items:
- "{{ messages }}"
- name: Message 2
debug:
msg: "Message 2: {{ item }}"
with_items:
- "{{ messages }}"

It is not possible. include/import statements operate with task files as a whole.
So with loops you'll have:
Task 1 with Item 1
Task 2 with Item 1
Task 3 with Item 1
Task 1 with Item 2
Task 2 with Item 2
Task 3 with Item 2
Task 1 with Item 3
Task 2 with Item 3
Task 3 with Item 3

Related

register with loop not giving expected output - Ansible

I am writing a playbook that gives me the status of list of processes in loop but the output is not coming a desired
I am using ansible 2.7.1
---
- hosts: test_group
gather_facts: false
tasks:
- name: checking status
shell: /etc/init.d/{{ item }} status
register: output
loop:
- gdac
- scac
- name : print status
debug:
msg: "{{ item.stdout }}"
loop: "{{ output.results }}"
expecting output like (which given me the stdout or stdout_lines from the registered variable.
"msg":"Poller is Running\nSpooler is Running"
"msg": scac.db1: 3 of 3 running ( 7067 7060 7040 )\nayld.db1: 1 of 1 running ( 7114 )\nscac.db2: 3 of 3 running ( 7227 7216 7203 )\nayld.db2: 0 of 1 running
but am getting error
fatal: [test01]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined
``
In your second task, you declared loop as an option of the debug module.
It should be an option of the task, not of the module. Since there is no loop declaration for the task, item is undefined.
You just have to fix your indentation:
- name : print status
debug:
msg: "{{ item.stdout }}"
loop: "{{ output.results }}"

How to run Ansible task to a limit number of items?

I have a dynamic inventory which returns me my hosts addresses.
But sometimes, I would like to apply some configuration to a limited number of hosts.
A sample with N hosts but only 5 are echoed:
- name: "Run silly shell script"
shell: |
echo {{ item }}
exit 0
with_items: "{{ hosts | only(5) }}"
to get the first X elements from a list, use: list_var[:X].
full example as PB below:
---
- hosts: localhost
gather_facts: false
vars:
list_var:
- 1
- 2
- 3
- 4
- 5
- 6
tasks:
- name: print full list
debug:
var: list_var
- name: print list of first 3 elements
debug:
var: list_var[:3]
hope it helps.

Run all tasks in playbook with_items

I want the playbook to run once with each item in the list and not all items in the list at once.
Ansible version: 2.6.1
Tasks.yaml:
---
- name: Task 1
debug:
msg: "Message 1: {{ item }}"
with_items: "{{ messages }}"
- name: Task 2
debug:
msg: "Message 2: {{ item }}"
with_items: "{{ messages }}"
Playbook:
- hosts: localhost
gather_facts: no
tasks:
- import_tasks: Tasks.yml
vars:
messages:
- 1
- 2
This is my expected result:
Task 1 with Item 1
Task 2 with Item 1
Task 3 with Item 1
Task 1 with Item 2
Task 2 with Item 2
Task 3 with Item 2
Task 1 with Item 3
Task 2 with Item 3
Task 3 with Item 3
But when I execute the playbook, then it is like this:
Task 1 with Item 1
Task 1 with Item 2
Task 2 with Item 1
Task 2 with Item 2
Task 3 with Item 1
Task 3 with Item 2
...
I tried both import and include - both have the same result.
Your playbook.yml should implement a loop (notice you cannot loop with import_tasks; it will raise an error):
- hosts: localhost
connection: local
gather_facts: no
vars:
messages:
- 1
- 2
- 3
tasks:
- include_tasks: Tasks.yml
loop: "{{ messages }}"
And Tasks.yml should look like this (no loops inside):
---
- name: Task 1
debug:
msg: "Message 1: {{ item }}"
- name: Task 2
debug:
msg: "Message 2: {{ item }}"

Search for a list of strings in ansible register variable

I am newbie to ansible. I have a task where in I have to register the output of a first task and execute second task when some list of variables are present in the output of first task. It looks like below
- name: execute first task
command: /tmp/somescript.sh
register: output
- fail:
msg: when {{ item }} present in. output.stdout or output.stdlines
with_items:
- a
- b
- c
You didn't test the output yet as you posted on your code.
It should be something like this:
- fail:
msg: 'Fail looking for {{ item }} in output'
when: item not in output.stdout or item not in output.stdlines
with_items:
- a
- b
- c
As #ilias-sp said, take a look here: https://docs.ansible.com/ansible/latest/modules/fail_module.html

Ansible playbook with_subelements

Ansible playbook with_subelements error with 3 levels.
My Config looks like
---
Firstlevel:
- fl_number: fln1
fl_data: fld1
Secondlevel:
- sl_number: sln_f1_1
sl_data: sld_f1_1
Thirdlevel:
- tl_number: tln_s1_f1_1
tl_data: tld_s1_f1_1
- tl_number: tln_s2_f1_2
tl_data: tld_s2_f1_2
The Ansible playbook is
>cat test_threelevels.yml
---
- hosts: localhost
gather_facts: no
vars_files:
- ../vars/testConfig-var.yml
tasks:
- name: DebugWorks
debug: msg="{{ item.1.Thirdlevel }}"
with_subelements:
- Firstlevel
- Secondlevel
- name: DebugDoesNotWork
debug: msg=" Sub element Thirdlevel test"
with_subelements:
- Firstlevel
- Secondlevel
- Thirdlevel
When it is executed with
ansible-playbook -v test_threelevels.yml
the task "DebugWorks" works but the task "DebugDoesNotWork" dosent.
Output
TASK: [DebugDoesNotWork] ******************************************************
fatal: [localhost] => subelements lookup expects a list of two items, first a dict or a list, and second a string
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
Need help in understanding if this is the right way to do and why it does not work.
Open to any suggestions.
Thanks.
The error description at least vaguely says what's meant. :)
Refer to the code to see exactly the error means here. terms is the list you pass.
if not isinstance(terms, list) or not 2 <= len(terms) <= 3:
In short: You can only go 2 levels, not 3.
The documentation does say clearly:
Optionally, you can add a third element to the subelements list, that
holds a dictionary of flags.

Resources