Split debug variable output into two separate variables in ansible - ansible

I am using below code snippet where image details would be printed:
- set_fact:
image_name: "{{ load.results|map(attribute='stdout_lines')|list }}"
- debug:
var: image_name
Output:
TASK [set_fact] ***************************************************************************************************************************************************************************
ok: [xx.xx.xx.xx]
TASK [debug] ******************************************************************************************************************************************************************************
ok: [xx.xx.xx.xx] => {
"image_name": [
[
"Loaded image(s): localhost/cim:v1.5"
],
[
"Loaded image(s): localhost/cim:v1.8"
]
]
}
Is there a way I can store the image name and tag in two separate variables under set_fact itself or in any other form so I can reuse those 2 variables for the next task?

You can use a regex_findall filter in order to achieve this.
The regex used here is (\S*):(\S+). if needed, more explanation on it can be found here
Given the playbook:
- hosts: all
gather_facts: no
vars:
load:
results:
- stdout_lines:
- "Loaded image(s): localhost/cim:v1.5"
- stdout_lines:
- "Loaded image(s): localhost/cim:v1.8"
tasks:
- set_fact:
images: "{{ images | default([]) + item | regex_findall('(\\S*):(\\S+)') }}"
loop: "{{ load.results | map(attribute='stdout_lines') | flatten }}"
- debug:
msg: "This image repository is `{{ item.0 }}` and its tag is `{{ item.1 }}`"
loop: "{{ images }}"
This yields the recap:
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [localhost] => (item=Loaded image(s): localhost/cim:v1.5)
ok: [localhost] => (item=Loaded image(s): localhost/cim:v1.8)
TASK [debug] *******************************************************************************************************
ok: [localhost] => (item=['localhost/cim', 'v1.5']) => {
"msg": "This image repository is `localhost/cim` and its tag is `v1.5`"
}
ok: [localhost] => (item=['localhost/cim', 'v1.8']) => {
"msg": "This image repository is `localhost/cim` and its tag is `v1.8`"
}
PLAY RECAP *********************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Related

my_list.pop() does not remove the selected item from original list

I have to iterate through a list. I want to use my_var.pop to select the first item in my list. Do some stuff with the selected item and remove it from the original list.
I can select the first item properly, however, it's not removed.
What is the proper way in Ansible to iterate through a list. What do I miss?
Thanks!
- hosts: localhost
gather_facts: no
vars:
cluster_params: "1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20\n3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
clusters: "{{ cluster_params.split('\n') }}"
select_first_cluster: "{{ clusters.pop(0) }}"
# Do some stuff on my selected cluster
with_nested:
- "{{ clusters }}"
tasks:
- name: clusters
debug:
msg:
- "{{ clusters }}"
- "The 'clusters' variable contains a {{ clusters | type_debug }}"
- name: select_first_cluster
debug:
msg:
- "{{ select_first_cluster }}"
- "The 'select_first_cluster' variable contains a {{ select_first_cluster | type_debug }}"
- name: updated_clusters
debug:
msg:
- "{{ clusters }}"
- "The 'clusters' variable contains a {{ clusters | type_debug }}"
Output:
PLAY [localhost] *************************************************************************************************************************************************************************************************************************************************************************************************
TASK [clusters] **************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
],
"The 'clusters' variable contains a list"
]
}
TASK [select_first_cluster] **************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"The 'select_first_cluster' variable contains a unicode"
]
}
TASK [updated_clusters] ******************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
],
"The 'clusters' variable contains a list"
]
}
TASK [separate_app1__from_app2] **********************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2:5002",
"10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20"
],
"The 'separate_app1__from_app2' variable contains a list"
]
}
TASK [separate_app1_ips__from_port] ******************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2",
"5002"
],
"The 'separate_app1_ips__from_port' variable contains a list"
]
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(app-root) ansible-playbook loop_test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] *************************************************************************************************************************************************************************************************************************************************************************************************
TASK [clusters] **************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
],
"The 'clusters' variable contains a list"
]
}
TASK [select_first_cluster] **************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"The 'select_first_cluster' variable contains a unicode"
]
}
TASK [updated_clusters] ******************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
[
"1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20",
"3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
],
"The 'clusters' variable contains a list"
]
}
PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
so i dont see where is your list of lists,
If you want to loop over clusters, you dont loop over vars but over task:
- hosts: localhost
gather_facts: no
vars:
cluster_params: "1.1.1.1,2.2.2.2:5002;10.10.0.1|17,10.10.0.2|18,10.10.0.3|19,10.10.0.4|20\n3.3.3.3,4.4.4.4:5003;10.10.1.1|21,10.10.1.2|22,10.10.1.3|23,10.10.1.4|24"
clusters: "{{ cluster_params.split('\n') }}"
tasks:
- name: clusters
debug:
msg:
- "{{ item }}"
- "The 'item' variable contains a {{ item | type_debug }}"
loop: "{{clusters}}"

