Nested Jinja2 dictionary valuable is disappearing - ansible

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'] }}"

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"
}

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'

What is the best way to do case statement in Ansible?

I am trying to convert my scripts into Ansible for automation. I am stuck in understanding loops or the "with_items" use case.
The original bash script:
for i in apple banana orange; do
case $i in
apple) export var="var.1:apple1,var.2:apple2" ;;
banana) export var="var.1:banana1,var.2:banana2,var.3:banana3" ;;
orange) export var="var.1:orange1" ;;
esac
echo "$i"
What I have tried so far:
VARS file:
fruits:
- name: apple
var: "{{ item }}"
with_items:
- apple1
- apple2
- name: banana
var: "{{ item }}"
with_items:
- banana1
- banana2
- banana3
- name: orange
var: "{{ item }}"
with_items:
- orange1
TASKS file:
- include_vars: vars.yml
- debug:
msg: "{{ fruits }}"
- name: output in shell using echo
shell: |
echo "{{ fruits.name }}" ;
echo "{{ fruits.var }}"
loop: "{{ fruits }}"
Outputs:
The output from include_vars task:
{
"ansible_included_var_files": [
"/etc/ansible/roles/openssl/tasks/vars.yml"
],
"ansible_facts": {
"fruits": [
{
"var": "{{ item }}",
"name": "apple",
"with_items": [
"apple1",
"apple2"
]
},
{
"var": "{{ item }}",
"name": "banana",
"with_items": [
"banana1",
"banana2",
"banana3"
]
},
{
"var": "{{ item }}",
"name": "orange",
"with_items": [
"orange1"
]
}
]
},
"_ansible_no_log": false,
"changed": false
}
Debug
debug task failed
{
"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/etc/ansible/roles/openssl/tasks/main.yml': line 262, 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- debug:\n ^ here\n",
"_ansible_no_log": false
}
I know that Yaml are space sensitive and formatting is important. I am a novice at writing playbooks and any pointers would be helpful.
With the dictionary
fruits:
apple:
- apple1
- apple2
banana:
- banana1
- banana2
- banana3
orange:
- orange1
the loop
- hosts: localhost
tasks:
- include_vars:
vars.yml
- debug:
msg: "{{ item.key }} {{ item.value }}"
loop: "{{ fruits|dict2items }}"
gives (abridged)
"msg": "orange [u'orange1']"
"msg": "apple [u'apple1', u'apple2']"
"msg": "banana [u'banana1', u'banana2', u'banana3']"
It's possible to reference the items in the dictionary. For example
- debug:
var: fruits.banana
- debug:
var: fruits.apple.1
gives
"fruits.banana": [
"banana1",
"banana2",
"banana3"
]
"fruits.apple.1": "apple2"

Ansible, list object has no attribute

I am using Ansible 2.3.0.0 and I have tested in Ansible 2.4.0.0, obtaining the same result. My problem is very simple, but I cannot see the problem.
I have defined a list of objects in Ansible as follows:
vars:
password_text_to_encrypt:
- { line: "{{truststore_pass }}" , regexp: '\${TRUSTSTORE_PASS}*'}
- { line: "{{ keystore_pass }}" , regexp: '\${KEYSTORE_PASS}*'}
- { line: "{{ gp_pass }}" , regexp: '\${GP_PASS}*'}
- { line: "{{ datasource_password }}" , regexp: '\${DATASOURCE_PASS}*'}
- { line: "{{ server_password }}" , regexp: '\${SERVER_PASSWORD}*'}
- { line: "{{ sftp_password }}" , regexp: '\${SFTP_PASSWORD}*'}
- { line: "{{ db_userpassword }}" , regexp: '\${DB_PASSWORD}*'}
roles:
- basic_role
My Basic_role just prints the items, and I would like to obtain the content of each line:
---
- name: "print password"
debug:
msg: "The content of the line is: {{ item.line}}"
with_nested:
- "{{password_text_to_encrypt}}"
But the result that I obtain is:
FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'list object' has no attribute 'line'\n\nThe error appears to have been in.....
If I change item.line to just item, it works but it prints:
ok: [localhost] => (item=[u'regexp', u'line']) => {
"item": [
"regexp",
"line"
],
"msg": "The content of the line is: [u'regexp', u'line']"
}
.
.
.
To summarize, Ansible does not consider the content of line o regexp. I have been doing tests and the variable which are used to init line and regexp are not empty.
Use with_items instead of with_nested.
I think you want loops and includes because you're getting a flattened list which is expected (as per the documentation).

Test value of all members in hash variable in Ansible playbook

I need to run a task only if one or more files from a pre-defined list of files are missing. I tried the following (and some variants):
touch a
cat test.yml
- hosts: localhost
vars:
filelist:
- a
- b
tasks:
- stat:
path: "{{ item }}"
with_items: "{{ filelist }}"
register: all_files
- debug:
var: all_files
- debug:
msg: "Some file(s) missing"
when: "false in all_files['results'][*]['stat']['exists']"
ansible-playbook test.yml
...
TASK [debug] ********************************************************************
ok: [localhost] => {
"all_files": {
...
"item": "a",
"stat": {
...
"exists": true,
...
"item": "b",
"stat": {
"exists": false
...
TASK [debug] ********************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "The conditional check 'false in all_files['results'][*]['stat']['exists']' failed. The error was: template error while templating string: unexpected '*'. String: {% if false in all_files['results'][*]['stat']['exists'] %} True {% else %} False {% endif %}\n\nThe error appears to have been in 'test.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\n - debug:\n ^ here\n"}
...
What is the correct syntax to use in the 'when:' clause? Or is this the wrong way altogether?
- hosts: localhost
gather_facts: false
vars:
file_vars:
- {name: file1}
- {name: file2}
tasks:
- name: Checking existing file name
stat:
path: ./{{ item.name }}
with_items: "{{ file_vars }}"
register: check_file_name
- debug:
msg: 'file name {{item.item.name}} not exists'
with_items: "{{ check_file_name.results }}"
when: item.stat.exists == False
- name: Create file
file:
path: "./{{item.item.name}}"
state: touch
with_items: "{{ check_file_name.results }}"
when: item.stat.exists == False

Resources