It's very common for vanilla configurations files to have settings commented out in default configuration files. For example
#HEAP_SIZE=2g
How do I remove the comment character, "#" in this case, with the Ansible replace module?
- name: Uncomment out HEAP_SIZE
replace:
dest: //etc/some_path/app.conf
replace="what to put here to remove #???"
regex="#HEAP_SIZE=2g"
Resulting in
HEAP_SIZE=2g
You can use lineinfile for your task:
- name: Uncomment parameters
lineinfile:
dest: app.conf
regexp: (?i)^\s*#\s*({{ item }}.*)
line: \1
backrefs: yes
with_items:
- heap_size
- aNoThEr_setting
Simply:
replace: "HEAP_SIZE=2g"
You'd also want to make sure it's from the beginning of the line.
Generally for this use case lineinfile module fits better.
Related
I am trying to write a playbook to add log forwarder lines to syslog.conf on AIX.
The tasks looks like this:
- set_fact:
log_servers:
- "auth.info\t#10.10.10.100"
- "*.info\t#log.example.com"
- lineinfile:
path: /etc/syslog.conf
regexp: '^{{item}}'
line: '{{item}}'
loop: "{{log_servers}}"
The first line is inserted with no issues, but I get a Python exception when the second line is encountered because of the leading asterisk.
An asterisk can be anywhere else in the line, but not at the start of the line. And escaping with a backslash (\*.info\t#log.example.com) causes a JSON parsing error, and a double backslash (\\*.info\t#log.example.com) just inserts a backslash at the front of the line.
Any advice on how to get around this?
Your issue is coming from the fact that you are trying to use the same string for a regex (where you need to escape the star) and for the line to add (where you don't need to escape the star).
There is a way to resolve this, though, it is to use the builtin regex_escape filter.
And so, your two task should become:
- set_fact:
log_servers:
- "auth.info\t#10.10.10.100"
- "*.info\t#log.example.com"
- lineinfile:
path: /etc/syslog.conf
regexp: '^{{ item | regex_escape() }}'
line: '{{ item }}'
loop: "{{ log_servers }}"
I want to remove only 'fsck.mode=auto' from the following line using ansible.
foo bar foo.bar=hold fsck.mode=auto foo foo bar foo
The hosts, root user and other privileges are set up else where in the project.
I prefer to use lineinfile if possible over replace. I don't want to delete the whole line but rather only remove whats in the regexp with ''.
- name: remove fsck
lineinfile:
dest: /etc/grub2.cfg
regexp: 'fsck.mode=auto'
line: ''
- name: Replacing the square brackets and single quotes on new VM IP address in hosts
hosts: 127.0.0.1
connection: local
become: true
tasks:
- name: Replacing the brackets from the end of the new ip with whitespace
replace:
path: /etc/ansible/hosts
regexp: \'\]
replace: ''
The above works for me to replace "']" with ''
edit: Just noticed you don't want to use 'replace' my bad. I believe you can use 'state=present' to replace using lineinfile
https://docs.ansible.com/ansible/2.4/lineinfile_module.html Take note of the 'backrefs' option
I think you are interested in backrefs. The code below does what you need. You can also play with white spaces if you want
- name: Change match only
lineinfile:
path: /whatever/file.txt
regexp: '^(. *)fsck.mode=auto (. *)$'
line: '\1\2'
backrefs: yes
Without those spaces between . and * (formatting piece of s>>t)
- name: Cassandra cassandra.yaml
lineinfile:
dest: "{{ home}}/conf/cassandra.yaml"
state: present
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
# backup: yes
with_items:
- { regexp: "data_file_directories:", line: "data_file_directories: \n - {{ data_directory }}" }
in the first file first run it looks good but in the second run it keeps adding new line. what needs to be done in order to the second run also looks good.
data_file_directories:
- /mount1/data
second run
data_file_directories:
- /mount1/data
- /mount1/data
- /mount1/data
I want some thing like
data_file_directories:
- /mount1/data
lineinfile ― as its name suggest ― is a module to ensure a certain line is in the target file; not lines.
To deal with multiple lines either:
use regexp module with matchgroup and backreference ― the exact implementation is dependent on other constructs in the target file,
use blockinfile module ― the exact implementation is dependent on other constructs in the target file,
or (preferably) use template module.
I'm new to Ansible and trying to modify a line in /etc/default/grub to enable auditing.
I need to add audit=1 within the quotes somewhere on a line that looks like:
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap biosdevname=0 net.ifnames=0 rhgb quiet net.ifnames=0"
So far I've managed to delete the line and am only left with
net.ifnames=0, audit=1
when I use something like
lineinfile:
state: present
dest: /etc/default/grub
backrefs: yes
regexp: "net.ifnames=0"
line: "\1 audit=1"
Can this be done?
You may try this:
- lineinfile:
state: present
dest: /etc/default/grub
backrefs: yes
regexp: '^(GRUB_CMDLINE_LINUX=(?!.* audit)\"[^\"]+)(\".*)'
line: '\1 audit=1\2'
This will add audit=1 (with a leading space) just before closing double quote. It will not match without double quotes.
And it tries to be idempotent: doesn't match lines that already have audit (with a leading space) after GRUB_CMDLINE_LINUX=.
I'd recommend to use sites like regex101 to test your regular expressions first (there's also a substitution mode there).
When you're satisfied with the result, proceed with the Ansible task.
I wanted to make sure the parameter is also set to the correct value, so I used this replace invocation:
replace:
path: /etc/default/grub
regexp: '^(GRUB_CMDLINE_LINUX=(?:(?![" ]{{ option | regex_escape }}=).)*"?)\s*(?:{{ option | regex_escape }}=\S+\s*)?(.*")$'
replace: '\1 {{ option }}={{ value }}\2'
vars:
option: audit
value: 1
This works if the option wasn't present previously, if it was but had the wrong option (only changes the value then) and if the whole string was empty (but adds a space before the option then). Also, it uses regex_escape to correctly work with option names that contain dots and the likes, and you only have to specify them once.
I'm using lineinfile as follows:
lineinfile dest=./hosts_exp insertafter='\[hosts1\]' line="xxxxxxxxx" state=present
My hosts_exp is as follows:
[local]
localhost
[hosts1]
[hosts2]
[hosts3]
lineinfile inserts the text after [hosts3] instead of inserting it after [hosts1].
use:
lineinfile:
dest: "./hosts_exp"
line: "xxxxxxxxx"
insertafter: '^\[hosts1\]'
state: present
It appears redundant, but you need to specify the regex too:
lineinfile:
dest: ./hosts_exp
insertafter: '\[hosts1\]'
regexp: '\[hosts1\]'
line: "xxxxxxxxx"
state=present
Why? The regexp says "look for this line". The insertafter says "inject the line here".
I tested this; here's the commit. There are a few minor changes in my commit from the line above, use as necessary.
example:
- name: "blah"
lineinfile:
dest: "/test.sh"
insertafter: 'test text'
line: "text add"
state: present
Use backrefs: yes
lineinfile:
backrefs: yes
dest: ./hosts_exp
insertafter: '\[hosts1\]'
regexp: '\[hosts1\]'
line: "xxxxxxxxx"
state=present
This flag changes the operation of the module slightly; insertbefore and insertafter will be ignored, and if the regexp doesn't match anywhere in the file, the file will be left unchanged. If the regexp does match, the last matching line will be replaced by the expanded line parameter.