我有一个 Ansible 剧本,需要传递
--extra-vars
,并且想知道是否有任何方法可以根据变量内的 --extra-vars
值验证主机名。
示例手册
test.yml
- hosts: localhost
gather_facts: false
vars:
prg:
prod_mgmt_network: "{{ ['prodsrv00']|product(range(prod_start,prod_end))|map('join')|list }}"
test_mgmt_network: "{{ ['testsrv00']|product(range(test_start,test_end))|map('join')|list }}"
prod_start: 4281
prod_end: 4283
test_start: 8281
test_end: 8283
tasks:
- debug:
var: prg.prod_mgmt_network, prg.test_mgmt_network
命令示例
ansible-playbook --extra-vars hostname=['prodsrv004281', 'prodsrv004282', 'testsrv008281', 'testsrv008282', 'testsrv008283', 'testsrv008284'] test.yml
如果主机名不在变量中,我希望任务失败。例如,
testsrv008283
和 testsrv008284
应该使任务失败。
第一个问题是额外变量的格式。请参阅在运行时定义变量。 key=value (INI) 语法始终被解释为字符串。您可能想测试一下。比如下面这个玩法
shell> cat pb.yml
- hosts: localhost
tasks:
- debug:
var: hostname
- debug:
var: hostname|type_debug
给出(删节)
shell> ansible-playbook pb.yml -e hostname=['host1','host2']
hostname: '[host1,host2]'
hostname|type_debug: str
如何获取列表还有更多选项:
hostname_list: "{{ hostname|from_yaml }}"
然后,你会得到
hostname_list:
- host1
- host2
hostname_list|type_debug: list
shell> ansible-playbook pb.yml -e '{"hostname": ["host1", "host2"]}'
hostname:
- host1
- host2
hostname_list|type_debug: list
shell> cat hostname.yml
hostname:
- host1
- host2
然后,下面的玩法给出了相同的结果
shell> ansible-playbook pb.yml -e @hostname.yml
为了测试您的案例,最简单的选择是将列表放入文件中
shell> cat hostname.yml
hostname:
- prodsrv004281
- prodsrv004282
- testsrv008281
- testsrv008282
- testsrv008283
- testsrv008284
问:“如果主机名不在变量内,则失败。例如,testsrv008283 和testsrv008284 应该失败。”
A:选择主机列表并比较差异。例如,
prod_hosts: "{{ hostname|select('match', 'prodsrv') }}"
test_hosts: "{{ hostname|select('match', 'testsrv') }}"
给予
prod_hosts:
- prodsrv004281
- prodsrv004282
test_hosts:
- testsrv008281
- testsrv008282
- testsrv008283
- testsrv008284
下面的断言将会通过
- assert:
that: prod_out|length == 0
fail_msg: "Hosts: {{ prod_out }} out of range."
vars:
prod_out: "{{ prod_hosts|difference(prg.prod_mgmt_network) }}"
ok: [localhost] => changed=false
msg: All assertions passed
但是,这个会失败
- assert:
that: test_out|length == 0
fail_msg: "Hosts: {{ test_out }} out of range."
vars:
test_out: "{{ test_hosts|difference(prg.test_mgmt_network) }}"
fatal: [localhost]: FAILED! => changed=false
assertion: test_out|length == 0
evaluated_to: false
msg: 'Hosts: [''testsrv008283'', ''testsrv008284''] out of range.'
用于测试的完整剧本示例
- hosts: localhost
vars:
prg:
prod_mgmt_network: "{{ ['prodsrv00']|
product(range(prod_start,prod_end))|map('join') }}"
test_mgmt_network: "{{ ['testsrv00']|
product(range(test_start,test_end))|map('join') }}"
prod_start: 4281
prod_end: 4283
test_start: 8281
test_end: 8283
prod_hosts: "{{ hostname|select('match', 'prodsrv') }}"
test_hosts: "{{ hostname|select('match', 'testsrv') }}"
tasks:
- debug:
var: prg.prod_mgmt_network
- debug:
var: prg.test_mgmt_network
- debug:
var: hostname
- debug:
var: prod_hosts
- debug:
var: test_hosts
- assert:
that: prod_out|length == 0
fail_msg: "Hosts: {{ prod_out }} out of range."
vars:
prod_out: "{{ prod_hosts|difference(prg.prod_mgmt_network) }}"
- assert:
that: test_out|length == 0
fail_msg: "Hosts: {{ test_out }} out of range."
vars:
test_out: "{{ test_hosts|difference(prg.test_mgmt_network) }}"