Ansible は属性リストに変数が存在するかどうかを確認します

Ansible は属性リストに変数が存在するかどうかを確認します

ネットワーク上のホスト マシンの詳細を含む変数 (「hostlist」と呼ばれる) があります。これは辞書と呼ぶべきだと思いますが、用語がよくわかりません。この変数は group_vars/all 内のファイルで定義されているため、すべてのプレイブックで使用できます (これが重要かどうかはわかりません)。

ansible_hostname が hostlist のホスト名のリストに見つからない場合にのみ実行したいプレイがあります。hostlist のホスト名は変数の属性の 1 つですが、ここでも「属性」という用語が適切かどうかはわかりません...

ホストリストは次のように定義されます:

hostlist:
  - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
  - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
  - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }

これを機能させるために私が使用しているプレイは次のとおりです。

- name: Conditional test
  debug:
    msg: "ansible_hostname not found in hostlist."
  when: ansible_hostname not in hostlist.name

条件に必要な構文がわかりません。また、私が望んでいることがこの方法で達成できるかどうかもわかりません。

答え1

おそらくもっとエレガントな方法もあるでしょうが、私の場合は次のような方法がうまくいきます:

在庫ファイルが次のようになっている場合

host1
host2
host3
host4

host4次に、次のコンテンツを含むプレイブックは、ホストリスト変数と一致しないため、それに対してのみ実行されます。
$ cat test.yml

- hosts: all
  vars:
    hostlist:
      - { name: 'host1', ip_addr: '192.168.2.31', hostgrp: 'physical_workstation' }
      - { name: 'host2', ip_addr: '192.168.2.32', hostgrp: 'physical_workstation' }
      - { name: 'host3', ip_addr: '192.168.2.33', hostgrp: 'virtual_machine' }
  tasks:

    - name: Conditional test
      debug:
        msg: "ansible_hostname not found in hostlist."
      when: hostlist|selectattr("name", "equalto", ansible_hostname)|list|length == 0

次のように呼び出された場合:

ansible-playbook test.yml

つまり、host4 のみがタスク ブロックを実行します。

PLAY [all] *************************************************

TASK [Gathering Facts] *************************************
ok: [host1]
ok: [host2]
ok: [host3]
ok: [host4]

TASK [debug] ***********************************************
ok: [host4] => {
    "msg": "hostname not in hostlist name list"
}
skipping: [host1]
skipping: [host2]
skipping: [host3]

答え2

オプションとして、この状態はよりクリーンである

    when: inventory_hostname not in hostlist|map(attribute="name")|list

在庫のエイリアスのリストと比較する場合は、inventory_hostnameの代わりにを使用します。ansible_hostnameinventory_hostnameとansible_hostnameの違いは何ですか?

答え3

別の解決策としては、(質問のコメントで提案されているように)ホストリストを次のようにインベントリにリファクタリングすることです。

[physical_workstation]
host1 ansible_host=192.168.2.31
host2 ansible_host=192.168.2.32

[virtual_machine]
host3 ansible_host=192.168.2.33

[all]
host4 ansible_host=192.168.2.34

次に、他のグループに属さないungroupedホストを選択する特別なグループを使用して、どのグループにも属さないホストに対してプレイを実行するようにプレイブックを簡素化できます。all

- hosts: ungrouped
  tasks:
    - name: only ungrouped
      debug:
        msg: "host not found in any other group."

または、グループ内の特定のホストに対して操作を実行します...

- hosts: physical_workstation:virtual_machine
  tasks:
    - name: only in specified groups
      debug:
        msg: |
          This will run on machines that are in groups:
          physical_workstation or virtual_machine

出力

PLAY [ungrouped] ***********************************************

TASK [only ungrouped] ******************************************
ok: [host4] => {
    "msg": "host not found in any other group."
}

PLAY [physical_workstation:virtual_machine] ********************

TASK [only in specified groups] ********************************
ok: [host1] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}
ok: [host2] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}
ok: [host3] => {
    "msg": "This will run on machines that are in groups:\nphysical_workstation or virtual_machine"
}

関連情報