如何为循环的每次迭代触发Ansible Play

时间:2019-09-23 16:35:25

标签: loops ansible

在注册变量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 }}中用每个记录的详细信息调用三次shell模块播放。

例如: 数据库可以返回任意数量的行,并考虑返回三行类型:<listofhosts>\t<somearguments>

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

我需要的是,循环with_items: {{ command_result.stdout_lines }}将运行3次,并且每次运行都将为该次运行及其各自的参数构建主机列表的动态主机组。

所以:

  • 对于首次运行的动态主机组,将为host5,host8,并且外壳程序应为arg1
  • 对于第二个循环迭代,动态主机组将为host6,host2,shell将获得arg3
  • 依此类推。

希望这使我的要求得到理解。

我正在使用最新版本的Ansible。

1 个答案:

答案 0 :(得分:1)

通过模块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 list 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 list 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的原则。 / p>

我们最终在此处生成的清单如下所示:

## 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库存为30行时,我们使用24行的库存kiss.yml实现了同样的效果。

但是,无论来源是哪种方式,都来自将生成主机列表的数据库,最终创建DRY发明家的努力并不会真正付出代价。