Remove a line from a file using ansible? - ansible

I have a file called authorized_keys. I need to delete a particular line using an Ansible script.
The problem is when I try to remove a line that includes a '+' character. Ansible is not able to remove this line.
e.g authorized_keys file is:
.....
abhi foo+bar saken
......(EOF)
I want to remove the abhi foo+bar saken line but Ansible is not removing this line because of the + character.
I am able to remove lines that do not contain a + character .
Task:
- name: Delete keys in sysadmin/.ssh/authoriezd_keys
lineinfile: dest=/home/{{name}}/.ssh/authorized_keys
state=absent
regexp='^{{key}}$'
PS: I am using Ansible's lineinfile module

The problem probably is that + has a meaning in a regular expression.
You should be able to fix it by escaping the +. If you can't do that from the source where {{ key }} is defined, you can escape it with the replace Jinja filter:
- name: Delete keys in sysadmin/.ssh/authoriezd_keys
lineinfile: dest=/home/{{name}}/.ssh/authorized_keys
state=absent
regexp='^{{ key | replace("+", "\+") }}$'
You might run into more problems if {{ key }} contains other characters which have a meaning in regular expressions. If that's the case I think the safe way would be to create your own filter plugin where you simply return the input passed through re.escape.

Related

Ansible/Jinja2 asterisk conditional

Trying to update a LDAP entry via Ansible, but I want to make sure that the LDAP host wildcard ("*") is not in the host list. If I use "*" not in hosts or '*' not in hosts, Ansible does not like those. I've also tried Jinja2 search filters. Any help would be great!
The problem has nothing to do with the asterisk. It is a pure yaml syntax problem
In yaml, if you quote a variable, the representation of the value will start with a single or double quote, then you get the value itself and the closing quote. After that, the yaml parser is expecting a yank <block end>, in your specific case a new line to move on to the next value definition.
In your example, your when clause value starts with a quote. So you have to quote your entire value:
when: '"*" not in hosts'
# or
when: "'*' not in hosts"
# even
when: "\"*\" not in hosts"
A good and more readable alternative IMO is to use a yaml scalar block marker:
when: >-
"*" not in hosts
Figured this out. Was trying to do it with pipes and didn't need to.
when:
- var is not regex("\\*")

Remove last three lines from file using ansible

I want to remove last three lines of file using ansible. I tried using lineinfile but it removed all the lines from file. I have posted below my file and ansible-playbook. I want to remove nfs_config, nfs_share and mount_path using lines using ansible.Thanks in advance.
file.txt
[images]
[tickets]
[unix sockets]
[nfs_config]
nfs_share=
mount_path=
Ansible-playbook
- name: Remove mount path from daemon.conf for clean-daemon
linefile:
path: /etc/ovirt-imageio-daemon/daemon.conf
regexp: "[nfs_config]"
state: absent
Use ini_file. The task below will remove the nfs_config section from the configuration file
- ini_file:
path: /etc/ovirt-imageio-daemon/daemon.conf
section: nfs_config
state: absent
regexp: "[nfs_config]" is not doing what you want, you need to use "[nfs_config]", otherwise you are matching any character that is between the []. This is why it's removing multiple lines.
https://docs.python.org/2/library/re.html
Also, just make 3 lineinfile command to match nfs_config, nfs_share and mount_path
You could use onee lineinifile with a complex regex to match them all, but it will be easier to read/maintain with 3 that are clear.

ansible syntax for lineinfile search and replace

My current etc/group wheel is setup as the following
wheel:x:10:admin,sshgroup,domaingroup
I need it be
wheel:x:10:admin4,sshlocal,domainusers,domainadmins
- name: add a string to the new file
lineinfile:
dest=/etc/group
backrefs=true
regexp='wheel:x:10:'
line='wheel:x:10:admin4,sshlocal,domainusers,domainadmins'
state = present
error:
The offending line appears to be:
line='wheel:x:10:admin4,sshlocal,domainusers,domainadmins'
state = present
^ here
I tried both with and without escaping : and commmas but to no avail. Can you please suggest. Im using ansible 2.2.1.0
Nevermind guys, playbook ran this time. I think last line where state = present is listed, i looked like used tab spaces instead of spaces for yaml. After I deleted that line and readded it with spaces, it works now.
cat /etc/group | grep wheel
wheel:x:10:admin4,sshlocal,domainusers,domainadmins
Apparently, single quote is good enough to escape: characters in YAML - which is good.

Ansible: repeated lines exists but update only specific occurrence

I have to change
`<!--<parameter name=\"HostnameVerifier\">DefaultAndLocalhost</parameter>-->`
to
<!--<parameter name=\"HostnameVerifier\">AllowAll</parameter>--> in APIM_HOME/repository/conf/axis2/axis2.xml.
I am using
- name: "Modify HostnameVerifier"
lineinfile:
dest: "/home/ec2-user/ansible-test/wso2am-2.0.0/repository/conf/axis2/axis2.xml"
state: "present"
line: "\t\t<parameter name=\"HostnameVerifier\">AllowAll</parameter>"
regexp: "<!--<parameter name=\"HostnameVerifier\">DefaultAndLocalhost</parameter>-->"
This is only replacing the 3rd occurrence of the regexp. I want it to replace only 2nd occurrence. How do I do that?
You can't do this with lineinfile. From the docs:
...only the last line found will be replaced...
And lineinfile iterates line-by-line – you can't add more context to it.
You should use replace module and add more context to the regexp to match exatly that part of file you want to modify. You can use multiline patterns here.

Using ansible lineinefile with colon in line

I am trying to make sure that a particular line is commented out in a source file.
The line is like this:
CFUNCTYPE(c_int)(lambda: None)
If it exists, I want to comment it out:
# CFUNCTYPE(c_int)(lambda: None)
If it doesn't exist, just ignore it.
If it exists and is already commented out, do nothing.
This is the playbook I wrote, but it doesn't work.
tasks:
- name: fix ctypes file
lineinfile: dest='/usr/local/lib/python2.7/ctypes/__init__.py' regexp="^#?CFUNCTYPE(c_int)(lambda: None)" line='# CFUNCTYPE(c_int)(lambda: None)'
The error says:
This one looks easy to fix. There seems to be an extra unquoted colon in the line
and this is confusing the parser. It was only expecting to find one free
colon. The solution is just add some quotes around the colon, or quote the
entire line after the first colon.
However, it is not easy to fix, and I've tried quoting it in every way I can think of, to no avail.
It's a YAML limitation; the parser likely wants to either see a name, colon, and name=value pairs with no more colons on the line, or just name, colon, and 1 quoted string value.
The lineinfile doc has an example for sudoers mentioning this (and another one further down that doesn't work...) and it references YAML as the problem. This means any time you need to have a colon in a value you may as well quote the entire string of arguments just to save yourself the debugging hassle.
I made it work with this quoting:
lineinfile: "dest='/usr/local/lib/python2.7/ctypes/__init__.py' regexp='^#?CFUNCTYPE(c_int)(lambda: None)' line='# CFUNCTYPE(c_int)(lambda: None)'"
In order to ignore a file that doesn't exist, I used this code:
- stat: path=/usr/local/lib/python2.7/ctypes/__init__.py
register: init
- name: fix ctypes file
replace: "dest='/usr/local/lib/python2.7/ctypes/__init__.py' regexp='^( CFUNCTYPE.c_int..lambda: None.)' replace=' # CFUNCTYPE(c_int)(lambda: None)'"
when: init.stat.exists == True
sudo: yes
I also had to change lineinfile to replace, because the line is prefixed with 4 spaces, and I couldn't get it to match correctly.

Resources