Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a dynamic role in ansible

After going through several documentation I concluded that, I can't use with_items for roles.

So, I created a filter_plugin to generate a list of dictionaries for roles.

Here is my Play:

---
- name: Boostrap vpc and subnets with route table
  hosts: localhost
  connection: local
  gather_facts: no
  pre_tasks:
    - include_vars: ec2_vars/common/regions.yml
    - include_vars: environment.yml
  roles:
    - {
        role: vpc,
        ec2_region: 'ap-southeast-2'
      }
    - {
        role: vpc,
        ec2_region: "ap-southeast-1",
      }
    - {
        role: vpc,
        ec2_region: "us-west-2",
      }

I want to generate above roles dynamically and for that I created a filter_plugin which generates a list of dictionaries and that is working right.

Here is my plugin:

# this is for generating vpc roles

def roles(ec2_regions):
    return [{'role': 'vpc', 'ec2_region': ec2_region} for ec2_region in ec2_regions]


class FilterModule(object):
    def filters(self):
        return {'vpcroles': roles}

My plan was to generate roles like following:

roles: "{{ EC2_REGIONS | vpcroles }}"

where EC2_REGIONS is ['ap-southeast-2', 'us-east-1']

But roles are not working in that way.

I am getting following error:

ERROR! A malformed role declaration was encountered.

Any thoughts/ideas ?

like image 599
Suku Avatar asked Aug 22 '16 05:08

Suku


1 Answers

Very rough proof-of-concept. I was curious, if it would work and it does.

The major problem is that dynamically-created playbook is called from inside a task and its stdout doesn't go into main Ansible log (can be registered in the variable of the main playbook and displayed as such). Errors propagate to the parent-playbook.

Main playbook:

---
- hosts: localhost
  connection: local
  vars:
    params:
      - val1
      - val2
  tasks:
    - template:
        src: role_call.yml.j2
        dest: ./dynamic/role_call.yml
    - command: ansible-playbook ./dynamic/role_call.yml

Dynamic playbook template in templates/role_call.yml.j2 file:

- hosts: localhost
  connection: local
  roles:
  {% for param in params %}
    - { role: role1, par: {{param}} }
  {% endfor %}

roles/role1/tasks/main.yml:

- debug: var=par

I guess the internal ansible-playbook command could be called with a separate ansible.cfg as an argument to save the log to a different file.

Overall not worth the hassle in your case, I guess, but for a problem that cannot be solved otherwise like this it looks promising.

like image 181
techraf Avatar answered Sep 30 '22 11:09

techraf