Ansible循环遍历组和引用索引

时间:2017-03-27 16:36:22

标签: ansible jinja2

我的库存文件定义如下:

[app]
app1.service.com ansible_host=192.168.1.1
app2.service.com ansible_host=192.168.1.2
app3.service.com ansible_host=192.168.1.3

我需要为每个主机生成多个配置文件。当前任务如下所示:

- name: Create node-specific csync2 config files
  template:
    src: "templates/etc/csync2_node.cfg"
    dest: "/etc/csync2_{{ hostvars[item]['ansible_hostname'] }}.cfg"
    owner: root
    group: root
    backup: no
  with_items: "{{ groups[csync2_cluster_nodes_group] }}"

我的模板看起来像这样:

nossl * *;
group {{ hostvars[item]['ansible_hostname'] }}
{
        {% for host in groups[csync2_cluster_nodes_group] %}
        {% if host != hostvars[item]['ansible_nodename'] %}
        host ({{ host }});
        {% else %}
        host {{ host }};
        {% endif %}
        {% endfor %}
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

这可以正常生成如下模板文件:

group app1
{
        host app1.service.com;
        host (app2.service.com);
        host (app3.service.com);
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

问题是此配置导致竞争条件,因此我需要链接配置。我的意思是我需要app1配置文件看起来类似于

group app1
{
        host app1.service.com;
        host (app2.service.com);
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

app2配置看起来像:

group app2
{
        host app2.service.com;
        host (app3.service.com);
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

app3配置看起来像:

group app3
{
        host app3.service.com;
        host (app1.service.com);
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

据我所知,最好的方法是利用模板中主机的索引。问题是我不确定这样做的语法是什么。我想在配置文件中做类似的事情(伪代码,因为我不知道这个的语法)

nossl * *;
group {{ hostvars[item]['ansible_hostname'] }}
{
        {% for host in groups[csync2_cluster_nodes_group] %}
          {% if host != hostvars[item]['ansible_nodename'] %}
          {# This "item" isn't the current "host", so check to see if this is the last item in the group #}
            {% if group.last == item %}
              {# this is the last host in the group, so pull the FIRST host from the group #}
              host ({{ hostvars[groups['app'][0]]['ansible_nodename'] }});
            {# OK, this isn't the last host in the group, so pull the NEXT host from the group #}
            {% else %}
              host ({{ hostvars[groups['app'][groups.app.index(host)+1]]['ansible_nodename'] }});
            {% endif %}
          {% else %}
            host {{ host }};
          {% endif %}
        {% endfor %}
        key /etc/csync2/csync2.key;
        include /home;
        exclude *.log;
        exclude *.swp;
        exclude /home/ansible;
        auto younger;
}

我希望我能够清楚地解释这个问题。我确信这有可能实现,但我只是坚持正确的语法来实现它。

1 个答案:

答案 0 :(得分:0)

这是我在reddit的一些帮助下想出来的。

{# This is our "cycle" of hosts - this way the first host is after the first instance of the last host #}
{% set hosts = groups[csync2_cluster_nodes_group] + groups[csync2_cluster_nodes_group] -%}
{% set current_host_index = hosts.index(hostvars[item].ansible_nodename) -%}
{% if current_host_index < 0 %}{{ fail() }}{% endif %}
{% set next_host = hosts[current_host_index + 1] %}


nossl * *;
group {{ hostvars[item]['ansible_hostname'] }}
{
    host {{ hostvars[hosts[current_host_index]].ansible_nodename }};
    host ({{ hostvars[next_host].ansible_nodename }});
    key /etc/csync2/csync2.key;
    include /home;
    exclude *.log;
    exclude *.swp;
    exclude /home/ansible;
    auto younger;
}    

似乎工作得很漂亮。