create k8s secrets by using nested ansible loops - ansible

I am trying to create k8s secrets with the storing username and secret in results module of ansible but i created one loop for the name and namespace section and i am trying to create one more loop from the json results output. but it was taking one secret for all the projects
variables:
project_namespaces:
- projectName: helm
Namespaces:
- default
- core
- projectName: proxy
Namespaces:
- default
- core
robot_result:
ok: [harbor_stg1_dkp1] => {
"robot_result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"content_type": "application/json",
"cookies": {
"sid": "557b377ba2bbe3f054d68bd56b0e10ef"
},
"invocation": {
"module_args": {
"attributes": null,
"body": {
"description": "pull artifacts for helm",
"disable": true,
"duration": -1,
"level": "system",
"name": "helm-robot",
"permissions": [
{
"access": [
{
"action": "pull",
"resource": "repository"
}
],
"kind": "project",
"namespace": "helm"
}
]
},
"body_format": "json",
"headers": {
"Accept": "application/json",
"Authorization": "Basic ",
"Content-Type": "application/json"
},
"http_agent": "ansible-httpget",
"status_code": [
201
],
"timeout": 30,
"unix_socket": null,
"validate_certs": false
}
},
"item": {
"name": "helm-robot",
"projectName": "helm"
},
"json": {
"creation_time": "2022-03-21T10:05:49.248Z",
"expires_at": -1,
"id": 67,
"name": "robot#helm-robot",
"secret": "Q8mjthgRJFmscjfmqW1QzXEyKjmLEPQm"
},
"x_envoy_upstream_service_time": "18",
"x_request_id": "496faaa6-bdc4-4e83-890a-2c577576f16b"
},
{
"ansible_loop_var": "item",
"content_type": "application/json",
"cookies": {
"sid": "6275d7bfe74e71db0a3947f4beb1e159"
},
"cookies_string": "sid=6275d7bfe74e71db0a3947f4beb1e159",
"date": "Mon, 21 Mar 2022 10:05:56 GMT",
"elapsed": 1,
"failed": false,
"failed_when_result": false,
"invocation": {
"module_args": {
"attributes": null,
"body": {
"description": "pull artifacts for proxy",
"disable": true,
"duration": -1,
"level": "system",
"name": "proxy-robot",
"permissions": [
{
"access": [
{
"action": "pull",
"resource": "repository"
}
],
"kind": "project",
"namespace": "proxy"
}
]
},
"body_format": "json",
"group": null,
"headers": {
"Accept": "application/json",
"Authorization": "Basic ",
"Content-Type": "application/json"
},
"http_agent": "ansible-httpget",
"method": "POST"
],
"timeout": 30,
"unix_socket": null,
"validate_certs": false
}
},
"item": {
"name": "proxy-robot",
"projectName": "proxy"
},
"json": {
"creation_time": "2022-03-21T10:05:56.807Z",
"expires_at": -1,
"id": 68,
"name": "robot#proxy-robot",
"secret": "slPnm8Zkp0OGBLec6tTcPuPITgOU2PAn"
},
"msg": "OK (144 bytes)",
"x_envoy_upstream_service_time": "15",
"x_request_id": "93478b05-897b-4df9-abb4-e07e03723af0"
}
task.yaml
- name: Create secrets
k8s:
state: present
definition:
apiVersion: v1
kind: Secret
metadata:
name: "{{ item.0.projectName }}"
namespace: "{{ item.1 }}"
stringData:
password: "{{ project.secret }}"
username: "{{ project.name }}"
type: Opaque
vars:
project: "{{ (robot_result.results | json_query('[*].json'))[ansible_loop.index0] }}"
loop: "{{ project_namespaces | subelements('Namespaces') }}"
loop_control:
extended: yes
label: "{{ item.0.projectName }}"
when i executing this task i was getting the output like
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: default, password: Q8mjthgRJFmscjfmqW1QzXEyKjmLEPQm, username: robot#helm-robot"
}
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: core, password: slPnm8Zkp0OGBLec6tTcPuPITgOU2PAn, username: robot#proxy-robot"
}
fatal: [harbor_shiplab_stg1_dkp1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: {{ (robot_result.results | json_query('[*].json'))[ansible_loop.index0] }}: list object has no element 2\n\nThe error appears to be in '/home/ubuntu/konvoy/ansible/roles/harbor-gc/tasks/main.yml': line 47, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Create secrets\n ^ here\n"}
but my requirement would be like this
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: default, password: Q8mjthgRJFmscjfmqW1QzXEyKjmLEPQm, username: robot#helm-robot"
}
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: core, password: Q8mjthgRJFmscjfmqW1QzXEyKjmLEPQm, username: robot#helm-robot"
}
ok: [localhost] => (item=proxy) => {
"msg": "name: proxy, namespace: default, password: slPnm8Zkp0OGBLec6tTcPuPITgOU2PAn, username: robot#proxy-robot"
}
ok: [localhost] => (item=proxy) => {
"msg": "name: proxy, namespace: core, password: slPnm8Zkp0OGBLec6tTcPuPITgOU2PAn, username: robot#proxy-robot"
}
As i am new to this ansible i was not much understanding this loops.Any help or suggestions would be appreciated and Thank you

