0

I'm having to make multiple changes to my network in a relatively short space of time so to save time I decided to use Ansible.

I have multiple types servers in multiple environments so need to iterate across each environment and each type of server and set the new IP, subnet etc.

For example in ENV1 I might have Web & DB for example with ENV1 on 192.168.64 and Web is .10 and DB is .20 .

So using Ansible and defining two lists and using these in a nested loop, I'd expect to be able to do this based on the environment and type of server.

I could use a command line variable and set the environments subnet for each one but if I can avoid that, I'd like to.

Playbook.

---
- 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 }}"

Vars file:

---
- 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" }

FAILED! => {"msg": "The conditional check 'item.type in group_names and '{{env}}' in group_names' failed. The error was: error while evaluating conditional (item.type in group_names and '{{env}}' in group_names): 'env' is undefined

I've tried with_nested but get a similar error. I've pretty much exhausted reading the man pages and searching for a solution, hence why I'm here.

TIA.

larsks
  • 277,717
  • 41
  • 399
  • 399
Ft00msh
  • 101
  • 2
  • 8

3 Answers3

0

You can use the product filter for this.

More documentation around ansible loop constructs can be found in official documentation on the Loops page.

#!/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  
Nick
  • 1,834
  • 20
  • 32
0

With respect to the error:

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

You're seeing that because of the nested {{env}} in the middle there.

  • The content of a when statement is implicitly inside a jinja {{...}} context, and
  • You never nest {{...}} markers.

You would write that expressions as:

when: item.type in group_names and env in group_names

But that's probably not a great way of solving your problem.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Thanks, yes that error was from me trying something and my code above it isn't nested . I just cut and pasted the wrong error. – Ft00msh May 15 '19 at 13:25
0

Thought I'd share how I got this to work without looping & not sure why I didn't think of this in the first place. I set a fact on each system, first to declare the network. Simple solutions are sometimes the easiest to miss.

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