Ansible - win_file module - force deletion if file in use - windows

We are using ansible win_file module to delete a particular folder in a Windows Server machine with the following code:
- name: Delete <folderName> directory
win_file: path=C:\<pathToFolder>\{{target_environment}}\<folderName> state=absent
tags: <folderName>
The problem: When a file from that directory is open in another program at the same time the ansible role runs, it fails saying:
"The process cannot access the file because it is being used by another process"
Now, i understand the error, but i am looking for suggestions to force this deletion, even if the file is in use, or if there is other module that i don't know that can't resolve this problem.
(currently using ansible 2.4.6)

So, after some searching and digging, i came out with a solution, i found a similar ansible module that can do the job, win_shell.
I resolved the problem with the following code:
name: Delete <folderName> directory
win_shell: Remove-Item –path <folderName> –recurse -force
args:
chdir: C:\<pathToFolder>\{{target_environment}}
removes: C:\<pathToFolder>\{{target_environment}}\<folderName>
tags: <folderName>
removes: checks if the folder exists else skips the task
force: does the trick of what i want, delete the folder and all his files even if some of the files are in use or open in any program.

Related

Create a sym link in ansible

I'm writing a playbook and i want to create a symlink.
While installing citrix on the linux system i need to create a sym link using this command:
ln -s /etc/ssl/serts cacerts
now in the playbook i use it as a :
- name: Link
command: ln -s /etc/ssl/serts cacerts
The thing is when I use the format above it works fine. But if I want to check if the file exists and if not creating and if yes then skip to the next task.
I could use ignore_errors: yes but I think there is a better way of doing it.
Thank you very much in advance.
You can use the "file" module:
- name: Link
file:
src: cacerts
dest: /etc/ssl/serts
state: link
It is generally better to use a proper module which will deal with failure conditions and check mode. In this case, it will not fail if the link already exists and it is correct.
You may want to give an absolute src depending on your application.
For more information: https://docs.ansible.com/ansible/latest/modules/file_module.html

Ansible idempotency issue with unarchive and then modify extracted file

In one of the ansible roles we extract some tar.gz file and then we replace one of the extracted files with another one to fix some issue.
The problem is when we run ansible again, ansible is extracting the archive back again since the directory content is changed and naturally marking the task changed and also replaces the file again as expected.
So we have two "changes" now everytime we run the playbook...
How should I handle this issue to keep the operation idempotent?
Use exclude option to ignore certain paths, see documentation.
i.e.
- unarchive:
src: https://example.com/example.zip
dest: /usr/local/bin
remote_src: True
exclude: bad.config
creates might also suit you, unarchive step will not be run if specified path already exists on remote machine

Ansible synchronize mode permissions

I'm using an Ansible playbook to copy files between my host and a server. The thing is, I have to run the script repeatedly in order to upload some updates. At the beginning I was using the "copy" module of Ansible, but to improve performance of the synchronizing of files and directories, I've now switched to use the "synchronize" module. That way I can ensure Ansible uses rsync instead of sftp or scp.
With the "copy" module, I was able to specify the file's mode in the destination host by adding the mode option (e.g. mode=644). I want to do that using synchronize, but it only has the perms option that accepts yes or no as values.
Is there a way to specify the file's mode using "synchronize", without having to inherit it?
Thx!
Finally I solved it using rsync_opts
- name: sync file
synchronize:
src: file.py
dest: /home/myuser/file.py
rsync_opts:
- "--chmod=F644"

How can I ensure that an Ansible shell command executes only once per host?

