compare value with list of int in ansible - ansible

Want to compare values with list for int and display msg values greater than 15
tasks:
- name: Create a List variable and print it
set_fact:
Continents: ["10","20"]
- name: set fatc
set_fact:
int_list: "{{ Continents|map('int')|list }}"
- debug:
msg: "{{greater than 15}}"
when: "{{int_list}}" > 15
Getting error as below:
The offending line appears to be:
msg: "{{ list }}"
when: "{{int_list}}" > 15
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Expected Output:
greater than 15

If your goal is to show only those integers in the list that are greater than 15, you can use the select filter:
- hosts: localhost
gather_facts: false
tasks:
- name: Create a list of integers
set_fact:
int_list: [10, 20]
- name: Find integers greater than 15
debug:
msg: "{{ item }}"
loop: "{{ int_list | select('>', 15) }}"
The output of this playbook is:
PLAY [localhost] ***************************************************************
TASK [Create a list of integers] ***********************************************
ok: [localhost]
TASK [Find integers greater than 15] *******************************************
ok: [localhost] => (item=20) => {
"msg": 20
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

You can achieve the same with two tasks. Change your list to integers. Make the debug task to loop through the Continents variable.
- hosts: localhost
tasks:
- name: Create a variable with a list of integers
set_fact:
Continents: [10, 20]
- debug:
msg: "greater than 15"
loop: "{{ Continents }}"
when: item > 15 ##item becomes each value of the Continents variable. So, 10, 20 and so on.
Gives:
skipping: [localhost] => (item=10)
ok: [localhost] => (item=20) => {
"msg": "greater than 15"
}

Related

Ansible filter filename list with substring list

This seems simple enough but I can't find the ansible/jinja way to do it nor the correct keywords to find some pointers.
There's a list of file names (firstlist) (read from a file if it makes anything easier).
There's a second list (secondlist) with partial filenames to filter the first one. This second list can have elements that don't match.
/tmp/filelist.txt contents:
A-ok.txt
B-ok.txt
C-ok.txt
Tasks extract:
- name: Read filelist
command: cat /tmp/filelist.txt
register: filelist_results
- name: "[FACT] filelist"
set_fact:
firstlist: "{{ filelist_results.stdout_lines }}"
secondlist: ['A', 'C', 'D']
- name: "print it"
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ firstlist }}" # <--- need to filter here?
Would result in looping just:
A-ok.txt
C-ok.txt
If secondlist contained the full filename, adding:
when: item in secondlist
would be enough.
It seems select() is half the answer but I can't find the correct test to match the partial filename from the second list
Take your "filter" list (["A", "C", "D"]) and transform it to a regex of chars to look for ("A|C|D") (using regex_escape on each list element for safety).
use the select filter to retain only element that pass the match test (i.e. the regex is found at the beginning of the expression)
In a nutshell, the following playbook:
---
- hosts: localhost
gather_facts: false
vars:
filelist:
- A-ok.txt
- B-ok.txt
- C-ok.txt
keeplist:
- A
- C
- D
filteredlist: "{{ filelist | select('match', keeplist | map('regex_replace') | join('|')) }}"
tasks:
- debug:
var: filteredlist
gives:
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"filteredlist": [
"A-ok.txt",
"C-ok.txt"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Note: Posting my final result in answer form as suggested.
After #Zeitounator this is where I ended up:
---
- hosts: localhost
gather_facts: false
vars:
filelist:
- plugin-test-v1.txt
- plugin-database.txt
- C-ok.txt
keeplist:
- plugin-database
- plugin-test
- plugin-none
regexp: "{{ keeplist | map('regex_escape') | join('|') }}"
filteredlist: "{{ filelist | select('match', regexp) }}"
tasks:
- name: "print it"
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ filteredlist|default(filelist) }}"
Couple points:
extracted the regexp in a separate variable because templating inline was giving me troubles with dash in the pattern
the loop defaults to the full list if the filter ends up empty
Outputs:
PLAY [localhost] *******************************************************************************************************
TASK [print it] ********************************************************************************************************
ok: [localhost] => (item=plugin-test-v1.txt) => {
"msg": "plugin-test-v1.txt"
}
ok: [localhost] => (item=plugin-database.txt) => {
"msg": "plugin-database.txt"
}
PLAY RECAP *************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ansible loop over list extracted from dict

I'm using Ansible 2.9 on RHEL 7.7, and I'm trying to loop over a list which is a value from a dict element. So far I have this var file and play:
ssh_keys:
account: blah
permissions: 600
keys:
- qa-publickeys['1']
- qa-publickeys['2']
- qa-publickeys['3']
the play:
- name: Traversing ssh keys
debug:
msg: "Here's: {{ item }}"
loop: "{{ ['keys'] | map('extract', ssh_keys) | list }}"
The problem is, msg is "msg": "Here's: [u\"qa-publickeys['1']\", u\"qa-publickeys['2']\", u\"qa-publickeys['3']\"]"
Why is it not giving me three outputs, with Here's: qa-publickeys['1'] as the first output, Here's: qa-publickeys['2'] as the second, and finally Here's: qa-publickeys['3'] ?
The list that I present to the loop in this play is not getting looped over, it's just iterating once in one chunk.
You seems to make is really complex for yourself for no apparent reason.
A dictionary in Ansible can be accessed via either the . dot notation or the [] square brackets notation.
Now because .keys() is indeed a built-in method of a dictionary in Python, you cannot use the first notation, but you can use the later one.
Given the playbook:
- hosts: all
gather_facts: no
tasks:
- debug:
msg: "Here's: {{ item }}"
loop: "{{ ssh_keys['keys'] }}"
vars:
ssh_keys:
account: blah
permissions: 600
keys:
- qa-publickeys['1']
- qa-publickeys['2']
- qa-publickeys['3']
This yields the recap:
PLAY [all] *******************************************************************************************************
TASK [debug] *****************************************************************************************************
ok: [localhost] => (item=qa-publickeys['1']) =>
msg: 'Here''s: qa-publickeys[''1'']'
ok: [localhost] => (item=qa-publickeys['2']) =>
msg: 'Here''s: qa-publickeys[''2'']'
ok: [localhost] => (item=qa-publickeys['3']) =>
msg: 'Here''s: qa-publickeys[''3'']'
PLAY RECAP *******************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ansible working with multiple loops in conditions

