ansible

in ansible can I use a variable for a module instead of using the module name?


I'm using ansible 2.9 and I would like to know if I can use a variable instead of the actual module name. For example:

---
- name: A Network play
  hosts: routers
  vars:
    router_module: ios_command
  tasks:
    - name: a network task
      {{router_module}}:
        commands:
          - show ip int brief 

Solution

  • No. You can't use a variable for the module, but you can dynamically create files with tasks from a template and include the files in a playbook. For example, see the playbook and the template below

    shell> cat test.yml
    - hosts: localhost
    
      vars:
    
        pb_tasks:
          - module: debug
            params:
              - {key: var, val: inventory_hostname}
          - module: debug
            params:
              - {key: msg, val: End of dynamic play}
    
      tasks:
    
        - file:
            state: directory
            path: tasks
    
        - template:
            src: task.yml.j2
            dest: tasks/task-{{ ansible_loop.index }}.yml
          loop: "{{ pb_tasks }}"
          loop_control:
            extended: true
    
        - include_tasks: tasks/task-{{ ansible_loop.index }}.yml
          loop: "{{ pb_tasks }}"
          loop_control:
            extended: true
    
    shell> cat task.yml.j2
    - {{ item.module }}:
    {% for param in item.params %}
        {{ param.key }}: {{ param.val }}
    {% endfor %}
    

    In the loop, the task "template" creates the files with the tasks

    shell> tree tasks
    tasks
    ├── task-1.yml
    └── task-2.yml
    
    0 directories, 2 files
    
    shell> cat tasks/task-1.yml 
    - debug:
        var: inventory_hostname
    
    shell> cat tasks/task-2.yml 
    - debug:
        msg: End of dynamic play
    

    The next task in the playbook includes these files in the loop. The playbook gives

    shell> ansible-playbook test.yml 
    
    PLAY [localhost] ****
    
    TASK [file] ****
    ok: [localhost]
    
    TASK [template] ****
    changed: [localhost] => (item={'module': 'debug', 'params': [{'key': 'var', 'val': 'inventory_hostname'}]})
    changed: [localhost] => (item={'module': 'debug', 'params': [{'key': 'msg', 'val': 'End of dynamic play'}]})
    
    TASK [include_tasks] ****
    included: /scratch/tasks/task-1.yml for localhost
    included: /scratch/tasks/task-2.yml for localhost
    
    TASK [debug] ****
    ok: [localhost] => {
        "inventory_hostname": "localhost"
    }
    
    TASK [debug] ****
    ok: [localhost] => {
        "msg": "End of dynamic play"
    }
    
    PLAY RECAP ****
    localhost: ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
    

    The same can be simplified with a dynamically created playbook. For example, see the playbook and the template below

    shell> cat test.yml
    - name: Create playbook from template
      hosts: localhost
      gather_facts: false
    
      vars:
    
        pb_tasks:
          - module: debug
            params:
              - {key: var, val: inventory_hostname}
          - module: debug
            params:
              - {key: msg, val: End of play}
    
      tasks:
    
        - template:
            src: playbook.yml.j2
            dest: playbook.yml
    
    shell> cat playbook.yml.j2
    - hosts: localhost
      gather_facts: false
      tasks:
    {% for item in pb_tasks %}
        - {{ item.module }}:
    {% for param in item.params %}
            {{ param.key }}: {{ param.val }}
    {% endfor %}
    {% endfor %}
    

    The task "template" creates the playbook

    shell> cat playbook.yml
    - hosts: localhost
      gather_facts: false
    
      tasks:
    
        - debug:
            var: inventory_hostname
    
        - debug:
            msg: End of play
    

    Then the playbook gives

    shell> ansible-playbook playbook.yml
    
    PLAY [localhost] ****
    
    TASK [debug] ****
    ok: [localhost] => {
        "inventory_hostname": "localhost"
    }
    
    TASK [debug] ****
    ok: [localhost] => {
        "msg": "End of play"
    }
    
    PLAY RECAP ****
    localhost: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0