Dictionary inside Dictionary in Ansible - ansible

I have the following Ansible playbook file:
1 ---
2 - name: Provision cluster
3 connection: local
4 hosts: localhost
5 gather_facts: False
6 vars_files:
7 - ../vars_files/credentials/foo.yml
8 - ../vars_files/credentials/bar.yml
9
10 vars:
11 - ec2_hosts:
12 - node1:
13 - address: 1.1.1.1
14 - node2:
15 - address: 1.1.1.2
16 - node3:
17 - address: 1.1.1.3
18 - node4:
19 - address: 1.1.1.4
What I'm trying to do is imply to have a dictionary inside another dictionary. On the second I'm going to declare a dictionary between hostname and its IP address. However I'm getting the following error:
ERROR: Syntax Error while loading YAML script, provision.yml
Note: The error may actually appear before this position: line 10, column 1
vars:

I personally prefer to use JSON (or Python'ish) expressions when defining complex variables as I find those more readable compared to complex vars defined in YAML syntax. E.g.:
vars:
ec2_hosts: {
node1: {
address: 1.1.1.1,
hostname: ec2_node1
},
node2: {
address: 1.1.1.2,
hostname: ec2_node2
},
},
If you must use YAML, hope that's actually the structure you want, it's different than the previous one:
vars:
- ec2_hosts:
- host1:
- address: 1.1.1.1
- host2:
- address: 1.1.1.2
Here is the tested code in case there are some other syntax errors:
- name: Provision cluster
connection: local
hosts: localhost
gather_facts: False
# vars_files:
# - ../vars_files/credentials/foo.yml
# - ../vars_files/credentials/bar.yml
vars:
- ec2_hosts:
- host1:
- address: 1.1.1.1
- host2:
- address: 1.1.1.2
tasks:
- debug: msg="{{ec2_hosts}}"
PS: I copied LOTS of trailing whitespaces from your post, hope they don't exist in your actual playbook YAML.

Related

Ansible separating hosts, group_vars and host_vars

I need to change some files in YAML format from one "big" yml to several smaller files. Unfortunately, I do not know which part belongs where. For example, I have the following .yml:
all:
hosts:
station01:
dns_name: localhost
ansible_host: localhost
work01:
dns_name: X.X.X.X
ansible_host: Y.Y.Y.Y
vars:
yum_proxy: false
zabbix_proxy_ip: A.A.A.A
yum_proxy_ip:
dns_servers:
- B.B.B.B
- C.C.C.C
timezone: XXX
ntp_servers:
- D.D.D.D
disable_firewall_tasks: true
children:
deploy:
hosts:
station01:
linux:
hosts:
work01:
work_users:
hosts:
work01:
vars:
users:
- john: user
- mike: user
I believe that hosts file should looke like this:
all:
hosts:
station01
work01
children:
deploy:
hosts:
station01:
linux:
hosts:
work01:
work_users:
hosts:
work01:
The group_vars "all.yml" looks like this, I guess:
---
all:
yum_proxy: false
zabbix_proxy_ip: A.A.A.A
yum_proxy_ip:
dns_servers:
- B.B.B.B
- C.C.C.C
timezone: XXX
ntp_servers:
- D.D.D.D
disable_firewall_tasks: true
And this is where the problem begins. I do not know where to put the "users:". Should it be in host_vars "work01.yml" assigned to one host, like this:
---
work01:
dns_name: X.X.X.X
ansible_host: Y.Y.Y.Y
users:
- john: user
- mike: user
Or should it be contained in the group_vars file named "work_users.yml"?
---
users:
- john: user
- mike: user
What the files host_vars and group_vars should look like? Any kind of help would be appreciated.
Q: "What the files host_vars and group_vars should look like?"
A: There are more options of how to name and organize the directories and files. See Organizing host and group variables.
Files named after the corresponding groups and hostnames
Below is an example of putting the variables into the files named after the corresponding groups and hostnames
shell> cat group_vars/all.yml
---
yum_proxy: false
zabbix_proxy_ip: A.A.A.A
yum_proxy_ip:
dns_servers:
- B.B.B.B
- C.C.C.C
timezone: XXX
ntp_servers:
- D.D.D.D
disable_firewall_tasks: true
shell> cat group_vars/work_users.yml
---
users:
- john: user
- mike: user
shell> cat host_vars/work01.yml
---
dns_name: X.X.X.X
ansible_host: Y.Y.Y.Y
shell> cat host_vars/station01.yml
---
dns_name: localhost
ansible_host: localhost
Files inside the directories named after the corresponding groups and hostnames
The next option is putting the variables into the files inside the directories named after the corresponding groups and hostnames
shell> cat group_vars/all/network.yml
---
yum_proxy: false
zabbix_proxy_ip: A.A.A.A
yum_proxy_ip:
dns_servers:
- B.B.B.B
- C.C.C.C
timezone: XXX
ntp_servers:
- D.D.D.D
disable_firewall_tasks: true
shell> cat group_vars/work_users/users.yml
---
users:
- john: user
- mike: user
shell> cat host_vars/work01/network.yml
---
dns_name: X.X.X.X
ansible_host: Y.Y.Y.Y
shell> cat host_vars/station01/network.yml
---
dns_name: localhost
ansible_host: localhost

Loop over nested dict

I need to iterate over a complex dict and apply properties from one key to another
I have tried many possibilities, such as with_nested, and with_subelements
I have an object as such
group_hosts:
- group:
name: a
hosts:
- host1
- host2
ports:
- 22
- 80
- group:
name: b
hosts:
- host3
- host4
ports:
- 22
- 80
And, given a host, I need to associate all the ports to it (host1 will have ports 22 and 80 associated to is, for example), so that in a later moment, while iterating I can use the wait_for module to check if the ports are open
The only workaround I found was to repeat the hostname for how many ports it had (by so doing I removed an extra list to loop)
More explicitly my var object became this
group_hosts:
- group:
name: a
hosts:
- name: host1
port: 80
- name: host1
port: 22
- name: host2
port: 22
- name: host2
port: 80
- group:
name: b
hosts:
- name: host3
port: 20
- name: host4
port: 2222
And my play this:
- name: traverse dict
debug:
msg: "group: {{item.0.group.name}} host is: {{item.1.name}} port is: {{item.1.port}}"
loop: "{{ group_hosts | subelements('group.hosts') | list }}"
But I don't like this workaround as I've had to modify the dict object by writing it in a less efficient way.
So, given the first dict object, how can I loop hosts and associate ports to them?
Meaning:
I want that given host1, I check its 22 and 80 ports, host 2 the same.
So:
hosts group a:
host1 : check ports 22, 80
host2: check ports 22, 80
hosts group b:
same as above
I already know how to "check" the ports on some host, my question is how to iterate such an object
Let's simplify the dictionary. The tasks below
- set_fact:
hosts2: "{{ hosts2|default({})|
combine({item.1:
{'name': item.0.group.name,
'ports': item.0.group.ports}}) }}"
loop: "{{ lookup('subelements', group_hosts, 'group.hosts') }}"
- debug:
var: hosts2
give a dictionary that can be easily iterated.
"hosts2": {
"host1": {
"name": "a",
"ports": [
22,
80
]
},
"host2": {
"name": "a",
"ports": [
22,
80
]
},
"host3": {
"name": "b",
"ports": [
22,
80
]
},
"host4": {
"name": "b",
"ports": [
22,
80
]
}
}

