Ansible parse JSON output - ansible

I am trying to parse the Ansible output the print a value
- name: Creating a new instance
os_server:
state: present
auth:
auth_url: "{{ auth_url }}"
username: "{{ username }}"
password: "{{ password }}"
project_name: "{{ project_name }}"
name: "{{ item.hostname }}"
image: "{{ item.image }}"
nics: "{{ nics }}"
with_items: "{{ servers }}"
register: "os"
Output:
"server": {
"OS-DCF:diskConfig": "MANUAL",
"OS-EXT-AZ:availability_zone": "zoneA",
"OS-EXT-STS:power_state": 1,
"OS-EXT-STS:task_state": null,
"OS-EXT-STS:vm_state": "active",
"OS-SRV-USG:launched_at": "2018-04-01T18:53:16.000000",
"OS-SRV-USG:terminated_at": null,
"accessIPv4": "10.190.230.23",
"accessIPv6": "",
"addresses": {
"provider_corenet_bif_757": [
{
"OS-EXT-IPS-MAC:mac_addr": "fa:1:3:3:5e:6a",
"OS-EXT-IPS:type": "fixed",
"addr": "10.19.23.23",
"version": 4
}
],
"provider_nmnet_bif_912": [
{
"OS-EXT-IPS-MAC:mac_addr": "fa:1:3:39:b:57",
"OS-EXT-IPS:type": "fixed",
"addr": "10.25.13.64",
"version": 4
}
]
server.addresses.provider_nmnet_bif_912.addr
},
I want to parse addr "10.25.13.64".
I tried {{ item.server.addresses.provider_nmnet_bif_912.addr }} and {{os.server.addresses.provider_nmnet_bif_912.addr}} both didnot work.
Need Help!!!

Finally figured it out:
"{{ item.server.addresses.provider_nmnet_bif_912[0].addr }}"

Related

Register return values from tasks_from when looping over include_role

I'd like to build an array of ticket numbers that are created by the create_srq.yaml task in role servicenow. Is it possible to do this when looping over an include_role?
roles/request_signed_certificate/tasks/main.yaml
- name: Create SNOW Records for Certificate Request
include_role:
name: servicenow
tasks_from: create_srq.yaml
register: result
loop: "{{ spreadsheet }}"
loop_control:
loop_var: csr
vars:
short_description: CSR for {{ csr.certname }}-{{ csr.env }}
attachment: "{{ cert_path }}/{{ csr.certname }}-{{ csr.env }}.csr"
- name: debug
debug:
var: result
roles/servicenow/tasks/create_srq.yaml
- name: Create a SRQ
snow_record:
state: present
table: u_request
username: "{{ snow_username }}"
password: "{{ snow_password }}"
instance: "{{ servicenow_instance }}"
data:
short_description: "{{ short_description }}"
attachment: "{{ attachment }}"
register: srq
- name: Attach file to {{ srq.record.number }}
snow_record:
state: present
table: u_request
username: "{{ snow_username }}"
password: "{{ snow_password }}"
instance: "{{ servicenow_instance }}"
number: "{{ srq.record.number }}"
attachment: "{{ attachment }}"
When running the playbook:
---
- hosts: "{{ hosts_list }}"
connection: local
gather_facts: false
vars:
cert_path: "/tmp/certs"
cert_version: "2023"
pre_tasks:
- name: Create facts from csv
csv_to_facts:
src: "file.csv"
delegate_to: localhost
run_once: true
roles:
- role: request_signed_certificate
The result does not include the registered srq variable from create_srq.yaml:
TASK [request_signed_certificate : debug] **************************************************************
ok: [host.example.com] => {
"result": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "csr",
"csr": {
"certname": "example_one",
"common_name": "domain_one.example.com",
"dns1": "domain_two.example.com",
"env": "development",
},
"include_args": {
"name": "servicenow",
"tasks_from": "create_srq.yaml"
}
},
{
"ansible_loop_var": "csr",
"csr": {
"certname": "example_two",
"common_name": "domain_123.example.com",
"dns1": "domain_456.example.com",
"env": "test",
},
"include_args": {
"name": "servicenow",
"tasks_from": "create_srq.yaml"
}
}
]
}
}
I was able to do this by appending results to a list. While this works, it wasn't exactly what I was after as I would have preferred to install a reusable role to create the srqs.
Adding this bit to the bottom of create_srq.yaml gave me what I was looking for:
- name: output csv entry + ticket number
set_fact:
csv: "{{ csv | default({}) | combine ( { item.key : item.value } ) | combine( { 'ticket': srq.record.number } ) }}"
loop: "{{ csr | dict2items }}"
# Create list of dictionaries to track
# also, a list is required for the to_csv plugin
- name: create list of dicts
set_fact:
contents: "{{ contents | default([]) + [ csv ] }}"

ansible create a new dict and add to list

