How to split string twice in ansible playbook hosts section.

537 views
Skip to first unread message

Know-Your-Tech

unread,
Dec 27, 2022, 9:04:39 AM12/27/22
to Ansible Project
Below is how i call my ansible-playbook and pass application names as parameters APP1 & APP2

ansible-playbook -i /web/aes/admin/playbooks/updated.hosts /web/aes/admin/playbooks/split.yml -e ENV=qa -e NODE=cluster -e instance_name=APP1,APP2

Playbook:

---
- hosts: "{{ [ENV] | product(instance_name.split(',')) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}"
  user: wladmin
  gather_facts: no

I get the desired Output as below:

PLAY [['qa_APP1_cluster_wladmin_mmsplit', 'qa_APP2_cluster_wladmin_mmsplit']]

The problem occurs when i pass the application names as APP1-brazil & APP2-Chile

and wish the same output as before.

ansible-playbook -i /web/aes/admin/playbooks/updated.hosts /web/aes/admin/playbooks/split.yml -e ENV=qa -e NODE=cluster -e instance_name=APP1-brazil,APP2-Chile

I tried the below but i get error:

- hosts: "{{ [ENV] | product(instance_name.split(',') | split('-')[0]) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}"

Error in output:

ERROR! template error while templating string: expected token ',', got '['. String: {{ [ENV] | product(instance_name.split(',') | split('-')[0]) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}

Can you please suggest how can i address this requirement? 
 

Richard Megginson

unread,
Dec 27, 2022, 11:48:27 AM12/27/22
to ansible...@googlegroups.com
`split` is not an ansible filter - you cannot use it like `| split(something)` - you have to use as a string method which is why `instance_name.split(',')` works

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/da1f5460-e7c8-4e84-814a-ed3b2e3a9828n%40googlegroups.com.

Know-Your-Tech

unread,
Dec 27, 2022, 11:49:45 AM12/27/22
to Ansible Project
Thanks, Richard, but I was looking for a specific solution which seems to be tricky.

Vladimir Botka

unread,
Dec 27, 2022, 1:25:18 PM12/27/22
to Richard Megginson, ansible...@googlegroups.com
On Tue, 27 Dec 2022 09:47:57 -0700
Richard Megginson <rmeg...@redhat.com> wrote:

> `split` is not an ansible filter

Wrong. The filter *split* is available since 2.11. See
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html#manipulating-strings

--
Vladimir Botka

Vladimir Botka

unread,
Dec 27, 2022, 10:19:53 PM12/27/22
to Richard Megginson, ansible...@googlegroups.com
> On Tue, Dec 27, 2022 at 7:04 AM Know-Your-Tech <knowy...@gmail.com> wrote:
> >
> > ansible-playbook -i /web/aes/admin/playbooks/updated.hosts
> > /web/aes/admin/playbooks/split.yml -e ENV=qa -e NODE=cluster -e
> > instance_name=APP1,APP2
> >
> > Playbook:
> >
> > ---
> > - hosts: "{{ [ENV] | product(instance_name.split(',')) | product([NODE]) |
> > product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}"

Put the logic into the inventory plugin *constructed*. See
shell> ansible-doc -t inventory ansible.builtin.constructed

In the example below, I'll use another inventory plugin *generator*
which you don't need because you obviously have another source of the
inventory. When you try the code below in your environment use this
source instead of 02-generator.yml. See
shell> ansible-doc -t inventory ansible.builtin.generator

I've ignored the case of the parameters.

1) Create the inventory

shell> tree inventory/
inventory/
├── 01-hosts
├── 02-generator.yml
└── 03-constructed.yml

shell> cat inventory/01-hosts
localhost

shell> cat inventory/02-generator.yml
plugin: ansible.builtin.generator
hosts:
name: "{{ env }}_{{ instance }}_{{ node }}_{{ ext }}"
layers:
env:
- dev
- qa
- prod
instance:
- app1
- app2
node:
- cluster1
- cluster2
ext:
- wladmin_mmsplit

shell> cat inventory/03-constructed.yml
plugin: ansible.builtin.constructed
use_extra_vars: true
compose:
layer_env: ENV.split(',')
layer_node: NODE.split(',')
layer_instance: instance_name.split(',')
groups:
my_group: inventory_hostname.split('_').0 in layer_env and
inventory_hostname.split('_').1 in layer_instance and
inventory_hostname.split('_').2 in layer_node

2) Test inventory

shell> ansible-inventory -i inventory --list --yaml
all:
children:
ungrouped:
hosts:
dev_app1_cluster1_wladmin_mmsplit: {}
dev_app1_cluster2_wladmin_mmsplit: {}
dev_app2_cluster1_wladmin_mmsplit: {}
dev_app2_cluster2_wladmin_mmsplit: {}
localhost: {}
prod_app1_cluster1_wladmin_mmsplit: {}
prod_app1_cluster2_wladmin_mmsplit: {}
prod_app2_cluster1_wladmin_mmsplit: {}
prod_app2_cluster2_wladmin_mmsplit: {}
qa_app1_cluster1_wladmin_mmsplit: {}
qa_app1_cluster2_wladmin_mmsplit: {}
qa_app2_cluster1_wladmin_mmsplit: {}
qa_app2_cluster2_wladmin_mmsplit: {}

3) Test inventory group *my_group*

shell> ansible-inventory -i inventory --list --yaml -e ENV=qa -e NODE=cluster2 -e instance_name=app1,app2
all:
children:
my_group:
hosts:
qa_app1_cluster2_wladmin_mmsplit:
ENV: qa
NODE: cluster2
instance_name: app1,app2
layer_env:
- qa
layer_instance:
- app1
- app2
layer_node:
- cluster2
qa_app2_cluster2_wladmin_mmsplit:
ENV: qa
NODE: cluster2
instance_name: app1,app2
layer_env:
- qa
layer_instance:
- app1
- app2
layer_node:
- cluster2
ungrouped:
hosts:
dev_app1_cluster1_wladmin_mmsplit:
...

4) Use *my_group* in a playbook

shell> cat pb.yml
- hosts: my_group
tasks:
- debug:
var: ansible_play_hosts_all
run_once: true

shell> ansible-playbook -i inventory -e ENV=qa -e NODE=cluster2 -e instance_name=app1,app2 pb.yml

PLAY [my_group]
*****************************************************************

TASK [debug]
*****************************************************************
ok: [qa_app1_cluster2_wladmin_mmsplit] =>
ansible_play_hosts_all:
- qa_app1_cluster2_wladmin_mmsplit
- qa_app2_cluster2_wladmin_mmsplit
...

5) The items added to the inventory (02-generator.yml in this example)

instance:
- app1
- app2
- app3-brazil

will be automatically available for selection

shell> ansible-playbook -i inventory -e ENV=qa -e NODE=cluster2 -e instance_name=app1,app3-brazil pb.yml

PLAY [my_group]
******************************************************************************

TASK [debug]
*********************************************************************************
ok: [qa_app1_cluster2_wladmin_mmsplit] => ansible_play_hosts_all:
- qa_app1_cluster2_wladmin_mmsplit
- qa_app3-brazil_cluster2_wladmin_mmsplit
...

--
Vladimir Botka
Reply all
Reply to author
Forward
0 new messages