Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible : host in multiple groups

Tags:

ansible

I have a host in 2 groups : pc and Servers I have 2 group_vars (pc and servers) with, in each the file packages.yml These files define the list of packages to be installed on pc hosts and on servers hosts

I have a role to install default package

The problem is : only the group_vars/pc/packages.yml is take into account by the role task, packages from group_vars/servers/packages.yml are not installed

Of course what I want is installation of packages defined for pc and servers

I do not know if it is a bug or a feature ...

Thanks for your help

here is the configuration :

# file: production
[pc]
armen
kerbel
kerzo

[servers]
kerbel

---
# packages on servers
packages:
  - lftp
  - mercurial

---
# packages on pc
packages:
  - keepassx
  - lm-sensors
  - hddtemp
like image 679
dype Avatar asked May 07 '14 18:05

dype


People also ask

How do I pass multiple hosts in Ansible?

If you have equal count of hosts in each group, you can use pattern + serial. Ansible forms host list by pattern moving through groups sequentially. So if you have equal count of hosts, then batches formed by serial will be equal to groups.

How do I limit Ansible hosts?

You can also limit the hosts you target on a particular run with the --limit flag. Negated limit. Note that single quotes MUST be used to prevent bash interpolation.

How does Ansible Group_vars work?

The group_vars in Ansible are a convenient way to apply variables to multiple hosts at once. Group_vars is an Ansible-specific folder as part of the repository structure. This folder contains YAML files created to have data models, and these data models apply to all the devices listed in the hosts. ini file.


2 Answers

It's not a bug. According to the docs about variable precedence, you shouldn't define a variable in multiple places and try to keep it simple. Michael DeHaan (Ansible's lead dev) responded to a similar question on this topic:

Generally I find the purpose of plays though to bind hosts to roles, so the individual roles should contain the package lists.

I would use roles as it's a bit cleaner IMO.

If you really want (and this is NOT the recommended way), you can set the hash_behaviour option in ansible.cfg:

[defaults]
hash_behaviour = merge

This will cause the merging of two values when a hash (dict) is redefined, instead of replacing the old value with the new one. This does NOT work on lists, though, so you'll need to create a hash of lists, like:

group_vars/all/package.yml:

packages:
    all: [pkg1, pkg2]

group_vars/servers/package.yml:

packages:
    servers: [pkg3, pkg4]

Looping though that in the playbook is a bit more complex though.

like image 144
hkariti Avatar answered Sep 19 '22 08:09

hkariti


If you want to use such scheme. You should set the hash_behaviour option in ansible.cfg:

[defaults]
hash_behaviour = merge

In addition, you have to use dictionaries instead of lists. To prevent duplicates I recommend to use names as keys, for example:

group_vars/servers/packages.yml:

packages:
 package_name1:
 package_name2:

group_vars/pc/packages.yml:

packages:
 package_name3:
 package_name4:

And in a playbook task (| default({}) - for an absent "package" variable case):

- name: install host packages
  yum: name={{ item.key }} state=latest
  with_dict: packages | default({})
like image 37
Denys Avatar answered Sep 18 '22 08:09

Denys