Register command output as 2 separate variables

I have an Ansible playbook that runs a script over my remote machines.
The script finds log files, determine the application the log file came from (so it would know the destination directory), and uploads the files back to the Ansible server (using scp).
Just because it worth mentioning - there are 2 different playbooks, one for Windows servers, using a PowerShell script, and the other is for Linux servers, using a bash script.
I would like to eliminate the scp part for those scripts, and instead using the fetch module in my playbooks. But I'm facing a problem with that - my scripts generates 2 variables for each application on each server:
the log file, full path.
the destination directory in the Ansible server (determined by the servers name and the application name).
My current playbook looks like that (this is the Windows one):
---
- hosts: <WindowsHosts>
gather_facts: no
tasks:
- name: Find and Copy Windows Applications Logs
script: fetchwinFindLogs.ps1 {{ server_partition }} {{days}} {{ansibleSRV_Port}} {{ansibleSRV_IP}}
register: result
- debug:
var: result
# - fetch: src={{ result }} dest={{ result }}
# with_items: "{{ result.stdout_lines }}"
The output:
PLAY [<WinHost>] *********************************************************************************************************************************************************************************************
TASK [Find and Copy Windows Applications Logs] ***************************************************************************************************************************************************************
changed: [<WinHost>]
TASK [debug] *************************************************************************************************************************************************************************************************
ok: [<WinHost>] => {
"result": {
"changed": true,
"failed": false,
"rc": 0,
"stderr": "",
"stderr_lines": [],
"stdout": "C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18\r\n/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/\r\nC:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18\r\n/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/\r\nC:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18\r\n/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/\r\nC:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18\r\n/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/\r\n",
"stdout_lines": [
"C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18",
"/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/",
"C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18",
"/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/",
"C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18",
"/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/",
"C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18",
"/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/"
]
}
}
PLAY RECAP ***************************************************************************************************************************************************************************************************
<WinHost> : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
How do I use the 2 separate values gotten from the script, so the fetch module would know to direct each log file from each application to the correct directory in my Ansible server?
This includes, of course, looping over every 2 values, so it would direct the correct log to the correct destination directory (since, again, the first value will always be the full path log, and the second would be the destination directory, for each application separately).
There is possibly plenty of ways to achieve this.
Here are two of them:
Using the extended loop variables and a when condition, you could skip every other item with a when and a modulo % and get the item along with the ansible_loop.nextitem.
Here is an example for that:
- hosts: all
gather_facts: no
tasks:
- debug:
msg:
- "src: {{ item  }}"
- "dest: {{ ansible_loop.nextitem }}"
loop: "{{ result.stdout_lines }}"
when: ansible_loop.index % 2 == 1
loop_control:
extended: yes
vars:
result:
stdout_lines:
- "C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/"
- "C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/"
- "C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/"
- "C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/"
This yields the recap:
PLAY [all] ********************************************************************************************************
TASK [debug] ******************************************************************************************************
ok: [localhost] => (item=C:\<Maindir>\<App1>\Logs\platform.log.2020-09-18) => {
"msg": [
"src: C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/"
]
}
skipping: [localhost] => (item=/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/)
ok: [localhost] => (item=C:\<Maindir>\<App2>\Logs\platform.log.2020-09-18) => {
"msg": [
"src: C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/"
]
}
skipping: [localhost] => (item=/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/)
ok: [localhost] => (item=C:\<Maindir>\<App3>\Logs\platform.log.2020-09-18) => {
"msg": [
"src: C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/"
]
}
skipping: [localhost] => (item=/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/)
ok: [localhost] => (item=C:\<Maindir>\<App4>\Logs\platform.log.2020-09-18) => {
"msg": [
"src: C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/"
]
}
skipping: [localhost] => (item=/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/)
PLAY RECAP ********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Another idea would be to use Python array slicing to separate odd from even elements and Ansible zip filter.
This would be the playbook:
- hosts: all
gather_facts: no
tasks:
- debug:
msg:
- "src: {{ item.0 }}"
- "dest: {{ item.1 }}"
loop: "{{ result.stdout_lines[::2] | zip(result.stdout_lines[1::2]) | list }}"
vars:
result:
stdout_lines:
- "C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/"
- "C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/"
- "C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/"
- "C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18"
- "/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/"
This yields the recap:
PLAY [all] ********************************************************************************************************
TASK [debug] ******************************************************************************************************
ok: [localhost] => (item=['C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18', '/<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/']) => {
"msg": [
"src: C:\\<Maindir>\\<App1>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App1>/"
]
}
ok: [localhost] => (item=['C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18', '/<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/']) => {
"msg": [
"src: C:\\<Maindir>\\<App2>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App2>/"
]
}
ok: [localhost] => (item=['C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18', '/<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/']) => {
"msg": [
"src: C:\\<Maindir>\\<App3>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App3>/"
]
}
ok: [localhost] => (item=['C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18', '/<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/']) => {
"msg": [
"src: C:\\<Maindir>\\<App4>\\Logs\\platform.log.2020-09-18",
"dest: /<LinuxMainDir>/<logs>/Applications/<serverName>.<App4>/"
]
}
PLAY RECAP ********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
When I would have a slight preference for the second approach, I could understand it could be less readable for people not used to Python's array slicing.