my playbook always show me just last value , looks like the script is overwrite.
From json file I need extract some value, create dictionary and put it to the list.
My json file .
{
"rade": [
{
"apiRawValues": {
"verificationStatus": "signature-verified"
},
"deviceReference": {
"name": "bigip02"
},
"port": "Ir_HTTP_HTTPs"
},
{
"apiRawValues": {
"verificationStatus": "signature-verified"
},
"deviceReference": {
"name": "bigip01"
},
"port": "Ir_HTTP_HTTPs"
}
]
}
and my playbook look like
---
- hosts: localhost
connection: local
gather_facts: false
vars:
cert1: {}
vars_files:
tasks:
- name : deploy json file AS3 to F5
set_fact:
json_file: "{{ lookup('file', 'parse2.json') }}"
- name: create dic and create list
set_fact:
cert1: "{{ cert1 | d({}) | combine({ 'device': item['deviceReference']['name']}, { 'port': item.port}, recursive=True) }}"
loop: "{{ json_file['rade'] }}"
- name: debug4
debug:
msg: "{{ cert1 }}"
the result is
ok: [localhost] => {
"msg": {
"device": "bigip01",
"port": "Ir_HTTP_HTTPs"
}
}
why it just show me last value ?
I need list of device and port.
thank you for help
The filter json_query makes it simpler e.g.
- debug:
msg: "{{ json_file.rade|
json_query('[].{device: deviceReference.name, port: port}') }}"
gives
msg:
- device: bigip02
port: Ir_HTTP_HTTPs
- device: bigip01
port: Ir_HTTP_HTTPs
If the names of the devices are unique you can create a dictionary, e.g.
- debug:
msg: "{{ dict(_keys|zip(_vals)) }}"
vars:
_keys: "{{ json_file.rade|map(attribute='deviceReference.name')|list }}"
_vals: "{{ json_file.rade|map(attribute='port')|list }}"
gives
msg:
bigip01: Ir_HTTP_HTTPs
bigip02: Ir_HTTP_HTTPs
I have found out solution
- name: create dic and create list
set_fact:
cert1: "{{ cert1 | default([]) + [{ 'device' : item['deviceReference']['name'], 'irule' : item.port }] }}"
loop: "{{ json_file['rade'] }}"
- name: debug4
debug:
msg: "{{ cert1 }}"

Filter debug msg

I am using Ansible 2.9.13 and I have this playbook:
---
- hosts: localhost
connection: local
vars:
ansible_python_interpreter: /usr/bin/env python3
vars_files:
- vars.yml
tasks:
- name: Get Tags from given VM Name
vmware_vm_info:
validate_certs: no
hostname: '{{ vcenter_server }}'
username: '{{ vcenter_user }}'
password: '{{ vcenter_pass }}'
folder: '{{ provision_folder }}'
delegate_to: localhost
register: vm_info
- debug:
msg: "{{ vm_info.virtual_machines | json_query(query) }}"
vars:
query: "[?guest_name=='C97A1612171478']"
When I run it I am getting this output:
ok: [localhost] => {
"msg": [
{
"attributes": {},
"cluster": "xxx01",
"esxi_hostname": "xxxx",
"guest_fullname": "Microsoft Windows 10 (64-bit)",
"guest_name": "C97A1612171478",
"ip_address": "10.x.x.x",
"mac_address": [
"0x:x:x:x:xd:x"
],
"power_state": "poweredOn",
"tags": [],
"uuid": "420xxaf-xxx-xe2-9xe-a5xxxxxa3c",
"vm_network": {
"0x:x:x:xa:x:x": {
"ipv4": [
"169.x.x.x"
],
"ipv6": [
"x::x:x:x:xc"
]
},
"x:x:x:x:x0:x1": {
"ipv4": [
"169.x.x.x"
],
"ipv6": [
"x::x7:xf:x:x"
]
},
"0x:5x:x:x:ax:x": {
"ipv4": [
"10.x.x.x"
],
"ipv6": [
"x::1xx:x:8xx:x"
]
}
}
}
]
}
How can I filter the output to make it show only the "ip_address": "10.x.x.x".
In the end only the 10.x.x.x.
I have tried some ways adding the key ip_address in the message code but all of them gave me an error.
I can filter the msg using Python but if there's a way to get it using Ansible I would like to know how.
If you want to get this information without a loop:
If you need an object as a result:
- debug:
msg: "{{ vm_info.virtual_machines | json_query(query) }}"
vars:
query: "[?guest_name=='C97A1612171478'] | [0].{ip_address: ip_address}"
will yield
{
"ip_address": "10.x.x.x"
}
If you need a string as a result:
- debug:
msg: "{{ vm_info.virtual_machines | json_query(query) }}"
vars:
query: "[?guest_name=='C97A1612171478'] | [0].ip_address"
will yield
"10.x.x.x"
I can't test this properly, but try to fiddle around with the following code:
- debug:
msg: "{{ item.ip_address | json_query(query) }}"
loop: "{{ vm_info.virtual_machines }}"
vars:
query: "[?guest_name=='C97A1612171478']"

Ansible - using for loops inside user module

