如何动态更改传递给剧本的额外变量
How can I dynamically change the extra vars passed to playbook
我正在尝试根据条件在一组主机上安装软件。执行播放后,我想计算安装发生的主机数和跳过的主机数。
我试过在像下面这样调用任务之前在 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。 None 这些将适合您尝试做的计数器。
同时,有多种方法可以实现您的要求。一个简单的 IMO。
- 选择一个您知道主机上不存在的变量。例如,我将选择
_OS_upgraded
- 在每台机器上将此 var 设置为
true
,installed/upgraded,false
过时。您可以删除 when
子句并直接设置测试结果。
- name: Set info about upgrade.
set_fact:
_OS_upgraded: "{{ switch_os_version != OS_version }}"
- 完成后,您可以使用 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') }}"
我正在尝试根据条件在一组主机上安装软件。执行播放后,我想计算安装发生的主机数和跳过的主机数。
我试过在像下面这样调用任务之前在 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。 None 这些将适合您尝试做的计数器。
同时,有多种方法可以实现您的要求。一个简单的 IMO。
- 选择一个您知道主机上不存在的变量。例如,我将选择
_OS_upgraded
- 在每台机器上将此 var 设置为
true
,installed/upgraded,false
过时。您可以删除when
子句并直接设置测试结果。- name: Set info about upgrade. set_fact: _OS_upgraded: "{{ switch_os_version != OS_version }}"
- 完成后,您可以使用 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') }}"