Difficulty Parsing Ansible Output - ansible

[ansible 2.9.6, Ubuntu 20.04]
This seems pretty straightforward, but I keep getting an error message saying:
fatal: [192.168.254.100]: FAILED! => {"msg": "template error while templating string: expected name or number. String: {{ipv4addrs.'host[0]'}}"}
Here's my ansible playbook:
---
- hosts: nios
connection: local
vars:
nios_provider:
host: 192.x.x.x
username: xxx
password: xxx
wapi_version: "2.11.2"
tasks:
- name: Find client app server records
set_fact:
recs: "{{ lookup('nios', 'record:host', filter={'name~':'sdk' }, provider=nios_provider) }}"
- name: check return
debug:
msg: "{{ recs }}"
- name: get host name
debug:
var: ipv4addrs.'host[0]'
And here's the output:
TASK [check return] **************************************************************************************************************************************************************
ok: [192.x.x.x] => {
"msg": [
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5lYWdsZWFjY2Vzcy5zZGstZDAwMQ:sdk-d001.somename.com/default",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQuY29tLmVhZ2xlYWNjZXNzLnNkay1kMDAxLjEwLjcwLjAuMS4:10.70.0.1/sdk-d001.somename.com/default",
"configure_for_dhcp": false,
"host": "sdk-d001.somename.com",
"ipv4addr": "10.70.0.1"
}
],
"name": "sdk-d001.somename.com",
"view": "default"
},
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5lYWdsZWFjY2Vzcy5zZGstZDAwMg:sdk-d002.somename.com/default",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQuY29tLmVhZ2xlYWNjZXNzLnNkay1kMDAyLjEwLjcwLjAuMi4:10.70.0.2/sdk-d002.somename.com/default",
"configure_for_dhcp": false,
"host": "sdk-d002.somename.com",
"ipv4addr": "10.70.0.2"
}
],
"name": "sdk-d002.somename.com",
"view": "default"
}
]
}
TASK [get host name] ***************************************************************************************************************************************************************
fatal: [192.168.254.100]: FAILED! => {"msg": "template error while templating string: expected name or number. String: {{ipv4addrs.'host[0]'}}"}
My objective is to find all of the host names beginning with (for example) "sdk". There may be 1 or several. And then I want to get the full name and ip address captured as variables. I have tried lots of different options: rec.ipv4addrs[0].host, ipv4addrs[0].host, rec.ipv4addrs[0].'host', rec.ipv4addrs[0].['host'] . . . but I cannot find the proper syntax.
This appears to be an array of dict blocks with an ipv4addrs array within it. So the first thing I tried was "ipv4addrs[0]['host']" with no joy.
Thanks in advance for the help.

You're trying to make use of a variable called ipv4addrs, but you
haven't defined any variables with that name. From the previous
debug task you apparently have a variable named recs, which is a
list of dictionaries each of which contains an ipv4addrs attribute.
If you wanted to look up the host attribute for each record in
recs, you could write something like this:
- name: get host name
debug:
var: item.ipv4addrs[0].host
loop: "{{ recs }}"
If you wanted the ipv4addrs.host value from the first record, you
could write:
- name: get host name
debug:
var: recs[0].ipv4addrs[0].host
The error you're seeing stems from the fact that the expression
ipv4addrs.'host[0]' doesn't make any sense; that's not a syntax that
Ansible supports. You can't use a string with dot-notation like that.

Related

Not able to read/print the csv file data