I want to be able to guarantee that after a long running shell command is executed successfully on a given host, it is not executed in subsequent playbook runs on that host.
I was happy to learn of the creates option to the Ansible shell task (see http://docs.ansible.com/ansible/shell_module.html); using this I can create a file after a shell command succeeds and not have that command execute in future runs:
- name: Install Jupiter theme
shell: wp theme install ~/downloads/jupiter-theme.zip --activate
&& touch ~/ansible-flags/install-jupiter-theme
args:
creates: ~/ansible-flags/install-jupiter-theme
As you can see, I have a directory ansible-flags for these control files in the home directory of my active user (deploy).
However, this is quite a kludge. Is there a better way to do this?
Also, the situation gets a lot more complicated when I need to run a step as a different user; in that case, I don't have access to the deploy home directory and its subdirectories. I could grant access, of course, but that's adding even more complexity. How would you recommend I deal with this?
Your playbook should be idempotent!
So either task should be safe to be executed multiple times (e.g. echo ok) or your should check whether you should execute it at all.
Your task may look like this:
- name: Install Jupiter theme
shell: wp theme is-installed jupiter || wp theme install ~/downloads/jupiter-theme.zip --activate
It will check if the jupiter theme is installed and will run wp theme install only if theme is not installed.
But this will mark the result of task as changed in any case.
To make it nice, you can do this:
- name: Install Jupiter theme
shell: wp theme is-installed jupiter && echo ThemeAlreadyInstalled || wp theme install ~/downloads/jupiter-theme.zip --activate
register: cmd_result
changed_when: cmd_result.stdout != "ThemeAlreadyInstalled"
First, it will check if the jupiter theme is already installed.
If this is the case, it will output ThemeAlreadyInstalled and exit.
Otherwise it will call wp theme install.
The task's result is registered into cmd_result.
We user changed_when parameter to state the fact that if ThemeAlreadyInstalled ansible shouldn't consider the task as changed, so it remains green in your playbook output.
If you do some preparation tasks before wp theme install (e.g. download theme), you may want to run the test as separate task to register the result and use when clauses in subsequent tasks:
- name: Check Jupiter theme is installed
shell: wp theme is-installed jupiter && echo Present || echo Absent
register: wp_theme
changed_when: false
- name: Download theme
get_url: url=...
when: wp_theme.stdout == "Absent"
- name: Install Jupiter theme
shell: wp theme install ~/downloads/jupiter-theme.zip --activate
when: wp_theme.stdout == "Absent"
Ansible itself is stateless, so whatever technique you use needs to be implement by yourself. There is no easier way like telling Ansible to only ever run a task once.
I think what you have already is pretty straight forward. Maybe use another path to check. I'm pretty sure the wp theme install will actually extract that zip to some location, which you then can use together with the creates option.
There are alternatives but nothing that makes it easier:
Create a script in any language you like, that checks for the theme and if it is not installed, install it. Instead of the shell task then you would execute the script with the script module.
Install a local fact in /etc/ansible/facts.d which checks if the theme in already installed. Then you could simply apply a condition based on that fact to the shell task.
Set up fact caching, then register the result of your shell task and store it as a fact. With fact caching enabled you can access the stored result on later playbook runs.
It only gets more complicated. The creates option is perfect for this scenario and if you use the location where the wp command extracted the zip to, it also is pretty clean.
Of course you need to grant access to that file, if you have a need to access it from another user account. Storing stuff in a users home directory with the permissions set to only be readable by the owner indeed is no ideal solution.

(no such process) while deploying app via Ansible

I am trying to follow the Ansible Tutorial by Matt Wright. I have forked it and updated with latest Ansible modules here.
But I'm getting
msg: hello_flask: ERROR (no such process)
while running deploy.yml at -name: start app. I have a open issue here on github.
Why I am getting this error?
So you are seeing the error because supervisor is not finding the hello_flask application.
This is probably because you have a newer configuration for supervisor that doesn't include ini files.
If you look at one of the latest /etc/supervisor/supervisor.conf it actually includes *.conf files not *.ini files.
[include]
files = /etc/supervisor/conf.d/*.conf
Also, if you look at this Ansible task:
- name: create supervisor program config
action: template src=templates/supervisor.ini dest=/etc/supervisor/${app_name}.ini
notify:
- restart app
You can see that the configuration for hello_flash is being put under /etc/supervisor/hello_flash.ini
So make sure either that your supervisor.conf includes *.ini files. Or simply change this step to this:
- name: create supervisor program config
action: template src=templates/supervisor.ini dest=/etc/supervisor/conf.d/${app_name}.conf
notify:
- restart app
Hope it helps.

Resources