Ansible - 如何使用循环设置var

时间:2016-04-26 16:40:02

标签: ansible ansible-playbook

我想创建一个复杂的var(nginx_ssl_vhosts_list),其中包含来自另一个简单var(reverse_proxy_ssl)的循环,但是我无法使其工作。是否可以使用类似下面的代码或者我应该使用自定义插件?

以下是我认为它会起作用的方式:

- hosts: localhost
  gather_facts: no
  connection: local
  vars:
    reverse_proxy_ssl:
      - name: foo.org
        frontport: 443
        fronturl : /
        backend: http://192.168.1.1:8080
      - name: bar.org
        frontport: 443
        fronturl : /
        backend: http://192.168.1.2:443
    nginx_ssl_vhosts_list:
      - listen: "{{ item.frontport }} ssl"
        server_name: "{{ item.name }}"
        access_log: "{{ item.name }}.access.log"
        error_log: "{{ item.name }}.error.log"
        extra_parameters: |
          location {{ item.fronturl }} {
            proxy_pass {{ item.backend }};
          }
          ssl_certificate     {{ item.name }}.crt;
          ssl_certificate_key {{ item.name }}.key;
      with_items: "{{ reverse_proxy_ssl }}"
  tasks:
    - debug: msg="{{ nginx_ssl_vhosts_list }}"

3 个答案:

答案 0 :(得分:2)

据我所知,你无法循环变量定义,但是你可以在模板或任务中循环。

在这种情况下,您最好创建一个template任务,从reverse_proxy_ssl列表变量生成虚拟主机,如下所示:

...
tasks:
  - name: template virtual hosts
    template:
      src: apache2.conf.j2
      dest: /etc/apache2/apache2.conf
...

apache2.conf.j2

...
{% for vhost in reverse_proxy_ssl %}
<VirtualHost *: {{ vhost.frontport }}>
    ServerName {{ vhost.name }}
    ProxyPreserveHost On
    ProxyPass {{ vhost.fronturl }} {{ vhost.backend }}
    ProxyPassReverse {{ vhost.fronturl }} {{ vhost.backend }}
</VirtualHost>
{% endfor %} 
...

在更一般的情况下,您应该能够使用set_fact创建变量并在循环中使用它:

- name: set foo
  set_fact: foo="{{ item.foo }}"
  with_items: foos 

答案 1 :(得分:2)

这是可能的。

我是通过使用Jinja2模板并在模板中使用普通python来实现的。最后,只需使用{{- temp_list -}}

返回列表

以下是我default/main.yml

的示例
# Arch List type
Mock_ArchType: ['epel-6-x86_64','epel-7-x86_64']

# Vars list Dictionary
Platform_Vars_list: [
{ var: "log_path", value: "'{{ Default_Home_String }}/logs/'" },
{ var: "python_site_packages_path", value: "'{{ Default_Python_String }}/lib/python{{ python_main_version }}/site-packages/'" }
                         ]

Platform_Vars:      "{%- set temp_list = [] -%}
                     {%- for item in Mock_ArchType if (client_code | search('Build')) -%}
                     {%- for vars in Platform_Vars_list  -%}
                     {%- set temp_dic = {} -%}
                     {%- set _= temp_dic.update({'var': vars.var }) -%}
                     {%- set _= temp_dic.update({'value': vars.value }) -%}
                     {%- set _= temp_dic.update({'path': '/var/lib/mock/' + item + '/root/builddir/build/BUILDROOT' + Default_Home_String }) -%}
                     {%- set _= temp_list.append(temp_dic) -%}
                     {%- endfor -%}
                     {%- endfor -%}
                     {{- temp_list -}}"

归功于此。 https://groups.google.com/forum/#!topic/ansible-project/aiBiuUGWZGs

答案 2 :(得分:0)

我知道这是一个老问题,但是我有一个类似的问题。这是我的方法。

首先,我认为@ydaetskcoR是正确的,解决此问题的最佳方法不是创建复杂的变量,而是将循环移动到模板上。

也就是说,在某些情况下,您想遍历字典或列表。就我而言,因为我想确保每个必需的键都在字典列表中设置,如果没有,则填写默认值,这取决于要写在模板中的一些逻辑。

sonance207的方法似乎非常强大,但是我注意到,Jinja2定义的“设置”变量以及Ansible设置的过滤器和变量使我有些不兼容。例如,在上面的示例中,该行

{%- set _= temp_dic.update({'var': vars.var }) -%}

不能写成

{%- set temp_dic = temp_dic | combines({'var': vars.var }) -%}

如果这样做,则会出现奇怪的错误,例如Ansible认为temp_dic为None而不是字典。

最后,我使用了Konstantin Suvorov在https://ansibledaily.com/process-complex-variables-with-set_fact-and-with_items/上写的内容的简化版本。但是,我没有使用register关键字写一个临时变量,而是在以后检索它,而是选择了一个简单的with_item循环,该循环用单个条目增加了所需的nginx_ssl_vhosts_list变量循环。

- hosts: localhost
  gather_facts: no
  connection: local
  vars:
    reverse_proxy_ssl:
      - name: foo.org
        frontport: 443
        fronturl : /
        backend: http://192.168.1.1:8080
      - name: bar.org
        frontport: 443
        fronturl : /
        backend: http://192.168.1.2:443
    nginx_ssl_vhosts_list: []
  tasks:
    - set_fact:
        nginx_ssl_vhosts_list: "{{ nginx_ssl_vhosts_list + [{
          'listen': (item.frontport |string) + ' ssl',
          'server_name': item.name,
          'access_log': item.name + '.access.log',
          'error_log': item.name + '.error.log'
        }] }}"
      with_items: "{{ reverse_proxy_ssl }}"

    - debug: msg="{{ nginx_ssl_vhosts_list }}"

(请注意,此示例省略了extra_parameters的多行格式。这种格式最好在jinja2模板文件中使用。