【问题标题】:creating dictionary with ansible用 ansible 创建字典
【发布时间】:2021-01-31 11:55:47
【问题描述】:

我想从一个列表中创建一个 ansible 字典;对字典的键值对中的值使用了一些变量,但它似乎不起作用。

我已经简化了问题并创建了一个示例剧本来重现该问题,有人可以帮助我吗?谢谢!

这是我的剧本

---
- name: create dictionary test
  hosts: all
  connection: local
  gather_facts: False

  vars:
    ports: [80, 443]
    server_base: "org.com"

  tasks:
    - name: print the ports
      debug:
        msg: "ports: {{ports}}"

    - name: create a dictionary
      set_fact:
        #server_rules: "{{server_rules|default([]) + [{'server': '{{server_base}}-{{item}}', 'port': item}]}}"
        server_rules: "{{server_rules|default([]) + [{'server': '{{server_base}}', 'port': item}]}}"
      loop: "{{ports|flatten(1)}}"

    - name: output
      debug:
        msg: "server_rules: {{server_rules}}"

通过上面的操作,输出如下:

$ansible-playbook -i "localhost," dicttest.yaml

PLAY [create dictionary test] ***************************************************************************************************************************************

TASK [print the ports] **********************************************************************************************************************************************
ok: [localhost] => {
    "msg": "ports: [80, 443]"
}

TASK [create a dictionary] ******************************************************************************************************************************************
ok: [localhost] => (item=80)
ok: [localhost] => (item=443)

TASK [output] *******************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "server_rules: [{'server': 'org.com', 'port': 80}, {'server': 'org.com', 'port': 443}]"
}

PLAY RECAP **********************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

但是当我将设置事实更改为(取消注释一个注释行并注释另一行)

server_rules: "{{server_rules|default([]) + [{'server': '{{server_base}}-{{item}}', 'port': item}]}}"

它失败并出现以下错误

$ansible-playbook -i "localhost," dicttest.yaml

PLAY [create dictionary test] ***************************************************************************************************************************************

TASK [print the ports] **********************************************************************************************************************************************
ok: [localhost] => {
    "msg": "ports: [80, 443]"
}

TASK [create a dictionary] ******************************************************************************************************************************************
ok: [localhost] => (item=80)
ok: [localhost] => (item=443)

TASK [output] *******************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/Users/dev/dicttest.yaml': line 22, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n    - name: output\n      ^ here\n"}

PLAY RECAP **********************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

谁能解释一下如何让它工作。

【问题讨论】:

    标签: loops dictionary ansible


    【解决方案1】:

    正确的语法是

        - name: create a list of dictionaries
          set_fact:
            server_rules: "{{ server_rules|default([]) +
                              [{'server': server_base  + '-' + item|string,
                                'port': item}] }}"
          loop: "{{ ports }}"
    

    给予

      server_rules:
      - port: 80
        server: org.com-80
      - port: 443
        server: org.com-443
    

    注意事项:

    • 双括号“{{ }}”不能嵌套。下面的表达式是错误的
          "{{ var1 + ['{{server_base}}-'] }}"
    

    正确

          "{{ var1 + [server_base + '-'] }}"
    

    在 YAML 中,运算符加“+”用于连接字符串和列表。这是因为 YAML 中的字符串在技术上是一个字符列表。建议使用“~”连接字符串

    也正确

          "{{ var1 + [server_base ~ '-'] }}"
    
    • debug 中使用var 属性。 stdout_callback = yaml 的输出更具可读性
        - debug:
            var: server_rules
    
    • 创建的变量server_rules 是一个列表。这些项目是字典。因此,它是一个字典列表。

    • 变量ports 是一个简单的列表。无需使用过滤器flatten

    • hosts: all”和“connection: local”的组合将使所有主机都在本地主机上运行

      hosts: all
      connection: local
    

    如果您想在 localhost 上运行 playbook,请使用“hosts: localhost”。在这种情况下,“连接:本地”是默认的

      hosts: localhost
    

    如果你想在 localhost 上运行任务,但仍希望 play 读取所有主机的变量,请使用 "delegate_to: localhost" 并将任务限制为 "run_once :真的”。例如

      - hosts: all
        tasks:
          - copy:
              content: "{{ ansible_play_hosts|to_nice_yaml }}"
              dest: /tmp/ansible_play_hosts.yml
            delegate_to: localhost
            run_once: true
    

    【讨论】:

    • 谢谢你,非常有帮助,在这里学到了很多东西,非常感谢你真诚的反馈和回答。
    【解决方案2】:

    从 stackoverflow 之外的另一个人那里得到答案,在这里发布只是为了确保任何人看到这个,也能得到解决方案

    如下修改即可解决问题

    server_rules: "{{server_rules|default([]) + [{'server': '{{server_base}}-' + item|string, 'port': item}]}}"
    

    完整的工作手册

    ---
    - name: create dictionary test
      hosts: all
      connection: local
      gather_facts: False
    
      vars:
        ports: [80, 443]
        server_base: "org.com"
    
      tasks:
        - name: print the ports
          debug:
            msg: "ports: {{ports}}"
    
        - name: create a dictionary
          set_fact:
            server_rules: "{{server_rules|default([]) + [{'server': '{{server_base}}-' + item|string, 'port': item}]}}"
          loop: "{{ports|flatten(1)}}"
    
        - name: output
          debug:
            msg: "server_rules: {{server_rules}}"
    

    【讨论】:

      猜你喜欢
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-06
      • 2020-06-04
      相关资源
      最近更新 更多