Search code examples
ansible

Dynamically load environment variables from config file in Ansible


I have the following (simplified) play:

- hosts: testing

  roles:
     - nginx
  vars_files:
     - config.yml
  environment:
    http_proxy: http://proxy.example.com:8080

Now, when I run my code, I can read process.env.http_proxy. I would however like to be able to set other environment variables dynamically under environment. For example, in my config.yml I have the following:

application_variables:
  - key: "NODE_ENV"
    value: "production"
  - key: "PORT"
    value: "3000"

How would I get the values from application_variables to be dynamically created under environment? I've tried a few different solutions I found out there to no avail.


Solution

  • You can feed the environment parameter from a templated Jinja expression, in your case:

    environment: "{{ application_variables | items2dict }}"
    

    Then you have the choice to:

    • either add the HTTP proxy variable to your application_variables list:
      application_variables:
        - key: http_proxy
          value: http://proxy.example.com:8080
        - key: NODE_ENV
          value: production
        - key: PORT
          value: 3000
      
    • or combine the dictionary created from the application_variables with a variable defined at the in your playbook:
      - hosts: testing
      
        environment: >-
          {{ 
            default_env | combine(
              application_variables | items2dict
            )
          }}
        vars:
          default_env:
            http_proxy: http://proxy.example.com:8080
      

    As an example, the playbook:

    - hosts: localhost
      gather_facts: true
    
      environment: >-
        {{ 
          default_env | combine(
            application_variables | items2dict
          ) 
        }}
      vars_files: config.yml
      vars:
        default_env:
          http_proxy: http://proxy.example.com:8080
    
      tasks:
        - debug:
            msg:
              http_proxy: "{{ ansible_facts.env.http_proxy }}"
              NODE_ENV: "{{ ansible_facts.env.NODE_ENV }}"
    

    Would give you:

    ok: [localhost] => 
      msg:
        NODE_ENV: production
        http_proxy: http://proxy.example.com:8080