英文:
How can I prompt the user for an inventory group and pass that variable to next plays in the same playbook?
问题
在这个手册中,我正在提示用户选择一个地区。用户选择了一个地区后,我希望对该特定的清单组运行操作。我还将该地区分配给一个事实,以便我可以在同一手册的另一个操作中使用它。
我的清单文件如下所示:
[ams]
device1
device2
[usa]
device1
device2
[jpn]
device1
device2
Playbook如下所示:
---
- name: Play 1
hosts: "{{ region }}"
gather_facts: false
connection: network_cli
vars_prompt:
- name: region
prompt: "Region (ams, usa, jpn)"
private: no
tasks:
- name: Make vars persistent
set_fact:
region: "{{ region }}"
- name: check var
debug:
msg: "{{ region }}"
- name: Play 2
hosts: "{{ region }}"
gather_facts: false
connection: network_cli
vars:
region: "{{ hostvars['region'] }}"
tasks:
- name: debug
debug:
msg: "{{ region }}"
但是,在启动“Play 2”时,我收到了以下错误消息:
错误!字段“hosts”具有无效值,其中包括未定义的变量。错误是:{{ hostvars['region'] }}:“hostvars['region']”未定义。hostvars['region']”未定义。{{ hostvars['region'] }}:“hostvars['region']”未定义。hostvars['region']”未定义。
我是不是在错误的方式下读取事实?
我还尝试了以下方式:
{{ hostvars['region']['region'] }}
但是,我收到相同的错误。
英文:
In this playbook, I'm prompting the user for a region. After the user selects a region, I want to run plays against that specific inventory group. I'm also assigning that region to a fact so I can use it on another play on the same playbook.
My inventory file looks like this:
[ams]
device1
device2
[usa]
device1
device2
[jpn]
device1
device2
Playbook looks like this:
---
- name: Play 1
hosts: "{{ region }}"
gather_facts: false
connection: network_cli
vars_prompt:
- name: region
prompt: "Region (ams, usa, jpn)"
private: no
tasks:
- name: Make vars persistent
set_fact:
region: "{{ region }}"
- name: check var
debug:
msg: "{{ region }}"
- name: Play 2
hosts: "{{ region }}"
gather_facts: false
connection: network_cli
vars:
region: "{{ hostvars['region'] }}"
tasks:
- name: debug
debug:
msg: "{{ region }}"
But I get the following error while starting "Play 2"
> ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: {{ hostvars['region'] }}: "hostvars['region']" is undefined. "hostvars['region']" is undefined. {{ hostvars['region'] }}: "hostvars['region']" is undefined. "hostvars['region']" is undefined
Am I trying to read facts the wrong way?
I also tried with
{{ hostvars['region']['region'] }}"
, but I get the same error.
答案1
得分: 2
以下是翻译好的代码部分:
{{ hostvars['region']['region'] }}
请注意,这段代码似乎包含了HTML编码字符(&
等)。如果需要更多帮助,请告诉我。
英文:
{{ hostvars['region']['region'] }}
Q: "Am I trying to read facts the wrong way?"
A: Yes. The first attribute should be the name of a host. Quoting from hostvars:
> "A dictionary/map with all the hosts in inventory and variables assigned to them"
{{ hostvars[name_of_host]['region'] }}
You can use for this purpose any of the hosts in the inventory (device1, device2, ...), but generally, it is not a good idea to hardcode in a playbook an inventory name that might be changed. You can use localhost for this purpose, but you'll have to include localhost in the inventory, for example
shell> cat hosts
localhost
[ams]
device1
device2
...
But this may have side effects on localhost variables if you use ones. The best option for this purpose seems to be a dummy host. Put it into a separate file. Other hosts might be generated dynamically. Create a project for testing
shell> tree .
.
├── ansible.cfg
├── inventory
│   ├── 01-hosts
│   └── 02-hosts
└── pb.yml
shell> cat inventory/01-hosts
dummy
shell> cat inventory/02-hosts
[ams]
device1
device2
[usa]
device3
device4
[jpn]
device5
device6
Run the first play on all hosts. Set the variable region once and delegate to dummy. This way, the variable region will be put into the hostvars (instantiated/made persistent) of all hosts
<sup>
shell> cat pb.yml
- name: Play 1
hosts: all
vars_prompt:
- name: region
prompt: "Region (ams, usa, jpn)"
private: no
tasks:
- block:
- name: Make vars persistent
set_fact:
region: "{{ region }}"
- name: Check var
debug:
var: dict(hostvars|dict2items|json_query('[].[key, value.region]'))
delegate_to: dummy
run_once: true
- name: Play 2
hosts: "{{ hostvars.dummy.region }}"
tasks:
- debug:
var: region
gives
shell> ansible-playbook -i inventory pb.yml
Region (ams, usa, jpn): usa
PLAY [Play 1] *********************************************************************************
TASK [Make vars persistent] *******************************************************************
ok: [dummy]
TASK [Check var] ******************************************************************************
ok: [dummy] =>
dict(hostvars|dict2items|json_query('[].[key, value.region]')):
device1: usa
device2: usa
device3: usa
device4: usa
device5: usa
device6: usa
dummy: usa
PLAY [Play 2] *********************************************************************************
TASK [debug] **********************************************************************************
ok: [device3] =>
region: usa
ok: [device4] =>
region: usa
PLAY RECAP ************************************************************************************
device3: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
device4: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
dummy: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
</sup>
<hr>
Ansible module ansible.builtin.add_host
The simpler and more straightforward option is the usage of the module add_host. Create a group, for example, my_region in the first play and use it in the second one. Create a project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
└── pb.yml
shell> cat hosts
[ams]
device1
device2
[usa]
device3
device4
[jpn]
device5
device6
<sup>
shell> cat pb.yml
- name: Play 1
hosts: localhost
vars_prompt:
- name: region
prompt: "Region (ams, usa, jpn)"
private: no
tasks:
- add_host:
name: "{{ item }}"
groups: my_region
region: "{{ region }}"
loop: "{{ groups[region] }}"
- name: Play 2
hosts: my_region
tasks:
- debug:
var: region
gives
shell> ansible-playbook pb.yml
Region (ams, usa, jpn): usa
PLAY [Play 1] *********************************************************************************
TASK [add_host] *******************************************************************************
changed: [localhost] => (item=device3)
changed: [localhost] => (item=device4)
PLAY [Play 2] *********************************************************************************
TASK [debug] **********************************************************************************
ok: [device3] =>
region: usa
ok: [device4] =>
region: usa
PLAY RECAP ************************************************************************************
device3: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
device4: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost: ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论