Running the below playbook and trying to print the value of that task. It fails with below error.
FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'name'\n\nThe error appears to be in '/Users/srikanth.venugopalan/ansible/roles/rmi_staging/tasks/main.yml': line 9, column 4, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n register: topics\n - debug:\n ^ here\n"
The code is
- name: Login to cluster
shell: /home/srikanth/ls.sh
- name: Read the CSV file
read_csv:
path: /home/srikanth/template1.csv
register: topics
- debug:
msg: 'Name {{ topics.list.name }}'
I have tried below as well, but no luck
- name: Login to cluster
shell: /home/srikanth/ls.sh
- name: Read the CSV file
read_csv:
path: /home/srikanth/template1.csv
register: topics
- debug:
msg: 'Name {{ topics.list.1.name }}'
CSV file format as per below
name,replica,partition
test-topic,3,3
I have gone through the link https://stackoverflow.com/questions/53799730/how-to-read-csv-file-data-in-ansible-playbook-using-with-lines, but one thing dont know in the debug how it come user.username.
Please guide me.
Actual goal is to take name alone from the debug output.
Your .1.name attempt didn't work because topics.list is, like all list data structures in python, 0-indexed
You can observe the behavior for yourself, as the comments asked you to:
tasks:
- copy:
dest: ./template1.csv
content: |
name,replica,partition
test-topic,3,3
- read_csv:
path: ./template1.csv
register: topics
- debug:
var: topics
- debug:
msg: 'Name {{ topics.list.0.name }}'
emits
ok: [localhost] => {
"topics": {
"changed": false,
"dict": {},
"failed": false,
"list": [
{
"name": "test-topic",
"partition": "3",
"replica": "3"
}
]
}
}
ok: [localhost] => {
"msg": "Name test-topic"
}

Nested Jinja2 dictionary valuable is disappearing

I'm using ansible and jinja2, and need to access a variable.
I have a data structure structure, and executing in a playbook:
- name: debug_1
debug:
msg: "{{ vars['structure'] }}"
Yields these results:
ok: [debug-test] => {
"msg": {
"Covo": [
{
"enabled": true
}
]
}
}
Furthermore, running
- name: debug_1
debug:
msg: "{{ vars['structure']['covo'] }}"
gives the expected result:
ok: [debug-test] => {
"msg": [
{
"enabled": true
}
]
}
However, attempting to access the enabled variable with:
- name: debug_1
debug:
msg: "{{ vars['structure']['covo']['enabled'] }}"
Will throw an error:
fatal: [debug-test]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'enabled'\n\nThe error appears to be in '/task/main.yml': line 16, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n when: vars['structure']['covo']['enabled']|default(False) == True\n - name: debug_1\n ^ here\n"}
How can I access this variable?
covo is an array, so you have to declare the index:
- name: debug_1
debug:
msg: "{{ vars['structure']['covo'][0]['enabled'] }}"

Pass a variable(value) from the JSON body to the URL in ansible

I would like to pass a particular value as an input to the URI from the JSON body. But i am getting an error as below. Please find below code and expectation is to put the netid = 12345 in the
place of netid in the URL as {{ api_uri }}/networks/12345/appliance
Error:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'rules'\n\nThe error appears to be in '/***/firewallrules.yml': line 35, column 10, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Firewall rule update\n ^ here\n"}
URI Task:
- name: Firewall rule update
uri:
method: PUT
url: "{{ api_uri }}/networks/{{ netid(from firewall.json) }}/appliance"
body: "{{ lookup('file', 'firewall.json') | from_json }}"
body_format: json
register: firewallresults
ignore_errors: yes
Firewall(JSON input to API):
{
"rules": [
{
"comment": "Test1.",
"destCidr": "x.x.x.x/24",
"srcCidr": "y.y.y.y/24",
"netid":"12345"
},
{
"comment": "Test2",
"destCidr": "a.a.a.a/24",
"srcCidr": "b.b.b.b/24",
"netid":"12345"
} ]
}
The error message reports AnsibleUnsafeText object' has no attribute 'rules' ... The error appears to be in '/***/firewallrules.yml' but I cant find anything about .rules or firewallrules.yml in your description.
In respect to the minimal information
I would like to pass a particular value as an input to the URI from the JSON body. ... need a solution to get the netid from my input JSON ... which will be used in the API URI
it seems that your URI task and URL parameter are misconstructed. I've created a debugging task to get a better understanding of the use case.
---
- hosts: localhost
become: false
gather_facts: false
vars:
BODY: "{{ lookup('file', 'firewall.json') | from_json }}"
tasks:
- name: Show BODY
debug:
msg: "{{ BODY }}"
- name: Show first 'netid' for URL
debug:
var: BODY.rules[0].netid
- name: Show all 'netid's for URL
debug:
msg: "{{ item.netid }}"
loop: "{{ BODY.rules }}"
Resulting into an output of
TASK [Show first 'netid' for URL] ***
ok: [localhost] =>
BODY.rules[0].netid: '12345'
TASK [Show all 'netid's for URL] ***
ok: [localhost] => (item={u'comment': u'Test1.', u'destCidr': u'x.x.x.x/24', u'netid': u'12345', u'srcCidr': u'y.y.y.y/24'}) =>
msg: '12345'
ok: [localhost] => (item={u'comment': u'Test2', u'destCidr': u'a.a.a.a/24', u'netid': u'12345', u'srcCidr': u'b.b.b.b/24'}) =>
msg: '12345'

