【问题标题】:Ansible template loopAnsible 模板循环
【发布时间】:2020-11-06 10:52:19
【问题描述】:

我正在尝试循环字典并设置一个变量。这是我的模板文件中的内容。

{% for item in db_server() %}
    {% if item.name in fqdn.stdout and item.mysql == "mysql-5-5-28" %}
        {% set version = "mysql-5.5.28-linux2.6-x86_64" %}
    {% elif item.name in fqdn.stdout and item.mysql == "mysql-5-1-51" %}
        {% set version = "mysql-5.1.51-linux-x86_64-glibc23" %}
    {% endif %}
{% endfor %}

我的 var 文件是

db_server:
  - name: "test1"
    mysql: "mysql_5_5_28"
  - name: "test2"
    mysql: "mysql_5_5_28"
  - name: "test3"
    mysql: "mysql_5_5_28"

我遇到了一个错误

fatal: [st-cms-db2]: FAILED! => {
    "changed": false, 
    "msg": "AttributeError: 'list' object has no attribute '__call__'"
}

我是 ansible 模板的新手。我是通过谷歌搜索写的。请善待...

【问题讨论】:

  • 错误似乎来自db_server()。在迭代列表时,您不需要()。尝试不使用这些括号。
  • 没有括号,变量“version”没有设置“msg”:“AnsibleUndefinedVariable: 'version' is undefined
  • 预期的结果是什么?模板迭代列表并在每次迭代中重写变量version。这既低效又容易出错。每次要添加新版本时,都必须更改代码。将逻辑放入字典中。请参阅我关于如何前进的答案。
  • 我看起来错误是因为您使用db_server 作为方法,请删除() 并重试。

标签: ansible jinja2 ansible-template


【解决方案1】:

您可能希望将逻辑放入字典而不是 Jinja 模板。例如,创建字典

    versions:
      mysql_5_5_28: mysql-5.5.28-linux2.6-x86_64
      mysql_5_1_51: mysql-5.1.51-linux-x86_64-glibc23

那么下面的playbook实现逻辑

shell> cat pb.yml
- hosts: localhost
  vars:
    versions:
      mysql_5_5_28: mysql-5.5.28-linux2.6-x86_64
      mysql_5_1_51: mysql-5.1.51-linux-x86_64-glibc23
    db_server:
      - name: "test1"
        mysql: "mysql_5_5_28"
      - name: "test2"
        mysql: "mysql_5_5_28"
      - name: "test3"
        mysql: "mysql_5_1_51"
  tasks:
    - debug:
        msg: "{{ item.name }} {{ versions[item.mysql] }}"
      loop: "{{ db_server }}"
      # when: item.name in fqdn.stdout

给予

shell> ansible-playbook pb.yml | grep msg
  msg: test1 mysql-5.5.28-linux2.6-x86_64
  msg: test2 mysql-5.5.28-linux2.6-x86_64
  msg: test3 mysql-5.1.51-linux-x86_64-glibc23

根据您的需求调整库存和其他条件(例如 fqdn.stdout)。将名称和版本放入字典将进一步简化代码。例如,

    db_server:
      test1:
        mysql: "mysql_5_5_28"
      test2:
        mysql: "mysql_5_5_28"
      test3:
        mysql: "mysql_5_1_51"

那么下面的playbook实现了多主机的逻辑

shell> cat pb.yml
- hosts: test1,test2,test3
  gather_facts: false
  vars:
    versions:
      mysql_5_5_28: mysql-5.5.28-linux2.6-x86_64
      mysql_5_1_51: mysql-5.1.51-linux-x86_64-glibc23
    db_server:
      test1:
        mysql: "mysql_5_5_28"
      test2:
        mysql: "mysql_5_5_28"
      test3:
        mysql: "mysql_5_1_51"
  tasks:
    - set_fact:
        version: "{{ versions[db_server[inventory_hostname].mysql] }}"
    - debug:
        msg: "{{ inventory_hostname }} {{ version }}"

给出相同的结果

shell> ansible-playbook pb.yml | grep msg
  msg: test2 mysql-5.5.28-linux2.6-x86_64
  msg: test1 mysql-5.5.28-linux2.6-x86_64
  msg: test3 mysql-5.1.51-linux-x86_64-glibc23

如果您仍想继续使用模板,请尝试以下任务和模板

    - set_fact:
        version: "{{ lookup('template', 'template.j2') }}"
shell> cat template.j2
{% for item in db_server %}
{% if item.name in fqdn.stdout and item.mysql == "mysql_5_5_28" %}
"mysql-5.5.28-linux2.6-x86_64"
{% elif item.name in fqdn.stdout and item.mysql == "mysql_5_1_51" %}
"mysql-5.1.51-linux-x86_64-glibc23"
{% endif %}
{% endfor %}

【讨论】:

  • 感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多