查找清单中每个主机的主机变量列表

And*_*sch 2 jinja2 ansible

我正在尝试找到一种使用 Ansible 调试模块创建以下结果的方法。

期望的结果

{
  "myserver01": {
    "host_var_one": "foo",
    "host_var_two": "bar"
  },
  "myserver02": {
    "host_var_one": "biz",
    "host_var_two": "baz"
  },
  "myserver03": {
    "host_var_one": "fizz",
    "host_var_two": "buzz"
  }
}
Run Code Online (Sandbox Code Playgroud)

库存示例

[my_servers]
myserver01 host_var_one=foo host_var_two=bar
myserver02 host_var_one=biz host_var_two=baz
myserver03 host_var_one=fizz host_var_two=buzz
Run Code Online (Sandbox Code Playgroud)

我希望能够提供主机变量列表,并将它们显示在清单中每个主机下的字典中,其中键是主机变量名称,值是主机变量值。理想情况下,在结果中包含另一个主机变量应该只需要向列表中添加另一个变量名称。

例如,在任务中,我会列出我想要的["host_var_one", "host_var_two"]清单中的每个主机,并获得上述所需的结果。

我有以下任务,有点接近我想要的。我只是想不出一种方法以上述格式列出每个主机所需的所有变量。以下仅适用于一个变量,并且不会列出变量名称及其值。

myplaybook.yml

---
- name: Test
  hosts: all
  gather_facts: yes
  user: ansible
  become: yes

  tasks:
    - name: Debug
      debug:
        msg: "{{ dict(query('inventory_hostnames', 'all') | zip(query('inventory_hostnames', 'all') | map('extract', hostvars, 'host_var_one'))) }}"
      run_once: yes
Run Code Online (Sandbox Code Playgroud)

myplaybook.yml 的结果

$ ansible-playbook -i inventory test.yml --limit "myserver01"
PLAY [Test] **************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************
ok: [myserver01]

TASK [Debug] *************************************************************************************************************************************************
ok: [myserver01] => {
    "msg": {
        "myserver01": "foo",
        "myserver02": "biz",
        "myserver03": "fizz"
    }
}
Run Code Online (Sandbox Code Playgroud)

pha*_*naz 5

我的解决方案如下:

- name: Dict of host_vars
  debug:
    msg: "{{ dict( keys | zip(values) ) }}"
  vars:
    keys: "{{ hostvars | dict2items | map(attribute='key') }}"
    values: "{{ hostvars | dict2items | map(attribute='value') | map('dict2items')
      | map('selectattr', 'key', 'match', 'host_var_') | map('items2dict') }}"
  run_once: yes
Run Code Online (Sandbox Code Playgroud)

结果如下:

TASK [Host vars dict] **************************************************
ok: [myserver01] => {
    "msg": {
        "myserver01": {
            "host_var_one": "foo",
            "host_var_two": "bar"
        },
        "myserver02": {
            "host_var_one": "biz",
            "host_var_two": "baz"
        },
        "myserver03": {
            "host_var_one": "fizz",
            "host_var_two": "buzz"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

逐步解释

创建两个单独的列表:keysvalues

的列表keys是通过用 转换字典来创建的dict2items,以便key可以通过 提取属性map。这样你就可以得到列表:

TASK [Host vars dict] **************************************************
ok: [myserver01] => {
    "msg": {
        "myserver01": {
            "host_var_one": "foo",
            "host_var_two": "bar"
        },
        "myserver02": {
            "host_var_one": "biz",
            "host_var_two": "baz"
        },
        "myserver03": {
            "host_var_one": "fizz",
            "host_var_two": "buzz"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它的工作方式相同,即生成属性values列表。value这些列表在每种情况下都是字典,因此必须map('dict2items')再次转换为列表。现在key可以通过 过滤列表selectattr。这里是通过(字符串的开头)host_var_过滤掉的。match然后,必须将结果(列表中的列表)转换map('items2dict')回字典。

[ "myserver01", "myserver02", "myserver03" ]
Run Code Online (Sandbox Code Playgroud)

最后,这两个列表被合并 viazip并转换回一个 via dict

按前缀过滤的变量

变量是通过其名称的前缀进行过滤的,因此可以为不同的主机定义多个不同的变量(具有相同的前缀),并且将被完全过滤掉。

例如库存:

[
  {
    "host_var_one": "foo",
    "host_var_two": "bar"
  },
  {
    "host_var_one": "biz",
    "host_var_two": "baz"
  },
  {
    "host_var_one": "fizz",
    "host_var_two": "buzz"
  }
]
Run Code Online (Sandbox Code Playgroud)

返回以下结果:

TASK [Dict of host_vars] **********************************************
ok: [myserver01] => {
    "msg": {
        "myserver01": {
            "host_var_one": "foo",
            "host_var_two": "bar"
        },
        "myserver02": {
            "host_var_four": "buz",
            "host_var_one": "biz",
            "host_var_three": "boz",
            "host_var_two": "baz"
        },
        "myserver03": {
            "host_var_one": "fizz",
            "host_var_six": "dazz",
            "host_var_two": "buzz"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)