populate yaml variable from jinja variable - ansible

I want to populate the nifi.web.https.host below after I run the below playbook. I am new to ansible jinja/yaml so I am not sure why is not working.
{% set external_ip = 'curl 169.254.169.254/2009-04-04/meta-data/public-ipv4' %}
- hosts: localhost
become: yes
roles:
- my.nifi
vars:
nifi_properties:
# HTTPS properties
nifi.web.https.host: 'external_ip'
nifi.web.https.port: 8443
nifi.web.https.network.interface.default: eth0
After I run the playbook I get this error:
{% set external_ip = 'curl 169.254.169.254/2009-04-04/meta-data/public-ipv4' %}
^ here

- hosts: localhost
become: yes
roles:
- my.nifi
pre_tasks:
- name: Get EC2 public IP
raw: curl http://169.254.169.254/2009-04-04/meta-data/public-ipv4
register: ec2_public_ip
vars:
nifi_properties:
# HTTPS properties
nifi.web.https.host: "{{ ec2_public_ip.stdout }}"
nifi.web.https.port: 8443
nifi.web.https.network.interface.default: eth0

Related

Create Local File With Ansible Template From Variables

I'm running an ansible playbook against a number of ec2 instances to check if a directory exists.
---
- hosts: all
become: true
tasks:
- name: Check if foo is installed
stat:
path:
/etc/foo
register: path
- debug: msg="{{path.stat.exists}}"
And I would like to generate a localfile that lists the private IP addresses of the ec2 instances and states whether or not the directory foo does exist.
I can get the private IP addresses of the instances with this task
- name: Get info from remote
shell: curl http://169.254.169.254/latest/meta-data/local-ipv4
register: bar
- debug: msg="{{bar.stdout}}"
How do I create a local file with content
IP address: 10.100.0.151 directory foo - false
IP address: 10.100.0.152 directory foo - true
I've tried adding a block for this as such
- hosts: localhost
become: false
vars:
installed: "{{bar.stdout}}"
status: "{{path.stat.exists}}"
local_file: "./Report.txt"
tasks:
- name: Create local file with info
copy:
dest: "{{ local_file }}"
content: |
"IP address {{ installed }} foo - {{ status }}"
But it doesn't look like I can read values of variables from earlier steps.
What am I doing wrong please?
A similar question has been answered here.
Basically what you want is to reference it through the host var variable.
This should work.
- hosts: localhost
become: false
vars:
local_file: "./Report.txt"
tasks:
- name: Create local file with info
lineinfile:
path: "{{ local_file }}"
line:
"IP Address: {{ hostvars[item]['bar'].stdout }} - Installed: {{ hostvars[item]['path'].stat.exists }}"
with_items: "{{ query('inventory_hostnames', 'all') }}"
And this should populate your local ./Report.txt file, with the info you need.
I've used the ec2_metadata_facts module to get the IP address us ingansible_ec2_local_ipv4
I've also created the directory /tmp/testdir on the second host.
- hosts: test_hosts
gather_facts: no
vars:
directory_name: /tmp/testdir
tasks:
- ec2_metadata_facts:
- name: check if directory '{{ directory_name }}' exsists
stat:
path: "{{ directory_name }}"
register: path
# I make the outputfile empty
# because the module lineinfile(as I know) can't overwrite a file
# but appends line to the old content
- name: create empty output file
copy:
content: ""
dest: outputfile
delegate_to: localhost
- name: write output to outputfile
lineinfile:
dest: outputfile
line: "IP Address: {{ ansible_ec2_local_ipv4 }} {{ directory_name }} - {{ path.stat.exists }}"
state: present
with_items: "{{ groups.all }}"
# with_items: "{{ ansible_play_hosts }}" can also be used here
delegate_to: localhost
The outputfile looks like:
IP Address: xxx.xx.x.133 /tmp/testdir - False
IP Address: xxx.xx.x.45 /tmp/testdir - True

Ansible Looping over dynamic inventory using jinja template

Here is my Ansible playbook. It reads /etc/waagent.conf file and checks if variable AutoUpdate.Enabled=y or not.And it uses Jinja template to generate output.csv file.
ansibleuser#server:~/plays$ cat report_waagent_local.yaml
---
- name: waagent auto update report
hosts: localhost
connection: ssh
remote_user: ewxxxx
become: true
become_user: root
gather_facts: true
tasks:
- name: "Ensure status of AutoUpdate.Enabled in /etc/waagent.conf"
lineinfile:
name: /etc/waagent.conf
line: AutoUpdate.Enabled=y
state: present
check_mode: yes #means make no change , just check
register: conf
failed_when: (conf is changed) or (conf is failed)
ignore_errors: yes
# logic
# if "conf.changed": false --> that mean AutoUpdate.Enabled=y
# if "conf.changed": true --> that means value is not set in file.
- name: generate report
template:
src: report_waagent_local.j2
dest: ./output.csv
ansibleuser#server:~/plays$
And here is Jinja Template.
ansibleuser#server:~/plays$ cat templates/report_waagent_local.j2
{% if conf.changed == false %}
{{ ansible_host }} , AutoUpdate.Enabled=y
{% else %}
{{ ansible_host }} , AutoUpdate.Enabled=n
{% endif %}
ansibleuser#server:~/plays$
It produces output.csv as expected.
127.0.0.1, AutoUpdate.Enabled=y
Now, I need to fetch similar reports for all the servers present in the Azure subscription.
I modified my playbook. Note: I am using dynamic inventory in azure, I have a group named "all_pls" on which I need to run a playbook.
ansibleuser#server:~/plays$ cat report_waagent.yaml
---
- name: "generate waagent report"
hosts: all
connection: ssh
remote_user : ewxxxxx
become: True
become_user: root
gather_facts: True
tasks:
- name: "Ensure status of AutoUpdate.Enabled in /etc/waagent.conf"
lineinfile:
name: /etc/waagent.conf
line: AutoUpdate.Enabled=y
state: present
check_mode: yes #means make no change , just check
register: conf
failed_when: (conf is changed) or (conf is failed)
ignore_errors: yes
# if "conf.changed": false --> that mean AutoUpdate.Enabled=y
# if "conf.changed": true --> that means the value is not set in the file.
- name: generate report
template:
src: report_waagent_local.j2
dest: ./output.csv
ansibleuser#server:~/plays$
I am running my playbook and getting no issues.
But I am getting no output in output.csv.
ansible-playbook --limit all_pls report_waagent.yaml
I guess I need to loop over hosts in a group name and also check conf.changed in the Jinja template. Can someone help please?
I fixed the issue.
- name: log conf.changed in output.csv using a template
lineinfile:
line: "{{ lookup('template', 'report_waagent_local.j2') }}"
insertafter: EOF
dest: output.csv
delegate_to: localhost

