无法使用Jinja创建conf文件-Nginx的预期变量

时间:2019-04-24 02:34:17

标签: nginx centos ansible jinja2

我今天正在学习使用Jinja来为我手动创建并为Nginx测试的配置文件建立模板。到目前为止,模板可以按预期工作,并且可以按预期提取动态变量。但是,我的conf中有一行需要分在两个单独的行中,由于某种原因,它将两个主机放在同一行中。

这看起来真的很简单,但是我似乎无法发现引起它的原因。我已经做到了!

我的nginx.yml文件

---
test_url: abc.{{ nginx_domain }}
nginx_ssl_port: 443
nginx_proxy_conf_dir: /etc/some/place
nginx_ssl_key_dir:  /etc/somekey/place
nginx_ssl_cert_dir: /etc/somecert/place
nginx_proxy_log_dir: /etc/some/proxy/place
##Env depends on ansible inventory

test_nginx_proxy_sites:
- name: test
  params:
  - 'listen {{ nginx_ssl_port }} ssl'
  - 'server_name {{test_url}}'
  - 'include {{ nginx_proxy_conf_dir }}/conf.d/ssl.conf'
  - 'ssl_certificate {{ nginx_ssl_cert_dir }}/{{ nginx_domain }}.crt'
  - 'ssl_certificate_key {{ nginx_ssl_key_dir }}/{{ nginx_domain }}.key'
  - 'access_log {{ nginx_proxy_log_dir }}/management_access.log'
  - 'error_log {{ nginx_proxy_log_dir }}/management_error.log'
  locations:
  - path: /
    location_params:
    - 'proxy_pass http://stream_{{ Env }}/'
    - 'include {{ nginx_proxy_conf_dir }}/conf.d/proxy.conf'
  upstreams:
  - name: stream_{{ Env }}
    params:
    - '{% for host in groups.tag_Class_host %}
    server {{ hostvars[host].ipv4_local }}:{{ management_port }};
    {% endfor %}
    '

我的sites.conf.j2

{{ remotely_managed }}
server {
{% if item.blocks is defined and item.blocks|length > 0 %}
{% for block in item.blocks %}
  {{ block }}
{% endfor %}
{% endif %}
{% for param in item.params %}
  {{ param }};
{% endfor %}
{% if item.locations is defined and item.locations|length > 0 %}

{% for location in item.locations %}
  location {% if location.match is defined %}{{ location.match }} {% endif %}{{ location.path }} {
{% if location.root is defined %}
    root {{ location.root }};
{% endif %}
{% if location.location_params is defined and location.location_params|length > 0 %}
{% for param in location.location_params %}
    {{ param }};
{% endfor %}
{% endif %}
  }
{% endfor %}
{% endif %}
{% if item.errors is defined and item.errors|length > 0 %}
{% for error in item.errors %}
  {{ error.directive }};
  location {{ error.location }} {
{% for param in error.error_params %}
    {{ param }};
{% endfor %}
  }
{% endfor %}
{% endif %}
}
{% if item.upstreams is defined %}
{% for u in item.upstreams %}
upstream {{ u.name }} {
{% if u.params is defined %}
{% for param in u.params %}
{{ param }}
{% endfor %}
{% endif %}
}
{% endfor %}
{% endif %}

我的输出

server {
  server_name abc.mytest.com;
  include /etc/nginx/conf.d/ssl.conf;
  ssl_certificate /etc/somecert/place/certs/abc.mytest.com.crt;
  ssl_certificate_key /etc/somekey/place/private/abc.mytest.com.key;
  access_log /var/log/nginx/management_access.log;
  error_log /var/log/nginx/management_error.log;

  location / {
    proxy_pass http://stream_qa/;
    include /etc/nginx/conf.d/proxy.conf;
  }
}
upstream stream_qa {
 server 1.1.1.09:11111;    server 1.1.1.10:11111;
  }

上游应打印如下:

upstream stream_qa {
 server 1.1.1.09:11111;
 server 1.1.1.10:11111;
  }

2 个答案:

答案 0 :(得分:0)

好的-是的。

要了解此问题,了解jinja模板的工作原理很重要。

解决方案:像这样简单地插入新行

{% if item.upstreams is defined %}
{% for u in item.upstreams %}
upstream {{ u.name }} {

{% if u.params is defined %}
{% for param in u.params %}
{{ param }}

{% endfor %}
{% endif %}

这样做的原因是由于Jinja模板的工作原理。

渲染jinja时,它不知道将内容放到新行中,而只是知道将循环中的内容放到一个副本中。因此,如果您的循环缺少对新行的准备,则不会将事情放到新行上。

因此,当您遇到类似您的循环时,或更简单地说,是一个[a, b, c, d, e, f]的数组

{% for i in items %}
{{ i }}
{% endfor %}

它将打印为abcdef,因为{{i}}的字面意思是在此处渲染i

通过在循环中放置新行。

{% for i in items %}
{{ i }}

{% endfor %}

它将在循环中最后一项的末尾(即在新行上)呈现i

简而言之,您想做的是i还包括在循环中提供新行,以便jinja渲染循环中的内容时,还可以渲染新行。

如果您这样看,我提到的第一个循环就是这样渲染的 abcde,但第二个循环的呈现方式如下:a\nb\nc\nd\ne,如您所见,该循环中每个项目的值都提供了新行。

ps:这真的很难解释:(

答案 1 :(得分:0)

我能够通过编辑nginx.yml文件来解决此问题:

upstreams:
  - name: stream_{{ Env }}
    params:
    - 
      {% for host in groups.tag_Class_host %}
        server {{ hostvars[host].ipv4_local }}:{{ management_port }};
      {% endfor %}

我应该查看YAML,而不是查看Jinja。 YAML中的新管道将使我的字符串成为多字符串行。

输出与上面的输出匹配。