是否可以遍历特定主机和配置的数组

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

我正在尝试弄清楚是否有可能播放一个循环遍历一组配置/定义了特定主机变量的主机。

比如这是我的库存文件

controlplanes:
  hosts:
    host1.example.com:
workers:
  hosts:
    host2.example.com:
      longhorn:
        storage: true
    host3.example.com:
      longhorn:
        storage: true

基本上我的目标是从一台主机运行

kubectl label
命令以将注释应用于特定的 kubernetes 节点,但我只想让命令针对特定的主机列表运行,例如有
longhorn.storage=true
的主机,所以在上面的例子中,我应该只循环遍历2个主机。

这可能吗?我知道我可以遍历所有主机,但我似乎无法访问任何给定主机的变量,我想

hostvars[hostname].longhorn.storage
可能会给我访问权限,但结果似乎表明它没有定义,所以我认为我的方法是不正确的。

- name: Loop Test
  hosts: controlplanes
  tasks:
    - debug:
        msg: "{{ item }}"
      loop:
        - "{{ groups['all'] }}"
ansible ansible-inventory
3个回答
1
投票

我怀疑,但刚刚确认,可以安全地调用

add_host:
与现有的清单主机,然后将“新”主机分配给组,以及添加您希望的任何其他主机变量

给定清单

[controlplane]
alpha ansible_host=127.0.0.5

[workers]
beta ansible_host=127.0.0.6
charlie ansible_host=127.0.0.7

[workers:vars]
longhorn=true

然后剧本:

- hosts: all
  tasks:
    - delegate_to: localhost
      run_once: true
      add_host:
        name: '{{ item }}'
        groups:
        - longer
        have_longhorn: true
      loop: '{{ long_hosts | from_yaml }}'
      vars:
        # this nonsense is because jinja2 does not have list comprehensions
        long_hosts: |
          {% for hn in groups["all"] if 'longhorn' in hostvars[hn] %}
          - {{ hn }}
          {% endfor -%}

- hosts: longer
  tasks:
    - debug:
        msg: |
          {{ inventory_hostname }} ({{ ansible_host }}) have_long={{ have_longhorn }}
          long={{ longhorn }}

0
投票

我以为

hostvars[hostname].longhorn.storage
可能会给我访问权限,但结果似乎表明它没有定义。

它仅针对清单中存在 var 的主机定义。例如,对于您的

controlplanes
,它是未定义的。因此,调用该 var 的正确方法是使用
default
过滤器
(别名
d
)以确保您始终获得一个值,例如:

    when: hostvars[hostname].longhorn.storage | d(false) | bool

还请注意使用

bool
过滤器 来保护结果,以防 var 被解析为清单中的字符串。

与此同时,如果我正确理解您的要求,这个例子在 IMO 中是

constructed
动态库存 的完美候选。

示例文件结构:

$ tree
.
├── dummy_playbook.yml
└── inventories
    └── demo
        ├── 01-hosts.yml
        └── 02-longhorn_group-constructed.yml

为了这个例子的需要,我稍微修改了你的初始库存。这是

inventories/demo/01-hosts.yml

的内容
---
controlplanes:
  hosts:
    host1.example.com:
workers:
  hosts:
    host2.example.com:
      longhorn:
        storage: true
    # Example to show it does not break if var isn't defined
    host3.example.com:
    host4.example.com:
      longhorn:
        storage: true
    host5.example.com:
      longhorn:
        storage: false

魔法发生在

inventories/demo/02-longhorn_group-constructed.yml
。我们根据之前的静态库存文件中的变量值创建一个动态组:

---
plugin: ansible.builtin.constructed
strict: False
groups:
  longhorn_storage: longhorn.storage | d(false) | bool

然后我们可以使用

dummy_playbook.yml
快速测试它:

---
- name: Run a task from controlplane for each host having longhorn storage
  hosts: controlplanes
  gather_facts: false

  tasks:
    - name: Dummy demo tasks
      ansible.builtin.debug:
        msg:
          - I'm running from {{ inventory_hostname }}
          - I would do something for target {{ item }}
      loop: "{{ groups.longhorn_storage }}"

测试剧本结果:

$ ansible-playbook -i inventories/demo/ dummy_playbook.yml 

PLAY [Run a task from controlplane for each host having longhorn storage] *****************************************************************************************************************************************************

TASK [Dummy demo tasks] *******************************************************************************************************************************************************************************************************
ok: [host1.example.com] => (item=host2.example.com) => {
    "msg": [
        "I'm running from host1.example.com",
        "I would do something for target host2.example.com"
    ]
}
ok: [host1.example.com] => (item=host4.example.com) => {
    "msg": [
        "I'm running from host1.example.com",
        "I would do something for target host4.example.com"
    ]
}

PLAY RECAP ********************************************************************************************************************************************************************************************************************
host1.example.com          : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

另一种检查库存是否按预期解析的方法是简单地使用命令列出其内容

ansible-inventory -i inventories/demo/ --list
给出:

{
    "_meta": {
        "hostvars": {
            "host2.example.com": {
                "longhorn": {
                    "storage": true
                }
            },
            "host4.example.com": {
                "longhorn": {
                    "storage": true
                }
            },
            "host5.example.com": {
                "longhorn": {
                    "storage": false
                }
            }
        }
    },
    "all": {
        "children": [
            "ungrouped",
            "controlplanes",
            "workers",
            "longhorn_storage"
        ]
    },
    "controlplanes": {
        "hosts": [
            "host1.example.com"
        ]
    },
    "longhorn_storage": {
        "hosts": [
            "host2.example.com",
            "host4.example.com"
        ]
    },
    "workers": {
        "hosts": [
            "host2.example.com",
            "host3.example.com",
            "host4.example.com",
            "host5.example.com"
        ]
    }
}

0
投票

在第一场比赛中创建列表longhorn_group

- hosts: all
  tasks:
    - set_fact:
        longhorn_storage: "{{ longhorn.storage|d(false) }}"
    - set_fact:
        longhorn_group: "{{ hostvars|dict2items|
                            selectattr('value.longhorn_storage')|
                            map(attribute='key') }}"
      run_once: true

并在第二场比赛中使用它

- hosts: controlplanes
  tasks:
    - debug:
        var: longhorn_group
    - debug:
        msg: "{{ item }}"
      loop: "{{ longhorn_group }}"

给(删节)

TASK [debug] *********************************************************************************
ok: [host1.example.com] => 
  longhorn_group:
  - host2.example.com
  - host3.example.com

TASK [debug] *********************************************************************************
ok: [host1.example.com] => (item=host2.example.com) => 
  msg: host2.example.com
ok: [host1.example.com] => (item=host3.example.com) => 
  msg: host3.example.com

完整的测试剧本示例

- hosts: all
  tasks:
    - set_fact:
        longhorn_storage: "{{ longhorn.storage|d(false) }}"
    - set_fact:
        longhorn_group: "{{ hostvars|dict2items|
                            selectattr('value.longhorn_storage')|
                            map(attribute='key') }}"
      run_once: true

- hosts: controlplanes
  tasks:
    - debug:
        var: longhorn_group
    - debug:
        msg: "{{ item }}"
      loop: "{{ longhorn_group }}"
© www.soinside.com 2019 - 2024. All rights reserved.