I recently discovered the use of for loops in Ansible and was very excited about it.
Tries to use it inside the debug module and it worked superfine, but when I am trying to use the same inside "user" module, the control flow is not able to identify the "name" keyword of user module. Below is my poetry,
- hosts: testservers
tasks:
- name: Setting user facts
set_fact:
username: "{{ lookup('ini', 'name section=userDetails file=details.ini') }}"
userpass: "{{ lookup('ini', 'password section=userDetails file=details.ini') }}"
- name: User creation
become: true
# debug:
# msg: |
# {% for x,y in item.1,item.2 %}
# {{ x }} is the username and its password is {{ y }}
# {% endfor %}
# with_items:
# - { 1: "{{ username.split(',') }}", 2: "{{ userpass.split(',') }}" }
user: |
{% for x,y in item.1,item.2 %}
name: "{{ x }}"
password: "{{ y }}"
{% endfor %}
with_items:
- { 1: "{{ username.split(',') }}", 2: "{{ userpass.split(',') }}" }
Details.ini file contents below
#User basic details
[userDetails]
name=vasanth,vasanthnagkv
password=vasanth12,pass2
The commented part above works fine. but the uncommented part throws the below error
failed: [10.0.0.47] (item={1: [u'vasanth', u'vasanthnagkv'], 2: [u'vasanth12', u'pass2']}) => {
"changed": false,
"invocation": {
"module_args": {
"append": false,
"create_home": true,
"force": false,
"move_home": false,
"non_unique": false,
"remove": false,
"ssh_key_bits": 0,
"ssh_key_comment": "ansible-generated on APUA-02",
"ssh_key_type": "rsa",
"state": "present",
"system": false,
"update_password": "always"
}
},
"item": {
"1": [
"vasanth",
"vasanthnagkv"
],
"2": [
"vasanth12",
"pass2"
]
},
"msg": "missing required arguments: name"
}
to retry, use: --limit #/home/admin/ansiblePlaybooks/userCreation/userCreate.retry
PLAY RECAP ************************************************************************************************************************************************************************************
10.0.0.47 : ok=2 changed=0 unreachable=0 failed=1
Appreciate any kind of help here.
This line user: | means your passing a string to user module using the block style indicator: https://yaml-multiline.info/)
Since Ansible will just treat it as a string, you are not passing the required name parameter to the user module
Try splitting the names after the lookup in the first task so you can have the names and passwords list:
- name: Setting user facts
set_fact:
username: "{{ lookup('ini', 'name section=userDetails file=details.ini').split(',') }}"
userpass: "{{ lookup('ini', 'password section=userDetails file=details.ini').split(',') }}"
Once you have both the username and password list, you can use both variables by:
- user:
name: "{{ item }}"
password: "{{ userpass[index] }}"
loop: "{{ username }}"
loop_control:
index_var: index

How to do multi-conditional loops with Ansible?

I have roles and users. I would like to loop over my roles for users that contains the state=present.
iam_roles:
- name: "developers-role"
assume_role_policy_document: "developers"
state: present
managed_policy:
- arn:aws:iam::XXXXXXXXXXX:policy/CustomAmazonS3ReadOnlyAccess
- name: "bigdata-role"
assume_role_policy_document: "bigdata"
state: present
managed_policy:
- arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
- arn:aws:iam::XXXXXXXXXXX:policy/CustomAmazonRDSReadOnlyAccess
iam_users:
- name: test-user-1
state: present
groups: [developers]
password:
slack_name:
access_key_state: create
- name: test-user-2
state: present
groups: [developers]
password:
slack_name:
I'm trying filter and get only the users with the state=present and use it on my when clause, but no luck so far.
- name: Loop all the present users
debug: msg={{ item }}
when: "{{ item.state == 'present' }}"
with_items: "{{ iam_users }}"
tags: always
register: present_users
- set_fact:
iam_present_users: "{{ present_users.results }}"
tags: always
- name: Show only present users, ideally
debug: msg="{{ iam_present_users }}"
tags: always
- name: Manage AWS IAM Roles
iam_role:
name: "{{ item.name }}"
assume_role_policy_document: "{{ lookup('template', policies_path + '/assume-role/' + item.assume_role_policy_document + '.json') }}"
state: "{{ item.state }}"
managed_policy: "{{ item.managed_policy }}"
when: "{{ item.managed_policy is defined and iam_present_users is defined }}"
with_items: "{{ iam_roles }}"
tags: manage_roles
Your use of a debug statement to try to extract users seems odd. If you want to select objects from a list based on the value of an attribute, your best choice is probably the Jinja2 selectattr filter. For example, given this input:
iam_users:
- name: test-user-1
state: present
groups: [developers]
password:
slack_name:
access_key_state: create
- name: test-user-2
state: present
groups: [developers]
password:
slack_name:
- name: test-user-3
state: absent
groups: [developers]
password:
slack_name:
You could use this set_fact task:
- set_fact:
iam_present_users: "{{ iam_users|selectattr('state', 'equalto', 'present')|list }}"
Which would result in iam_present_users containing:
"iam_present_users": [
{
"access_key_state": "create",
"groups": [
"developers"
],
"name": "test-user-1",
"password": null,
"slack_name": null,
"state": "present"
},
{
"groups": [
"developers"
],
"name": "test-user-2",
"password": null,
"slack_name": null,
"state": "present"
}
]
See the jinja documentation for the stock list of filters, and the ansible documentation for a list of filters specific to ansible.

Resources