我在尝试使用 jinja2 模板构建配置时遇到错误,未检测到变量的字段。这是使用 ansible 将 Linux 存储库从黄金源同步到基于 yum 和 apt 的系统。每个存储库配置将进入不同的文件,并使用变量名称更新任务。基本系统配置应该能够使用多次使用“-”然后是属性列表放入一个文件中。
我已经评论过:
https://omarkhawaja.com/accessing-ansible-variables-with-jinja2-loops/
以及与我正在做的事情不太相关的其他内容。
变量文件:
---
repo:
- name: google_chrome
async: 1
url: http://dl.google.com/linux/chrome/rpm/stable/x86_6
...
包含 var 任务:
- name: Include var into the 'chrome' variable.
include_vars:
file: google_chrome_repo.yaml
name: chrome
使用模板模块的任务:
- name: generate config for Centos
template:
src: yum_template.j2
dest: "/etc/yum.repos.d/{{ item }}.repo"
backup: yes
with_items:
- chrome
when:
- ansible_distribution == 'CentOS'
模板:
{% for i in item %}
[ {{ i.name }} ]
async = {{ i.async }}
baseurl = {{ i.url }}
enabled = {{ i.repo_enable }}
enablegroups = {{ i.pkggrp_enable }}
failovermethod = {{ i.ha_method }}
gpgkey = {{ i.gpgkey_url }}
http_caching = {{ i.http_caching }}
keepcache = {{ i.keepcache }}
metadata_expire = {{ i.metadata_expire }}
mirrorlist = {{ i.mirrorlist }}
mirrorlist_expire = {{ i.mirrorlist_expire }}
name = {{ i.descrip }}
protect = {{ i.protect }}
proxy = {{ i.proxy_config }}
proxy_password = {{ i.proxy_username }}
proxy_username = {{ i.proxy_password }}
repo_gpgcheck = {{ i.repo_gpgcheck }}
retries = {{ i.repo_retry_count }}
s3_enabled = {{ i.s3_enabled }}
sslverify = {{ i.ssl_verify }}
timeout = {{ i.timeout }}
{% endfor %}
错误:
failed: [192.168.33.31] (item=chrome) => {"changed": false, "item": "chrome", "msg": "AnsibleUndefinedVariable: 'unicode object' has no attribute 'name'"}
无论 jinja2 模板首先调用角色中的哪个属性,都会以这种方式失败。如果我更改以下内容,则不会引用名称,并且“i.name”变为“chrome”,它将在异步时失败
我可以看到变量已导入
ok: [192.168.33.31] => {"ansible_facts": {"chrome": {"repo": [{"async": 1, "descrip": "Google Chrome Repository", "gpgkey_url": "https://dl.google.com/linux/linux_signing_key.pub", "ha_method": "roundrobin", "http_caching": 1, "keepcache": 1, "metadata_expire": 21600, "mirrorlist": null, "mirrorlist_expire": 21600, "name": "google_chrome", "pkggrp_enable": 1, "protect": 0, "proxy_config": "__None__", "proxy_password": null, "proxy_username": null, "repo_enable": 1, "repo_gpgcheck": 1, "repo_retry_count": 10, "s3_enabled": 0, "ssl_verify": 1, "timeout": 1, "url": "http://dl.google.com/linux/chrome/rpm/stable/x86_6"}]}}, "ansible_included_var_files": ["/var/lib/awx/projects/_6__trowe/playbooks/roles/Manage_Linux_Repos/vars/google_chrome_repo.yaml"], "changed": false}
我确实看到它说“unicode”变量,我希望它是一个字典。我也尝试过 with_dict ,错误表明该变量不是字典。但是,如果我在没有“repo:”的情况下构造变量文件,则会错误说它没有传递字典对象......
答案1
我想出了一个更好的方法来实现目标。
目标:允许用户使用存储库信息创建 var 文件。一个文件中的多个存储库一对一。 (例如:CentOS-Base repo 文件有很多不同的项目,但 elasticsearch、epel 等应该放在不同的文件中)
- 创建 var 文件,命名为 {repo}_{pkg_mgr}_repo.yml
- 在角色的main.yml文件中,找到所有带有{repo}_{pkg_mgr}的文件repo.yml 文件或 *{pkg_mgr}.yml 文件,基于从 Tower/AWX 传递的变量并注册到变量。对从 AWX/Tower 传递的 yum 和 apt 执行此操作
- 将 {variable}.files 传递给生成 yum 或 apt repo 配置的任务。
- 使用模板模块和jinja2模板文件创建repo文件并将其放置在远程服务器上。
- 运行任务以确保为当前存储库导入所有 gpg 密钥
** 需要考虑默认 apt 存储库放置在 resources.list 中,其他存储库位于 /etc/apt/sources.list.d/ 中
这已经过测试并适用于基于 yum 的发行版,目前适用于 APT。
答案2
改成{% for i in item %}
{% for i in item.repo %}
应该可以做到这一点,因为您的项目正在存储整个 dict 变量,您需要在 chrome 变量下调用子字典项目,即repo
.