I’ve been playing around with ansible a lot lately, and I noticed that while changing stuff from “installed and configured manually” to “installed and configured by ansible” I was running into quite a few configuration files that needed to be manually turned into templates. It can be quite tedious to replace values in a configuration file with placeholders and put all those placeholders in a .yml file with default values.
Automating this is something I would have typically done in perl, but since I wanted to learn more about using regex in bash I decided to have a go at it in bash using regex and ${BASH_REMATCH}
The script takes a configuration file and spits out an ansible template, as well as the variable definitions you will need to add to your defaults/main.yml or vars/main.yml
The whole script is a bit to long to post here, but the interesting part is:
1 2 3 4 5 6 | if [[ ${line} =~ ^([^#][^\ ]+)[\ ]*[${Separator}][\ ]*([^\ ]+)$ ]] ; then VariableName="${Prefix}_${BASH_REMATCH[1]//-/_}" # create a name for this configuration variable VariableName="${VariableName,,}" # make lowercase sed -ri "s/^(${BASH_REMATCH[1]}[\ ]*[${Separator}][\ ]*).+$/\1{{ ${VariableName} }}/" "${Template}" # change the ansible template printf "%-40s %s\n" "${VariableName}:" "'${BASH_REMATCH[2]}'" # print variable info to stdout fi |
(You can download the full script here ansible_template.sh).
You can use regular expressions in a [[ ]] with =~ (e.g. if [[ “boot” =~ ^b ]]), and you can access the result of the regular expression by using ( ) to mark what parts of the result to store and access them via $BASH_REMATCH (comparable to how you would do it for other languages). Here I am parsing out anything that looks like a key=value from the configfile (with multiple possible separators) and storing the results in BASH_REMATCH[1] and BASH_REMATCH[2]
Usage of the script is pretty straightforward. you give it a prefix for the variable names (so you don’t end up with multiple roles all using a common variable name like “port”), and either a local or remote file to work with, and it spits out something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $ ./ansible_template.sh php webserver.somewhere.tld:/etc/php5/conf.d/xcache.ini - name: Template template: src={{ item.local }} dest={{ item.remote }} owner={{ item.owner }} group={{ item.group }} mode={{ item.mode }} with_items: - { local: 'xcache.ini.j2', remote: '/etc/php5/conf.d/xcache.ini', owner: 'root', group: 'root', mode: '0644' } php_zend_extension: '/usr/lib/php5/20090626/xcache.so' php_xcache.admin.enable_auth: 'On' php_xcache.admin.user: 'admin' php_xcache.admin.pass: 'ea6299af10b40ba80236a0f015ed627d' php_xcache.shm_scheme: 'mmap' php_xcache.size: '16M' php_xcache.count: '1' php_xcache.slots: '8K' php_xcache.ttl: '0' |
There a tons of different configuration file formats out there so this script won’t work perfectly 100% of the time, but it does do quite well and reduces the manually copy&pasting to a minimum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | $ cat xcache.ini.j2 ; configuration for php Xcache module [xcache-common] zend_extension = {{ php_zend_extension }} [xcache.admin] xcache.admin.enable_auth = {{ php_xcache.admin.enable_auth }} xcache.admin.user = "{{ php_xcache.admin.user }}" xcache.admin.pass = "{{ php_xcache.admin.pass }}" [xcache] xcache.shm_scheme = "{{ php_xcache.shm_scheme }}" xcache.size = {{ php_xcache.size }} xcache.count = {{ php_xcache.count }} xcache.slots = {{ php_xcache.slots }} xcache.ttl = {{ php_xcache.ttl }} ... |