You have to link secret with projectName:
- name: link projectname and json
set_fact:
dico: "{{ dico | d({}) | combine({item.projectName: project[ansible_loop.index0]}) }}"
vars:
project: "{{ (robot_result.results | json_query('[*].json')) }}"
it: "{{ (robot_result.results | json_query('[*].item')) }}"
loop: "{{ it }}"
loop_control:
extended: yes
- debug:
msg: "name: {{ item.0.projectName }}, namespace: {{ item.1 }}, password: {{ dico[item.0.projectName].secret }}, username: {{ dico[item.0.projectName].username }}" #{{ ansible_loop.index0 }}"
vars:
project: "{{ (robot_result.results | json_query('[*].json')) }}"
loop: "{{ project_namespaces | subelements('Namespaces') }}"
loop_control:
label: "{{ item.0.projectName }}"
result:
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: default, password: YzDDEtJcqYoBL2soZHfTqZxvhIfGKURT, username: robot#helm-robot"
}
ok: [localhost] => (item=helm) => {
"msg": "name: helm, namespace: core, password: YzDDEtJcqYoBL2soZHfTqZxvhIfGKURT, username: robot#helm-robot"
}
ok: [localhost] => (item=proxy) => {
"msg": "name: proxy, namespace: default, password: 7imXCVAGHV91AkeN7LAhWxQHabmYDRmg, username: robot#proxy-robot"
}
ok: [localhost] => (item=proxy) => {
"msg": "name: proxy, namespace: core, password: 7imXCVAGHV91AkeN7LAhWxQHabmYDRmg, username: robot#proxy-robot"
}

Related

In ansible, how to update a value of a dict withing a loop into a list of dict

