Ansible动态选择主机组

Ansible动态选择主机组,ansible,Ansible,我的清单文件如下所示 [host-group-1] x.x.x.1 x.x.x.2 [host-group-2] x.x.x.3 x.x.x.4 现在,我想根据脚本返回的参数在这些组上选择并执行任务。 剧本如下 --- - host: 127.0.0.1 tasks: - name: something local_action: /home/script.py register: result - host: host-group-1:host-gro

我的清单文件如下所示

[host-group-1]
 x.x.x.1
 x.x.x.2

[host-group-2]
 x.x.x.3
 x.x.x.4
现在,我想根据脚本返回的参数在这些组上选择并执行任务。 剧本如下

---
- host: 127.0.0.1
  tasks:
  - name: something 
    local_action: /home/script.py
    register: result

 - host: host-group-1:host-group-2
   task: ?????????
在第二个任务中,我希望类似于if result==yes在host-group-1上执行任务,if result==no在host-group-2上执行任务


请在此帮助我。

下面的示例演示如何在剧本中使用Jinja。大多数人只使用Jinja表达式
{{…}}
。但是如果您需要执行更复杂的任务,也可以使用Jinja语句
{%…%}
。但是语句没有返回值。因此,如果要将值返回到
set\u fact
任务,则必须以表达式结尾

---
- name: Get group
  hosts: localhost
  connection: local
  tasks:
    - shell: |-
        echo {{ say }}
      register: group
      ignore_errors: true
      changed_when: false
    - set_fact:
        group: >-
          {% if group.stdout == "yes"     -%}
          {%   set group = "host-group-1" -%}
          {% elif group.stdout == "no"    -%}
          {%   set group = "host-group-2" -%}
          {% else                         -%}
          {%   set group = ""             -%}
          {% endif                        -%}
          {{ group }}

- hosts: "{{ hostvars.localhost.group }}"
  tasks:
    - debug: var=group
如果使用
yes
运行剧本,它将使用第一组。已跳过调试操作,因为我尚未指定清单文件

$ ansible-playbook if.yml --extra-vars say=yes

PLAY [Get group] *****************************************************************************

TASK [command] *******************************************************************************
ok: [localhost]

TASK [set_fact] ******************************************************************************
ok: [localhost]

PLAY [host-group-1] **************************************************************************
skipping: no hosts matched

PLAY RECAP ***********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
如果使用
no
运行它,它将使用第二个组

$ ansible-playbook if.yml --extra-vars say=no

PLAY [Get group] *****************************************************************************

TASK [command] *******************************************************************************
ok: [localhost]

TASK [set_fact] ******************************************************************************
ok: [localhost]

PLAY [host-group-2] **************************************************************************
skipping: no hosts matched

PLAY RECAP ***********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
关于shell脚本的一些提示:

  • 只要shell脚本的返回值不为零,Ansible就会将其视为错误。这打断了你的跑步。如果要处理Ansible代码中的任何错误,必须使用
    ignore\u errors:true
    忽略该错误

  • 每个shell脚本都被视为更改,因为Ansible不了解shell代码的作用。因为它可能会改变某些东西,Ansible总是把它当作一种改变。如果您只是在本地主机上收集信息,这一点都没有变化。因此,有必要告诉Ansible,当:false时,
    changed\u代码不会改变任何内容

Ansible如何存储信息的提示:

Ansible的内部数据结构是一个大而混乱的全局变量,称为
hostvars
。Ansible实际上没有任何作用域,这使得嵌套循环具有挑战性(但这是另一个主题)。所有任务的结果都存储在这个全局monster哈希变量中,主机名作为密钥。无论您在
localhost
上运行什么,都存储在
hostvars.localhost
中。每个主机都可以完全访问其他主机的数据。这使得可以在localhost中收集信息,以便稍后在其他主机上的任务中使用


顺便说一句,我不知道你为什么会得到这么多的反对票。我认为这不是一个简单的问题。