ansible JEMSPATH errors while parasing ansible facts

i am trying to filter all the strings which contains "RegButton-" from the below ansible facts and use the output as list of items in the next play.
trying to use json_query filter but it is failing with below error
ansible fact
{
"ansible_facts": {
"srcgrpname": [
"RegButton-48773",
"test_vio",
"RegButton-23395",
"RegButton-520859",
"RegButton-743141",
"RegButton-297578",
"RegButton-186156"
]
},
"changed": false
}
playbook entry
- name: "Filter Regbutton policy Names"
set_fact:
srcgrpname2: "{{ resultid1 | json_query(query) }}"
vars:
query: "ansible_facts.srcgrpname[?contains(#, 'RegButton-') == `true`]"
Error that i am receiving.
{
"msg": "JMESPathError in json_query filter plugin:\nIn function contains(), invalid type for value: RegButton-48773, expected one of: ['array', 'string'], received: \"unknown\"",
"_ansible_no_log": false
}
It's possible to use select and regex. For example the tasks below
- set_fact:
srcgrpname2: "{{ ansible_facts.srcgrpname|
select('regex', '^RegButton-(.*)$')|
list }}"
- debug:
var: srcgrpname2
give
"srcgrpname2": [
"RegButton-48773",
"RegButton-23395",
"RegButton-520859",
"RegButton-743141",
"RegButton-297578",
"RegButton-186156"
]
Notes
It's an open issue with contains.
json_query filter fails when using the functions "contains", "starts_with", others #27299
Allow for subclassed types #158
It's reproducible "RegButton-48773, expected one of: ['array', 'string'], received: unknown"
See json format query with contains

Ansible: How to specify an array or list element fact with yaml?

When we check hostvars with:
- name: Display all variables/facts known for a host
debug: var=hostvars[inventory_hostname]
We get:
ok: [default] => {
"hostvars[inventory_hostname]": {
"admin_email": "admin#surfer190.com",
"admin_user": "root",
"ansible_all_ipv4_addresses": [
"192.168.35.19",
"10.0.2.15"
],...
How would I specify the first element of the "ansible_all_ipv4_addresses" list?
Use dot notation
"{{ ansible_all_ipv4_addresses.0 }}"
This should work just like it would in Python. Meaning you can access the keys with quotes and the index with an integer.
- set_fact:
ip_address_1: "{{ hostvars[inventory_hostname]['ansible_all_ipv4_addresses'][0] }}"
ip_address_2: "{{ hostvars[inventory_hostname]['ansible_all_ipv4_addresses'][1] }}"
- name: Display 1st ipaddress
debug:
var: ip_address_1
- name: Display 2nd ipaddress
debug:
var: ip_address_2
I had this same challenge when trying to parse the result of a command in Ansible.
So the result was:
{
"changed": true,
"instance_ids": [
"i-0a243240353e84829"
],
"instances": [
{
"id": "i-0a243240353e84829",
"state": "running",
"hypervisor": "xen",
"tags": {
"Backup": "FES",
"Department": "Research"
},
"tenancy": "default"
}
],
"tagged_instances": [],
"_ansible_no_log": false
}
And I wanted to parse the value of state into the result register in the ansible playbook.
Here's how I did it:
Since the result is an hash of array of hashes, that is state is in the index (0) hash of the instances array, I modified my playbook to look this way:
---
- name: Manage AWS EC2 instance
hosts: localhost
connection: local
# gather_facts: false
tasks:
- name: AWS EC2 Instance Restart
ec2:
instance_ids: '{{ instance_id }}'
region: '{{ aws_region }}'
state: restarted
wait: True
register: result
- name: Show result of task
debug:
var: result.instances.0.state
I saved the value of the command using register in a variable called result and then got the value of state in the variable using:
result.instances.0.state
This time when the command ran, I got the result as:
TASK [Show result of task] *****************************************************
ok: [localhost] => {
"result.instances.0.state": "running"
}
That's all.
I hope this helps

Resources