passing numeric parameter on ansible variable array

I got this ansible variable array, weblogic[1].name which will give me the name of the second array "manageServer1".
weblogic: [
{
name: "adminServer"
address: "1.1.1.1"
port: 1701
ssl: 1702
},
{
name: "manageServer1"
address: "1.1.1.2"
port: 1703
ssl: 1704
},
]
How can I pass parameter x=1 on the array, this one won't work, weblogic[x].name or weblogic['x'].name?
I'm working on Ansible 2.6-2.7.
Commas are missing in the lists. See example below.
> cat test.yml
---
- hosts: localhost
gather_facts: no
vars:
weblogic:
- { name: "adminServer", address: "1.1.1.1", port: 1701, ssl: 1702 }
- { name: "manageServer1", address: "1.1.1.2", port: 1703, ssl: 1704 }
tasks:
- debug: var=weblogic[item].name
loop:
- 0
- 1
> ansible-playbook test.yml | grep weblogic
"weblogic[item].name": "adminServer"
"weblogic[item].name": "manageServer1"

ansible cisco modifying multiple object-groups with single playbook lines

I have following playbook to modify ASA object-group:
---
- hosts: us_asa
connection: local
gather_facts: false
tasks:
- name: change config
asa_config:
auth_pass: "{{ ansible_ssh_password }}"
username: "{{ ansible_ssh_user }}"
password: "{{ ansible_ssh_password }}"
authorize: yes
timeout: 45
lines:
- network-object host 1.2.3.4
- network-object host 2.3.2.3
parents: ['object-group network BAD_IPs']
This works fine for single group.
Any suggestion how to modify multiple groups with same connection? If I add another object-group after parents: ['object-group network BAD_IPs'] example:
---
- hosts: us_asa
connection: local
gather_facts: false
tasks:
- name: change config
asa_config:
auth_pass: "{{ ansible_ssh_password }}"
username: "{{ ansible_ssh_user }}"
password: "{{ ansible_ssh_password }}"
authorize: yes
timeout: 45
lines:
- network-object host 1.2.3.4
- network-object host 2.3.2.3
parents: ['object-group network BAD_IPs']
- network-object host 4.4.4.4
parents: ['object-group network Good_IPs']
This fails
The offending line appears to be:
parents: ['object-group network BAD_IPs']
- network-object host 4.4.4.4
^ here
Any recommendation on syntax I should use?
Thank you in advance!
You just have a basic YAML syntax error there. A YAML dictionary key with a list value looks either like this:
key: [item1, item2, item3]
Or like this:
key:
- item1
- item2
- item3
You have some weird combination of the two:
parents: ['object-group network BAD_IPs']
- network-object host 4.4.4.4
I don't know exactly what structure you want, but what you have there is simply invalid.

