'Ansible: lineinfile module using regexp and backrefs
I am trying to ensure that a line ends with 'audit=1"'. The before state is:
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg00/lv_root rhgb quiet"
The after state should be:
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg00/lv_root rhgb quiet audit=1"
Working with the Ansible lineinfile module I can add that statement if its missing, but repeated runs keep appending 'audit=1"' even if it's present. I have been playing with the regexp and negative look-ahead assertions, and just cannot get the syntax correct.
Here is example play I have:
- name: grub - adjust
lineinfile:
path: /home/vwadmin/grub-test
regexp: '(GRUB_CMDLINE_LINUX=.*)"(?!audit=1")'
line: '\1 audit=1"'
backrefs: yes
state: present
Edit: Using Pacifist's suggestion I have a working solution. Confirmed to add my audit=1 statement if missing, and do nothing if present.
- name: grub - check
shell: grep -c 'audit' /etc/default/grub
register: grub_file
ignore_errors: true
- name: grub - adjust
lineinfile:
path: /etc/default/grub
regexp: '(GRUB_CMDLINE_LINUX=.*)"'
line: '\1 audit=1"'
backrefs: yes
state: present
when: grub_file.stdout == "0"
Note: I can't help but feel the reason I couldn't get it working without a pre-step, and why it doesn't work properly with check_mode, is that the negative look-ahead is not defined correctly for this case. From what I understand, the regexp match should fail when the negative look-ahead succeeds, which should cause the module to not take action. Looking at another example of this on GG I am wondering if root issue is the greedy nature of the .* wildcard in the first group match. /shrug
Solution 1:[1]
i wanted to do something similar with console kernel options and ended up with this:
- name: "Ensure console kernel options are set"
lineinfile:
path: /etc/default/grub
regexp: ^GRUB_CMDLINE_LINUX=\"(?P<defaults>.*?)\s*(?P<console> console=.*)?\"$
line: GRUB_CMDLINE_LINUX="\g<defaults> {{ kernel_console }}"
backrefs: yes
register: grub_changed
- name: "Rebuild grub"
command: grub2-mkconfig –o /boot/grub2/grub.cfg >/dev/null
when:
- grub_changed.changed
the key part of the regexp is (?P<defaults>.*?): the last question mark - which makes the match less greedy, allows the optional console=.* to be picked up without continually appending another console to the end of the line in the line as it did with your audit. main issue is that it assumes that its always the last (set of) options in the line and i always end up with a white space if there is no console defined. but it works!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | yee379 |
