【问题标题】:Ansible: How to convert a dictionary (indeterminate number of key:value pairs) to a string?Ansible:如何将字典(不确定数量的键:值对)转换为字符串?
【发布时间】:2021-05-18 03:38:07
【问题描述】:

在 Ansible 剧本中,如何过滤具有不确定数量的键:值对的字典以转换为字符串,然后我可以将其用作 Ansible shell 模块的命令字符串?

下面的示例手册说明了数据、问题和期望的结果。

---

- name: Convert a dictionary into a string containing the key value pairs to run as a shell command

  hosts:
    - all

  vars:
    devices:
      - parameter_key: foo_device
        parameter_a: value1
        parameter_b: value2
        parameter_c: value3
      - parameter_key: bar_device
        parameter_a: value4
        parameter_b: value5
        parameter_d: value6
        parameter_e: value7

      # or like this
      - foo_device:
          parameter_a: value1
          parameter_b: value2
          parameter_c: value3
      
      - bar_device:
          parameter_a: value4
          parameter_b: value5
          parameter_d: value6
          parameter_e: value7
      
  tasks:

    - set_fact:
        # I have no idea what to do here
      loop: devices

# desired result is a string, or array or strings I can then feed to the ansible shell module for execution on the host

      command_str1: "{{ foo_cmd foo_device --parameter_a value1 --parameter_b value2 --parameter_c value3 }}"

      command_str2: "{{ foo_cmd bar_device --parameter_a value4 --parameter_b value5 --parameter_d value6 --parameter_e value7 }}"

# and so on if there was more devices

【问题讨论】:

    标签: python ansible yaml jinja2


    【解决方案1】:

    请查看循环中的dict2item 过滤器。所以你可以遍历一个字典并使用item.key 来获取字典的键,然后使用dict[item.key] 来获取值。所有这些都在 set_fact 中,您将拥有您的字符串。

    我想,没有更简单的方法了。

    - hosts: localhost
      vars:
        devices:
          - parameter_key: foo_device
            parameter_a: value1
            parameter_b: value2
            parameter_c: value3
          - parameter_key: bar_device
            parameter_a: value4
            parameter_b: value5
            parameter_d: value6
            parameter_e: value7
      tasks:
        - include_tasks: "task.yml"
          loop: "{{ devices }}"
          loop_control:
            loop_var: device
    

    并且包含的​​ task.yml 包含:

    ---
    - set_fact:
        cmd: "my_command"
    
    - set_fact:
        cmd: "{{ cmd }} {{ item.value }}"
      when: "item.key == 'parameter_key'"
      loop: "{{ device | default({}) | dict2items }}"
    
    - set_fact:
        cmd: "{{ cmd }} --{{ item.key }} {{ item.value }}"
      when: "item.key != 'parameter_key'"
      loop: "{{ device | default({}) | dict2items }}"
    
    - debug:
        msg: "{{ cmd }}"
    

    输出将是:

    ok: [localhost] => 
      msg: my_command foo_device --parameter_a value1 --parameter_b value2 --parameter_c value3
    
    
    ok: [localhost] => 
      msg: my_command bar_device --parameter_a value4 --parameter_b value5 --parameter_d value6 --parameter_e value7
    

    【讨论】:

    • 在 vars 中提供的值是一个列表,而不是一个字典。
    • 感谢您的明确回答@TRW。我没有想到在主剧本中循环外部 task.yml。
    【解决方案2】:

    这应该可行:

      tasks:
        - debug:
            msg: "command is: {{ item.key }} with value of --parameter_b {{ item.value.parameter_b }}"
          loop: "{{ devices[2] | dict2items }}"
    

    给予

        "msg": "command is: foo_device with value of --parameter_b value2"
    

    请注意,变量中的值以列表形式放置。如果将其转换为实际的字典会更方便。

    【讨论】:

      猜你喜欢
      • 2015-09-16
      • 1970-01-01
      • 2016-06-07
      • 2017-02-11
      • 2011-02-17
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多