Modifying PATH variable via Ansible - ansible

Below is the bash profile of the root user in my system.
[root#newvm-2 ~]# cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
I want to write a ansible code that will add the below path at the end of PATH in the bash_profile of root user:
/usr/edb/efm
eg: the new PATH will look like
PATH=$PATH:$HOME/bin:/usr/edb/efm

- lineinfile:
regexp: '^(PATH=.*)$'
backrefs: yes
line: '\1:/user/edb/efm'
path: '/root/.bashrc'
lineinfile manipulates individual lines in files.
regexp: '^(PATH=.*)$' says: Find the last line beginning with PATH= and remember the line. This also specifies which line will be changed.
backrefs: yes means that I can use that remembered line in the line I set.
line: '\1:/user/edb/efm' means take the first group the regex matched (the entire line in the () ) and write :/user/edb/efm behind it.
path: '/root/.bashrc' just specifies which file is manipulated, I guessed here, you probably know the right one.
This is just a single task, if you want a whole play for this just prepend
- hosts: all
tasks:
and indent everything once

Related

Rename file using ansible playbook on windows [duplicate]

This question already has answers here:
How to rename/move a file on a remote windows host with ansible?
(4 answers)
Closed last month.
Looking at rename file using ansible playbook on windows with below option, but is leading to below error.
Tried few mix match with " and ' but no luck in getting it sorted.
Kindly suggest correct way of handling on windows machine.
- name: Rename foo.bar
win_command: 'cmd.exe /c rename 'C:\windows\some\path\foo.bar' foo.zzz'
Error its leading to is per below :
^ here 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.
For instance, if the original line was:
copy: src=file.txt dest=/path/filename:with_colon.txt
It can be written as:
copy: src=file.txt dest='/path/filename:with_colon.txt'
Or:
copy: 'src=file.txt dest=/path/filename:with_colon.txt'
Looks like there is no viable option with copy on local machine using win_command.
Ended up implementing same with copy to different file name with win_copy & removing original file with win_file to achieve effective result of renaming file!
- name: Rename foo.bar
win_copy:
src: C:\windows\some\path\foo.bar
dest: C:\windows\some\path\foo.zzz
remote_src: yes
- win_file:
path: C:\windows\some\path\foo.bar
state: absent

How to empty a directory using ansible

I have some directories and files inside a directory called dir1
I am trying to empty that directory using the below code
- name: Clean path
file:
state: absent
path: "/home/location/dir1"
But it is deleting the dir1 itself, i would like to empty it and keep this dir1, what am i missing here, any help on this would be appreciated.
You can try to use a command instead.
- name: Clean path
command: rm -r /home/location/dir1/*
To empty a directory you can use the shell module to run rm with a fileglob:
- name: empty directory
shell: rm -r /home/location/dir1/*
Note that if your directory contains hidden dotfiles, you'll need to explicitly remove those as well:
- name: empty directory containing hidden files
shell: rm -r /home/location/dir1/* /home/location/dir1/.*
Your provided task isn't doing what you want because you're declaring that the directory should be absent, so it gets completely removed rather than emptied.
The command module won't work for the rm because it will not expand file globs, resulting in an error like:
rm: cannot remove '/home/location/dir1/*': No such file or directory
Why not remove the directory with the same task you're using, and re-add it immediately after using the same module? Seems like the most straightforward way to me. You could do some stuff with fileglob and with_items but that seems like over complicating a simple task.
- name: Remove folder
file:
state: absent
path: "/home/location/dir1"
- name: Re-make folder
file:
state: directory
path: "/home/location/dir1"

Want to insert a text in a file beforealine using lineinfile in ansible playbook

I need to add a text before the end of a parameter in file. I need to insert my text just before </abc>. I am using lineinfile and it enters the text before <abc> and not </abc>.
My current text file :
<domain-log-broadcast-filter>MultiDataSourceLogFilter</domain-log-broadcast-filter>
<abc>Info is already here. i just need to append the text at end of this parameter. new values to be inserted here</abc>
My Playbook :
- lineinfile:
path: /tmp/tochange.xml
insertbefore: '\<\/abc\>'
line: "Tisisthelinetobeinsertedbyme"
state: present
My Output for this is :
<domain-log-broadcast-filter>MultiDataSourceLogFilter</domain-log-broadcast-filter>
Thisisthelinetobeinsertedbyme
<abc>Info is already here. i just need to append the text at end of this parameter. new values to be inserted here</abc>
Now i have 2 requirements :
I want to insert my text just before </abc>
I have 4 </abc> parameters in my file. I want to ignore the first </abc> and the line is to be inserted before other 3 </abc> parameters.
Please sugest me a best way to do it, all i need is this work to be done, with any modules any script in the playbook. Thanks in advance.
Q: "... with any modules any script in the playbook."
A: Ansible file modules are not able to do it. You'll need the module command or shell to run file editing tools like sed or awk.
Module lineinfile is not able not to fulfill the requirements. This module modifies single lines in a file. It's not possible to change 3 out of 4 lines that match regexp. Neither replace nor blockinfile modules will help you either, I'm afraid. The module template modifies whole files. The next option might be the module patch.
Quoting from lineinfile:
"... For other cases, see the copy or template modules."

Is it safe to edit /etc/sudoers with the Ansible "lineinfile" module?

I want to change sudo session timeout according to this answer. I can edit ordinary file:
lineinfile:
path: /etc/sudoers
regexp: ^Defaults env_reset
line: Defaults env_reset,timestamp_timeout=60
But in first line of my /etc/sudoers written: # This file MUST be edited with the 'visudo' command as root. How to deal with it?
P.S.
Despite the fact that the short answer is yes, one must read Konstantin Suvorov answer about right way to do it with lineinfile and very interesting techraf answer about possible pitfalls on this way
There's a safenet option for such cases: validate.
The validation command to run before copying into place. The path to the file to validate is passed in via '%s' which must be present as in the example below. The command is passed securely so shell features like expansion and pipes won't work.
If you look at the examples section of lineinfile module, you'll see exactly what you need:
# Validate the sudoers file before saving
- lineinfile:
path: /etc/sudoers
state: present
regexp: '^%ADMIN ALL='
line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
validate: '/usr/sbin/visudo -cf %s'
It's safe if you've tested the syntax to be correct.
The point of encouraging visudo is to prevent someone from locking themselves out from administering a system by creating an invalid /etc/sudoers, whether by a typo or a thinko.
When you're using Ansible to perform an edit, you can test the code performing that edit to do the right thing with your actual config files, environment, and version of sudo before you roll it out. Thus, the concerns about people making a typo or a syntax error by hand aren't immediately relevant.
While this answer defines things correctly and this one provides a mitigation to potential problems, let's look at your code.
You ask Ansible to (potentially) replace the line defined in the following way:
regexp: ^Defaults env_reset
This is clearly a bad practice and if repeated for a parameter other than Defaults in sudoers file, it is likely to cause a critical problem.
Generally Defaults is the configuration parameter and env_reset is one of possible values.
You cannot assume that the actual configuration file will always contain ^Defaults env_reset string.
If there was a different value set, the regexp wouldn't match and you'd end up adding a second line starting with Defaults.
So the proper way to use lineinfile is to use regexp argument to match only the configuration parameter, not its value. In your case:
regexp: ^Defaults
line: Defaults env_reset,timestamp_timeout
The other potential pitfall is that sudoers contain sections which should be written in proper order. If the file you modify does not contain the line specified by the regular expression, lineinfile will add a new line to the end of the file, where it might get ignored, or result in an error (but that should be discovered by validation), and most likely cause confusion if human looked at the file later. So it might be wise to specify insertafter or insertbefore.
I think what you are missing is that in order to edit /etc/sudoers you need sudo-access. To do this in Ansible, you just need to add the become flag.
name: Change Sudo Timeout
become: yes
lineinfile:
path: /etc/sudoers
regexp: ^Defaults env_reset
line: Defaults env_reset,timestamp_timeout=60
Instead of directly editing the /etc/sudoers you can place your desired setting into the /etc/sudoers.d directory like this:
- name: Change sudo session timeout
lineinfile:
dest: /etc/sudoers.d/ssh_session_timeout
line: 'Defaults env_reset,timestamp_timeout=60K'
create: yes
owner: root
group: root
mode: "0440"
state: present
validate: 'visudo -c -f %s'

ansible before insert not creating duplicate record in the second run?

in ansible I'm trying to add a line before '' infile. iam using insert before. it is working as expected. but when ever i ran second time its not creating the duplicate entry of " '" this is also as expected but my concern is i havent mentioned any where not to duplicate in second run why is noot adding the line again
- name: Change the Log Level for log in path/logback.xml
lineinfile:
dest: "path/logback.xml"
line: ' <logger name="org.log" level="DEBUG"/>'
insertbefore: '</configuration>'
backup: yes
lineinfile module doesn't add duplicates, it ensures that specified line is present in the file.
If line is not there, Ansible will add it before insertbefore pattern.
So, if the line is added on the first run, Ansible will do nothing on the second run – it's idempotence in action.

Resources