How to use loop items or variable as the parameter key for a module in Ansible

86 Views Asked by At

I am writing a role to export configurations from Ansible AWX deployment. I want to loop over the items to export as follows. How is something like this possible?

- name: Export Config
  awx.awx.export:
    "{{ item }}": []
    controller_host: ...
    controller_username: ...
    controller_password: ...
  loop:
  - projects
  - inventory
  - applications
  - credentials 
1

There are 1 best solutions below

1
On BEST ANSWER

Whereby it is possible to have dynamic or variable values, it is not possible to have tasks with dynamic parameter keys.

Even using Templating (Jinja2) with import_tasks module – Import a task list, please take note about What's the difference between include_tasks and import_tasks?, such approach will run into errors.

A minimal example

dyn_task.yml

- shell:
    "{{ parameter }}": "{{ value }}"

main.yml

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:

    module: shell
    parameter: cmd
    value: exit 1

  tasks:

  - include_tasks: dyn_task.yml

will result into an error and output of

TASK [shell] *******************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (ansible.legacy.command) module: {{ parameter }}. Supported parameters include: warn, executable, chdir, strip_empty_ends, _raw_params, removes, argv, creates, _uses_shell, stdin_add_newline, stdin."}

as the parameter became not resolved.


It might be possible via

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:

    module: shell
    parameter: cmd
    value: exit 1

  tasks:

  - copy:
      dest: dyn_task.yml
      content: |
        - {{ module }}:
            {{ parameter}}: {{ value }}

  - include_tasks: dyn_task.yml

resulting into an correct and expected output of

TASK [shell] *******************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "exit 1", "delta": "0:00:00.010517", "end": "2023-12-14 10:00:00.715979", "msg": "non-zero return code", "rc": 1, "start": "2023-12-14 10:00:00.705462", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}

but I would consider this as very bad practice here in this case and recommend to use such not at all. See What are the uses of Self Modifying Code (SMC)?


Summary

How to use loop items or variable as the parameter key for a module in Ansible?

To summarize the above description, either you can't or it is recommended not to do such.

And for completeness

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:

    components:
      - projects
      - inventory
      - applicatitons
      - credentials

  tasks:

  - copy:
      dest: export_awx_{{ item }}.yml
      content: |
        - name: Export AWX Config
          awx.awx.export:
            {{ item }}: []
            controller_host: ...
            controller_username: ...
            controller_password: ...
    loop: "{{ components }}"

  - include_tasks: export_awx_{{ item }}.yml
    loop: "{{ components }}"

whereby the dest path needs to be the path under in example /var/lib/awx/projects/.