如何在Ansible playbook中将包含嵌套字典的列表展开

72次阅读
没有评论

问题描述

在使用Ansible playbook时,遇到了一个问题。他有一个名为packages的变量,其中包含了一个混合了嵌套字典的列表。他想要使用类似下面的指令来安装所有在变量中定义的软件包:

- name: Install a list of packages
  become: yes
  apt:
    name: "{{ packages }}"

但是他不知道应该使用什么过滤器将变量转换为普通的列表,他需要获取嵌套字典中的项目。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据用户提供的示例,你可以将变量定义为一个字典,其中值是一个列表。这样可以避免使用嵌套字典。
以下是一个示例:

packages:
  - apt-file
  - axel
  - ibus-rime
  - rofi
  - i3
  - ffmpeg
  - xclip
  - cargo
  - httpie
  - ttf-ubuntu-font-family
  - tldr-py
  - glances
  - brave-browser
  - chromium
  - emacs

然后,你可以使用with_items循环来遍历列表,并在每次迭代中安装软件包。
以下是一个示例任务:

- name: Install a list of packages
  become: yes
  apt:
    name: "{{ item }}"
  with_items: "{{ packages }}"

这将安装变量packages中定义的所有软件包。

方案2

如果你仍然希望保留嵌套字典的结构,你可以使用json_query过滤器来提取嵌套字典中的项目。
以下是一个示例任务:

- name: Install a list of packages
  become: yes
  apt:
    name: "{{ packages | json_query('[].*') }}"

在上面的示例中,json_query('[].*')将提取嵌套字典中的所有项目,并返回一个列表。然后,这个列表将作为apt模块的name参数的值,用于安装软件包。

请注意,使用json_query过滤器需要安装jmespath库。你可以使用以下命令安装它:

pip install jmespath

方案3

如果你希望在变量中保留嵌套字典的结构,并且不想使用json_query过滤器,你可以编写一个自定义的Ansible过滤器来提取嵌套字典中的项目。
以下是一个示例自定义过滤器的代码:

# filters/flatten_list.py
def flatten_list(value):
    result = []
    for item in value:
        if isinstance(item, list):
            result.extend(item)
        else:
            result.append(item)
    return result

class FilterModule(object):
    def filters(self):
        return {
            'flatten_list': flatten_list
        }

将上面的代码保存为flatten_list.py文件,并将其放置在Ansible playbook的filters目录中。
然后,你可以在playbook中使用自定义过滤器来提取嵌套字典中的项目。
以下是一个示例任务:

- name: Install a list of packages
  become: yes
  apt:
    name: "{{ packages | flatten_list }}"

这将使用自定义过滤器flatten_list来提取嵌套字典中的项目,并将其作为apt模块的name参数的值,用于安装软件包。

请注意,使用自定义过滤器需要在Ansible playbook中配置filter_plugins选项,以指定自定义过滤器的路径。例如:

- hosts: localhost
  gather_facts: no
  vars:
    packages:
      - apt-file
      - axel
      - ibus-rime
      - rofi
      - i3
      - ffmpeg
      - xclip
      - cargo
      - httpie
      - ttf-ubuntu-font-family
      - tldr-py
      - glances
      - browsers:
        - brave-browser
        - chromium
      - editors:
        - emacs
  tasks:
    - name: Install a list of packages
      become: yes
      apt:
        name: "{{ packages | flatten_list }}"
  filter_plugins:
    - filters

在上面的示例中,filter_plugins选项指定了自定义过滤器的路径为filters目录。

以上是几种解决方案,你可以根据自己的需求选择其中一种来解决问题。希望对你有帮助!

正文完