如何通过“assert”从额外变量验证主机名列表?

问题描述 投票:0回答:1

我有一个 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
应该使任务失败。

ansible
1个回答
0
投票

第一个问题是额外变量的格式。请参阅在运行时定义变量。 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
  • 使用JSON格式
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) }}"
© www.soinside.com 2019 - 2024. All rights reserved.