group_names variable in ansible - ansible

I am running some issues when I execute this playbook:
- hosts: all
connection: local
tasks:
- template: src=/etc/ansible/{{group_names}}/common.j2 dest=/etc/ansible/configs/{{inventory_hostname}}.txt
name: create common config snippets
the error that I am getting is:
fatal: [R1]: FAILED! => {"changed": false, "failed": true, "msg": "Unable to find '/etc/ansible/[u'ios']/common.j2' in expected paths."}
fatal: [R2]: FAILED! => {"changed": false, "failed": true, "msg": "Unable to find '/etc/ansible/[u'ios1']/common.j2' in expected paths."}
and here are my groups:
/etc/ansible# cat hosts | grep ios
[ios]
[ios1]
and here are my common.j2 files:
/etc/ansible# ls ios1/
common.j2
/etc/ansible# ls ios/
common.j2
Could someone elaborate why the group_names returns [u'group_names] please?

Because group_names a list (that's why it is surrounded by [ ]) -- a host can belong to multiple groups.
You need to decide, what is your objective:
If you wanted to include files for all groups, you have to add a loop:
- hosts: all
connection: local
tasks:
- name: create common config snippets
template:
src: /etc/ansible/{{item}}/common.j2
dest: /etc/ansible/configs/{{inventory_hostname}}.txt
with_items: "{{group_names}}"
If you wanted to add a single group, you could refer to a single element (group_names[0]), but that doesn't seem practical...

Related

Multiple variables in with_items made error

I created the following playbook to set ufw settings.
---
- name: setup ufw for multi ports
hosts: db
become: yes
tasks:
- name: 'Allow all access for multi ports'
community.general.ufw:
rule: allow
port: "{{ item.port_num }}"
src: "{{ item.dest_ip }}"
with_items:
- { port_num: "33787", dest_ip: "{{web_ip_band}}" }
And this is my group_vars file.
web_ip_band:
- '192.168.101.13/24'
- '192.168.101.44/24'
when I execute this playbook, I get this error.
failed: [dbserver01] (item={'port_num': '33787', 'dest_ip': ['192.168.101.13/24', '192.168.101.44/24']}) => {"ansible_loop_var": "item", "changed": false, "commands": ["/usr/sbin/ufw status verbose", "/bin/grep -h '^### tuple' /lib/ufw/user.rules /lib/ufw/user6.rules /etc/ufw/user.rules /etc/ufw/user6.rules /var/lib/ufw/user.rules /var/lib/ufw/user6.rules", "/usr/sbin/ufw --version", "/usr/sbin/ufw allow from ['192.168.101.13/24', '192.168.101.44/24'] to any port 33787"], "item": {"dest_ip": ["192.168.101.13/24", "192.168.101.44/24"], "port_num": "33787"}, "msg": "ERROR: Wrong number of arguments\n"}
Is there a syntax error in my playbook?
From the community.general.ufw module documentation (extract rearranged to fit in SO answer)
from_ip (aliases: from, src)
string - Default: "any"
You are passing a list of IPs, which explains your error message:
ERROR: Wrong number of arguments
You have to play that task for each combination of port_num and individual entries in dest_ip. What you need here is a subelements loop:
- name: 'Allow all access for multi ports'
community.general.ufw:
rule: allow
port: "{{ item.0.port_num }}"
src: "{{ item.1 }}"
vars:
my_rules:
- { port_num: "33787", dest_ip: "{{web_ip_band}}" }
loop: "{{ my_rules | subelements('dest_ip') }}"

Not able to gather facts of ansible host machine

Set up module in ansible gives an error when i tried to set custom facts on host machine using control machine
---
- hosts: test-servers
gather_facts: false
tasks:
- name: deleting Facts directory
file:
path: /etc/ansible/facts.d/
state: absent
- name: Creates a directiory
file:
path: /etc/ansible/facts.d/
recurse: yes
state: directory
- name: Copy custom date facts to host machine
copy:
src: /app/ansible_poc/roles/custom_facts/templates/facts.d/getdate.fact
dest: /etc/ansible/facts.d/getdate.fact
mode: 0755
- name: Copy custom role facts to host machine
copy:
src: /app/ansible_poc/roles/custom_facts/templates/facts.d/getrole.fact
dest: /etc/ansible/facts.d/getrole.fact
mode: 0755
- name: Reloading facts
setup:
- name: Display message
debug:
msg: "{{ ansible_local.getdate.date.date }}"
- name: Display message
debug:
msg: "{{ ansible_local.getrole.role.role }}"
I get following error when i tried to collect facts of ansible host machine. I have set up a file getdate.fact and getrole.fact which has code respectively
#############getdate.fact###############
echo [date]
echo date= `date`
########################################
#############getrole.fact###############
echo [role]
echo role= `whoami`
########################################
and when i tried to run the playbook main.yml then it following error.
[root#ansibletower tasks]# ansible -m setup test-servers
192.168.111.28 | FAILED! => {
"changed": false,
"cmd": "/etc/ansible/facts.d/getdate.fact",
"msg": "[Errno 8] Exec format error",
"rc": 8
}
192.168.111.27 | FAILED! => {
"changed": false,
"cmd": "/etc/ansible/facts.d/getdate.fact",
"msg": "[Errno 8] Exec format error",
"rc": 8
}
If I recall correctly, executables are expected to return JSON:
#!/bin/bash
echo '{ "date" : "'$( date )'" }'
You probably need to add "shebang" line to your fact scripts. I.e., getdate.fact should look like:
#!/bin/sh
echo [date]
echo date=`date`

Ansible: Use of Diff command using Ansible

I am trying to one simple task which is find out the difference between the two files and store it in notepad. I am not able to do it with command as well as shell. Please suggest where i am going wrong-
---
- hosts: myserver
tasks:
- name: get the difference
command: diff hosts.new hosts.mod
register: diff
- debug: var=diff.cmd
Error -
fatal: [zlp12037]: FAILED! => {"changed": true, "cmd": ["diff", "hosts.new", "hosts.mod"], "delta": "0:00:00.003102", "end": "2017-03-29 10:17:34.448063", "failed": true, "rc": 1, "start": "2017-03-29 10:17:34.444961", "stderr": "", "stdout":
I'm not quite sure what your input play looks like with your formatting. But the following should be a solution:
- name: "Get difference from two files"
command: diff filea fileb
args:
chdir: "/home/user/"
failed_when: "diff.rc > 1"
register: diff
- name: debug output
debug: msg="{{ diff.stdout }}"
Some explanation:
If something fails with the diff command, the return code is > 1. We evaluate this by the "failed_when".
To get the output of the command, we print the ".stdout" element.
To make sure we're in the folder where the files are, we use "chdir".
I would move the hosts.new or hosts.mod to the ansible control machine.
Run the copy module with the src as hosts.new and the dest as hosts.mod with --check and --diff. I find this method most useful to spot differences in files across a large enterprise.
Run:
ansible all -m copy -a "src=hosts.new dest=/tmp/hosts.mod" --check --diff -i hosts
Output:
--- before: /tmp/hosts.mod
+++ after: /home/ansible/hosts.new
## -1,5 +1,5 ##
host1
+host2
host3
host4
-host6
-host99
+host5
test10 | SUCCESS => {
"changed": true,
"failed": false
}

Using facts from one host group to configure another host group with Ansible

I am trying to configure one set of hosts [nodes] using facts from another set of hosts [etcd]. Here is my hosts file
[master]
kubernetes ansible_ssh_host=10.2.23.108
[nodes]
n1 ansible_ssh_host=10.2.23.192
n2 ansible_ssh_host=10.2.23.47
[etcd]
etcd01 ansible_ssh_host=10.2.23.11
etcd02 ansible_ssh_host=10.2.23.10
etcd03 ansible_ssh_host=10.2.23.9
Note that the group [etcd] is not the target of provisioning - [nodes] is. But provisioning [nodes] requires knowledge of the facts of [etcd].
Here is my playbook:
---
- name: Configure common
hosts: nodes
sudo: True
tasks:
- name: etcd endpoints
file: dest=/etc/kubernetes state=directory
- name: etcd endpoints
template: src=files/k.j2 dest=/etc/kubernetes/apiserver
Finally, here is the template for files/k.j2
KUBE_ETCD_SERVERS="--etcd_servers="{% for host in groups['etcd'] %}https://{{hostvars[host]['ansible_eth0']["ipv4"]["address"]}}:2380{% if not loop.last %},{% endif %}{% endfor %}"
The goal is to produce a KUBE_ETCD_SERVERS value that looks like
--etcd_servers=https://10.2.23.11:2380,https://10.2.23.10:2380,https://10.2.23.10:2380
When I run this playbook I get console output
TASK [etcd endpoints] **********************************************************
fatal: [n1]: FAILED! => {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_eth0'"}
fatal: [n2]: FAILED! => {"changed": false, "failed": true, "msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'ansible_eth0'"}
What is the idiomatic Ansible way to make the etcd facts available to the node play?
If you want to use facts of some host, you should gather them first.
Run setup task on [etcd] hosts to populate hostvars.
---
- name: Gather etcd facts
hosts: etcd
tasks:
- setup:
- name: Configure common
hosts: nodes
sudo: True
tasks:
- name: etcd endpoints
file: dest=/etc/kubernetes state=directory
- name: etcd endpoints
template: src=files/k.j2 dest=/etc/kubernetes/apiserver

When hostvars data is populated and how it is accessible?

Here is my play:
- name: Tag ec2 instances
hosts: localhost
tasks:
- name: Print Hosts
debug: var=hostvars[item]['ec2_id']
with_inventory_hostnames: all
- name: Print Hosts 2
debug: msg={{hostvars[item]['ec2_id']}}
with_inventory_hostnames: all
- name: Tag Hosts
ec2_tag:
resource: "{{ hostvars[item]['ec2_id'] }}"
region: ap-southeast-2
args:
tags: {mytag: 'myvalue'}
with_inventory_hostnames: all
Can anyone explain why the second task fails with the following error while the first one is successful?
...
ok: [localhost] => (item=172.31.11.37) => {
"hostvars[item]['ec2_id']": "i-xxxxxx",
"item": "172.31.11.37"
}
TASK [Print Hosts 2] ***********************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'ec2_id'"}
debug module with var=hostvars[item]['ec2_id'] will not fail if anything to the right of equal sign is undefined.
While msg={{hostvars[item]['ec2_id']}} will fail if the part in braces can't be templated.
In your example this may fail for localhost because I'm almost sure that ec2_id is not defined for localhost.
To avoid this, you can apply when statement to your loop, as follows:
- name: Print Hosts 2
debug: msg={{hostvars[item]['ec2_id']}}
when: hostvars[item]['ec2_id'] is defined
with_inventory_hostnames: all

Resources