Ansible-如何使用循环设置变量

Ansible-如何使用循环设置变量,ansible,ansible-playbook,Ansible,Ansible Playbook,我想创建一个复杂的var(nginx_ssl_vhosts_列表),其中包含来自另一个简单var(reverse_proxy_ssl)的循环,但我无法实现这一点。是否有可能有如下代码,或者我应该使用自定义插件 以下是我认为它会起作用的方式: - hosts: localhost gather_facts: no connection: local vars: reverse_proxy_ssl: - name: foo.org frontport:

我想创建一个复杂的var(nginx_ssl_vhosts_列表),其中包含来自另一个简单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 }}"

据我所知,不能在变量定义中循环,但可以在模板或任务中循环

在这种情况下,您最好创建一个任务,通过
reverse\u proxy\u ssl
list变量生成虚拟主机,如下所示:

...
tasks:
  - name: template virtual hosts
    template:
      src: apache2.conf.j2
      dest: /etc/apache2/apache2.conf
...
apache2.conf.j2 这是可能的

我通过使用Jinja2模板和模板中的普通python来实现这一点。最后,只需返回带有
{{-temp\u 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 -}}"
这是值得赞扬的。
我知道这是一个老问题,但我也遇到了类似的问题。这是我的方法

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

也就是说,在某些情况下,您需要循环使用dicts或list。在我的例子中,因为我想确保在dict列表中设置了每个必需的键,如果没有,则填写一个默认值,这取决于在模板中编写时需要复杂的逻辑

sonance207的方法似乎非常强大,但我注意到,Jinja2定义的“set”变量与Ansible设置的过滤器和变量之间存在一些不兼容。例如,在上面的示例中

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

{%- set temp_dic = temp_dic | combines({'var': vars.var }) -%}
如果你这样做,你会犯一些奇怪的错误,比如Ansible认为temp_dic是None而不是dictionary

最后,我使用了康斯坦丁·苏沃洛夫(Konstantin Suvorov)所写内容的简化版本。但是,我没有用
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 }}"

(请注意,此示例省去了
额外参数的多行格式设置。
。此类格式设置最好在jinja2模板文件中提供。

我不认为这是可能的,但您可以修改或编写模板,使其从反向代理ssl获取值。如果您能描述您的全部要求,我可以帮助您n这个。谢谢@arbabanazar我会设置一个模板。谢谢你的帮助,我会用一个模板来完成。
{%- set temp_dic = temp_dic | combines({'var': vars.var }) -%}
- 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 }}"