Ansible: lineinfile with regex to robustly populate key/value pairs in config file

If your Ansible automation includes modifying an existing configuration file (versus managing your own fully templatized version of the config), then you will need to account for variations in that existing file when using ‘lineinfile‘ for key/value pairs.

A naive lineinfile replacement will not find commented-out keys and might not even find valid keys that do not exactly match the expected spacing, and will simply append to the existing file.  Using a proper regex can avoid this problem.  Assume a sample config file such as:

# spacing variations
thiskey1=thisvalue1
thiskey2 = thisvalue2
thiskey3 =thisvalue3

# comment variations
#thiskey4 = thisvalue4
# thiskey5 = thisvalue5
## thiskey6 = thisvalue6

This has various spacing patterns and comment variations.  In order to intelligently find these keys a proper regular expression is required.

- name: Replace values in config file
  lineinfile:
    state: present
    path: ./key-value.cfg
    regexp: '^[# ]*{{ item.search }}\s*=\s*'
    line: '{{ item.replace }}'
  with_items:
    - { search: 'thiskey1', replace: 'thiskey1 = NEWthisval1' }
    - { search: 'thiskey2', replace: 'thiskey2 = NEWthisval2' }
    - { search: 'thiskey3', replace: 'thiskey3 = NEWthisval3' }
    - { search: 'thiskey4', replace: 'thiskey4 = NEWthisval4' }
    - { search: 'thiskey5', replace: 'thiskey5 = NEWthisval5' }
    - { search: 'thiskey6', replace: 'thiskey6 = NEWthisval6' }
    # keys that do not exist get created
    - { search: 'thiskey7', replace: 'thiskey7 = INSthisnewval7' }

This regular expression takes into account keys that start with whitespace or comments.

Run through an ansible playbook, this results in a file that looks like:

# spacing variations
thiskey1 = NEWthisval1
thiskey2 = NEWthisval2
thiskey3 = NEWthisval3

# comment variations
thiskey4 = NEWthisval4
thiskey5 = NEWthisval5
thiskey6 = NEWthisval6

thiskey7 = INSthisnewval7

If you have Ansible installed and want to test on a local playbook, download my files here:

 

REFERENCES

ansible.com, lineinfile documentation

wiredgorilla.com, replacing strings and lines with ansible