Conditional statements should not include jinja2 templating delimiters such as {{ }} or {{% %}} - ansible

I searched online and tried all examples but in vain. I am getting the following error "Conditional statements should not include jinja2 templating delimiters such as {{ }} or {{ % %}}
Appreciate if you could re-write
Contents of hosts.ini
[DEVprimaryappservers]
host1.example.com
[SITprimaryappservers]
host2.example.com
Playbook has
- name: add service Service
include_vars:
file: inventory/{{ env }}/group_vars/primarystartservices.yml
- name: Start Service
win_service:
name: "{{ item }}"
state: started
loop: "{{ services }}"
when: "inventory_hostname in groups[~ env 'primaryappservers']"
I had before like below which is when I got conditional statements should not include jinja2 template warning
---
- name: sample code
win_service:
state: started
when: "inventory_hostname in group[{{ env }}'primaryappservers']"

when: inventory_hostname in group[env ~ 'primaryappservers']
Conditionals are implicitly Jinja statements, so you do not need to do anything special to access variables.

Create a variable if you find the concatenation of the strings confusing. For example,
- name: sample code
win_service:
state: started
when: inventory_hostname in groups[my_group]
vars:
my_group: "{{ env }}primaryappservers"
Example of a complete playbook for testing
shell> cat pb.yml
---
- hosts: all
gather_facts: false
vars:
my_group: "{{ env }}primaryappservers"
tasks:
- debug:
msg: "{{ inventory_hostname }} comes from {{ my_group }}"
when: inventory_hostname in groups[my_group]
gives
shell> ansible-playbook pb.yml -e env=DEV
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
skipping: [host2.example.com]
ok: [host1.example.com] =>
msg: host1.example.com comes from DEVprimaryappservers
PLAY RECAP ***********************************************************************************
host1.example.com: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2.example.com: ok=0 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

Related

How to calculate ansible_uptime_seconds and output this in os.csv

I am trying to create a csv file that can be used to review certain systems details. One of these items is the system uptime, which is reflected in unix seconds. But in the os.csv output file I would like to see it as days, HH:MM:SS.
Below my yaml script:
---
- name: playbook query system and output to file
hosts: OEL7_systems
vars:
output_file: os.csv
tasks:
- block:
# For permisison setup.
- name: get current user
command: whoami
register: whoami
run_once: yes
- name: clean_file
copy:
dest: "{{ output_file }}"
content: 'hostname,distribution,version,release,uptime'
owner: "{{ whoami.stdout }}"
run_once: yes
- name: fill os information
lineinfile:
path: "{{ output_file }}"
line: "{{ ansible_hostname }},\
{{ ansible_distribution }},\
{{ ansible_distribution_version }},\
{{ ansible_distribution_release }},\
{{ ansible_uptime_seconds }}"
# Tries to prevent concurrent writes.
throttle: 1
delegate_to: localhost
Any help is appreciated.
tried several conversions but can't get it to work.
There is actually a (somewhat hard to find) example in the official documentation on complex data manipulations doing exactly what you are looking for (check at the bottom of the page).
Here is a full example playbook to run it on localhost
---
- hosts: localhost
tasks:
- name: Show the uptime in days/hours/minutes/seconds
ansible.builtin.debug:
msg: Uptime {{ now().replace(microsecond=0) - now().fromtimestamp(now(fmt='%s') | int - ansible_uptime_seconds) }}
which gives on my machine:
PLAY [localhost] ************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************
ok: [localhost]
TASK [Show the uptime in days/hours/minutes/seconds] ************************************************************************************************************
ok: [localhost] => {
"msg": "Uptime 1 day, 3:56:34"
}
PLAY RECAP ******************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Display Ansible playbook with lookups interpolated

