Rename file using ansible playbook on windows [duplicate] - windows

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

Related

How can I parse part of a URL from an variable?

I'm trying to write a playbook that will go and download the version of ombi I supply on the command line as a variable, then parse part of it so I can rename the file and keep a local copy of it. Then gunzip then untar then stop the service overwrite the existing app, then restart the service.
I've written several other playbooks but parsing this part out has me stumped.
So if say this was the URL
https://github.com/Ombi-app/Ombi/releases/download/v4.32.0/linux-x64.tar.gz
I want to extract the 4.32.0 out of that url. So my playbook run line might be something like:
ansible-playbook updateombi.yml --extra-vars "ombi_release=https://github.com/Ombi-app/Ombi/releases/download/v4.32.0/linux-x64.tar.gz"
I'm assuming I would declare a var like:
ombi_version: "{{ ombi_release | urlsplit('path') }}"
but the urlsplit is what's got me stumped. Anyone able to throw me a bone?
I'm trying to write a playbook that will go and download the version of Ombi I supply on the command line as a variable ...
To do so you could simply provide the version number only
ansible-playbook updateombi.yml --extra-vars "ombi_release=4.32.0"
and construct the URL and filename afterwards within your playbook
url: "https://github.com/Ombi-app/Ombi/releases/download/v{{ ombi_release }}/linux-x64.tar.gz"
dest: /tmp/linux-x64-v{{ ombi_release }}.tar.gz
since they don't have a variable part except the version number. By doing this there would be no need for
... then parse part of it so I can rename the file ...

How to make ansible with_fileglob work recursively for all subdirectories or alternative?

I am using Ansible and have a directory structure like the example below:
configs
something
files
1.conf
2.conf
// and so on
Those files are templates and I am using Ansible to parse these templates and create them automatically in the destination server.
My problem is that with_fileglob is working only of first level directory and cannot seem to enable some recursive mode.
I have
- name: "Apply templates"
template:
src: "{{ item }}"
dest: "{{ item | replace('.j2', '') }}"
with_fileglob:
- "{{ user_configs_path }}/*"
by the way user_configs_path=configs exists and all good here.
The above does nothing.
If I add something under configs, example configs/blabla.j2 and re-run the playbook it is parsed and copied fine.
So seems somehow that the directories are not searched recursively.
I am not limited to only use the fileglob solution so feel free to suggest anything I can learn to reach my goal.
Basically I want to recursively iterate all directories for files only, and in a loop apply the template module to them and create them in remote server
Thank you
Regarding
My problem is that with_fileglob is working only of first level directory and cannot seem to enable some recursive mode.
and according the documentation fileglob
Matches all files in a single directory, non-recursively, that match a pattern. It calls Python’s “glob” library.
for
How to make Ansible with_fileglob work recursively for all subdirectories
one would need to enhance the module code.
Regarding
Basically I want to recursively iterate all directories for files only, and in a loop apply the template module to them and create them in remote server
as solution and depending on your requirements and what you try to achieve, you could use just
find module – Return a list of files based on specific criteria, in example .conf files. It works with parameter recursive: true and will you provide with a list of full path(s) over which you can loop after.
shell module – Execute shell commands on targets like find and register: result
Similar Q&A
Ansible playbook to find out specific files in sub directories
Ansible: How to find latest files from a directory recursively?
How to search for files containing a particular text with Ansible?

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"

How can I lookup properties in a slurped file?

According to the ansible documentation, I can use slurp to read a remote file.
I have a java properties file on a remote host that I want to slurp so I did:
- name slurp xyz properties
slurp:
src: /some/path/on/the/remote/my.properties
register: myprops
- debug:
msg: "{{ myprops['content'] | b64decode }}"
If I do that I get the content.
Now I want to use that conent in ansible. E.g. through a lookup. Something like this:
{{lookup('somePropertyInPropertiesFile', myprops['content'])}}
But this doesn't work since the lookup module only allows lookup in files.
How can I pass the slurped file to the lookup?
I'm using ansible 2.9.9
Given ansible lookups work on the control host, you can also get a file from remote to local using fetch module. Then use ini lookup to read a specific property from the properties file.
I couldn't test the code but something like below should work.
- name: Fetch my properties
fetch:
src: /some/path/on/the/remote/my.properties
dest: /tmp/
flat: yes
- debug:
msg: "content is {{ lookup('ini', 'content type=properties file=/tmp/my.properties') }}"
flat: yes will copy the file under /tmp without creating a dir with hostname in the given destination dir which is the default behavior. This might be useful if you have a single host or do not care if the file gets overwritten.
The answer of Moon is correct, but I want to add more details about java property files.
It seems that ansible can only hanlde simple java property files like:
user.name=robert
user.pass=somerandompassword
But the java properties file format also allowes values to span serveral lines, e.g.
targetCities=\
Detroit,\
Chicago,\
Los Angeles
When you have entries like this, ansible doesn't parse them correctly. Ansible's result is:
ok: [..............] => {
"msg": "content is \\\nDetroit,\\\nChicago,\\\nLos Angeles"
}
But the java Properties documentation say:
Properties are processed in terms of lines. There are two kinds of line, natural lines and logical lines. A natural line is defined as a line of characters that is terminated either by a set of line terminator characters (\n or \r or \r\n) or by the end of the stream. A natural line may be either a blank line, a comment line, or hold all or some of a key-element pair. A logical line holds all the data of a key-element pair, which may be spread out across several adjacent natural lines by escaping the line terminator sequence with a backslash character .
Thus
targetCities=\
Detroit,\
Chicago,\
Los Angeles
should be equivalent to
targetCities=Detroit,Chicago,Los Angeles
which is not the case as explained above.
EDIT
Sadly some property files, like tomcat's catalina.properties, can not be parsed at all.
fatal: [..............]: FAILED! => {"msg": "An unhandled exception occurred while running
the lookup plugin 'ini'. Error was a <class 'ConfigParser.ParsingError'>, original
message: File contains parsing errors: <???>\n\t[line 35]: u'org.apache.jasper.,org.apache.naming.,org.apache.tomcat.\\r\\n'\n\t[line 110]:
...

ansible local file path for unarchive

I have what I think is a fairly common task of taking a local archive file, transferring it to a server, and extracting it there. I'm using the unarchive module for this but struggling with an elegant way to deal with the local filename always being different because the filename includes the software version. For example, here's a excerpt from a playbook:
- name: Upload code
unarchive: src={{payload_file}} dest={{install_dir}}
I can run this and use -e to set the variable:
ansible-playbook -e payload_file=/tmp/payload-4.2.1.zip -i production deploy.yml
My question is is this the best way to handle this situation? All the docs have hardcoded example file names and paths and I haven't seen any evidence in the docs that makes a variable that will be different each deployment straightforward to set.
While passing extra args on the command line will work, I generally don't like having to type to run the job -- this is to say that I don't think your solution is inelegant or bad in any way.
However, if you're willing to change your process a little, you can avoid having to add options when calling your playbook.
Option 1: Put the payload-version.zip file in a directory and target that directory with a glob. Any file in that directory will get unarchived (if there's only one file, this achieves the same behavior):
- name: Upload code
unarchive: src={{item}} dest={{install_dir}}
with_fileglob:
- /tmp/payloads/*
Option 2: Symlink the versioned file to a simple, general name of payload-latest.zip and target it with your play (using the modified date or setting a fact for metadata). I assume you have a build process or script to generate the zip, so add a step to symlink the build version to payload-latest.zip and target that in your play.

Resources