Iterating via nested loops

The packages.yml file defined as:
---
- packages:
- name: Some description 1,
packageList:
- package1,
- package2,
- package3
- name: Some description 2,
package: package4
The first item contains a field packageList, the 2nd item does not have it, but only package field.
Playbook:
---
- hosts: all
become: yes
vars_files:
- packages.yml
How to iterate via all packageList items of the packages list only if this packageList is defined for an item.
Here is how I can iterate through items which contain package field:
- name: iteration
debug:
msg: "name: {{ item.package }}"
when: item.package is defined
with_items: "{{ packages }}"
As noted in my comment, if you simply want to install multiple yum/apt packages, it is usually more efficient to simply pass the list to the apt/yum/package module. As the docs state:
"When used with a loop: each package will be processed individually, it is much more efficient to pass the list directly to the name option."
However, if you really need a loop, here is a possible solution:
playbook.yml:
---
- hosts: all
gather_facts: false
vars_files:
- packages.yml
tasks:
- name: iteration over single items
debug:
msg: "name: {{ item.package }}"
when: item.package is defined
with_items: "{{ packages }}"
- name: iteration over lists
debug:
msg: "name: {{ item.packageList }}"
when: item.packageList is defined
with_items: "{{ packages }}"
- name: Do something with individual packages in the list
include_tasks: process_list.yml
vars:
mylist: "{{outer.packageList}}"
when: outer.packageList is defined
loop: "{{ packages }}"
loop_control:
loop_var: outer
process_list.yml:
- name: See what we have received
debug:
var: item
loop: "{{mylist}}"
result:
PLAY [all] *******************************************************************************************************************************
TASK [iteration over single items] *******************************************************************************************************
skipping: [localhost] => (item={u'packageList': [u'package1,', u'package2,', u'package3'], u'name': u'Some description 1,'})
ok: [localhost] => (item={u'name': u'Some description 2,', u'package': u'package4'}) => {
"msg": "name: package4"
}
TASK [iteration over lists] **************************************************************************************************************
ok: [localhost] => (item={u'packageList': [u'package1,', u'package2,', u'package3'], u'name': u'Some description 1,'}) => {
"msg": "name: [u'package1,', u'package2,', u'package3']"
}
skipping: [localhost] => (item={u'name': u'Some description 2,', u'package': u'package4'})
TASK [Do something with individual packages in the list] *********************************************************************************
skipping: [localhost] => (item={u'name': u'Some description 2,', u'package': u'package4'})
included: /root/tmp/process_list.yml for localhost
TASK [See what we have received] *********************************************************************************************************
ok: [localhost] => (item=package1,) => {
"ansible_loop_var": "item",
"item": "package1,"
}
ok: [localhost] => (item=package2,) => {
"ansible_loop_var": "item",
"item": "package2,"
}
ok: [localhost] => (item=package3) => {
"ansible_loop_var": "item",
"item": "package3"
}
PLAY RECAP *******************************************************************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
The loop_control/loop_var part is used because otherwise both the outer and inner loop will use {{item}} as the loop variable - and this will cause... interesting results :)
You can define a default value with an empty list for the cases, where the packageList is undefined.
{{ item.packageList | default ([]) }}
If the packageList is undefined, the job iterates over an empty list, which means, it does not do anything.
You can use default, as #ceving mentioned:
---
- hosts: localhost
connection: local
vars_files:
- packages.yml
tasks:
- name: iteration
debug:
msg: "name: {{ item.packageList | default([item.package]) }}"
with_items: "{{ packages }}"
If packageList exists, it will use that, else package put into a single-element array to match the form of packageList:
PLAY [localhost] **********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************
ok: [localhost]
TASK [iteration] **********************************************************************************************
ok: [localhost] => (item=None) => {
"msg": "name: [u'package1,', u'package2,', u'package3']"
}
ok: [localhost] => (item=None) => {
"msg": "name: [u'package4']"
}
PLAY RECAP ****************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0