As i am stuck, i need some help. I want to update a value of a dict in a list of dict (ideally, i don't want to create another list)
Under an ansible playbook i have a variable declared:
a:
- id: 'test1id'
name: 'test1name'
description: ''
- id: 'test2id'
name: 'test2name'
description: 'init'
- id: 'test3id'
name: 'test3name'
description: 'init3'
I have a task that loop into "a" should update the description.
- name: Update description in a
when: a is defined
set_fact:
a: "{{ item | combine({'description': new_description}) }}"
vars:
new_description: "{{ item.description + "test" + item.id }}"
loop: a
Expected result:
a:
- id: 'test1id'
name: 'test1name'
description: 'test test1id'
- id: 'test2id'
name: 'test2name'
description: 'init test test2id'
- id: 'test3id'
name: 'test3name'
description: 'init3 test test3id'
Actual result:
a:
- id: 'test3id'
name: 'test3name'
description: 'init3 test test3id'
Looks like i'm missing something, i just have the last item. I also tried other format but that never give me the expected result.
What you've done is right.
There were some errors, but I think it was caused by a typo, like loop: "{{ a }}" and spaces around the word test here new_description: '{{ item.description + " test " + item.id }}'.
If you run it in debug mode:
ok: [localhost] => (item={'id': 'test1id', 'name': 'test1name', 'description': ''}) => {
"ansible_facts": {
"a": {
"description": " test test1id",
"id": "test1id",
"name": "test1name"
}
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"description": "",
"id": "test1id",
"name": "test1name"
}
}
ok: [localhost] => (item={'id': 'test2id', 'name': 'test2name', 'description': 'init'}) => {
"ansible_facts": {
"a": {
"description": "init test test2id",
"id": "test2id",
"name": "test2name"
}
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"description": "init",
"id": "test2id",
"name": "test2name"
}
}
ok: [localhost] => (item={'id': 'test3id', 'name': 'test3name', 'description': 'init3'}) => {
"ansible_facts": {
"a": {
"description": "init3 test test3id",
"id": "test3id",
"name": "test3name"
}
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"description": "init3",
"id": "test3id",
"name": "test3name"
}
}
You just need to read the values back from ansible_facts you set.
The result should be registered temporarily and then convert the results to the original format with the updated values.
- hosts: localhost
gather_facts: no
vars:
a:
- id: 'test1id'
name: 'test1name'
description: ''
- id: 'test2id'
name: 'test2name'
description: 'init'
- id: 'test3id'
name: 'test3name'
description: 'init3'
tasks:
- name: Update description in a
when: a is defined
set_fact:
a: "{{ item | combine({'description': new_description}) }}"
vars:
new_description: '{{ item.description + " test " + item.id }}'
loop: "{{ a }}"
register: temporary_a
- name: Results
set_fact:
a: "{{ temporary_a.results | map(attribute='ansible_facts.a') | list }}"
- debug:
var: a
Results:
ok: [localhost] => {
"a": [
{
"description": " test test1id",
"id": "test1id",
"name": "test1name"
},
{
"description": "init test test2id",
"id": "test2id",
"name": "test2name"
},
{
"description": "init3 test test3id",
"id": "test3id",
"name": "test3name"
}
]
}

To collect backing_datastore from the vmware_guest_disk_info module output

I'm using the below tasks in the playbook to find the backing datastore in the vmware but I tried various options, which is not helping to gather the backing_datastore name, kindly suggest how to fetch:
- name: Take Snapshot
hosts: patching
serial: 1
vars_files:
- 1credentials.yml
tasks:
- name: Gather data of the registered virtual machines
community.vmware.vmware_vm_info:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
vm_type: vm
validate_certs: no
delegate_to: localhost
register: vminfo
- debug:
msg: "{{ item.datacenter }}"
loop: "{{ vminfo.virtual_machines}}"
when: item.ip_address == inventory_hostname
- name: Gather Disk facts for the server - {{ inventory_hostname }}
vmware_guest_disk_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
datacenter: "{{ item.datacenter }}"
uuid: "{{ item.uuid }}"
validate_certs: False
delegate_to: localhost
register: disk_fact
loop: "{{ vminfo.virtual_machines }}"
when: item.ip_address == inventory_hostname
- debug:
msg: "{{ item.backing_datastore }}"
loop: "{{ disk_fact }}"
The raw output of the registered variable disk_fact is mentioned below:
ok: [172.17.92.62] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"item": {
"allocated": {},
"attributes": {},
"cluster": "Training",
"datacenter": "opendc-rookie",
"datastore_url": [
{
"name": "Rookie-Core",
"url": "/vmfs/volumes/60ebc5fb-2e22fef3-ec42-1402ec6fadc8"
},
{
"name": "ENV08",
"url": "/vmfs/volumes/60ebd414-4e6253d6-7e29-1402ec6fadc8"
}
],
"esxi_hostname": "172.17.138.13",
"folder": "/opendc-rookie/vm/ENV08",
"guest_fullname": "Microsoft Windows 8.x (64-bit)",
"guest_name": "win1",
"ip_address": "172.17.92.43",
"mac_address": [
"00:50:56:81:2e:64"
],
"moid": "vm-968",
"power_state": "poweredOn",
"tags": [],
"uuid": "4201e3dd-0cf5-1027-7eaf-d2b8804761d9",
"vm_network": {
"00:50:56:81:2e:64": {
"ipv4": [
"172.17.92.43"
],
"ipv6": []
}
}
},
"skip_reason": "Conditional result was False",
"skipped": true
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"guest_disk_info": {
"0": {
"backing_datastore": "ENV04",
"backing_disk_mode": "persistent",
"backing_diskmode": "persistent",
"backing_eagerlyscrub": false,
"backing_filename": "[ENV04] ansible_automation_platofrm_RHEL8/ansible_automation_platofrm_RHEL8-000005.vmdk",
"backing_thinprovisioned": false,
"backing_type": "FlatVer2",
"backing_uuid": "6000C294-c77a-56fa-180c-d17ac9693433",
"backing_writethrough": false,
"capacity_in_bytes": 25769803776,
"capacity_in_kb": 25165824,
"controller_bus_number": 0,
"controller_key": 1000,
"controller_type": "paravirtual",
"key": 2000,
"label": "Hard disk 1",
"summary": "25,165,824 KB",
"unit_number": 0
}
},
"invocation": {
"module_args": {
"datacenter": "opendc-rookie",
"folder": null,
"hostname": "172.17.168.212",
"moid": null,
"name": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"use_instance_uuid": false,
"username": "Administrator#vsphere.local",
"uuid": "42013f12-5142-2b83-1ce7-6c334958afd5",
"validate_certs": false
}
},
"item": {
"allocated": {},
"attributes": {},
"cluster": "Training",
"datacenter": "opendc-rookie",
"datastore_url": [
{
"name": "Rookie-Core",
"url": "/vmfs/volumes/60ebc5fb-2e22fef3-ec42-1402ec6fadc8"
},
{
"name": "ENV04",
"url": "/vmfs/volumes/60ebd318-7c586ef0-5838-1402ec6fadc8"
}
],
"esxi_hostname": "172.17.138.13",
"folder": "/opendc-rookie/vm/Pugaz",
"guest_fullname": "Red Hat Enterprise Linux 8 (64-bit)",
"guest_name": "ansible_automation_platofrm_RHEL8",
"ip_address": "172.17.92.62",
"mac_address": [
"00:50:56:81:c6:e3"
],
"moid": "vm-836",
"power_state": "poweredOn",
"tags": [],
"uuid": "42013f12-5142-2b83-1ce7-6c334958afd5",
"vm_network": {
"00:50:56:81:c6:e3": {
"ipv4": [
"172.17.92.62"
],
"ipv6": [
"fe80::250:56ff:fe81:c6e3"
]
}
}
}
}
Kindly suggest how can I fetch the backing_datastore from the above mentioned output.
The result is a list because there might be more items with the attribute backing_datastore. For example,
backing_datastores: "{{ disk_fact.results|json_query(_query) }}"
_query: '[].guest_disk_info[].*.backing_datastore'
gives
backing_datastores:
- - ENV04
If you want the first one
backing_datastore: "{{ backing_datastores|flatten|first }}"
gives
backing_datastore: ENV04
If you want to iterate results
- debug:
msg: "{{ item.guest_disk_info['0'].backing_datastore }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)
gives the attribute backing_datastore of the disk "0"
TASK [debug] **************************************************
skipping: [localhost] => (item=172.17.92.43)
ok: [localhost] => (item=172.17.92.62) =>
msg: ENV04
If you want to get the list of attributes backing_datastore of all disks use json_query in the loop
- debug:
msg: "{{ item.guest_disk_info|json_query('*.backing_datastore') }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)
gives
TASK [debug] **************************************************
skipping: [localhost] => (item=172.17.92.43)
ok: [localhost] => (item=172.17.92.62) =>
msg:
- ENV04
Example of a complete playbook for testing
- hosts: localhost
vars_files:
- disk_fact.json
vars:
backing_datastores: "{{ disk_fact.results|json_query(_query) }}"
_query: '[].guest_disk_info[].*.backing_datastore'
backing_datastore: "{{ backing_datastores|flatten|first }}"
tasks:
- debug:
var: backing_datastores
- debug:
var: backing_datastore
- debug:
msg: "{{ item.guest_disk_info['0'].backing_datastore }}"
loop: "{{ disk_fact.results }}"
loop_control:
label: "{{ item.item.ip_address }}"
when: not item.skipped|d(false)

