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:
|
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 }}
...
|