Reputation: 3245
Below is sample inventory host file:
cat inventory.hosts
[dev_flipkart_app]
myhost6 ansible_user=fappuser
myhost9 ansible_user=fappuser
[dev_amazon_app]
myhost1 ansible_user=aappuser
[dev_snapdeal_app]
myhost4 ansible_user=sappuser
Below is my playbook main.yml
---
- name: Playbook
hosts: "{{ ENV }}_{{ appname }}_app"
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
This works fine when single {{ appname }}
is passed, but how to i build a dynamic inventory from inventory.hosts
using add_host
when multiple {{ appname }}
is passed?
ansible-playbook -i inventory.hosts main.yml -e ENV=dev -e appname="flipkart,amazon"
Expected dynamic host group should be as below:
myhost6 ansible_user=fappuser
myhost9 ansible_user=fappuser
myhost1 ansible_user=aappuser
Kindly suggest.
Upvotes: 1
Views: 1287
Reputation: 68044
For example, the playbook
- hosts: "{{ [ENV]|product(appname.split(','))|product(['app'])|
map('flatten')|map('join', '_') }}"
tasks:
- debug: var=ansible_user
gives (abridged)
shell> ansible-playbook pb.yml -e ENV=dev -e appname="flipkart,amazon"
...
ok: [myhost6] =>
ansible_user: fappuser
ok: [myhost9] =>
ansible_user: fappuser
ok: [myhost1] =>
ansible_user: aappuser
The next option is to compose a group. See
shell> ansible-doc -t inventory constructed
Create the inventory files
shell> cat hosts/01-hosts
[dev_flipkart_app]
myhost6 ansible_user=fappuser
myhost9 ansible_user=fappuser
[dev_amazon_app]
myhost1 ansible_user=aappuser
[dev_snapdeal_app]
myhost4 ansible_user=sappuser
shell> cat hosts/02-constructed.yml
plugin: constructed
strict: True
use_extra_vars: True
compose:
my_dev_regex: ENV
my_appname_regex: appname.split(',')|join('|')
my_groups: group_names
my_composed_group: group_names|
select('search', ENV)|
select('search', appname.split(',')|join('|'))
groups:
my_composed_group: my_groups|
select('search', my_dev_regex)|
select('search', my_appname_regex)|
length > 0
and enable the constructed plugin in the configuration. For example,
shell> grep constructed ansible.cfg
enable_plugins = ini, constructed
Test the inventory. For example,
shell> ansible-inventory -e ENV=dev -e appname="flipkart,amazon" --list --yaml
all:
children:
dev_amazon_app:
hosts:
myhost1:
ENV: dev
ansible_user: aappuser
appname: flipkart,amazon
my_appname_regex: flipkart|amazon
my_composed_group:
- dev_amazon_app
my_dev_regex: dev
my_groups:
- dev_amazon_app
dev_flipkart_app:
hosts:
myhost6:
ENV: dev
ansible_user: fappuser
appname: flipkart,amazon
my_appname_regex: flipkart|amazon
my_composed_group:
- dev_flipkart_app
my_dev_regex: dev
my_groups:
- dev_flipkart_app
myhost9:
ENV: dev
ansible_user: fappuser
appname: flipkart,amazon
my_appname_regex: flipkart|amazon
my_composed_group:
- dev_flipkart_app
my_dev_regex: dev
my_groups:
- dev_flipkart_app
dev_snapdeal_app:
hosts:
myhost4:
ENV: dev
ansible_user: sappuser
appname: flipkart,amazon
my_appname_regex: flipkart|amazon
my_composed_group: []
my_dev_regex: dev
my_groups:
- dev_snapdeal_app
my_composed_group:
hosts:
myhost1: {}
myhost6: {}
myhost9: {}
ungrouped: {}
Create a playbook and use the group my_composed_group
- hosts: my_composed_group
tasks:
- debug: var=ansible_user
This playbook gives the same results
shell> ansible-playbook pb.yml -e ENV=dev -e appname="flipkart,amazon"
...
ok: [myhost6] =>
ansible_user: fappuser
ok: [myhost9] =>
ansible_user: fappuser
ok: [myhost1] =>
ansible_user: aappuser
Upvotes: 1
Reputation: 33203
You seem to have noticed that hosts:
can be a jinja2 expression, but then stopped short of realizing that hosts:
can be a jinja2 expression
- hosts: "{{ appname | split(',') | map('regex_replace', '(.+)', ENV ~ '_\\1_app') }}"
tasks:
- debug: var=ansible_user
when run with your cited example command line
ansible-playbook -i inventory.hosts main.yml -e ENV=dev -e appname="flipkart,amazon"
produces
ok: [myhost6] => {
"ansible_user": "fappuser"
}
ok: [myhost9] => {
"ansible_user": "fappuser"
}
ok: [myhost1] => {
"ansible_user": "aappuser"
}
Upvotes: 2