Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible: How to inherit variables?

Tags:

ansible

I want to achieve variable inheritance in Ansible. Lets say I have:

group_vars/all

---
ifaces:
   -   name: eth0
       adress: 10.107.13.236
       netmask: 255.255.255.192
       routes:
           - {from: 10.108.100.34/31, via: 10.107.13.193}
           - {from: 10.108.105.128/31, via: 10.107.13.193}
   -   name: eth1
       adress: 10.112.13.236
       netmask: 255.255.255.192
       gateway: 10.112.13.193
       routes:
           - {from: 10.2.1.0/26, via: 10.112.13.254}

Now I want to extend the routes of eth0, like this:

group_vars/webserver

--- ifaces:
   -   name: eth0
       routes:
           - {from: 1.2.3.34, via: 5.6.7.8}
           - {from: 9.9.9.9/9, via: 5.6.7.8}

My desired result is:

---
ifaces:
   -   name: eth0
       adress: 10.107.13.236
       netmask: 255.255.255.192
       routes:
           - {from: 10.108.100.34/31, via: 10.107.13.193}
           - {from: 10.108.105.128/31, via: 10.107.13.193}
           - {from: 1.2.3.34, via: 5.6.7.8}
           - {from: 9.9.9.9/9, via: 5.6.7.8}
   -   name: eth1
       adress: 10.112.13.236
       netmask: 255.255.255.192
       gateway: 10.112.13.193
       routes:
           - {from: 10.2.1.0/26, via: 10.112.13.254}

So the routes should be extendend and not overwritten. I know about setting hash_behaviour: merge in ansible.cfg but that does not satisfy my needs, because I want to append values to the list stored in routes.

The background is, that I need to be able to define some standard routes (note: this is not limited to routes, it is just an example) and enhance these standards for specific groups instead of overriding them.

Is this possible in Ansible?

like image 336
Johannes Avatar asked Jul 31 '15 06:07

Johannes


People also ask

How do you pass variables in Ansible playbook?

The easiest way to pass Pass Variables value to Ansible Playbook in the command line is using the extra variables parameter of the “ansible-playbook” command. This is very useful to combine your Ansible Playbook with some pre-existent automation or script.

How do you pass an environment variable in Ansible?

You can use the environment keyword at the play, block, or task level to set an environment variable for an action on a remote host. With this keyword, you can enable using a proxy for a task that does http requests, set the required environment variables for language-specific version managers, and more.

What is the order of precedence for Ansible variables?

Ansible defines the precedence order as follows: Extra vars (from command-line) always win. Task vars (only for the specific task). Block vars (only for the tasks within the block).

How do I register variables in Ansible?

Ansible registers are used when you want to capture the output of a task to a variable. You can then use the value of these registers for different scenarios like a conditional statement, logging etc. The variables will contain the value returned by the task. The common return values are documented in Ansible docs.


1 Answers

I would suggest creating lookup_plugin that will do all the heavy-ligting of the merging/appending variables.

for example:

lookup_plugins/myvars.py

import yaml
class LookupModule(object):
    def __init__(self, basedir=None, **kwargs):
        self.basedir = basedir
        self.plugin_name = 'myvars'
    def run(self, vars_file, variable=None, **kwargs):
        all_routes = yaml.load(file('group_vars/all'))['ifaces'][0]['routes']
        all_routes.extend(
            yaml.load(file('group_vars/%s' % vars_file[0]))['ifaces'][0]['routes'])
        return [all_routes]

playbook.yml

---
- hosts: webservers
  gather_facts: no
  connection: local
  tasks:
    - debug: msg=" Hey {{ item }}"
      with_myvars:
        - webservers

Of cource it doesn't fully solve your plroblem and you still need to tweak it to make it work. But you should get an idea on how to achive this from this example.

An output of this should look like this:

PLAY [webservers] ************************************************************* 

TASK: [debug msg=" Hey {{ item }}"] ******************************************* 
ok: [localhost] => (item=[{'via': '10.107.13.193', 'from': '10.108.100.34/31'}, {'via': '10.107.13.193', 'from': '10.108.105.128/31'}, {'via': '5.6.7.8', 'from': '1.2.3.34'}, {'via': '5.6.7.8', 'from': '9.9.9.9/9'}]) => {
    "item": [
        {
            "from": "10.108.100.34/31",
            "via": "10.107.13.193"
        },
        {
            "from": "10.108.105.128/31",
            "via": "10.107.13.193"
        },
        {
            "from": "1.2.3.34",
            "via": "5.6.7.8"
        },
        {
            "from": "9.9.9.9/9",
            "via": "5.6.7.8"
        }
    ],
    "msg": " Hey [{'via': '10.107.13.193', 'from': '10.108.100.34/31'}, {'via': '10.107.13.193', 'from': '10.108.105.128/31'}, {'via': '5.6.7.8', 'from': '1.2.3.34'}, {'via': '5.6.7.8', 'from': '9.9.9.9/9'}]"
}

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

So as you can see it's returning a list of routes, so you can easily place {{ item }} in what ever spot you need.

like image 147
Vor Avatar answered Sep 25 '22 04:09

Vor