how can I add a condition to ansible task that is based on a loop, when the task itself also based on a loop?
For example, here's my code:
- hosts: all
gather_facts: False
vars:
current_version: 826
versions:
- 805
- 821
- 824
- 826
tasks:
- name: First Task
find:
paths: /Users/tomer/projects/personal/ansible/test
patterns: snapshot*
register: files
when:
- current_version == item
loop: "{{versions}}"
- name: Second task
set_fact:
test_work: "{{ true if item > 0 else false}}"
loop:
- "{{ files | json_query('results[*].matched') }}"
So far, this is working as expected.
The first task is looking for any file with the name snapshot if the current_version is matching one of the versions in the list.
The second task iterates over the dictionary result from the first task and based on each item it is setting the fact. (In my case, only one item has this attribute).
I wanted to run the second task, only when the first task did run, however, the changed status is always false, so this condition is not useful.
I wanted to add the same condition of current_version == item but I can't use item twice here.
Any idea how to achieve that?
The find command is not really going to change anything, it just queries the file system without doing any modification, so it will indeed always give you a false.
On the other hand, you can definitely use the skipped field of the item.
This said, I would simplify the loop on your set_fact, because there is no real need to use json_query here.
This task would do the job perfectly fine:
- set_fact:
test_work: "{{ item.matched > 0 }}"
loop: "{{ files.results }}"
when: item is not skipped
Another extra tip is to not do things like
true if condition_that_evaluates_to_true else false
But rather do right away
condition_that_evaluates_to_true
Here would be a made up example playbook
- hosts: all
gather_facts: no
tasks:
- find:
path: /tmp
pattern: dummy*
when: item == current_version
register: files
loop: "{{ versions }}"
vars:
current_version: 826
versions:
- 805
- 821
- 824
- 826
- debug:
msg: "{{ item.matched > 0 }}"
loop: "{{ files.results }}"
when: item is not skipped
loop_control:
label: "{{ item.item }}"
This would yield the result
PLAY [all] *******************************************************************************************************
TASK [find] ******************************************************************************************************
skipping: [localhost] => (item=805)
skipping: [localhost] => (item=821)
skipping: [localhost] => (item=824)
ok: [localhost] => (item=826)
TASK [debug] *****************************************************************************************************
skipping: [localhost] => (item=805)
skipping: [localhost] => (item=821)
skipping: [localhost] => (item=824)
ok: [localhost] => (item=826) => {
"msg": true
}
PLAY RECAP *******************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

How to print a list of items in a multiline string output in ansible

I have a list in ansible and want to print the contents in a block, if I do loop like below:
- test_list
- one
- two
- three
- debug:
msg: "{{ item }}"
loop: "{{ test_list }}"
it will produce output something like:
{ msg: "one" }
{ msg: "two" }
{ msg: "three" }
here I have multiple msg values, I want output like:
msg:"one
two
three"
where list items are broken won into multiple lines. Can anyone direct me to the correct path or provide a hint.
Any help would be appreciated.
You can achieve the desired result by the following steps :
Set callback plugin to debug using the following command:
export ANSIBLE_STDOUT_CALLBACK=debug
Replace loop with for loop on jinja2:
Example:
The desired output could be obtained using the following playbook:
---
- name: Sample playbook
connection: local
gather_facts: no
hosts: localhost
vars:
test_list:
- one
- two
- three
tasks:
- debug:
msg: "{% for item in test_list %}{{ item + '\n'}}{% endfor %}"
The above playbook would result in:
PLAY [Sample playbook] ***************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [localhost]
TASK [debug] *************************************************************************************************************************
ok: [localhost] => {}
MSG:
one
two
three
PLAY RECAP ***************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
if you need starting/ending double quotes:
msg: "\"{% for item in test_list %}{{ item + '\n'}}{% endfor %}\""

ansible: create a list from comma separated string

I want to create a list from comma separated string to pass to loop in ansible, sometime variable can have only one value also
var1=test1,test2 and it can be var1=test1 also
here is my code
- name: Separate facts
set_fact: groups="{{ var1.split(',') }}"
- name: delete
gcp_compute_instance_group:
name: "{{ item }}"
zone: xxx
project: xxx
auth_kind: serviceaccount
service_account_file: xxx
state: absent
loop: "{{ groups }}"
this doesn't work, how can i achieve my requirement
your filter is correct, you do get a list variable. please see below PB and output:
---
- hosts: localhost
gather_facts: false
vars:
var1: test1,test2
var2: test3
tasks:
- name: Create the list
set_fact:
list_var1: "{{ var1.split(',') }}"
list_var2: "{{ var2.split(',') }}"
- debug:
var: list_var1
- debug:
var: list_var2
result:
[is#orangehat-29 temp]$ ansible-playbook test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [Create the list] *****************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"list_var1": [
"test1",
"test2"
]
}
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"list_var2": [
"test3"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[is#orangehat-29 temp]$

Resources