Ansible vmware_guest module with_items how to loop the debug msg output

I'm trying to deploy some virtual machines which seems to be working fine, and I can get the output to a debug screen, but what I would like is to be able to filter the output a bit and show hostname and IP address really. But I'm not sure how to loop the output! I've tried:
- debug:
msg: {{ item.instance.ipv4 }}
with_items: _result.results
Here is my playbook:
---
- name: Clone VMs
hosts: localhost
gather_facts: false
vars_files:
- vars.yml
- secrets.yml
tasks:
- name: Clone multiple VMs from template
local_action:
module: vmware_guest
hostname: "{{ vcenter_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
validate_certs: no
folder: "{{ folder }}"
template: "{{ item.template }}"
name: "{{ item.name }}"
esxi_hostname: "{{ esxi_hostname }}"
datacenter: "{{ datacenter }}"
state: "{{ state }}"
# customization_spec: "{{ customization_spec }}"
with_items: "{{ servers }}"
register: _result
- name: Output
debug:
msg: "{{ _result.results }}"
#with_items: _result.results.msg
In my vars I have the following (amongst other things)
servers:
- { name: centos8_01, template: centos8 }
- { name: centos7_01, template: centos7-minimal }
The output in the debug currently is:
ok: [localhost] => {
"msg": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"instance": {
"annotation": "",
"current_snapshot": null,
"customvalues": {},
"guest_consolidation_needed": false,
"guest_question": null,
"guest_tools_status": "guestToolsRunning",
"guest_tools_version": "10346",
"hw_cluster": "Cluster",
"hw_cores_per_socket": 1,
"hw_datastores": [
"SSD"
],
"hw_esxi_host": "******",
"hw_eth0": {
"addresstype": "assigned",
"ipaddresses": [],
"label": "Network adapter 1",
"macaddress": "00:50:56:a3:4b:ba",
"macaddress_dash": "00-50-56-a3-4b-ba",
"portgroup_key": null,
"portgroup_portkey": null,
"summary": "10.0.0.0"
},
"hw_files": [
"[SSD] centos8_01/centos8_01.vmx",
"[SSD] centos8_01/centos8_01.nvram",
"[SSD] centos8_01/centos8_01.vmsd",
"[SSD] centos8_01/centos8_01.vmdk"
],
"hw_folder": "/Learn/vm/L2L",
"hw_guest_full_name": "CentOS 8 (64-bit)",
"hw_guest_ha_state": null,
"hw_guest_id": "centos8_64Guest",
"hw_interfaces": [
"eth0"
],
"hw_is_template": false,
"hw_memtotal_mb": 4096,
"hw_name": "centos8_01",
"hw_power_status": "poweredOn",
"hw_processor_count": 2,
"hw_product_uuid": "4223465f-32ce-38ab-0d0e-a92f187b7d4d",
"hw_version": "vmx-14",
"instance_uuid": "5023b456-cda0-1fa6-c0a5-67d57ede5707",
"ipv4": null,
"ipv6": null,
"module_hw": true,
"moid": "vm-12173",
"snapshots": [],
"vimref": "vim.VirtualMachine:vm-12173",
"vnc": {}
},
"invocation": {
"module_args": {
"annotation": null,
"cdrom": [],
"cluster": null,
"convert": null,
"customization": {},
"customization_spec": null,
"customvalues": [],
"datacenter": "******",
"datastore": null,
"disk": [],
"esxi_hostname": "******",
"folder": "L2L",
"force": false,
"guest_id": null,
"hardware": {},
"hostname": "******",
"is_template": false,
"linked_clone": false,
"name": "centos8_01",
"name_match": "first",
"networks": [],
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"resource_pool": null,
"snapshot_src": null,
"state": "poweredon",
"state_change_timeout": 0,
"template": "centos8",
"use_instance_uuid": false,
"username": "******#vsphere.local",
"uuid": null,
"validate_certs": false,
"vapp_properties": [],
"wait_for_customization": false,
"wait_for_ip_address": false
}
},
"item": {
"name": "centos8_01",
"template": "centos8"
}
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"instance": {
"annotation": "",
"current_snapshot": null,
"customvalues": {},
"guest_consolidation_needed": false,
"guest_question": null,
"guest_tools_status": "guestToolsRunning",
"guest_tools_version": "10309",
"hw_cluster": "Corby",
"hw_cores_per_socket": 1,
"hw_datastores": [
"SSD"
],
"hw_esxi_host": "******",
"hw_eth0": {
"addresstype": "assigned",
"ipaddresses": [
"10.0.0.137",
"fe80::e1b4:c7c5:8268:4e7b"
],
"label": "Network adapter 1",
"macaddress": "00:50:56:a3:f8:9f",
"macaddress_dash": "00-50-56-a3-f8-9f",
"portgroup_key": null,
"portgroup_portkey": null,
"summary": "VM Network"
},
"hw_files": [
"[SSD] centos7_01/centos7_01.vmx",
"[SSD] centos7_01/centos7_01.nvram",
"[SSD] centos7_01/centos7_01.vmsd",
"[SSD] centos7_01/centos7_01_2.vmdk"
],
"hw_folder": "/Learn/vm/L2L",
"hw_guest_full_name": "CentOS 6 (64-bit)",
"hw_guest_ha_state": null,
"hw_guest_id": "centos6_64Guest",
"hw_interfaces": [
"eth0"
],
"hw_is_template": false,
"hw_memtotal_mb": 2048,
"hw_name": "centos7_01",
"hw_power_status": "poweredOn",
"hw_processor_count": 1,
"hw_product_uuid": "4223d5ef-9363-03d4-8aea-7b1822b21e36",
"hw_version": "vmx-14",
"instance_uuid": "5023eea9-85ac-1c18-48bb-e0b63339c9fa",
"ipv4": "10.0.0.137",
"ipv6": null,
"module_hw": true,
"moid": "vm-12174",
"snapshots": [],
"vimref": "vim.VirtualMachine:vm-12174",
"vnc": {}
},
"invocation": {
"module_args": {
"annotation": null,
"cdrom": [],
"cluster": null,
"convert": null,
"customization": {},
"customization_spec": null,
"customvalues": [],
"datacenter": "******",
"datastore": null,
"disk": [],
"esxi_hostname": "******",
"folder": "******",
"force": false,
"guest_id": null,
"hardware": {},
"hostname": "******",
"is_template": false,
"linked_clone": false,
"name": "centos7_01",
"name_match": "first",
"networks": [],
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"resource_pool": null,
"snapshot_src": null,
"state": "poweredon",
"state_change_timeout": 0,
"template": "centos7-minimal",
"use_instance_uuid": false,
"username": "******",
"uuid": null,
"validate_certs": false,
"vapp_properties": [],
"wait_for_customization": false,
"wait_for_ip_address": false
}
},
"item": {
"name": "centos7_01",
"template": "centos7-minimal"
}
}
]
}
There are multiple ways to do this.
A loop is one of them:
- debug:
msg:
hostname: "{{ item.invocation.module_args.hostname }}"
ip: "{{ item.instance.ipv4 }}"
loop: "{{ _result.results }}"
loop_control:
label: "item.invocation.module_args.hostname"
This would yield:
ok: [localhost] => (item=item.invocation.module_args.hostname) =>
msg:
hostname: '******'
ip: ''
ok: [localhost] => (item=item.invocation.module_args.hostname) =>
msg:
hostname: '******'
ip: 10.0.0.137
Another solution is to use JMESPath and the json_query filter:
- debug:
var: >-
_result.results
| json_query('[].{
hostname: invocation.module_args.hostname, ip: instance.ipv4
}')
This would yield:
ok: [localhost] =>
? |-
_result.results | json_query('[].{
hostname: invocation.module_args.hostname, ip: instance.ipv4
}')
: - hostname: '******'
ip: null
- hostname: '******'
ip: 10.0.0.137

