Search code examples
ansibleansible-facts

Ansible: How to use Jinja2 variable as dynamic YAML key?


I would like to create a dynamic YAML key name for the HTTP header of uri module within the task.

playbook.yml

- name: "Set variable"
  set_fact:
    ACCESS_TOKEN_TYPE: "TEST-TOKEN"

- name: Check API
  ansible.builtin.uri:
    url: "https://my-url.com"
    headers:
      "{{ ACCESS_TOKEN_TYPE }}": "my-token"

But the substitution doesn't work. It works, when I replace "{{ ACCESS_TOKEN_TYPE }}" with "TEST-TOKEN".

The result content should be:

headers:
  "TEST-TOKEN": "my-token"

Solution

  • You may have a look into the following similar Q&A about

    YAML does not support dynamic keys in any circumstance

    and the following minimal example playbook

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        ACCESS_TOKEN_TYPE: "TEST-TOKEN"
    
      tasks:
    
      - name: Check Example API
        ansible.builtin.uri:
          url: "https://example.com"
          method: GET
          headers: >-
            {{
              {
                ACCESS_TOKEN_TYPE: "my-token"
              }
            }}
          return_content: true
        register: result
    
      - debug:
          var: result
    

    called via

    ansible-playbook uri.yml -vvv # to get the invocation and module_args used
    

    resulting into an output of

    TASK [Check Example API] *********************
    task path: /home/user/test/uri.yml:12
    ok: [localhost] => changed=false
    ...
      invocation:
        module_args:
          attributes: null
          body: null
          body_format: raw
          ca_path: null
          client_cert: null
          client_key: null
          creates: null
          dest: null
          follow_redirects: safe
          force: false
          force_basic_auth: false
          group: null
          headers:
            TEST-TOKEN: my-token
          http_agent: ansible-httpget
          method: GET
          mode: null
          owner: null
          remote_src: false
          removes: null
          return_content: true
          selevel: null
          serole: null
          setype: null
          seuser: null
          src: null
          status_code:
          - 200
          timeout: 30
          unix_socket: null
          unsafe_writes: false
          url: https://example.com
          url_password: null
          url_username: null
          use_gssapi: false
          use_proxy: true
          validate_certs: true
      last_modified: Thu, 17 Oct 2019 07:18:26 GMT
      msg: OK (2815 bytes)
      redirected: false
      server: ECS (dcb/7F83)
    ...
      status: 200
      url: https://example.com
      vary: Accept-Encoding
      x_cache: HIT
    
    TASK [debug] *********************************
    task path: /home/user/test/uri.yml:29
    ok: [localhost] =>
      result:
    ...
        content: |-
          <!doctype html>
          <html>
          <head>
              <title>Example Domain</title>
    ...
          </head>
    
          <body>
          <div>
              <h1>Example Domain</h1>
              <p>This domain is for use in illustrative examples in documents. You may use this
              domain in literature without prior coordination or asking for permission.</p>
              <p><a href="https://www.iana.org/domains/example">More information...</a></p>
          </div>
          </body>
    ...
    

    and containing the requested dynamic token type

          headers:
            TEST-TOKEN: my-token
    

    Some Documentation

    and in order to get

      invocation:
        module_args:
    

    for this example.