Ansible replace all values with matching variable name

5,102

Solution 1

The ini_file module might be used.

The task below

- ini_file:
    path: /scratch/testenvironment.ini
    section: "{{ item.key.split('--').0 }}"
    option: "{{ item.key.split('--').1 }}"
    value: "{{ item.value }}"
  loop: "{{ testenvironment|dict2items }}"

gives

$ cat /scratch/testenvironment.ini 

[sectionheader2]
keyname1 = value2
[sectionheader1]
keyname1 = value1

If the sections shall be alphabetically sorted use

 loop: "{{ testenvironment|dict2items|sort(attribute='key') }}"

Solution 2

With an appropriate setup template you should be able to set everything with a dict.
A .ini is in essence a 2 depth dict, so we're just going to treat it as such using 2 nested jinja2 for loops in a .j2 template.

In this example I'm setting the env variable on the commandline for compactness, but it can be set in inventory, host_vars, or group_vars files.

ansible/example.yml

---
- hosts: localhost
  gather_facts: false
  vars:
    dev:
      section1:
        key1: value1
      section2:
        key1: value1
    prod:
      section1:
        key1: value2 #(specific to prod)
      section2:
        key1: value2 #(specific to prod)
  tasks:
    - template: src=example.ini.j2  dest=/tmp/ansible.ini

ansible/templates/example.ini.j2

{% for section in vars[vars.env] %}
[{{section}}]
{% for key in vars[env][section] %}
{{key}}={{vars[env][section][key]}}
{% endfor %}
{% endfor %}

.

$ ansible-playbook ansible/test.yml -e env=dev; cat /tmp/ansible.ini

PLAY [localhost] ********************************************************************************************************************************************

TASK [template] *********************************************************************************************************************************************
changed: [localhost]

PLAY RECAP **************************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[section1]
key1=value1
[section2]
key1=value1

.

$ ansible-playbook ansible/test.yml -e env=prod; cat /tmp/ansible.ini

PLAY [localhost] ********************************************************************************************************************************************

TASK [template] *********************************************************************************************************************************************
changed: [localhost]

PLAY RECAP **************************************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[section1]
key1=value2
[section2]
key1=value2
Share:
5,102

Related videos on Youtube

user3066571
Author by

user3066571

Updated on September 18, 2022

Comments

  • user3066571
    user3066571 over 1 year

    I'm a noob to Ansible, and could be going the wrong way about this, but this is the only way I know how to deal with this problem.

    I have an ini file that's 4000 someodd entries long. In an attempt to do configuration as code, I have extracted out the values of each entry out into a variable file in the format of sectionheader--keyname: originalvalue and replaced them with a token pattern and the name of the variable that now contains their value.

    I know Ansible can do regex replacement, but haven't been able to find a way that can do it as dynamically as this.

    original file:

    [sectionheader1]
    
    keyname1=value1
    
    [sectionheader2]
    
    keyname1=value2
    

    file with token replacements now kept in source and deployable:

    [sectionheader1]
    
    keyname1=%<sectionheader1--keyname1>
    
    [sectionheader2]
    
    keyname1=%<sectionheader2--keyname1>
    

    variables:

    testenvironment:
      sectionheader1--keyname1: value1
      sectionheader2--keyname1: value2
    prodenvironment:
      sectionheader1--keyname1: value1 (specific to prod)
      sectionheader2--keyname1: value2 (specific to prod)
    

    And then the idea is, I would replace every occurence of the token pattern %<> that I find a matching variable name for, and viola, I've constructed my config file specific to the environment I'm operating in. And now, I can check and if I have any lingering %<> patterns, I know that not all of the variables were defined, and can throw an error. Octopus deploy handles variable replacement in config files this way, which is what I have the most experience with.

    Does Ansible have any way of doing this? I could write a script to do it I suppose and just have Ansible call that, but I was hoping for a built in way of configuration variable replacement as code.

    • HBruijn
      HBruijn almost 5 years
      I think that you’re looking for the Ansible template function and the jinja2 templating syntax