Вы должны быть в состоянии выполнить задачу такого рода с созданием динамической группы хостов через модуль add_host
.
Кроме того, чтобы выполнить требование, которое будетбыть несколькими хостами на строку, мы сначала воссоздаем чистый массив с помощью модуля set_fact
.
Затем, с помощью вновь созданного массива, мы можем использовать цикл with_subelements
, для создания правильных кортежей (check_arg, host)
.
Вот пример, где я подделал вывод вашей базы данных в переменной dynamic_hosts
в игре:
---
- hosts: 127.0.0.1
gather_facts: false
connection: local
vars:
dynamic_hosts:
- "host5,host8\targ1"
- "host6,host2\targ3"
- "host9,host3,host4\targ4"
tasks:
- debug:
msg: "{{ dynamic_hosts }}"
- name: Make a clean array out of the hosts and arguments
set_fact:
hosts: "{{ hosts | default([]) + [ {'hosts': item.split('\t')[0].split(','), 'check_arg': item.split('\t')[1]} ] }}"
with_items: "{{ dynamic_hosts }}"
- debug:
msg: "{{ hosts }}"
- name: Adding hosts to a dynamic group based on the faked database output stored in hosts
add_host:
name: "{{ item.1 }}"
check_arg: "{{ item.0.check_arg }}"
ansible_host: 127.0.0.1
ansible_connection: local
groups: nodes_to_run_on
with_subelements:
- "{{ hosts }}"
- hosts
- hosts: nodes_to_run_on
gather_facts: false
tasks:
- debug:
msg: "Run the shell with the argument `{{ check_arg }}` here"
Как видите, я создаю группу хостов с именем nodes_to_run_on
в первой части пьесы с помощью add_host
.Позже я использую эту группу хостов для запуска нового набора задач на всех хостах в этой группе.
Это будет вывод этой пьесы:
PLAY [127.0.0.1] **********************************************************************************************************************************
TASK [debug] **************************************************************************************************************************************
ok: [127.0.0.1] => {
"msg": [
"host5,host8\targ1",
"host6,host2\targ3",
"host9,host3,host4\targ4"
]
}
TASK [Make a clean array out of the hosts and arguments] ******************************************************************************************
ok: [127.0.0.1] => (item=host5,host8 arg1)
ok: [127.0.0.1] => (item=host6,host2 arg3)
ok: [127.0.0.1] => (item=host9,host3,host4 arg4)
TASK [debug] **************************************************************************************************************************************
ok: [127.0.0.1] => {
"msg": [
{
"check_arg": "arg1",
"hosts": [
"host5",
"host8"
]
},
{
"check_arg": "arg3",
"hosts": [
"host6",
"host2"
]
},
{
"check_arg": "arg4",
"hosts": [
"host9",
"host3",
"host4"
]
}
]
}
TASK [Adding hosts to a dynamic group based on the faked database output stored in hosts] *********************************************************
changed: [127.0.0.1] => (item=[{'check_arg': 'arg1'}, 'host5'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg1'}, 'host8'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg3'}, 'host6'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg3'}, 'host2'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg4'}, 'host9'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg4'}, 'host3'])
changed: [127.0.0.1] => (item=[{'check_arg': 'arg4'}, 'host4'])
PLAY [nodes_to_run_on] ****************************************************************************************************************************
TASK [debug] **************************************************************************************************************************************
ok: [host5] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host8] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host6] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host2] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host9] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host3] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host4] => {
"msg": "Run the shell with the argument `arg4` here"
}
PLAY RECAP ****************************************************************************************************************************************
127.0.0.1 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host4 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host5 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host6 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host8 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host9 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Обратите внимание: это не совсем DRY список хостов, который мы создаем здесь, но он сохраняет решение наивным и более соответствует принципу KISS .
Инвентарь, который мы в итоге генерируем здесь, будет выглядеть следующим образом:
## kiss.yml ## lots of repetition
nodes_to_run_on:
hosts:
host5:
check_arg: arg1
ansible_host: 127.0.0.1
ansible_connection: local
host8:
check_arg: arg1
ansible_host: 127.0.0.1
ansible_connection: local
host6:
check_arg: arg3
ansible_host: 127.0.0.1
ansible_connection: local
host2:
check_arg: arg3
ansible_host: 127.0.0.1
ansible_connection: local
host9:
check_arg: arg4
ansible_host: 127.0.0.1
ansible_connection: local
host3:
check_arg: arg4
ansible_host: 127.0.0.1
ansible_connection: local
host4:
check_arg: arg4
ansible_host: 127.0.0.1
ansible_connection: local
Когда его определенно можно высушить до
## dry.yaml ## no repetition with the help of group variables
nodes_to_run_on:
vars:
ansible_host: 127.0.0.1
ansible_connection: local
children:
with_arg1:
hosts:
host5:
host8:
vars:
check_arg: arg1
with_arg3:
hosts:
host6:
host2:
vars:
check_arg: arg3
with_arg4:
hosts:
host9:
host3:
host4:
vars:
check_arg: arg4
Рассмотрим эти два прогона в этой игре:
---
- hosts: nodes_to_run_on
gather_facts: false
tasks:
- debug:
msg: "Run the shell with the argument `{{ check_arg }}` here"
С kiss.yml
$ ansible-playbook example.yml --inventory=kiss.yml
PLAY [nodes_to_run_on] ****************************************************************************************************************************
TASK [debug] **************************************************************************************************************************************
ok: [host5] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host8] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host6] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host2] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host9] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host3] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host4] => {
"msg": "Run the shell with the argument `arg4` here"
}
PLAY RECAP ****************************************************************************************************************************************
host2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host4 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host5 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host6 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host8 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host9 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
С dry.yml
$ ansible-playbook example.yml --inventory=dry.yml
PLAY [nodes_to_run_on] ****************************************************************************************************************************
TASK [debug] **************************************************************************************************************************************
ok: [host5] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host8] => {
"msg": "Run the shell with the argument `arg1` here"
}
ok: [host6] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host2] => {
"msg": "Run the shell with the argument `arg3` here"
}
ok: [host9] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host3] => {
"msg": "Run the shell with the argument `arg4` here"
}
ok: [host4] => {
"msg": "Run the shell with the argument `arg4` here"
}
PLAY RECAP ****************************************************************************************************************************************
host2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host3 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host4 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host5 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host6 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host8 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host9 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Итак, вы можете видеть, что мы достигаем того же с инвентарем, dry.yml
из 24 строк, когда инвентарь kiss.yml
был длиной 30 строк.
Но, в конечном счете, усилия по созданию изобретателя, который был бы СУХИМ, на самом деле не окупились бы, если бы источник, так или иначе, происходил избаза данных, которая будет генерировать список хостов.