group_names和嵌套变量

时间:2019-05-14 13:46:38

标签: ansible ansible-template

我必须在相对较短的时间内对网络进行多次更改,以便节省时间,因此我决定使用Ansible。

我在多个环境中都有多种类型的服务器,因此需要遍历每种环境和每种类型的服务器并设置新的IP,子网等。

例如在ENV1中,我可能拥有Web和DB,例如在192.168.64上具有ENV1,而Web为.10,DB为.20。

因此,使用Ansible并定义两个列表并在嵌套循环中使用它们,我希望能够根据服务器的环境和类型来做到这一点。

我可以使用命令行变量并为每个变量设置环境子网,但是如果可以避免的话,我想这样做。

剧本。

---
- hosts: web:db
  become: yes
  vars_files: 
    - vars/network-vars.yaml
  tasks:
    - name: Update the ifcfg-eth0 file
      template:
        src: templates/ifcfg-template.yaml
        dest: /etc/sysconfig/network-scripts/ifcfg-eth0.new
        owner: root
        group: root
        mode: 0644

      when: item.type in group_names and item.env in group_names
      with_items: 
          - "{{ ips }}"
          - "{{ subnets }}"

各种文件:

---
- netmask: 255.255.255.0
- network: 192.168.64
- dns1: 192.168.64.254
- search: lab.int

- subnets:
    - { env: "env1", net: "192.168.64.2" }

- ips:
    - { type: "web", ip: "10" }
    - { type: "db", ip: "20" }

  

失败! => {“ msg”:“ group_names中的条件检查'item.type和group_names中的'{{env}}''失败。错误是:评估条件时出错(group_names中的item.type和'{{env} }”(在组名中):“ env”未定义

我尝试了with_nested,但是遇到了类似的错误。我几乎已经筋疲力尽地阅读手册页并寻找解决方案,因此我为什么在这里。

TIA。

3 个答案:

答案 0 :(得分:0)

您可以为此使用product过滤器。

可以在Loops页面上的官方文档中找到有关ansible循环构造的更多文档。

#!/usr/bin/env ansible-playbook
- name: Lets do some loops
  hosts: localhost
  gather_facts: false
  become: false
  vars:
    arr_one:
    - env: dev
    - env: prod
    arr_two:
    - type: web
    - type: db
  tasks:
  - name: Only print when env=dev and type=db
    debug:
      msg: "{{ item.0.env }} {{ item.1.type }}"
    when: (item.0.env == 'dev') and
          (item.1.type == 'db')
    loop: "{{ arr_one
            | product(arr_two)
            | list }}"

PLAY [Lets do some loops] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Only print when for env=dev and type=db] *****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [localhost] => (item=[{'env': 'dev'}, {'type': 'web'}]) 
ok: [localhost] => (item=[{'env': 'dev'}, {'type': 'db'}]) => {
    "msg": "dev db"
}
skipping: [localhost] => (item=[{'env': 'prod'}, {'type': 'web'}]) 
skipping: [localhost] => (item=[{'env': 'prod'}, {'type': 'db'}]) 

PLAY RECAP ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0  

答案 1 :(得分:0)

关于错误:

'item.type in group_names and '{{env}}' in group_names

由于中间{{env}}的嵌套,您会看到它。

  • when语句的内容隐含在jinja {{...}}上下文中,并且
  • 您永远不会嵌套{{...}}个标记。

您可以将这些表达式写为:

when: item.type in group_names and env in group_names

但这可能不是解决问题的好方法。

答案 2 :(得分:0)

我想分享一下如何在不循环的情况下运行它,并且不确定为什么我一开始就没有想到这一点。我在每个系统上设置一个事实,首先声明网络。简单的解决方案有时最容易遗漏。

    - name: set the network
      set_fact: net="{{ item.net }}"
      when: item.env in group_names
      with_items:
        - "{{ subnets }}"