I have an Ansible playbook that looks, in part, like this:
...
environment:
F2B_DB_PURGE_AGE: "{{ lookup('env','F2B_DB_PURGE_AGE') }}"
F2B_LOG_LEVEL: "{{ lookup('env','F2B_LOG_LEVEL') }}"
SSMTP_HOST: "{{ lookup('env','SSMTP_HOST') }}"
SSMTP_PORT: "{{ lookup('env','SSMTP_PORT') }}"
SSMTP_TLS: "{{ lookup('env','SSMTP_TLS') }}"
...
Is there any way to run ansible-playbook so that it will show the results of the YAML file after replacing the lookups with their values? That is, I would like to be able to run something like ansible-playbook file.yaml --dry-run and see on standard output (assuming the environment variables were set appropriately):
...
environment:
F2B_DB_PURGE_AGE: "20"
F2B_LOG_LEVEL: "debug"
SSMTP_HOST: "smtp.example.com"
SSMTP_PORT: "487"
SSMTP_TLS: "true"
...
Set the environment for testing
shell> cat env.sh
#!/usr/bin/bash
export F2B_DB_PURGE_AGE="20"
export F2B_LOG_LEVEL="debug"
export SSMTP_HOST="smtp.example.com"
export SSMTP_PORT="487"
export SSMTP_TLS="true"
shell> source env.sh
Given the inventory
shell> cat hosts
localhost ansible_connection=local
Q: "Run something like ansible-playbook file.yaml --dry-run and see environment"
A: The below playbook does the job
shell> cat file.yml
- hosts: all
vars:
my_environment:
F2B_DB_PURGE_AGE: "{{ lookup('env','F2B_DB_PURGE_AGE') }}"
F2B_LOG_LEVEL: "{{ lookup('env','F2B_LOG_LEVEL') }}"
SSMTP_HOST: "{{ lookup('env','SSMTP_HOST') }}"
SSMTP_PORT: "{{ lookup('env','SSMTP_PORT') }}"
SSMTP_TLS: "{{ lookup('env','SSMTP_TLS') }}"
tasks:
- block:
- debug:
msg: |
my_environment:
{{ my_environment|to_nice_yaml|indent(2) }}
- meta: end_play
when: dry_run|d(false)|bool
- debug:
msg: Continue ...
Set dry_run=true
shell> ansible-playbook file.yml -e dry_run=true
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
ok: [localhost] =>
msg: |-
my_environment:
F2B_DB_PURGE_AGE: '20'
F2B_LOG_LEVEL: debug
SSMTP_HOST: smtp.example.com
SSMTP_PORT: '487'
SSMTP_TLS: 'true'
TASK [meta] **********************************************************************************
PLAY RECAP ***********************************************************************************
localhost: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
By default, the playbook will execute tasks
shell> ansible-playbook file.yml
PLAY [all] ***********************************************************************************
TASK [debug] *********************************************************************************
skipping: [localhost]
TASK [meta] **********************************************************************************
skipping: [localhost]
TASK [debug] *********************************************************************************
ok: [localhost] =>
msg: Continue ...
PLAY RECAP ***********************************************************************************
localhost: ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Optionally, let the playbook gather facts and use the dictionary ansible_env. Use the filer ansible.utils.keep_keys to select your variables
- hosts: all
gather_facts: true
vars:
my_environment_vars:
- F2B_DB_PURGE_AGE
- F2B_LOG_LEVEL
- SSMTP_HOST
- SSMTP_PORT
- SSMTP_TLS
my_environment: "{{ ansible_env|
ansible.utils.keep_keys(target=my_environment_vars) }}"
tasks:
- block:
- debug:
msg: |
my_environment:
{{ my_environment|to_nice_yaml|indent(2) }}
- meta: end_play
when: dry_run|d(false)|bool
- debug:
msg: Continue ...

How to execute on multiple hosts in ansible

I have a script that will execute in two parts. First it will execute on localhost and query a database table to get a hostname. second part of the script should run on the host which was registered in the query before. I am not able to set the host with the set_fact I did in the first part of the code.
this is what iam trying to do:
- hosts: localhost
gather_facts: false
become: yes
become_user: oracle
vars_files:
- vars/main.yml
tasks:
- name: Get new hostname
tempfile:
state: file
register: tf
- name: create sql file
template:
src: get_hostname.sql.j2
dest:"{{ tf.path }}"
mode: 0775
- name: login
command:
argv:
- "sqlplus"
- -s
- "#{{ tf.path }}"
environment:
ORACLE_HOME: "oracle/home"
register: command_out
- set_fact:
NEW_HOST: "{{ command_out.stdout }}"
- hosts: "{{ NEW_HOST }}"
gather_facts: false
become: yes
become_user: oracle
vars_file:
- vars/main.yml
tasks:
- name: debug
command: hostname
register: new_host_out
- debug:
msg: "new host is {{ new_host_out.stdout }}"
Everything works fine in the first part of the code, but errors out at the second part saying it cannot find the NEW_HOST.
Use hostvars to reference such a variable. Create a dummy host to keep this variable. For example, given the inventory
shell> cat hosts
dummy
[test]
test_11
test_12
test_13
The playbook creates the variable. See Delegated facts
shell> cat pb.yml
- hosts: localhost
tasks:
- set_fact:
NEW_HOST: test_12
delegate_to: dummy
delegate_facts: true
- debug:
var: hostvars.dummy.NEW_HOST
- hosts: "{{ hostvars.dummy.NEW_HOST }}"
gather_facts: false
tasks:
- debug:
var: inventory_hostname
gives
shell> ansible-playbook pb.yml
PLAY [localhost] ****************************************************************************
TASK [set_fact] *****************************************************************************
ok: [localhost -> dummy]
TASK [debug] ********************************************************************************
ok: [localhost] =>
hostvars.dummy.NEW_HOST: test_12
PLAY [test_12] ******************************************************************************
TASK [debug] ********************************************************************************
ok: [test_12] =>
inventory_hostname: test_12
PLAY RECAP **********************************************************************************
localhost: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_12 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can use localhost for this purpose as well. The playbook below works as expected
- hosts: localhost
tasks:
- set_fact:
NEW_HOST: test_12
- hosts: "{{ hostvars.localhost.NEW_HOST }}"
gather_facts: false
tasks:
- debug:
var: inventory_hostname

