Print Ansible-format variable from inside a loop - ansible

I would like to print, in a configuration file, the following line:
{{ variable.method }}
This will be interpreted by a third-party software and will do whatsoever.
I am using Ansible.
Printing the line with the following code, in a simple template block, is working well:
{{ '{{' }} variable.method {{ '}}' }}
However, when I want to loop on my template code to generate more files, using with_items, I can not print what I want anymore.
- name: Debug Print my variable
with_items:
- { name: "someObject", prop: "{{ '{{' }} variable.method {{ '}}' }}" }
debug: msg="{{ item.prop }}"
I receive the following:
FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: {u'name': u'someObject', u'prop': u'{{ variable.method }}'}: 'variable.method' is undefined\n\nThe error appears to have been in 'my_file.yml': line 1, 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: \"Debug Print my variable\"\n ^ here\n"}
It looks like Ansible is working in a different environment/context and is trying to actually execute this piece of code.
How can I escape this context and actually print what I wish?
Thanks

I think you first need to fix your loop to something like this if you would like to use template within a loop:
- name: Debug Print my variable
template: ........ {{ item }} #you write your template here
with_items:
- { name: "someObject", prop: "{{ '{{' }} variable.method {{ '}}' }}" }
debug: ............

Related

Ansible play fails with_items FOO

- name: Debug msg for imagepull {{ ansible_operator_meta.name }}
debug:
msg: "{{ final_resource_checks_pod_status_check_filtered_image }}"
I got an error with below
- name: Debug msg for imagepull {{ ansible_operator_meta.name }}
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"

ansible using hostname as a condition

I have an HA setup that I am building. I am using Ansible 2.9.11. I need to search the hostname and if it is the b side copy the backup config over. I have tried the following code and it is not working. Or is there a different way to accomplish this?
[WARNING]: conditional statements should not include jinja2 templating
delimiters such as {{ }} or {% %}. Found: 'b' in {{ inventory_hostname
}} fatal: [dev-sca02b]: FAILED! => {"msg": "The conditional check ''b'
in {{ inventory_hostname }}' failed. The error was: error while
evaluating conditional ('b' in {{ inventory_hostname }}): 'dev' is
undefined\n\nThe error appears to be in
'/Users/user1/Documents/Ansible/sca_fusion.yaml': line 134, 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 - name: "Change
keepalived to backup"\n ^ here\n"}
- name: "Change keepalived to backup"
replace:
path: /etc/keepalived/keepalived.conf
regexp: "MASTER"
replace: "BACKUP"
when: "'b' in {{ inventory_hostname }}"
That warning should point you to the main source of your problem:
WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}.
A when condition is already in an implicit jinja templating context, so you don't need to create one explicitly. You want:
- name: "Change keepalived to backup"
replace:
path: /etc/keepalived/keepalived.conf
regexp: "MASTER"
replace: "BACKUP"
when: "'b' in inventory_hostname"

Ansible: how to check if a variable is being loaded in a playbook?

I'm trying to write a playbook that will load vars from a group vars file then check if a variable exists
my playbook is like this:
---
- hosts: "{{ target }}"
roles:
- app
tasks:
- name: alert if variable does not exist
fail:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
with_items:
- country
- city
- street
...
My inventory file contains
[app]
ansible-slave1
ansible-slave2
[db]
ansible-db
[multi:children]
app
db
and I have the roles/app/vars/main.yml containing
country: "France"
city: "Paris"
What I was expecting is the playbook to output "street is not defined" but I have a syntax issue I can't resolve
[vagrant#ansible-master vagrant]$ ansible-playbook --inventory-file=ansible_master_hosts test_variables.yml --extra-vars "target=ansible-slave1" --syntax-check
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/vagrant/test_variables.yml': line 10, column 24, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
msg: "{{ item }} is not defined"
when: "{{ item }}" is not defined
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
I'd be happy with any hints.
Thanks
You have "" in invalid place of "when" statement. This should be like this:
msg: "{{ item }} is not defined"
when: "{{ item }} is not defined"
So the output will be:
failed: [hostname] (item=street) => {"changed": false, "item": "street", "msg": "street is not defined"}
there is on open issue conditional is defined fails to capture undefined var .
as a workaround I'd suggest to change the where condition to the following:
when: "{{ item }}" == ""

How to register with_items and act on conditional check result for each item

I'd like to register the contents of bashrc for two users and edit as/if required. My play is as follows.
- name: Check bashrc
shell: cat {{ item }}/.bashrc
register: bashrc
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Configure bashrc
shell:
cmd: |
cat >> {{ item }}/.bashrc <<EOF
STUFF
EOF
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
when: '"STUFF" not in bashrc.stdout'
It fails as follows:
fatal: [ca-o3lscizuul]: FAILED! => {"failed": true, "msg": "The conditional check '\"STUFF\" not in bashrc.stdout' failed. The error was: error while evaluating conditional (\"STUFF\" not in bashrc.stdout): Unable to look up a name or access an attribute in template string ({% if \"STUFF\" not in bashrc.stdout %} True {% else %} False {% endif %}).\nMake sure your variable name does not contain invalid characters like '-': argument of type 'StrictUndefined' is not iterable\n\nThe error appears to have been in '/root/openstack-ci/infrastructure-setup/staging/zuul/create-user.yml': line 35, 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 - name: Configure bashrc\n ^ here\n"}
I think, if I understand your requirement correctly, you can use the 'lineinfile' or 'blockinfile' modules and save yourself the hassle of testing for the existence of the content:
- name: Noddy example data
set_fact:
single_line: "STUFF"
multi_line: |
STUFF
STUFF
profile_dirs:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Ensure STUFF exists in file
lineinfile:
path: "{{ item }}/.bashrc"
line: "{{ single_line }}"
loop: "{{ profile_dirs }}"
- name: Ensure block of STUFF exists in file
blockinfile:
path: "{{ item }}/.bashrc"
block: "{{ multi_line }}"
loop: "{{ profile_dirs }}"
Both modules give a lot more control and you can find their docs here: lineinfile | blockinfile

Ansible: do not run shell command if a file exists

I would like to do the following in an Ansible playbook:
- name: "Generate variant html report"
shell: "<my command>"
with_items: "{{ variants | default([]) }}"
when: ({{ folderReports }}/{{ item }}).exists == False
Inside the when, I need a way to create the file path, and determine if it exists or not. I tried to use the "(" ")" to surround my first expression, but it doesn't seem to be working:
2016-10-13 16:22:48,130 p=94292 u=sautomation | fatal: [localhost]: FAILED! => {"failed": true, "msg": "The conditional check '({{ folderReports }}/{{ item }}).exists == True' failed. The error was: template error while templating string: unexpected '/'. String: {% if (/opt/diff-test1.diff).exists == True %} True {% else %} False {% endif %}\n\nThe error appears to have been in '/opt/ansible/roles/stats/tasks/main.yml': line 45, 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: \"Generate report\"\n ^ here\n"}
To prevent a task from executing if a specified file already exists, use creates parameter of the shell module:
- name: "Generate variant html report"
shell: "<my command>"
args:
creates: "{{ folderReports }}/{{ item }}"
with_items: "{{ variants | default([]) }}"
You get an error because .exists, in your conditional, checks if a variable (fact) exist, not a file on the target node.

Resources