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:
- key-value.cfg.bak – sample config file
- test-lineinfile.yml – local playbook for doing regex lineinfile replacement
- test-ansible-lineinfile.sh – script that executes local playbook
REFERENCES
ansible.com, lineinfile documentation
wiredgorilla.com, replacing strings and lines with ansible