Ansible playbook to get all private Ip of my AWS environments

I'm running a scan against all the instances on my AWS using Ansible pLaybook . I need to get their Private IP and list them
I have tried to use json query to filter the Json format. The format output look like this..............
ok: [localhost] => {
"msg": [
{
"private_dns_name": "ip-10.89.3.12.ec2.internal",
"private_ip_address": "10.89.3.12",
"public_dns_name": "",
"public_ip_address": null,
},
- hosts: localhost
connection: local
gather_facts: yes
tasks:
- name: Gather EC2 remote facts.
ec2_remote_facts:
region: "{{ region | default('us-east-1') }}"
filters:
instance-state-name: running
register: ec2_remote_facts
- set_fact:
msg: "{{ ec2_remote_facts | json_query('results[*].instances[*].private_ip_address') }} "
- debug: var=msg
I expect the output to be list of private_IP only
I tried with "ec2_instance_facts" as below :
- hosts: localhost
connection: local
gather_facts: yes
tasks:
- name: Gather EC2 remote facts.
ec2_instance_facts:
filters:
availability-zone: ap-south-1b
register: ec2_instance_facts
- set_fact:
msg: "{{ ec2_instance_facts | json_query('instances[*].private_ip_address') }} "
- debug: var=msg
and below is the output :
PLAY [localhost] **************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Gather EC2 remote facts.] ***********************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] ***************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"172.31.6.87"
]
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Which is correct as per EC2 instance I had created.

How to check few keywords in a string and assert if not present in Ansible tasks

I have a string like this
"3000 Native active Po121, Po123"
I need to check if 3000 is present and active is present in this string. If not assert
I wanted to use when command and set_fact. Check if the variable present and assert. (which I haven't finished). Right now I am just printing a message. This is not the good to way to do it. If I can assert directly when 3000 and active not present, that would be great.
Also another question about when, if it matches first condition, it prints the debug message. It should match both right as its an and?
var:
vlan_output: "3000 Native active Po121, Po123"
item={vlan_id: 3000, state: present}
I tried like this
- name: Validate vlan for delete
debug: msg="VLAN FAILED "
when: item.state == "present" and "item.vlan_id not in vlan_output"
We can directly use the when condition if "3000" and "active" is present in the output
I believe the vlan_id would be a registered variable so the value can be accessed using vlan_id.stdout.
The below play works with when and assert module of ansible
for assertion +ve:
command -->
ansible-playbook tmp.yml --extra-vars "vlan_output='3000 active'"
playbook -->
---
- hosts: localhost
tasks:
- debug:
msg: "Strings Matched"
when: vlan_output | search("3000") and vlan_output | search("active")
- debug:
var: vlan_output
- assert:
that:
- "'3000' in vlan_output"
- "'active' in vlan_output"
output -->
ok: [localhost] => {
"msg": "Strings Matched"
}
TASK [debug] *****************************************************************************************************************************
ok: [localhost] => {
"vlan_output": "3000 active"
}
TASK [assert] ****************************************************************************************************************************
ok: [localhost] => {
"changed": false,
"msg": "All assertions passed"
}
PLAY RECAP *******************************************************************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
for assertion -ve:
command -->
ansible-playbook tmp.yml --extra-vars "vlan_output='is'"
playbook -->
---
- hosts: localhost
tasks:
- debug:
msg: "Strings Matched"
when: vlan_output is not search("3000") and vlan_output is not search("active")
- debug:
var: vlan_output
- assert:
that:
- "'3000' not in vlan_output"
- "'active' not in vlan_output"
output -->
PLAY [localhost] *******************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ***********************************************************************************************************************************************************
ok: [localhost] => {
"msg": "Strings Matched"
}
TASK [debug] ***********************************************************************************************************************************************************
ok: [localhost] => {
"vlan_output": "is"
}
TASK [assert] **********************************************************************************************************************************************************
ok: [localhost] => {
"changed": false,
"msg": "All assertions passed"
}
PLAY RECAP *************************************************************************************************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
There's a couple of issues here
Firstly, you should not quote "item.vlan_id not in vlan_output" - this is a string and will always evaluate to True.
Secondly, the not in test requires the operands to be type string (currently vlan_id is an integer).
You should see the behaviour you are looking for with these changes:
vars:
vlan_output: "3000 Native active Po121, Po123"
item:
vlan_id: "3000"
state: present
tasks:
- debug: msg="VLAN FAILED"
when: item.state == "present" and item.vlan_id not in vlan_output

Resources