ansible using hostname as a condition - ansible

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"

Related

Check multiple conditions in ansible when

I am giving a condition to my ansible task:
- hosts: "{{ env }}"
user: "{{ us1 }}"
gather_facts: no
tasks:
- name: Deploy Services on "{{ env }}"
shell: sh "{{ script_path }}/test.sh"
when: (package == "abc") and (env.startswith('PA_') or env.startswith('lon'))
I am running the above playbook, when the package=abc and env=PA_, its running. But when env=lon, it is giving error:
fatal: [lonxxx.abc.com]: FAILED! =>
{
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'lonxxx'\n\nThe error appears to be in '/home/dbrun/dbRunPlaybooks/deploy_application.yml': line 25, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Deploy Services on \"{{ env }}"\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"
}
I tried giving the when condition in below manner:
when: >
(package == "abc") and
(env.startswith('PA_')) or (env.startswith('lon'))
But giving the same error.
Please help.

How to use a combination of variable and a string in ansible when condition?

I want to search for a combination of a string and a file in a particular command output and if both exists then skip the task
Here my data_dir variable value is /data/dbdata/test
- name: Extracting existing selinux context
shell: "semanage fcontext -l -C|grep -i {{data_dir|dirname}}"
register: selin_context
- name: Setting Selinux context for data and log dir
command: "semanage fcontext -a -t {{item.name}} {{item.dirpath|dirname}}(/.*)?"
with_items:
- { name: 'postgresql_db' , dirpath: "{{data_dir}}" }
when: "'postgresql_db' and {{data_dir}} not in selin_context.stdout'
If i try above then getting below error
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: 'postgresql_db' and
{{data_dir}} not in selin_context.stdout
fatal: [pgdbsql-02]: FAILED! => {
"msg": "The conditional check ''postgresql_db' and {{data_dir|dirname}} not in selin_context.stdout' failed. The error was: template error while templating string: unexpected '/'. String: {% if 'postgresql_db' and /data/dbdata not in selin_context.stdout %} True {% else %} False {% endif %}\n\nThe error appears to be in '/home/ec2-user/ansible/pgdb/roles/pgdb/tasks/main.yml': line 56, 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: Setting Selinux context for data and log dir\n ^ here\n"
Please guide me how to handle this?

Ansible variable check in playbook

I have in the vars file the databases configured as the following:
project_dbs:
- { project_db_name: "project1", project_db_user: "user", tenon_db_password: "pass" }
- { project_db_name: "project2", project_db_user: "dev", tenon_db_password: "pass2"}
- { project_db_name: "project3", project_db_user: "{{datadog_mysql_username}}", project_db_password: "{{datadog_mysql_password}}" }
Now in a playbook I have a check:
- name: copy config.json template to server
tags: provision
template: src=config.json dest={{ project_root }}/config
when: item.project_db_name == "project2"
with_items: project_dbs
But the when check is failing. Any idea how to make that work?
The error message looks like this:
fatal: [test]: FAILED! => {"failed": true, "msg": "The conditional check 'item.projects_db_name == \"project2\"' failed. The error was: error while evaluating conditional (item.projects_db_name == \"project2\"): 'unicode object' has no attribute 'projects_db_name'\n\nThe error appears to have been in '/var/lib/jenkins/project/ansible/roles/project2/tasks/main.yml': line 28, 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: copy config.json template to server\n ^ here\n"}
You use an outdated syntax called "bare variables" in with_items:
with_items: project_dbs
This way your item becomes a string object with the value of project_dbs and Ansible reports it doesn't have the attribute ("'unicode object' has no attribute 'projects_db_name'").
In Ansible 2.x you should quote variables in the following way:
with_items: "{{ project_dbs }}"
That said, your task makes no use of the values from the loop. The following will have the same effect:
- name: copy config.json template to server
tags: provision
template: src=config.json dest={{ project_root }}/config
Instead of using when you could just filter the list of project_dbs so it looks like this:
- name: "copy config.json template to server"
tags: provision
template: src=config.json dest={{ project_root }}/config
with_items: "{{ project_dbs | selectattr("project_db_name", "project2") }}"

Print Ansible-format variable from inside a loop

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: ............

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