yml format for inventory file...fails - ansible

---
all:
zones:
- name: accessswitch
hosts:
- name: accessswitch-x0
ip: 192.168.4.xx
- name: groupswitch
hosts:
- name: groupswitch-x1
ip: 192.168.4.xx
- name: groupswitch-x2
ip: 192.168.4.xx
- name: groupswitch-x3
ip: 192.168.4.xx
Basically i have a access switch and to that switch there are many group switches connected to it...Tried already "children" but this does not work. A typical ini file works....
Also i have some variables...which do apply to all zones aka. access witch & group switches...
in the future there will be more than 1 ..multiple access switches..
....
some docs use ansible-host:...confusing..
And yes..checked the uml structure...
cat#catwomen:~/workspace/ansible-simulator/inventories/simulator/host_vars$ sudo ansible -i testdata.yaml all -m ping
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'
cat#catwomen:~/workspace/ansible-simulator/inventories/simulator/host_vars$ sudo ansible -i testdata.yaml all -m ping
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'

You have yaml indentation problems which is an error (indentation in yaml is significant). Moreover, you must follow the specific format described in the documentation.
Very basically, the file is an imbrication of groups in parent/child relationship starting with the top element special group all. A group definition looks like:
---
my_group1: # group name, use `all` at top level
vars:
# definition of vars for this group. Apply to all hosts if defined for `all`
hosts:
# hosts in that group (host is ungrouped if it appears only in `all`)
children:
# mapping of children group definitions (repeat the current format)
A host definition looks like:
my_host1:
# definition of vars specific to that host if any
A var definition (either for vars in group or for a specific host) looks like:
my_variable1: some value
If I understand correctly from your example, here is how your yaml inventory should look like (inventories/so_example.yml)
---
all:
children:
accessswitch:
hosts:
accessswitch-x0:
ansible_host: 192.168.4.xx
groupswitch:
hosts:
groupswitch-x1:
ansible_host: 192.168.4.xx
groupswitch-x2:
ansible_host: 192.168.4.xx
groupswitch-x3:
ansible_host: 192.168.4.xx
You can then easilly see how the above is interpreted with the ansible-inventory command:
$ ansible-inventory -i inventories/so_example.yml --graph
#all:
|--#accessswitch:
| |--accessswitch-x0
|--#groupswitch:
| |--groupswitch-x1
| |--groupswitch-x2
| |--groupswitch-x3
|--#ungrouped:
$ ansible-inventory -i inventories/so_example.yml --list
{
"_meta": {
"hostvars": {
"accessswitch-x0": {
"ansible_host": "192.168.4.xx"
},
"groupswitch-x1": {
"ansible_host": "192.168.4.xx"
},
"groupswitch-x2": {
"ansible_host": "192.168.4.xx"
},
"groupswitch-x3": {
"ansible_host": "192.168.4.xx"
}
}
},
"accessswitch": {
"hosts": [
"accessswitch-x0"
]
},
"all": {
"children": [
"accessswitch",
"groupswitch",
"ungrouped"
]
},
"groupswitch": {
"hosts": [
"groupswitch-x1",
"groupswitch-x2",
"groupswitch-x3"
]
}
}

The incident is not correct for the line #6. Try below please.
---
all:
zones:
- name: accessswitch
hosts:
- name: accessswitch-x0
ip: 192.168.4.xx
- name: groupswitch
hosts:
- name: groupswitch-x1
ip: 192.168.4.xx
- name: groupswitch-x2
ip: 192.168.4.xx
- name: groupswitch-x3
ip: 192.168.4.xx

Related

Use variable group in playbook like target hosts