下面的示例演示了如何在剧本中使用Jinja。大多数人只使用Jinja表达式
{{…}}
。但是如果您需要执行更复杂的任务,也可以使用Jinja语句
{%…%}
。但是语句没有返回值。因此,如果要将值返回到
set\u fact
任务,则必须以表达式结尾

---
- name: Get group
  hosts: localhost
  connection: local
  tasks:
    - shell: |-
        echo {{ say }}
      register: group
      ignore_errors: true
      changed_when: false
    - set_fact:
        group: >-
          {% if group.stdout == "yes"     -%}
          {%   set group = "host-group-1" -%}
          {% elif group.stdout == "no"    -%}
          {%   set group = "host-group-2" -%}
          {% else                         -%}
          {%   set group = ""             -%}
          {% endif                        -%}
          {{ group }}

- hosts: "{{ hostvars.localhost.group }}"
  tasks:
    - debug: var=group
如果使用
yes
运行剧本,它将使用第一组。已跳过调试操作,因为我尚未指定清单文件

$ ansible-playbook if.yml --extra-vars say=yes

PLAY [Get group] *****************************************************************************

TASK [command] *******************************************************************************
ok: [localhost]

TASK [set_fact] ******************************************************************************
ok: [localhost]

PLAY [host-group-1] **************************************************************************
skipping: no hosts matched

PLAY RECAP ***********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
如果使用
no
运行它,它将使用第二个组

$ ansible-playbook if.yml --extra-vars say=no

PLAY [Get group] *****************************************************************************

TASK [command] *******************************************************************************
ok: [localhost]

TASK [set_fact] ******************************************************************************
ok: [localhost]

PLAY [host-group-2] **************************************************************************
skipping: no hosts matched

PLAY RECAP ***********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   
关于shell脚本的一些提示:

  • 只要shell脚本的返回值不为零,Ansible就会将其视为错误。这打断了你的跑步。如果要处理Ansible代码中的任何错误,必须使用
    ignore\u errors:true
    忽略该错误

  • 每个shell脚本都被视为更改,因为Ansible不了解shell代码的作用。因为它可能会改变某些东西,Ansible总是把它当作一种改变。如果您只是在本地主机上收集信息,这一点都没有变化。因此,有必要告诉Ansible,当:false时,
    changed\u代码不会改变任何内容

Ansible如何存储信息的提示:

Ansible的内部数据结构是一个大而混乱的全局变量,称为
hostvars
。Ansible实际上没有任何作用域,这使得嵌套循环具有挑战性(但这是另一个主题)。所有任务的结果都存储在这个全局monster哈希变量中,主机名作为密钥。无论您在
localhost
上运行什么,都存储在
hostvars.localhost
中。每个主机都可以完全访问其他主机的数据。这使得可以在localhost中收集信息,以便稍后在其他主机上的任务中使用


顺便说一句,我不知道你为什么会得到这么多的反对票。我认为这不是一个无关紧要的问题。

你能澄清一下你的例子吗?不能将主机(或主机组)应用于任务,只能应用于播放。也就是说,
host
不是任务上的有效键(就此而言,
task
)。如果你能更具体地描述你要做的事情,那也会有帮助,因为可能有一个解决方案不是你所描述的。@larsks要求很简单,我想根据脚本返回的参数来选择主机组。这并不“简单”,你的例子也不清楚。如果您可以使用有效的anisble语法显示您希望的行为,那么提供答案就更容易了。您是否只是尝试了
-hosts:{{hostvars['127.0.0.1'].result.stdout='yes'| trialum('host-group-1','host-group-2')}}?(我同意你的例子真的很糟糕,但是没有有效的ansible代码)你能澄清一下你的例子吗?不能将主机(或主机组)应用于任务,只能应用于播放。也就是说,
host
不是任务上的有效键(就此而言,
task
)。如果你能更具体地描述你要做的事情,那也会有帮助,因为可能有一个解决方案不是你所描述的。@larsks要求很简单,我想根据脚本返回的参数来选择主机组。这并不“简单”,你的例子也不清楚。如果您可以使用有效的anisble语法显示您想要的行为,那么提供答案就更容易了。您是否只是尝试了
-hosts