Locate string/integer not in list

Im pulling a list of VLANs from our IPAM via an API and I want to be able to locate an unused "vlanId" that isnt in the list. I was expecting that I could use with_items for the JSON content and then use the random function with an until loop and occasionally it will initially generate a number that doesnt exist in the list. Mostly it just gets stuck and doesnt generate a new random number when the one generated already exists.
Playbook:
- uri:
url: "#"
validate_certs: no
headers:
token: "{{ token }}"
method: GET
force_basic_auth: yes
return_content: yes
register: ipam
- set_fact:
value: "{{ 4094 | random(start=1) }}"
until: value not in item.vlanId
with_items: "{{ ipam.json.data }}"
retries: 4093
- debug: msg="{{ value }}"
Relevant Output:
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2241', u'vlanId': u'548', u'name': u'2241', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "2727"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2241",
"number": "2241",
"vlanId": "548"
}
}
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2242', u'vlanId': u'549', u'name': u'2242', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "1955"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2242",
"number": "2242",
"vlanId": "549"
}
}
FAILED - RETRYING: set_fact (4000 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3999 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 2,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3998 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 3,
"changed": false,
"retries": 4001
Im currently using ansible 2.4.2.0
If this is something that cant/shouldnt be done in Ansible, any guidance would be appreciated.
Here's what you want:
- debug:
msg: "{{ range(1, 4095) | difference(vlanIds) | random }}"
vars:
vlanIds: "{{ ipam.json.data | map(attribute='vlanId') | list }}"
Explanation:
map(attribute=... - create a list of vlan IDs,
range - generate a sequence from 1 to 4094,
difference - select all the elements from the above. that are not on the vlanIds list,
random - select a random element from the above.
For strings (as the title suggests) replace range with a list of possible strings.

ansible V2 -> "skip_reason": "Conditional check failed" with_items

I am getting some errors while doing the following:
group_vars:
tomcat_servers:
- name: tomcat_1
shutdown_port: 8005
connector_port: 8080
ajp_port: 8009
- name: tomcat_2
shutdown_port: 8105
connector_port: 8180
ajp_port: 8109
main code:
- name: "Check if tomcat is already installed"
stat: path={{ tomcat_server_dir }}/{{ item.name }}/RELEASE-NOTES
register: status
with_items: "{{ tomcat_servers }}"
- debug: var=status
- name: "Copy tomcat into folder if it is not installed"
command: /bin/tar -zxvf /tmp/{{ tomcat_catalina_base }} -C {{ tomcat_server_dir }}/{{ item.name }} --strip 2
when: not status.results[0].stat.exists
with_items:
- "{{ tomcat_servers }}"
- "{{ status.results }}"
Debug result:
ok: [VM1] => {
"status": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8009,
"connector_port": 8080,
"name": "tomcat_1",
"shutdown_port": 8005
},
"stat": {
"exists": false
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8109,
"connector_port": 8180,
"name": "tomcat_2",
"shutdown_port": 8105
},
"stat": {
"exists": false
}
}
]
}
}
Now unfortunally I seem to get the error
"skip_reason": "Conditional check failed", "skipped": true
I have been around the "have you googled it" many times but cannot seem to find the solution here. Google ansible check if file exists with_items and you will probably see the same results.
Any one got an idea how to get this working?
Correct second loop:
---
- hosts: localhost
vars:
results:
- item:
ajp_port: 8009
connector_port: 8080
name: tomcat_1
shutdown_port: 8005
stat:
exists: false
- item:
ajp_port: 8109
connector_port: 8180
name: tomcat_2
shutdown_port: 8105
stat:
exists: false
- item:
name: tomcat_exist
stat:
exists: true
tasks:
- debug:
msg: "name: {{ item.item.name }}, exists: {{ item.stat.exists }}"
when: not item.stat.exists
with_items: "{{ results }}"
So in your setup you need to loop over status.results and refer to item.item.name and item.stat.exists.

Resources