I have a json file (/tmp/lst_instalaciones_wordpress.json) on a group of servers.
This json has the info about some Wordpress installs (domain, path, version...)
{
"id": 1,
"name": "My blog",
"version": "5.9.1",
"fullPath": "/var/www/vhosts/myblog"
}
{
"id": 2,
"name": "My blog2",
"version": "5.9.2",
"fullPath": "/var/www/vhosts/myblog2"
}
{
"id": 3,
"name": "My blog3",
"version": "5.7.6",
"fullPath": "/var/www/vhosts/myblog3"
}
{
"id": 4,
"name": "My blog4",
"version": "5.9.2",
"fullPath": "/var/www/vhosts/myblog4"
}
I slurped it in a var:
- slurp:
src: /tmp/lst_instalaciones_wordpress.json
register: fichero_json
- set_fact:
lst_versiones: "{{ fichero_json.content | b64decode | from_json}}"
I have a list of all the versions, and I need to print how much installs are for each versions.
all_vers:
- 5.7.6
- 5.9.1
- 5.9.2
I'am trying different options like this but nothing works:
- set_fact:
all_installs_vers: "{{ lst_versiones | json_query('[?version==`'{{item}}'`].version') | length }}"
with_items: "{{all_vers}}"
Given the fixed YAML
shell> cat tmp/lst_instalaciones_wordpress.yml
---
[
{
"id": 1,
"name": "My blog",
"version": "5.9.1",
"fullPath": "/var/www/vhosts/myblog"
},
{
"id": 2,
"name": "My blog2",
"version": "5.9.2",
"fullPath": "/var/www/vhosts/myblog2"
},
{
"id": 3,
"name": "My blog3",
"version": "5.7.6",
"fullPath": "/var/www/vhosts/myblog3"
},
{
"id": 4,
"name": "My blog4",
"version": "5.9.2",
"fullPath": "/var/www/vhosts/myblog4"
}
]
Read the file and decode the list
- slurp:
src: tmp/lst_instalaciones_wordpress.yml
register: fichero_json
- set_fact:
lst_versiones: "{{ fichero_json.content|b64decode|from_yaml }}"
gives
lst_versiones:
- fullPath: /var/www/vhosts/myblog
id: 1
name: My blog
version: 5.9.1
- fullPath: /var/www/vhosts/myblog2
id: 2
name: My blog2
version: 5.9.2
- fullPath: /var/www/vhosts/myblog3
id: 3
name: My blog3
version: 5.7.6
- fullPath: /var/www/vhosts/myblog4
id: 4
name: My blog4
version: 5.9.2
Then, given the list of the versions
all_vers:
- 5.7.6
- 5.9.1
- 5.9.2
iterate the list, select the version, count the items and combine the dictionary
- set_fact:
all_installs_vers: "{{ all_installs_vers|d({})|
combine({item: _val|int}) }}"
loop: "{{ all_vers }}"
vars:
_val: "{{ lst_versiones|selectattr('version', 'eq', item)|length }}"
gives
all_installs_vers:
5.7.6: 1
5.9.1: 1
5.9.2: 2
Another solution with only one step
- set_fact:
versions: "{{ versions | d({}) | combine({ item.version: nbversion }) }}"
loop: '{{ lst_versiones }}'
vars:
nbversion: >-
{{ (versions[item.version] | int + 1) if versions[item.version] is defined
else (1 | int) }}
result if you debug versions:
ok: [localhost] => {
"msg": {
"5.7.6": "1",
"5.9.1": "1",
"5.9.2": "2"
}
}
Related
This ansible playbook works
---
- hosts: localhost
gather_facts: False
vars:
jq: "[?contains(name, 'Pizza')]"
json: |
[{
"name": "Ted's Sub Shop - 720895714701",
"templateid": "24632"
},
{
"name": "Ted's Pizza - 720895714702",
"templateid": "24663"
}]
tasks:
- name: DEBUG
debug:
msg: "{{ json | from_json | json_query(jq) }}"
It returns the following
ok: [localhost] => {
"msg": [
{
"name": "Ted's Pizza - 720895714702",
"templateid": "24663"
}
]
}
I need to take it a few steps further and when the value of name contains Pizza I need it to return just the 12 digit number on the end. So the return output would look like this
ok: [localhost] => {
"msg": "720895714702"
}
Thoughts?
you could try
- name: testplaybook jinja2
hosts: localhost
gather_facts: no
vars:
json: |
[{
"name": "Ted's Sub Shop - 720895714701",
"templateid": "24632"
},
{
"name": "Ted's Pizza - 720895714702",
"templateid": "24663"
}]
tasks:
- name: DEBUG
debug:
msg: "{{ json | from_json | selectattr('name', 'contains' , 'Pizza')
| map(attribute='name')
| map('regex_replace', '^.*?(\\d*)$', '\\1')}}"
result:
ok: [localhost] => {
"msg": [
"720895714702"
]
}
It might be more efficient to add an attribute. For example the declaration below
json_id: "{{ json|zip(id_hash)|map('combine')|list }}"
id_hash: "{{ id_list|
map('community.general.dict_kv', 'id')|list }}"
id_list: "{{ json|
map(attribute='name')|
map('split', '-')|
map('last')|
map('int')|list }}"
expands to
json_id:
- id: 720895714701
name: Ted's Sub Shop - 720895714701
templateid: '24632'
- id: 720895714702
name: Ted's Pizza - 720895714702
templateid: '24663'
Then, the usage is trivial. For example
- debug:
msg: "{{ json_id|
selectattr('name', 'contains' , 'Pizza')|
map(attribute='id')|list }}"
gives
msg:
- 720895714702
The same result gives also json_query below
- debug:
msg: "{{ json_id|
json_query('[?contains(name, `Pizza`)].id') }}"
I am using the Ansible vmware_vm_info module to generate json like this:
{
"virtual_machines": [
{
"guest_name": "serverx",
"datacenter": "datacenter",
"guest_fullname": "Red Hat Enterprise Linux 7 (64-bit)",
"esxi_hostname": "host1",
"tags": [
],
"cluster": "cluster1",
"vm_network": {
},
"mac_address": [
],
"attributes": {
},
"folder": "",
"power_state": "poweredOff",
"ip_address": "",
"uuid": "33234323oijdlk"
},
{
"guest_name": "server2_01112022",
"datacenter": "datacenter",
"guest_fullname": "Microsoft Windows Server 2012 (64-bit)",
"esxi_hostname": "host1",
"tags": [
],
"cluster": "cluster1",
"vm_network": {
},
"mac_address": [
],
"attributes": {
},
"folder": "",
"power_state": "poweredOff",
"ip_address": "",
"uuid": "287292lkqjjjjd"
},
I have a variable that reads a csv and sets the vmname like this:
vmname
server1
server2
I need set a new fact that will look for the vmname string existing in the vminfo json output. In the example above, server2 would match server2_01112022.
I have tried the following but I don't get a match:
- set_fact:
renamedvm: "{{ item.guest_name }}"
with_items:
- "{{ vminfo.virtual_machines }}"
when:
- item.guest_name |regex_search('^result_item.vmname.$')
For example, given the list
vmname: [server1, server2]
the task
- set_fact:
renamedvm: "{{ renamedvm|d({})|combine({item: _value}) }}"
loop: "{{ vmname|unique|sort }}"
vars:
_selection: "{{ virtual_machines|selectattr('guest_name', 'search', item) }}"
_value: "{{ _selection|map(attribute='guest_fullname')|list }}"
gives
renamedvm:
server1: []
server2:
- Microsoft Windows Server 2012 (64-bit)
I am trying to loop over 2 different JSON array and filter only if the 2 key values are same.
I am comparing cidr from po-orig.json/po file and subnet from pocooling json. If the key values are same in both file, then print the pertaining details of pocooling json file as a list.
- name: Combine GP MGMT
vars:
pocidr: >-
{{
po
| json_query('ansible_facts.policyobject[].json[]')
}}
poname: >-
{{
pocidr
| selectattr('cidr', '==', item.subnet)
| map(attribute='name')
| list
}}
set_fact:
result: >-
{{
result | default([])
+
[poname]
}}
with_items: "{{ pocooling }}"
Updated code
- name: Compare the Current & Actual GP policy
set_fact:
pocidr: "{{ po | json_query(\"ansible_facts.policyobject[].json[]\") }}"
- name: Combine GP MGMT
vars:
poname:
"{{
pocidr
| selectattr('cidr', '==', item.subnet)
| map(attribute='name')
| first
}}"
set_fact:
result:
"{{
result | default([])
+
[poname]
}}"
with_items: "{{ pocooling }}"
pocooling.json
[
{
"applianceIp": "10.10.10.10",
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"dhcpOptions": [],
"dnsNameservers": "upstream_dns",
"fixedIpAssignments": {},
"id": 2222,
"name": "Cooling",
"networkId": "78984654989",
"reservedIpRanges": [],
"subnet": "10.10.10.0/28"
},
{
"applianceIp": "10.10.10.10",
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"dhcpOptions": [],
"dnsNameservers": "upstream_dns",
"fixedIpAssignments": {},
"id": 2222,
"name": "Cooling",
"networkId": "123456789",
"reservedIpRanges": [],
"subnet": "10.11.11.0/28"
}
]
po-orig.json(po)
{
"ansible_facts":{
"policyobject":[
{
"invocation":{
"module_args":{
"status_code":[
200,
201,
202
],
"validate_certs":false
}
},
"item":{
"id":"123456",
"name":"DC"
},
"json":[
{
"category":"network",
"cidr":"10.1.1.1/28",
"createdAt":"2021-11-23T19:48:21Z",
"groupIds":[
],
"id":"545649843651365",
"name":"JM-Privat",
"networkIds":[
"545649843651365"
],
"type":"cidr",
"updatedAt":"2021-11-23T19:48:21Z"
},
{
"category":"network",
"cidr":"10.10.10.0/28",
"createdAt":"2021-12-07T13:54:05Z",
"groupIds":[
"897987654689854"
],
"id":"564678984565465",
"name":"PO-L-DE-MCC-COOLING_DMZ_LAB",
"networkIds":[
],
"type":"cidr",
"updatedAt":"2021-12-07T13:54:05Z"
}
]
}
]
}
}
Error:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: {{ pocidr\n | selectattr('cidr', '==', item.subnet)\n | map(attribute='name')\n | list\n}}: 'dict object' has no attribute 'cidr
Expected result
[
{
"applianceIp": "10.10.10.10",
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"dhcpOptions": [],
"dnsNameservers": "upstream_dns",
"fixedIpAssignments": {},
"id": 2222,
"name": "Cooling",
"networkId": "78984654989",
"reservedIpRanges": [],
"subnet": "10.10.10.0/28"
}
]
Complete Playbook
- name: Test
hosts: localhost
connection: local
gather_facts: false
vars:
pocooling: "{{ lookup('file', 'pocooling.json') | from_json }}"
tasks:
- include_vars:
file: po-orig.json
name: po
- name: Combine GP MGMT
vars:
poname: "{{ po|json_query('ansible_facts.policyobject[].json[]')|
selectattr('cidr', '==', item.subnet)|
map(attribute='name')|
list }}"
set_fact:
result: "{{ result|default([]) + [poname] }}"
loop: "{{ pocooling }}"
Given the list
pocooling:
- networkId: '78984654989'
subnet: 10.10.10.0/28
- networkId: '123456789'
subnet: 10.11.11.0/28
Select list of cidr
_cidr: "{{ ansible_facts.policyobject|json_query('[].json[].cidr') }}"
gives
_cidr:
- 10.1.1.1/28
- 10.10.10.0/28
Then select the items that fit the condition
- debug:
msg: "{{ pocooling|selectattr('subnet', 'in' , _cidr) }}"
vars:
_cidr: "{{ ansible_facts.policyobject|json_query('[].json[].cidr') }}"
gives
msg:
- networkId: '78984654989'
subnet: 10.10.10.0/28
Your code, fixed and simplified
- include_vars:
file: po-orig.json
name: po
- name: Combine GP MGMT
vars:
poname: "{{ po|json_query('ansible_facts.policyobject[].json[]')|
selectattr('cidr', '==', item.subnet)|
map(attribute='name')|
list }}"
set_fact:
result: "{{ result|default([]) + [poname] }}"
loop: "{{ pocooling }}"
gives
result:
- - PO-L-DE-MCC-COOLING_DMZ_LAB
- []
I have a json file with server information and the applications related.
Something like this:
{
"Apps": [
{
"AppOwner": "Me",
"AppNm": "Vacations"
}
],
"Hostnm": "some_server",
"Environment": "Prod",
"OSnm": "Windows Server 2008",
"OSManu": "Microsoft",
"SerialNum": "VMware-42 14 e1 37 7a 63 9b 0e-43 07 15 46 64 9c 3c 12"
}
I want to create a list with all the applications and the servers related
For example
{
"Vacations": [server1, server2]
},
{
"other_app": [server2, server3]
},
For that, I have been trying the following.
- set_fact:
apps: "{{ apps }} + {{ item.Apps | map(attribute='AppNm') | list}}"
loop: "{{ server_changes }}"
- set_fact:
apps_revised: "{{apps | unique}}"
- set_fact:
apps_server: "{{ apps_revised | default([]) + [{item : []}] }}"
with_items: "{{ apps_revised }}"
The first part of the code, will obtain all the applications with the duplicates from the json.
The second part of the code, will clean the apps with unique.
The last part its going to create a list of application with a nested list (of servers).
The problem is that I don't understand how to navigate the nested server_changes application list and then add the server to my new list.
Probably there is an easier way to do it, so any help will be appreciated.
Thanks
Given a test data
server_changes:
- "Apps":
- {"AppOwner": "Me", "AppNm": "Vacations"}
"Hostnm": "server1"
- "Apps":
- {"AppOwner": "Me", "AppNm": "Vacations"}
- {"AppOwner": "Me", "AppNm": "other_app"}
"Hostnm": "server2"
- "Apps":
- {"AppOwner": "Me", "AppNm": "other_app"}
"Hostnm": "server3"
Let's simplify the data. For example
- set_fact:
my_server_changes: "{{ my_server_changes|default([]) +
[{'hostname': item.Hostnm,
'applications': item.Apps|
json_query('[].AppNm')}] }}"
loop: "{{ server_changes }}"
- debug:
var: my_server_changes
gives
"my_server_changes": [
{
"applications": [
"Vacations"
],
"hostname": "server1"
},
{
"applications": [
"Vacations",
"other_app"
],
"hostname": "server2"
},
{
"applications": [
"other_app"
],
"hostname": "server3"
}
]
Create the list of the applications
- set_fact:
my_apps: "{{ server_changes|json_query('[].Apps[].AppNm')|unique }}"
- debug:
var: my_apps
gives
"my_apps": [
"Vacations",
"other_app"
]
Then loop the list of the applications, select records that contains the item and combine the dictionary
- set_fact:
apps_server: "{{ apps_server|default({})|
combine({item: my_server_changes|json_query(query)}) }}"
loop: "{{ my_apps }}"
vars:
query: "[?applications.contains(#, '{{ item }}')].hostname"
- debug:
var: apps_server
gives
"apps_server": {
"Vacations": [
"server1",
"server2"
],
"other_app": [
"server2",
"server3"
]
}
I'm trying to use a variable in a variable.
I have one JSON variable :
os: {
"centos_7_5": {
offer: "CentOS",
publisher: "OpenLogic",
sku: "7.5",
version: "latest"
},
"debian_9": {
offer: "Debian",
publisher: "credativ",
sku: "9",
version: "latest"
}
}
If I use
- debug:
msg: " {{ os.debian_9.offer }}"
The output is as desired :
"msg": " Debian"
Now, I'm trying to put the OS name in a variable (so that the variable can be in a config file) as follows :
desired_os: debian_9
I would like to do something like this :
- debug:
msg: " {{ os.desired_os.offer }}"
But I can't find a way to make it work.
I tried some concatenation in a set_fact using '{{ "os."~desired_os~".offer" }}' but the output is not as desired :
"msg": "stuff.os.debian_9.offer"
Thanks.
Hi try use this snippet:
json
{
"os": {
"centos_7_5": {
"offer": "CentOS",
"publisher": "OpenLogic",
"sku": "7.5",
"version": "latest"
},
"debian_9": {
"offer": "Debian",
"publisher": "credativ",
"sku": "9",
"version": "latest"
}
}
}
playbook:
---
- hosts: all
gather_facts: False
vars:
jsonVar: "{{ lookup('file', 'j.json') | from_json }}"
dist: "debian_9"
tasks:
- name: test loop
debug: msg="{{ jsonVar['os'][dist] }}"
You can use the varname[var] notation.
- hosts: localhost
gather_facts: no
vars:
os: {
"centos_7_5": {
offer: "CentOS",
publisher: "OpenLogic",
sku: "7.5",
version: "latest"
},
"debian_9": {
offer: "Debian",
publisher: "credativ",
sku: "9",
version: "latest"
}
}
desired_os: debian_9
tasks:
- debug:
msg: " {{ os['debian_9'].offer }}"
- debug:
msg: " {{ os[desired_os].offer }}"
Simply add the variable within double brackets.
- debug:
msg: " {{ os.{{ desired_os }}.offer }}"
Please try as below
debug: msg= "{{os.vars[desired_os].offer}}"