ansible模板中的循环字典
Loop dictionary in ansible template
我正在尝试使用 jinja2 通过 ansible 模板循环字典以创建多个数据源,但收到此错误 [{'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'value'", 'failed': True}]}
当 运行 一个调试任务时,它确实得到了正确的值,所以我觉得我的问题出在模板本身,但我一直无法弄清楚我做错了什么。
Ansible 任务
- name: debug dictionary
debug: msg="{{ item.value.db_url }}"
with_dict: databases
- name: copy tomcat config files
template: src="{{ item.src }}" dest="{{ item.dest }}"
with_items:
- { src: 'context.xml.j2', dest: '/opt/tomcat/conf/context.xml'}
notify: restart tomcat
with_dict: databases
Ansible 字典
databases:
db1:
db_resource: jdbc/db1
db_maxidle: 50
db_maxconn: 350
db_maxwait: 10000
db_user: dbuser
db_pass: "{{ dbpass }}"
db_url: jdbc:postgresql://server:5432/dbname
db_driver: org.postgresql.Driver
Jinja2 模板
{% for items in databases %}
<resource name="{{ item.value.db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ item.value.db_maxconn }}" maxidle="{{ item.value.db_maxidle }}" maxwaitmillis="{{ item.value.db_maxwait }}" username="{{ item.value.db_user }}" password="{{ item.value.db_pass }}" driverclassname="{{ item.value.db_driver }}" url="{{ item.value.db_url }}" />
{% endfor %}
调试输出
ok: [IP] => (item={'key': 'db1', 'value': {'db_maxwait': 10000, 'db_maxconn': 350, 'db_maxidle': 50, 'db_driver': 'org.postgresql.Driver', 'db_pass': u'REDACTED', 'db_resource': 'jdbc/db1', 'db_user': 'dbuser', 'db_url': 'jdbc:postgresql://server:5432/dbname'}}) => {
"item": {
"key": "db1",
"value": {
"db_driver": "org.postgresql.Driver",
"db_maxconn": 350,
"db_maxidle": 50,
"db_maxwait": 10000,
"db_pass": "REDACTED",
"db_resource": "jdbc/db1",
"db_url": "jdbc:postgresql://server:5432/db",
"db_user": "dbuser"
}
},
"msg": "jdbc:postgresql://server:5432/dbname"
}
在 Jinja 中,当 databases
是字典时,for items in databases
将(与 Python 中一样)遍历字典的 keys ,而不是它的 key/value 对。因此,在您的模板中,item.value
(我假设是 items.value
)应该是 databases[items]
,以便获得与键 items
关联的值。
您可以像这样修改您的 jinja2 模板和任务来实现您的目标:
Jinja2 模板:
<resource name="{{ databases[item].db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ databases[item].db_maxconn }}" maxidle="{{ databases[item].db_maxidle }}" maxwaitmillis="{{ databases[item].db_maxwait }}" username="{{ databases[item].db_user }}" password="{{ databases[item].db_pass }}" driverclassname="{{ databases[item].db_driver }}" url="{{ databases[item].db_url }}" />
Ansible 任务:
- name: debug dictionary
debug: msg="{{ databases[item].db_url }}"
with_items: "{{ databases | list }}"
- name: copy tomcat config files
template: src="{{ item.src }}" dest="{{ item.dest }}"
with_items:
- { src: 'context.xml.j2', dest: '/opt/tomcat/conf/context.xml'}
notify: restart tomcat
with_items: "{{ databases | list }}"
希望对您有所帮助,请根据您的要求调整任务
我今天发现使用 dict.values() 循环遍历每个 dict 元素的值而不是它的键。所以你应该可以为你的模板使用类似这样的东西。
{% for item in databases.values() %}
<resource name="{{ item.db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ item.db_maxconn }}" maxidle="{{ item.db_maxidle }}" maxwaitmillis="{{ item.db_maxwait }}" username="{{ item.db_user }}" password="{{ item.db_pass }}" driverclassname="{{ item.db_driver }}" url="{{ item.db_url }}" />
{% endfor %}
我知道这是事后的事情,但也许搜索此答案的其他人可以利用这个额外的发现。
迈克,你的回答让我今天省去很多搜索工作。
在我的例子中,我使用了一个字典列表,所以我必须有两个 if 语句,如下所示:
{% for dict_item in quotes %}
{% for item in dict_item.values() %}
.. {{ item.symbol }}
.. {{ item.price }}
{% endfor %}
{% endfor %}
谢谢!
如果您使用的是 Python 3,则应为:
{% for key, value in dictionary.items() %}
<resource name="{{ value.db_resource }}" ...
{% endfor %}
我正在尝试使用 jinja2 通过 ansible 模板循环字典以创建多个数据源,但收到此错误 [{'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'value'", 'failed': True}]}
当 运行 一个调试任务时,它确实得到了正确的值,所以我觉得我的问题出在模板本身,但我一直无法弄清楚我做错了什么。
Ansible 任务
- name: debug dictionary
debug: msg="{{ item.value.db_url }}"
with_dict: databases
- name: copy tomcat config files
template: src="{{ item.src }}" dest="{{ item.dest }}"
with_items:
- { src: 'context.xml.j2', dest: '/opt/tomcat/conf/context.xml'}
notify: restart tomcat
with_dict: databases
Ansible 字典
databases:
db1:
db_resource: jdbc/db1
db_maxidle: 50
db_maxconn: 350
db_maxwait: 10000
db_user: dbuser
db_pass: "{{ dbpass }}"
db_url: jdbc:postgresql://server:5432/dbname
db_driver: org.postgresql.Driver
Jinja2 模板
{% for items in databases %}
<resource name="{{ item.value.db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ item.value.db_maxconn }}" maxidle="{{ item.value.db_maxidle }}" maxwaitmillis="{{ item.value.db_maxwait }}" username="{{ item.value.db_user }}" password="{{ item.value.db_pass }}" driverclassname="{{ item.value.db_driver }}" url="{{ item.value.db_url }}" />
{% endfor %}
调试输出
ok: [IP] => (item={'key': 'db1', 'value': {'db_maxwait': 10000, 'db_maxconn': 350, 'db_maxidle': 50, 'db_driver': 'org.postgresql.Driver', 'db_pass': u'REDACTED', 'db_resource': 'jdbc/db1', 'db_user': 'dbuser', 'db_url': 'jdbc:postgresql://server:5432/dbname'}}) => {
"item": {
"key": "db1",
"value": {
"db_driver": "org.postgresql.Driver",
"db_maxconn": 350,
"db_maxidle": 50,
"db_maxwait": 10000,
"db_pass": "REDACTED",
"db_resource": "jdbc/db1",
"db_url": "jdbc:postgresql://server:5432/db",
"db_user": "dbuser"
}
},
"msg": "jdbc:postgresql://server:5432/dbname"
}
在 Jinja 中,当 databases
是字典时,for items in databases
将(与 Python 中一样)遍历字典的 keys ,而不是它的 key/value 对。因此,在您的模板中,item.value
(我假设是 items.value
)应该是 databases[items]
,以便获得与键 items
关联的值。
您可以像这样修改您的 jinja2 模板和任务来实现您的目标:
Jinja2 模板:
<resource name="{{ databases[item].db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ databases[item].db_maxconn }}" maxidle="{{ databases[item].db_maxidle }}" maxwaitmillis="{{ databases[item].db_maxwait }}" username="{{ databases[item].db_user }}" password="{{ databases[item].db_pass }}" driverclassname="{{ databases[item].db_driver }}" url="{{ databases[item].db_url }}" />
Ansible 任务:
- name: debug dictionary
debug: msg="{{ databases[item].db_url }}"
with_items: "{{ databases | list }}"
- name: copy tomcat config files
template: src="{{ item.src }}" dest="{{ item.dest }}"
with_items:
- { src: 'context.xml.j2', dest: '/opt/tomcat/conf/context.xml'}
notify: restart tomcat
with_items: "{{ databases | list }}"
希望对您有所帮助,请根据您的要求调整任务
我今天发现使用 dict.values() 循环遍历每个 dict 元素的值而不是它的键。所以你应该可以为你的模板使用类似这样的东西。
{% for item in databases.values() %}
<resource name="{{ item.db_resource }}" auth="container" type="javax.sql.datasource" maxtotal="{{ item.db_maxconn }}" maxidle="{{ item.db_maxidle }}" maxwaitmillis="{{ item.db_maxwait }}" username="{{ item.db_user }}" password="{{ item.db_pass }}" driverclassname="{{ item.db_driver }}" url="{{ item.db_url }}" />
{% endfor %}
我知道这是事后的事情,但也许搜索此答案的其他人可以利用这个额外的发现。
迈克,你的回答让我今天省去很多搜索工作。
在我的例子中,我使用了一个字典列表,所以我必须有两个 if 语句,如下所示:
{% for dict_item in quotes %}
{% for item in dict_item.values() %}
.. {{ item.symbol }}
.. {{ item.price }}
{% endfor %}
{% endfor %}
谢谢!
如果您使用的是 Python 3,则应为:
{% for key, value in dictionary.items() %}
<resource name="{{ value.db_resource }}" ...
{% endfor %}