I hava this situation:
A play that run in localhost use include_task for create, on the fly with add_host, two sub-group extracting only one host from two group that are present in the inventory file.
Another play in the same yaml file use this group as hosts (host:sub-group).
This is the inventory file:
all:
children:
group_one:
hosts:
hostA01:
ansible_host: host1a
hostA02:
ansible_host: host2a
hostA03:
ansible_host: host3a
vars:
cluster: hosta
vip: 192.168.10.10
home: /cluster/hosta
user: usr_hosta
pass: pass_hosta
group_two:
hosts:
hostB01:
ansible_host: host1b
hostB02:
ansible_host: host2b
hostB03:
ansible_host: host3b
vars:
cluster: hostb
vip: 192.168.10.20
home: /cluster/hostb
user: usr_hostb
pass: pass_hostb
other groups...
I have created the sub groups, with add_host, for each group in inventoty file. The name the sub-groups add the prefix "sub-" to inventory original groups, like sub-(one/two/etc..)
In hostvars i retrieve this situation:
"groups": {
"all": [
"hostA01",
"hostA02",
"hostA03",
"hostB01",
"hostB02",
"hostB03",
"other_host_from _other groups"
],
"group_one": [
"hostA01",
"hostA02",
"hostA03"
],
"group_two": [
"hostB01",
"hostB02",
"hostB03"
],
"other_group": [
"other_host",
.....
],
"sub-group_one": [
"hostA01"
],
"sub_group_two": [
"hostB01"
],
"sub-other_group": [
"other_first_host"
],
"ungrouped": []
},
"vars_for_group": {
"group_one": {
"cluster: hosta
"vip: 192.168.10.10
"home: /cluster/hosta
"user: usr_hosta
"pass: pass_hosta,
"ansible_host": "host1a",
"host": "hostA01"
},
"group_two": {
"cluster: hostb
"vip: 192.168.10.20
"home: /cluster/hostb
"user: usr_hostb
"pass: pass_hostb,
"ansible_host": "host1b",
"host": "hostB01"
},
"otehr_groups": {
.......
},
},
"inventory_hostname": "127.0.0.1",
"inventory_hostname_short": "127",
"module_setup": true,
"playbook_dir": ""/home/foo/playbook",
"choice": "'sub-two'"
}
}
The environment variable "choice" in the last line of hostvars derives from other tool and indicates the group on which the final user wants to operate (one, two, ..., all).
Now, my playbook is:
---
- hosts: 127.0.0.1
become: yes
gather_facts: yes
remote_user: root
tasks:
- name: include news_groups
ansible.builtin.include_tasks:
newsgroups.yaml
vars:
choice: "{{ lookup('env','CHOICE') }}"
- hosts: "{{ hostvars['localhost']['groups']['{{ hostvars['localhost']['choice'] }}'] }}"
name: second_play
become: yes
gather_facts: no
remote_user: root
tasks:
- hosts: all
name: other play
gather_facts: no
vars:
other_vars:...
tasks:
.....
Unfortunately this line don't work.
- hosts: "{{ hostvars['localhost']['groups']['{{ hostvars['localhost']['choice'] }}'] }}"
I have made several attempts with many different configuration and different sintax (without {{...}}, with or without "double quotes" and 'single quote' but it always seems syntactically wrong or still cannot find the group indicated by the variable. Or, maybe could it also be that the approach is wrong?
Any suggestions?
Thanks in advance

Accessing values from role defaults

I need to access the values from role defaults in the context of other hosts in the inventory. While the values defined in the inventory are available, the role defaults are not.
The following example demonstrates my problem:
#inventory.yml:
all:
hosts:
srv01:
ansible_connection: local
user_name: srv-1-user
domain: example.com
srv02:
ansible_connection: local
user_name: srv-2-user
domain: example.net
#role-a/defaults.yml
user_email_address: {{ user_name }}#{{ domain }}
#role-a/main.yml
- set_fact:
_values: "{{ _values | default([]) + [hostvars[item]['user_email_address'] | default(user_email_address)] }}"
with_inventory_hostnames:
- all
- name: output
debug: var=_values
#site.yml
#!/usr/bin/env ansible-playbook
- hosts: all
tasks:
- import_role:
name: role-a
tags: 'role-a'
#command:
ansible-playbook -i inventory.yml site.yml
The code above generates (as expected) the following output:
ok: [srv02] => {
"_values": [
"srv-2-user#example.net",
"srv-2-user#example.net"
]
}
ok: [srv01] => {
"_values": [
"srv-1-user#example.com",
"srv-1-user#example.com"
]
}
What I need is the following output:
ok: [srv02] => {
"_values": [
"srv-1-user#example.net",
"srv-2-user#example.net"
]
}
ok: [srv01] => {
"_values": [
"srv-1-user#example.com",
"srv-2-user#example.com"
]
}
It is not viable defining all values in the inventory. This problem makes role defaults in this context unusable for me.
Any help or suggestion is appreciated.
You could define user_email_address as
user_email_address: "{{ hostvars[item]['user_name'] }}#{{ hostvars[item]['domain'] }}"
to take advantage of the lazy loading.

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 a list to a role in Ansible

I need to read from a config file which needs to contain a list. The list needs to be passed to a role as argument.
---
- name: run command on localhost
hosts: localhost
tasks:
- name: read variables from file
shell: cat {{ conf1/TMP.txt }}
register: contents
- name: role to trigger the run script process
hosts: otherhost
roles:
- { role: run_script, applist: "{{ contents }}" }
The content of the conf1/TMP.txt file is as follows:
[ 'a', 'b', 'c', 'd' ]
The above mentioned code segment is not working but the following code segment works:
---
- name: main yml file to trigger the whole process
hosts: otherhost
roles:
- { role: run_script, applist: [ 'a', 'b', 'c', 'd' ] }
Try using a lookup filter instead of a shell command. Example below..
---
- name: run command on localhost
hosts: localhost
tasks:
- set_fact:
contents: "{{ lookup('file', 'tmp.txt') }}"
- debug: var=contents
- name: role to trigger the run script process
hosts: localhost
roles:
- { role: foo, applist: "{{ contents }}" }
The output of debug should look like this
ok: [localhost] => {
"foo": [
"1",
"2",
"3",
"4"
]}

Ansbile AWS Dynamic Inventory Groups Fail to Match Play Hosts

I'm having trouble getting my Ansible play's hosts to match the AWS dynamic groups that are coming back for my dynamic inventory. Let's break this problem down.
Given this output of ec2.py --list:
$ ./devops/inventories/dynamic/ec2.py --list
{
"_meta": {
"hostvars": {
"54.37.213.132": {
"ec2__in_monitoring_element": false,
"ec2_ami_launch_index": "0",
"ec2_architecture": "x86_64",
"ec2_client_token": "",
"ec2_dns_name": "ec2-52-37-203-132.us-west-2.compute.amazonaws.com",
"ec2_ebs_optimized": false,
"ec2_eventsSet": "",
"ec2_group_name": "",
"ec2_hypervisor": "xen",
"ec2_id": "i-d352c50b",
"ec2_image_id": "ami-63b25203",
"ec2_instance_profile": "",
"ec2_instance_type": "t2.micro",
"ec2_ip_address": "54.37.213.132",
"ec2_item": "",
"ec2_kernel": "",
"ec2_key_name": "peaker-v1-keypair",
"ec2_launch_time": "2016-03-11T20:45:44.000Z",
"ec2_monitored": false,
"ec2_monitoring": "",
"ec2_monitoring_state": "disabled",
"ec2_persistent": false,
"ec2_placement": "us-west-2a",
"ec2_platform": "",
"ec2_previous_state": "",
"ec2_previous_state_code": 0,
"ec2_private_dns_name": "ip-172-31-43-132.us-west-2.compute.internal",
"ec2_private_ip_address": "172.31.43.132",
"ec2_public_dns_name": "ec2-52-37-203-132.us-west-2.compute.amazonaws.com",
"ec2_ramdisk": "",
"ec2_reason": "",
"ec2_region": "us-west-2",
"ec2_requester_id": "",
"ec2_root_device_name": "/dev/xvda",
"ec2_root_device_type": "ebs",
"ec2_security_group_ids": "sg-824ac0e5",
"ec2_security_group_names": "peaker-v1-security-group",
"ec2_sourceDestCheck": "true",
"ec2_spot_instance_request_id": "",
"ec2_state": "running",
"ec2_state_code": 16,
"ec2_state_reason": "",
"ec2_subnet_id": "subnet-b96e1bce",
"ec2_tag_Environment": "v1",
"ec2_tag_Name": "peaker-v1-ec2",
"ec2_virtualization_type": "hvm",
"ec2_vpc_id": "vpc-5fe8ae3a"
}
}
},
"ec2": [
"54.37.213.132"
],
"tag_Environment_v1": [
"54.37.213.132"
],
"tag_Name_peaker-v1-ec2": [
"54.37.213.132"
],
"us-west-2": [
"54.37.213.132"
]
}
I should be able write a playbook that matches some of the groups coming back:
---
# playbook
- name: create s3 bucket with policy
hosts: localhost
gather_facts: yes
tasks:
- name: s3
s3:
bucket: "fake"
region: "us-west-2"
mode: create
permission: "public-read-write"
register: s3_output
- debug: msg="{{ s3_output }}"
- name: test on remote machine
hosts: ec2
gather_facts: yes
tasks:
- name: test on remote machine
file:
dest: "/home/ec2-user/test/"
owner: ec2-user
group: ec2-user
mode: 0700
state: directory
become: yes
become_user: ec2-user
However, when I --list-hosts that match these plays it's obvious that the play hosts are not matching anything coming back:
$ ansible-playbook -i devops/inventories/dynamic/ec2/ec2.py devops/build_and_bundle_example.yml --ask-vault-pass --list-hosts
Vault password:
[WARNING]: provided hosts list is empty, only localhost is available
playbook: devops/build_and_bundle_example.yml
play #1 (localhost): create s3 bucket with policy TAGS: []
pattern: [u'localhost']
hosts (1):
localhost
play #2 (ec2): test on remote machine TAGS: []
pattern: [u'ec2']
hosts (0):
The quick fix for what you're doing:
change hosts: localhost in your playbook to hosts: all
It would never work just with dynamic inventory if you're going to keep hosts: localhost in your playbook...
If so, – you must combine dynamic & static inventories. Create file with path ./devops/inventories/dynamic/static.ini (on the same level with ec2.py and ec2.ini) and put this content:
[localhost]
localhost
[ec2_tag_Name_peaker_v1_ec2]
[aws-hosts:children]
localhost
ec2_tag_Name_peaker_v1_ec2
After that, you will be able to run a quick check:
ansible -i devops/inventories/dynamic/ec2 aws-hosts -m ping
and your playbook itself:
ansible-playbook -i devops/inventories/dynamic/ec2 \
devops/build_and_bundle_example.yml --ask-vault-pass
NOTE: devops/inventories/dynamic/ec2 is a path to the folder, but it will be automatically resolved into hybrid dynamic&static inventory with access to aws-hosts group name.
In fact, this isn't the best use of inventory. But it's important to understand, that by combining dynamic&static inventories, you're just appending new group names for particular dynamic host
ansible -i devops/inventories/dynamic/ec2 all -m debug \
-a "var=hostvars[inventory_hostname].group_names"

Resources