iterate over the hostname stored in var_files

I have two type of server host names added in the ansible main.yml var file:
main.yml file:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
I am having an ansible playbook which essentially runs on foo_server1 and initializes/formats all other servers in the list one at a time - starting with foo_server2 then bar_server1, bar_server2 and so on...
---
- name: Reading variables from var files
hosts: localhost
connection: local
vars_files:
- main.yml
tasks:
- name: Initialize foo server2
command: initialize --host1 {{foo_server1}} to --host2 {{foo_server2}}
- name: Initialize bar server1
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server1}}
- name: Initialize bar server2
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server2}}
- name: Initialize bar server3
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server3}}
I dont want to add multiple lines in the playbook for each server rather wants to loop over the host names from the variable file. I am not sure how i would get this done..i am trying to loop over the hostname.. tried something below but no luck as i am getting undefined variable name..
---
server_list:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
Ansible playbook...
---
- hosts: localhost
gather_facts: no
vars_files:
- input.yml
tasks:
- name: Enable replication
local_action: shell initialize --host1 {{item.foo_server1}} --host2 {{item.foo_server2}}
with_items:
- "{{ server_list }}"
Can some one please suggest how can i run the same command on multiple servers. Would appreciate any help offered..
Here is an example for you:
---
- hosts: localhost
gather_facts: no
vars:
servers:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
tasks:
- debug:
msg: shell initialize --host1 {{ servers.foo_server1 }} --host2 {{ item.value }}
when: item.key != 'foo_server1'
with_dict: "{{ servers }}"

Resources