how to run multiple items using variables

I am trying to call port. But it is taking as array as two values instead of one.
Example:
cmd: nc -z msgq0003.svc.ops.wd5.wd ['2181', '5674']
Instead of:
nc -z servername 2181
This is my ansible palybook:
become: true
gather_facts: false
name: "Check all port numbers are accessible from current host"
hosts: ops-mgmt-aod,ops-mgmt-ots
vars:
server: "{{ groups['mgmt-server'] }}"
port: "{{ groups['mgmt-port'] }}"
tasks:
- name: network connection for zookeeper
shell: "nc -z {{ item }} {{ port }}"
with_items:
- "{{ server }}"
register: network_reachable_zoo
- debug: msg={{network_reachable_zoo}}

jinja2 - AnsibleUndefinedVariable: 'dict object' has no attribute '"{{ target_hosts }}"'"

This is my Ansible playbook to update /etc/hosts file:
- name: Update /etc/hosts file
hosts: "{{ target_hosts }}"
remote_user: awx
become: yes
become_method: sudo
tasks:
- debug:
msg: 'show me the variable: {{ target_hosts }}'
- name: Update /etc/hosts file
template: src=../../templates/hosts.j2 dest=/etc/hosts
And this is the jinja template:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for item in groups['"{{ target_hosts }}"'] %}
{{ hostvars[item]['ansible_ssh_host'] }} {{ hostvars[item]['openstack']['name'] }}
{% endfor %}
Everything works fine if I put a static value in the template (for example for item in groups['my-server-group']), but I would like to use a variable, passed dinamically to the playbook.
The error I get is:
AnsibleUndefinedVariable: 'dict object' has no attribute '\"{{ target_hosts }}\"'"
With the debug msg I'm sure that the playbook gets the parameter:
> "msg": "show me the variable: my-server-group".
Maybe the j2 template doesn't?
Is the syntax wrong? I tried both with quotes, double quotes and combination of two.
Is the syntax wrong?
Yes. Don't nest Jinja2 expressions. In your case {{ inside of {%.
Correct syntax:
{% for item in groups[target_hosts] %}
name: Update /etc/hosts file
hosts: "{{ target_hosts }}"
remote_user: awx
become: yes
become_method: sudo
tasks:

item from list of nodes depend on current index of host from hostgroup

I am having below setup,
groups_var/all.yml
---
cassandra_restore:
nodes:
- 192.168.0.1
- 192.168.0.2
- 192.168.0.3
inventory contains,
[just_created]
192.168.0.4
192.168.0.5
192.168.0.6
main.yml
---
# playbook
- name: setup
hosts: just_created
remote_user: ubuntu
become: true
become_method: sudo
gather_facts: yes
vars:
current_index: "{{ ansible_play_batch.index(inventory_hostname) }}"
tasks:
- debug:
msg: "current host index: {{ ansible_play_batch.index(inventory_hostname) }} : {{ current_index }}"
- debug:
msg: "first target host: {{ cassandra_restore.nodes.0 }}"
- name: get mapped value
debug:
msg: "current target host: {{ cassandra_restore.nodes.current_index }} "
I want to access item from list of nodes depend on current index of host from hostgroup just_created.
So when the host is 192.168.0.4 it should print 192.168.0.1 and when host is 192.168.0.5 it should print 192.168.0.2 and so on.
How can I achieve this?
You have to use the map form to access with a dynamic index or key:
- name: get mapped value
debug:
msg: "current target host: {{ cassandra_restore.nodes[current_index] }} "
But I'm not sure the order of the hosts is deterministic.
---
# playbook for creating cassandra setup
- name: setup cassnadra
hosts: just_created
remote_user: ubuntu
become: true
become_method: sudo
gather_facts: yes
vars:
current_index: "{{ ansible_play_batch.index(inventory_hostname) }}"
tasks:
- name: get mapped value
debug:
msg: "current_index current target host: {{ item.index }} : {{ item.host }} : {{ current_index }} "
when: current_index == item.index
with_items:
- "{{ cassandra_restore }}"
I got this working with following variables,
cassandra_restore:
- { index: "0", host: 192.168.0.1 }
- { index: "1", host: 192.168.0.2 }
- { index: "2", host: 192.168.0.3 }

Resources