Ansible Advanced lineinfile

By on

Ansible is great, it’s really simple to setup and easy to use. There are still some hidden tricks that can make your workflow more efficient.

I was setting up new machines with PHP-FPM support. I’d like to change several FPM parameters using Ansible, you can copy (transfer) the whole configurations from your Ansible task to remote machines via synchronize or template, it’s fast but you can’t handle config changes from program updates. So my idea is dynamically replace the parameters I want to change via lineinfile:

After googling around, I found this answer by Ben Whaley fit the bill:

- name: Set some kernel parameters
    dest: /etc/sysctl.conf
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
    - { regexp: '^kernel.shmall', line: 'kernel.shmall = 2097152' }
    - { regexp: '^kernel.shmmax', line: 'kernel.shmmax = 134217728' }
    - { regexp: '^fs.file-max', line: 'fs.file-max = 65536' }

That snippet works but it’s tedious. regexp and line has the duplicated parameter key names, let’s clean up the code:

- name: set PHP-FPM parameters
    dest: /etc/php-fpm.conf
    regexp: "^{{ item.param }}"
    insertafter: "^;{{ item.param }}"
    line: "{{ item.param }} = {{ item.value }}"
    - { param: 'error_log', value: '/var/log/php-fpm/error.log' }
    - { param: 'log_level', value: 'error' }
    - { param: 'emergency_restart_threshold', value: '10' }

Everything works fine untill I meet the following config:

php_value[session.save_handler] = 'files'

I can’t target keys like this with previous regexp, and cannot match square brackets directly or Ansible will fall running this task. So I have to escape speciall characters:

- name: set PHP-FPM pool parameters
    dest: /etc/php-fpm.d/www.conf
    regexp: '^{{ item.param|replace("[", "\[")|replace("]", "\]") }} *?='
    insertafter: '^;{{ item.param|replace("[", "\[")|replace("]", "\]") }} *?='
    line: "{{ item.param }} = {{ item.value }}"
    - { param: 'php_value[session.save_handler]', value: 'memcache' }
    - ...

Cool for the summer.