Sean Cav
Sean Cav

Reputation: 133

In Ansible is there a way to use with_items and host variables at the same time?

So I have 3 hosts I want to run a playbook on. Each host needs 3 files (all with the same names).

the files are going to be

Each file has a unique IP address that goes into it based on the vars/ file.

The task looks like this->

- name: configure subinterface bonds
  template: src="ifcfg-lacpbondsub.j2" dest=/etc/sysconfig/network-scripts/ifcfg-lacpbond.{{item.vlan}}
  with_items:
    - { vlan: "100" }
    - { vlan: "200" }
    - { vlan: "300" }
  tags:
    - bonding

So the vars looks like this->

  server01:
    loopbacks:
      ipv4: "10.0.0.100"
    SVIS:
      100:
        ipv4: "192.168.0.1"
        prefix: "28"
      200:
        ipv4: "192.168.1.1"
        prefix: "28"
      300:
        ipv4: "192.168.2.1"
        prefix: "28"

Now here comes the problem. I am not sure how to use with_items and vars in the same time so I can use with_items to defer which variable to use.... this would greatly simplify the complexity of the playbook

here is the template file->

{% set host = interfaces[ansible_hostname] -%}
{% set VLAN = item.vlan -%}

DEVICE=lacpbond.{{item.vlan}}
IPADDR={{host.SVIS.{{item.vlan}}.ipv4}}
ONBOOT=yes
BOOTPROTO=none
VLAN=yes

So the above works obviously if I don't use the {{}} within another {{}}. But you can see what I am trying. I can use item.X by itself fine, and I can use anything from vars/ fine. But I don't know how to do something like host.SVIS[VLAN].ipv4....

is this possible? Otherwise I will need 3 tasks with 3 templates.... and if i need more files this is not as scalable....

Upvotes: 1

Views: 2342

Answers (1)

larsks
larsks

Reputation: 311606

Your question is a bit unclear (in part because of the issue I pointed out in my comment), but if I understand what you're asking, you can just do something like:

IPADDR={{host.SVIS[item.vlan].ipv4}}

See the Variables section of the Jinja documentation, which says:

The following lines do the same thing:

{{ foo.bar }} 
{{ foo['bar'] }}

Update

You are getting that error ("AnsibleUndefinedVariable: 'dict object' has no attribute u'100'") because the keys in your dictionary are integers, but the values of the vlan keys in your with_items loop are strings. That is, host.SVIS[100] exists, but hosts.SVIS['100'] does not exist.

Given this playbook:

- hosts: localhost
  vars:
    interfaces:
      server01:
          loopbacks:
            ipv4: "10.0.0.100"
          SVIS:
            100:
              ipv4: "192.168.0.1"
              prefix: "28"
            200:
              ipv4: "192.168.1.1"
              prefix: "28"
            300:
              ipv4: "192.168.2.1"
              prefix: "28"
    ansible_hostname: server01
  tasks:
    - name: configure subinterface bonds
      template:
        src: "ifcfg-lacpbondsub.j2"
        dest: ./ifcfg-lacpbond.{{item.vlan}}
      with_items:
        - { vlan: 100 }
        - { vlan: 200 }
        - { vlan: 300 }
      tags:
        - bonding

And this template:

{% set host = interfaces[ansible_hostname] -%}

DEVICE=lacpbond.{{item.vlan}}
IPADDR={{host.SVIS[item.vlan].ipv4}}
ONBOOT=yes
BOOTPROTO=none
VLAN=yes
Raw

I get three files:

$ ls ifcfg-lacpbond.*
ifcfg-lacpbond.100  ifcfg-lacpbond.200  ifcfg-lacpbond.300

The content of each looks something like:

DEVICE=lacpbond.100
IPADDR=192.168.0.1
ONBOOT=yes
BOOTPROTO=none
VLAN=yes

Upvotes: 1

Related Questions