Ansible replace text in file - ansible

So ive been tasked with replaceing zabbix server. To do so i have to modify zabbix_agent file in all server and there are many. Tho in this job is the first time i see ansible so i need some help. And i am using ansible-playbook.
In zabbix_agentd.conf file there is the old zabbix conf:
HostMetadata=Linux
PidFile=/var/run/zabbix/zabbx_agentd.pid
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=0
Server=zabbix.company.com
ServerActive=zabbix.company.com
HostnameItem=system.hostname
Include=/etc/zabbix_agentd.d/
Now i need to replace "Server" and "ServerActive" to "zabbix2.company.com"
I have tried various codes from this page to work for my needs but so far it has failed. No clue what im doing wrong

Try this one
- lineinfile:
path: /etc/zabbix_agentd.conf
regexp: '^\s*{{ key }}\s*=(.*)$'
line: '{{ key }}={{ value }}'
notify: reload zabix
loop:
- {key: 'Server', value: 'zabbix2.company.com'}
- {key: 'ServerActive', value: 'zabbix2.company.com'}
Notes
Path is required; probably /etc/zabbix_agentd.conf ?
It is not necessary to search the white-space \s* in regexp. However, it would match and fix potential spaces in the configuration.
Create and notify a handler reload zabix when anything changed. See Handlers: Running Operations On Change.
Take a look at Zabix modules.

I have manged to solve this issue using this code.
---
tasks:
- name: 'replace line'
lineinfile:
dest: /etc/zabbix/zabbix_agentd.conf
regexp: '^(.*)Server=zabbix.company.com(.*)$'
line: 'Server=zabbix2.company.com'
backrefs: yes

Related

Adding asterisk (*) to configuration file with Ansible lineinfile module

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 }}"

Modify delete a line using ansible

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)

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
lineinfile is doing its work that is adding whatever is given in line and line is identified by your regexp. So no matter what value your setting already has, it will be overridden by your new line.
There are two approaches that you can use :
Using check_mode with failed_when.
Using shell module to grep the content beforehand.
Check_Mode (I can not get this working though but it has been recommended everywhere else):
- name: grub - adjust
lineinfile:
name: /home/vwadmin/grub-test
regexp: '(GRUB_CMDLINE_LINUX=.*)'
line: '\1 audit=1"'
backrefs: yes
state: present
check_mode: yes
register: presence
failed_when: presence.changed
Using grep (This one is working fine for me)
- name: grub - adjust
shell: grep -c 'audit' /home/vwadmin/grub-test
register: file
ignore_errors: true
- name: Present
debug: msg="audit is present"
when: file.stdout != "0"
- name: Not Present
debug: msg="audit is not present"
when: file.stdout == "0"
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!

Ansible looping when a variable has no value

I have created a variable to disable sites in nginx within my main set of tasks. Since this is a one time task, meaning once domain1.com is disabled I can comment the entire line out. When I do, I receive an error
" {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'None' has no attribute 'domain'".
What can I do to modify my task to only run when there are domains listed within the variable?
nginx_sites_disabled:
#- domain: "domain1.com"
- name: Disable sites
file:
path: /etc/nginx/sites-enabled/{{ item.domain }}
state: absent
with_items: "{{nginx_sites_disabled}}"
notify:
- Reload nginx
Apply default filter within your task:
- name: Disable sites
file:
path: /etc/nginx/sites-enabled/{{ item.domain }}
state: absent
with_items: "{{ nginx_sites_disabled | default([]) }}"
notify:
- Reload nginx
Related answer: Ansible: apply when to complete loop
You don't need to comment out the lines when the work is done.
Like most of Ansible modules, file module is idempotent : if the desired state is absent and the file isn't there, it won't do anything.
Just leave nginx_sites_disabled list unchanged.
By the way, if you still need nginx_sites_disabled to be an empty list, you need to write this :
---
nginx_sites_disabled: []
otherwise, nginx_sites_disabled will be equal to None. That's why you have this error.

using {{item}} inside a regexp in a lineinfile task of Ansible

I have a task in an Ansible playbook that is supposed to iterate with a list of users and do a lineinfile to enable access to a postgress database:
- name: Postgres localhost access
lineinfile:
dest: "{{postgres_dest}}/data/pg_hba.conf"
line: "host all {{item.user}} 127.0.0.1/32 trust"
regexp: "^host[\s\t]*all[\s\t]*{{item.user}}[\s\t]*127.0.0.1/32[\s\t]*trust"
insertbefore: EOF
with_items: "{{postgres_users}}"
notify: postgres reload
tags:
- postgres
- postgres_hba
the problem I'm getting is that ansible thinks that the {{item.user}} is not being escaped with "", which actually is not true, since this will expand due to the "" of the whole line. The exact error I get:
Syntax Error while loading YAML script, jenkins.yml
Note: The error may actually appear before this position: line 156, column 9
line: "host all {{item.user}} 127.0.0.1/32 trust"
regexp: "^host[\s\t]*all[\s\t]*{{item.user}}[\s\t]*127.0.0.1/32[\s\t]*trust"
^
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
any ideas on how to do this?
first of all, thanks to the guys in IRC on the #ansible channel :)
seems that the issue wasn't with the vars itself but with the un-scaped backslashes
changed the line to:
regexp: "^host[\\s\\t]*all[\\s\\t]*{{item.user}}[\\s\\t]*127.0.0.1/32[\\s\\t]*trust"
and now it works great

Resources