如何使用 jinja2 模板和 with_items 文件中包含的变量

如何使用 jinja2 模板和 with_items 文件中包含的变量

我在尝试使用 jinja2 模板构建配置时遇到错误,未检测到变量的字段。这是使用 ansible 将 Linux 存储库从黄金源同步到基于 yum 和 apt 的系统。每个存储库配置将进入不同的文件,并使用变量名称更新任务。基本系统配置应该能够使用多次使用“-”然后是属性列表放入一个文件中。

我已经评论过:

jinja2 中的 for 循环

https://omarkhawaja.com/accessing-ansible-variables-with-jinja2-loops/

https://stackoverflow.com/questions/25418158/templated-multiple-yum-repo-files-with-ansible-template-module

以及与我正在做的事情不太相关的其他内容。

变量文件:

---
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 等应该放在不同的文件中)

  1. 创建 var 文件,命名为 {repo}_{pkg_mgr}_repo.yml
  2. 在角色的main.yml文件中,找到所有带有{repo}_{pkg_mgr}的文件repo.yml 文件或 *{pkg_mgr}.yml 文件,基于从 Tower/AWX 传递的变量并注册到变量。对从 AWX/Tower 传递的 yum 和 apt 执行此操作
  3. 将 {variable}.files 传递给生成 yum 或 apt repo 配置的任务。
  4. 使用模板模块和jinja2模板文件创建repo文件并将其放置在远程服务器上。
  5. 运行任务以确保为当前存储库导入所有 gpg 密钥

** 需要考虑默认 apt 存储库放置在 resources.list 中,其他存储库位于 /etc/apt/sources.list.d/ 中

这已经过测试并适用于基于 yum 的发行版,目前适用于 APT。

答案2

改成{% for i in item %} ​ {% for i in item.repo %}

应该可以做到这一点,因为您的项目正在存储整个 dict 变量,您需要在 chrome 变量下调用子字典项目,即repo.

相关内容