How store full host name as variable in ansible?

I need to use one out of two hosts as a variable. I do have inventory_hostname_short of both but I need a full host as a variable. Currently, for testing I am using a hardcoded value. My playbook will run on both hosts at a same time so How I can identify and store as a variable.
host_1_full = 123.abc.de.com
host_2_full = 345.abc.de.com
above both are hosts and I do have
---
- name: Ansible Script
hosts: all
vars:
host1_short : '123'
host2_short : '345'
tasks:
- name: set host
set_fact:
host1_full: "{{inventory_hostname}}"
when: inventory_hostname_short == host1_short
- name: print info
debug:
msg: "host - {{host1_full}}"
- name: block1
block:
- name:running PS1 file
win_shell: "script.ps1"
register: host1_output
when: inventory_hostname_short == host1_short
- name: block2
block:
- name: set host
set_fact:
IN_PARA: "{{ hostvars[host1_full]['host1_output']['stdout']}}"
- name:running PS1 file
win_shell: "main.ps1 -paramater {{ IN_PARA }}"
register: output
when: inventory_hostname_short == host2_short
SO to access any file from different host required full hostname. How can I get that full host name
Given the following inventories/test_inventory.yml
---
all:
hosts:
123.abc.de.com:
345.abc.de.com:
ansible will provide the needed result in inventory_hostname automagically as demonstrated by the following test.yml playbook
---
- name: print long and short inventory name
hosts: all
gather_facts: false
tasks:
- name: print info
debug:
msg: "Host full name is {{ inventory_hostname }}. Short name is {{ inventory_hostname_short }}"
which gives:
$ ansible-playbook -i inventories/test_inventory.yml test.yml
PLAY [print long and short inventory name] *********************************************************************************************************************************************************************************************
TASK [print info] **********************************************************************************************************************************************************************************************************************
ok: [345.abc.de.com] => {
"msg": "Host full name is 345.abc.de.com. Short name is 345"
}
ok: [123.abc.de.com] => {
"msg": "Host full name is 123.abc.de.com. Short name is 123"
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
123.abc.de.com : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
345.abc.de.com : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As already suggested, the ansible_hostname and ansible_fqdn are automatic facts about hosts in your inventory. However, your requirement is a little unique. So we might have to apply a unique method to accomplish this. How about something like this?
Consider example inventory as below:
---
all:
hosts:
192.168.1.101: # 123.abc.de.com
192.168.1.102: # 345.abc.de.com
We can have a play like this:
- hosts: all
vars:
host1_short: 123
host2_short: 345
tasks:
- command: "hostname -f"
register: result
- block:
- set_fact:
host1_full: "{{ result.stdout }}"
- debug:
msg: "Host1 fullname: {{ host1_full }}"
when: host1_short in result.stdout

Passing variables between nested playbooks

I have a playbook where I'm spinning up an instance in aws with the ec2 module. To be more flexible I ask via prompt for the hostname. I found in the ec2 examples the code snippet, which allows you to run a second playbook with newly spun up instance for further configuration.
Now I want to set the hostname via module hostname but I cannot access the variable in the second playbook.
This is how my playbook looks like:
---
- hosts: localhost
...
vars_prompt:
- name: var_hostname
prompt: "Please enter the hostname"
private: no
tasks:
- name: Spin up instance
local_action:
module: ec2
...
register: ec2
- name: Add new instance to host group
add_host: hostname={{ item.public_ip }} groupname=launched
with_items: ec2.instances
- hosts: launched
...
tasks:
- name: Set hostname
hostname: name="{{ var_hostname }}"
fatal: [launched] => One or more undefined variables: 'var_hostname' is undefined
Is there a way to pass a variable from one playbook to another one?
I found Ansible best practice for passing vars to nested playbooks? but unfortunately it didn't had a solution which I can use.
You can use set_fact and hostvars together to achieve what you want.
Do set_fact on one group of hosts( i.e localhost), and access them in a different play using hostvars
{{hostvars['localhost']["new_fact"]}}
You can use local files.
1) Write
- name: write public ip
local_action:
template:
dest: /tmp/ansible_master_public_ip.txt
src: templates/public_ip.j2
2) Retrieve with http://docs.ansible.com/ansible/playbooks_lookups.html
hostname: "{{ lookup('file', '/tmp/ansible_master_public_ip.txt') | trim }}"
PS. Ini file lookup also an option if you need more than few variables.
Add the host's variable to the parameters. For example,
- name: Add new instance to host group
add_host:
hostname: "{{ ec2.instances.0.public_ip }}"
groupname: launched
var_hostname: "{{ var_hostname }}"
See examples
Use only the first item from the list because you have only one hostname. There is no reason to iterate the list.
Example of a complete playbook for testing
- hosts: localhost
gather_facts: false
vars_prompt:
- name: var_hostname
prompt: "Please enter the hostname"
private: no
vars:
ec2:
instances:
- public_ip: AAA.BBB.CCC.DDD
tasks:
- name: Add new instance to host group
add_host:
hostname: "{{ ec2.instances.0.public_ip }}"
groupname: launched
var_hostname: "{{ var_hostname }}"
- hosts: launched
gather_facts: false
tasks:
- debug:
var: var_hostname
shell> ansible-playbook pb.yml
Please enter the hostname: host_2
PLAY [localhost] *****************************************************************************
TASK [Add new instance to host group] ********************************************************
changed: [localhost]
PLAY [launched] ******************************************************************************
TASK [debug] *********************************************************************************
ok: [AAA.BBB.CCC.DDD] =>
var_hostname: host_2
PLAY RECAP ***********************************************************************************
AAA.BBB.CCC.DDD: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use pause instead of vars_prompt if you have more hosts. For example,
- name: Get var_hostname(s)
pause:
prompt: "Please enter the hostname for {{ item.public_ip }}"
echo: yes
loop: "{{ ec2.instances }}"
register: var_hostnames
- name: Add new instances to host group
add_host:
hostname: "{{ item.item.public_ip }}"
groupname: launched
var_hostname: "{{ item.user_input }}"
loop: "{{ var_hostnames.results }}"
loop_control:
label: "{{ item.user_input }}"
Example of a complete playbook for testing
- hosts: localhost
gather_facts: false
vars:
ec2:
instances:
- public_ip: AAA.BBB.CCC.DD1
- public_ip: AAA.BBB.CCC.DD2
tasks:
- name: Get var_hostname(s)
pause:
prompt: "Please enter the hostname for {{ item.public_ip }}"
echo: yes
loop: "{{ ec2.instances }}"
register: var_hostnames
- name: Add new instances to host group
add_host:
hostname: "{{ item.item.public_ip }}"
groupname: launched
var_hostname: "{{ item.user_input }}"
loop: "{{ var_hostnames.results }}"
loop_control:
label: "{{ item.user_input }}"
- hosts: launched
gather_facts: false
tasks:
- debug:
var: var_hostname
shell> ansible-playbook pb.yml
PLAY [localhost] *****************************************************************************
TASK [Get var_hostname(s)] *******************************************************************
[Get var_hostname(s)]
Please enter the hostname for AAA.BBB.CCC.DD1:
host_1^Mok: [localhost] => (item={'public_ip': 'AAA.BBB.CCC.DD1'})
[Get var_hostname(s)]
Please enter the hostname for AAA.BBB.CCC.DD2:
host_2^Mok: [localhost] => (item={'public_ip': 'AAA.BBB.CCC.DD2'})
TASK [Add new instances to host group] *******************************************************
ok: [localhost] => (item=host_1)
ok: [localhost] => (item=host_2)
PLAY [launched] ******************************************************************************
TASK [debug] *********************************************************************************
ok: [AAA.BBB.CCC.DD1] =>
var_hostname: host_1
ok: [AAA.BBB.CCC.DD2] =>
var_hostname: host_2
PLAY RECAP ***********************************************************************************
AAA.BBB.CCC.DD1: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
AAA.BBB.CCC.DD2: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Resources