【问题标题】:How to convert a config file (of lines) to a dict list in Ansible如何将配置文件(行)转换为 Ansible 中的字典列表
【发布时间】:2019-08-20 09:17:44
【问题描述】:

从多行文本转换为字典项目列表。

我正在尝试将配置文件转换为 dict 条目列表。 Ansible 可以将该列表用于各种任务。该文件是具有“item=value”对的通用文本 .conf 文件。我需要将文件转换为字典列表。变量 => [ "item1":"value", "item2":"value", ... ]

我遵循了这个解决方案:Converting output of Python script to dict in Ansible 得到了部分解决方案,因为我只得到了文件的最后一行,变量中只有一个 dict。 (单个字典列表)

.conf 文件的一部分

# Flags if dhcp should be used or not
use_dhcp=1

# The NOS300s IP address
ip_address=

# Netmask to use for this NOS300
netmask=

# Default gateway
gateway=

# DNS Server
dns_server=

# Local folder to download the files to (required, absolute path)
# download_folder = /tmp

需要删除所有的 cmets 和空白,然后将带有 '=' 的行转换为字典列表。

<< playbook def >>
  vars:
     remote_config_file: /etc/my/general.conf

  tasks:
  - name: "Get {{ remote_config_file }} to a list of terms and add to var"
    shell: "egrep -v \'(^$|^#)\' {{remote_config_file}} | grep \'=\' "
    register: NosConf

  - name: "Convert to dict list"
    set_fact:
      NosFactDict: "{{ parameter | default({}) | combine ( { item.split('=')[0]: item.split('=')[1] } ) }}"
    with_items: "{{ NosConf.stdout_lines }}"

  - debug:
      msg: "{{ NosFactDict }}"

shell 命令去除空白行和注释行,然后使用 '=' 过滤这些行,然后将过滤后的行拆分并合并为一个字典。

然后我想要一个更长的列表:

task path: /media/sf_Virtualbox-share/FactfileAdd.yml:30
ok: [192.168.2.112] => {
    "msg": {
        "docker0_network": "172.17.0.0/16"
    }
}

应该是更多

ok: [192.168.2.112] => {
    "msg": {
        "base_path": "/var/www/desert", 
        "buildnumber": "os", 
        ...
        "use_proxy": "0", 
        "use_sat_distribution": "0", 
        "version": "1.6.1.8-os"
    }
}

【问题讨论】:

标签: string dictionary ansible jinja2


【解决方案1】:

你做得很好,但你错过的 prat 是关于将 dict 连接到列表中。可以这样做:

   - name: "Convert to dict list"
    set_fact:
      NosFactDict: "{{ NosFactDict|default([]) + [ parameter | default({}) | combine ( { item.split('=')[0]: item.split('=')[1] } ) ] }}"
    with_items: "{{ NosConf.stdout_lines }}"

所以你将NosFactDict+ [ &lt;your_item&gt; ] 连接起来。 |default([]) 在第一个循环期间将 NosFactDict 声明为空列表(以避免错误。

参考:Similar queston on StackOverlow

【讨论】:

    【解决方案2】:

    我确实找到了一个类似于 xenlo answer 的可行解决方案,但分两步设置输出变量。

      - name: Set default dict for NosFactDict
        set_fact:
          NosFactDict: {}
    
      - name: "Convert to dict list"
        set_fact:
          NosFactDict: "{{ NosFactDict | combine ( { item.split('=')[0]: item.split('=')[1] } ) }}"
        with_items: "{{ NosConf.stdout_lines }}"
    

    我怀疑我可以找到一个“默认”的版本。这是一个笨重的解决方案,但它确实有效。如果我要执行更多这样的任务,那么我将运行 xenlo 的解决方案,因为它看起来运行起来要快得多。

    【讨论】:

      【解决方案3】:

      我认为下面的任务可以完成这项工作。

      - name: Create list of variables
        set_fact:
          my_vars: "{{ my_vars|default([]) +
                       [item.split('=').0|trim] }}"
        with_lines: "cat {{ remote_config_file }}"
        when: item is match('^(\s*[a-zA-Z0-9_]+\s*)=(.*)$')
      
      - name: Create list of values
        set_fact:
          my_values: "{{ my_values|default([]) +
                         [lookup('ini', item ~ ' type=properties file=' ~ remote_config_file)] }}"
        loop: "{{ my_vars }}"
      
      - name: Create dictionary of variables and values
        set_fact:
          my_dict: "{{ my_dict|default({})| 
                       combine({item.0: item.1}) }}"
        with_together:
          - "{{ my_vars }}"
          - "{{ my_values }}"
      
      - debug:
          var: my_dict
      

      注意。不幸的是 ini 插件只返回值。 (见source

      if is_regexp:
          return [v for k, v in self.cp.items(section) if re.match(key, k)]
      

      【讨论】:

        猜你喜欢
        • 2021-07-17
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        • 2011-07-11
        • 2011-03-06
        • 2012-07-12
        • 1970-01-01
        相关资源
        最近更新 更多