Как запустить Ansible Play для каждой итерации цикла - PullRequest
2 голосов
/ 23 сентября 2019

Ниже зарегистрированной переменной command_result получает записи из базы данных, которые могут быть многострочными.

Ниже приведен цикл для каждой записи в базе данных в переменной command_result.

   - debug:
       msg: "This is a database line: {{ item }}"
     with_items: "{{ command_result.stdout_lines }}"

Теперь мне нужно запустить новую игру, как показано ниже, для каждой итерации цикла вместе с соответствующим {{ item }}.

- hosts: "{{ item.stdout.split('\t')[0] }}"
  tasks:
    - name: Check if reboot is required
      shell: /home/ansible/scripts/check.sh "{{ item.stdout.split('\t')[1] }}"
      register: output

    - debug: var=output.stdout_lines

    - add_host: name={{ item }}
               groups=dest_nodes
               ansible_user={{ USER }}
     with_items: "{{ dest_ip.split(',') }}"

Значение элемента будет меняться в каждом цикле, и это будетбыть введенным в игру выше.

Таким образом, в итоге: если база данных возвращает три записи в {{ command_result.stdout_lines }}, то воспроизведение модуля оболочки должно запускаться трижды с подробностями каждой записи в {{ item }} соответственно.

Например: база данных может возвращать любое количество строк, и давайте посмотрим, что она возвращает три строки типа: <listofhosts>\t<somearguments>:

host5,host8\targ1
host6,host2\targ3
host9,host3,host4\targ4

Мне нужно, чтобы цикл with_items: {{ command_result.stdout_lines }} выполнял трииграет и каждый играет, чтобы построить динамическую группу хостов из списка хостов для этого прогона и его соответствующего аргумента.

Итак:

  • для группы динамических хостов первого запуска будет host5,host8, а оболочка должна получить arg1
  • для группы динамических хостов итерации второго циклабудет host6,host2, а оболочка получит arg3
  • и т. д.

Надеюсь, это понимает мое требование.

Я на последнейверсия Ansible.

1 Ответ

1 голос
/ 23 сентября 2019

Вы должны быть в состоянии выполнить задачу такого рода с созданием динамической группы хостов через модуль 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 строк.

Но, в конечном счете, усилия по созданию изобретателя, который был бы СУХИМ, на самом деле не окупились бы, если бы источник, так или иначе, происходил избаза данных, которая будет генерировать список хостов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...