如何动态更改传递给 playbook 的额外变量

问题描述

我正在尝试根据条件在一组主机上安装软件。执行 play 后,我想计算安装发生的主机数量以及跳过的主机数量

调用如下任务之前,我尝试在 play 中声明一个变量,但该变量被每个主机覆盖,因此我无法获得实际计数:它始终为 1 或 0

播放:

- name: Install Junos OS
  hosts: reachable_a_hosts
  connection: local
  gather_facts: no
  roles:
    - Juniper.junos
  vars:
    credentials:
      host: "{{ loopback_v4 }}"
      username: "username"
    
      port: "{{ port }}"
      timeout: 60
  tasks:
  - name: Extra variable test
      debug:
        msg: "upgrade count {{ upgrade_count }}"
  - name: OS Install
    import_role:
      name: os_install
      tasks_from: change__os
  - name: debug
    debug:
      msg: "upgrade count {{ upgrade_count }}"

任务:

---
- name: Increment installation count
  set_fact:
    upgrade_count : ( {{ upgrade_count|int + 1|int }} )
  when: switch_os_version != OS_version

输出

TASK [debug] *************************************
ok: [site1] => {
    "msg": "upgrade count (1)"
}
ok: [site2] => {
    "msg": "upgrade count (1)"
}

所以我使用 -e 作为命令行传递变量。现在输出总是0,不管条件是否满足

更新输出

TASK [os_install : Increment installation count] *********************
ok: [site1]
ok: [site2]


TASK [debug] *************************************
ok: [site1] => {
    "msg": "upgrade count 0"
}
ok: [site2] => {
    "msg": "upgrade count 0"
}

有人可以帮助我使变量表现得像全局变量,以便我可以获得实际计数吗?

解决方法

要解决此问题,您可以使用 ansible 寄存器,当您想要将任务的输出捕获到变量时使用 Ansible 寄存器。然后,您可以将这些寄存器的值用于不同的场景,例如条件语句、日志记录等。 示例:

---
- name: Increment installation count
  set_fact:
    upgrade_count : ( {{ upgrade_count|int + 1|int }} )
  register: upgrade_count # add this line
  when: switch_os_version != OS_version

和剧本:

- name: Install Junos OS
  hosts: reachable_a_hosts
  connection: local
  gather_facts: no
  roles:
    - Juniper.junos
  vars:
    credentials:
      host: "{{ loopback_v4 }}"
      username: "username"
    
      port: "{{ port }}"
      timeout: 60
  tasks:
  - name: Extra variable test
      debug:
        msg: "upgrade count {{ upgrade_count }}"
  - name: OS Install
    import_role:
      name: os_install
      tasks_from: change__os
  - name: debug
    debug:
      msg: "upgrade count {{ upgrade_count }}"

有关详细信息,请访问此 example

,

正如您所发现的,set_fact 是...设置事实,即设置特定于播放循环中当前目标主机的变量的值。此外,正如我在评论中所报告的,在播放过程中不能更改额外的变量,因为它们具有最高的 level of precedence。这些都不适合您尝试做的柜台。

同时,有多种方法可以实现您的要求。一个简单的 IMO。

  1. 选择一个你知道主机上不存在的变量。对于示例,我将选择 _OS_upgraded
  2. 在正在安装/升级的每台机器上将此变量设置为 truefalse 过度。您可以删除 when 子句并直接设置测试结果。
    - name: Set info about upgrade.
      set_fact:
        _OS_upgraded: "{{ switch_os_version != OS_version }}"
    
  3. 完成后,您可以使用 magic variable hostvars 和一些过滤器轻松计算主机数
    - name: Give some info about the tasks
      vars:
        processed_hosts: "{{ hostvars | dict2items | selectattr('value._OS_upgraded','defined') | list }}"
        num_host: "{{ processed_hosts | count }}"
        upgraded_hosts: "{{ processed_hosts | selectattr('value._OS_upgraded') | list | count }}"
        untouched_hosts: "{{ processed_hosts | rejectattr('value._OS_upgraded') | list | count }}"
        message: |-
          We processed {{ num_host }} hosts
          {{ upgraded_hosts }} were upgraded
          {{ untouched_hosts }} were left alone
      debug:
        msg: "{{ message.split('\n') }}"
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...