How can I use the mv module Ansible - ansible

I am trying to use the mv module on Ansible but I am not having luck.
In my initial attempt I did the following:
- name: changing the name of the file
shell: mv /tmp/bundle /opt/Rocket.Chat
And I get the following error:
FAILED! => {"changed": true, "cmd": "mv /tmp/bundle /opt/Rocket.Chat", "delta": "0:00:00.033553", "end": "2019-02-11 06:06:43.273787", "msg": "non-zero return code", "rc": 1, "start": "2019-02-11 06:06:43.240234", "stderr": "mv: cannot move ‘/tmp/bundle’ to ‘/opt/Rocket.Chat/bundle’: File exists", "stderr_lines": ["mv: cannot move ‘/tmp/bundle’ to ‘/opt/Rocket.Chat/bundle’: File exists"], "stdout": "", "stdout_lines": []}
So, I changed it to:
- name: create directory
file:
state: directory
path: "/opt/Rocket.Chat"
- name: copy the files
copy:
src: "/tmp/bundle"
dest: "/opt/Rocket.Chat"
remote_src: yes
- name: delete the other files
file: path=/tmp/bundle state=absent
My new error is:
FAILED! => {"changed": false, "msg": "Remote copy does not support recursive copy of directory: /tmp/bundle"}

Seems that the "copy module to work with recursive and remote_src" does not work yet, but will be supported from May 2019
Here is a workaround, edit the folder names to your setup.
# Copy all files and directories from /usr/share/easy-rsa to /etc/easy-rsa
- name: List files in /usr/share/easy-rsa
find:
path: /usr/share/easy-rsa
recurse: yes
file_type: any
register: find_result
- name: Create the directories
file:
path: "{{ item.path | regex_replace('/usr/share/easy-rsa','/etc/easy-rsa') }}"
state: directory
mode: "{{ item.mode }}"
with_items:
- "{{ find_result.files }}"
when:
- item.isdir
- name: Copy the files
copy:
src: "{{ item.path }}"
dest: "{{ item.path | regex_replace('/usr/share/easy-rsa','/etc/easy-rsa') }}"
remote_src: yes
mode: "{{ item.mode }}"
with_items:
- "{{ find_result.files }}"
when:
- item.isdir == False

Related

Ansible: Creating multiples paths with usernames defined in vars file

How can I create multiple paths with usernames defined in vars file?
---
- hosts: hostname
gather_facts: false
vars_files:
- /home/ansible/usernames
tasks:
- name: Checking if home directory exists
with_items: "{{ username }}"
vars:
paths: &paths
- "/home/{{ username }}/"
- "/home/{{ username }}/data"
loop: "{{ paths }}"
become: yes
become_user: "{{ username }}"
stat:
path: "{{ paths }}"
register: play1
- name: Check paths from play1
debug:
var: play1
- name: Creating directories
loop: "{{ play1.results }}"
register: play2
become: yes
become_user: "{{ item.item }}"
file:
path: /home/{{ item.item }}/.ssh
state: directory
mode: '0700'
owner: "{{ item.item }}"
group: "system-group"
when: not item.stat.exists and not item.stat.pw_name == '"{{ item }}"'
- name: Display Creating directories
debug:
var: play2
Extract from input file.
username:
- user1
- user2
This is the error I'm getting:
ERROR: failed: [server] (item=/home/[u'user1', u'user2']/) => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "ansible_loop_var": "item", "changed": false, "item": "/home/[u'user1', u'user2']/", "module_stderr": "Shared connection to server closed.\r\n", "module_stdout": "sudo: unknown user: [uuser1,\r\nsudo: unable to initialize policy plugin\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Find files in a loop and delete them

I would like to delete file in some sub directory which contains certain format. However, I am getting the error
'dict object' has no attribute 'files'.
Below is my code. The file pattern would be file_name.file_extension.processID.YYYY-MM-DD#HH:MM:SS~
My variables
fileToFindInAllSubDirecotry
- "home/usr/file1"
- "home/usr/file2"
- "home/usr/file3/file4"
- "home/usr/file5"
My playbook role
- name: Find file
find:
paths: "{{ item }}"
use_regex: yes
patterns:
- '.*\.\d+\.\d{4}-\d{2}-\d{2}#\d{2}:\d{2}:\d{2}~$'
age: 1d
recurse: yes
register: fileToDelete
loop: "{{ fileToFindInAllSubDirecotry }}"
- name: Delete file
file:
path: "{{ item.path }}"
state: absent
loop: "{{ fileToDelete.files }}"
This is the sample file and directory
home
|-------usr
|-------file1
|-------configFile.xml
|-------file2
|-------propertiesFile.txt.2012.2020-07-13#23:08:10~
|-------file3
|-------file4
|-------content.yml.2012.2020-04-04#23:08:10~
|-------file5
|-------configFile.xml.2012.2020-03-05#13:08:10~
This is happening because you are populating the find with a loop, so you end up with a result that would be a dictionary having a list or results.
Something like:
ok: [localhost] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
...
"files": [ ... ],
...
"item": "/home/usr/file1",
...
},
{
...
"files": [ ... ],
...
"item": "/home/usr/file2",
...
},
...
]
}
}
There is two ways to fix this:
The nicest one, because, as pointed by the documentation, the paths parameter of the module find can accept lists of paths, just pass it your whole fileToFindInAllSubDirecotry variables instead of using a loop, this way your deletion works as is:
- name: Find file
find:
paths: "{{ fileToFindInAllSubDirecotry }}"
use_regex: yes
patterns:
- '.*\.\d+\.\d{4}-\d{2}-\d{2}#\d{2}:\d{2}:\d{2}~$'
age: 1d
recurse: yes
register: fileToDelete
- name: Delete file
file:
path: "{{ item.path }}"
state: absent
loop: "{{ fileToDelete.files }}"
Use json_query to fetch the result[*].files then flatten the resulting list of list
- name: Find file
find:
paths: "{{ item }}"
use_regex: yes
patterns:
- '.*\.\d+\.\d{4}-\d{2}-\d{2}#\d{2}:\d{2}:\d{2}~$'
age: 1d
recurse: yes
register: fileToDelete
loop: "{{ fileToFindInAllSubDirecotry }}"
- name: Delete file
file:
path: "{{ item.path }}"
state: absent
loop: "{{ fileToDelete | json_query('results[*].files') | flatten }}"

Ansible: Copying files from local to remote - "AttributeError: 'dict' object has no attribute 'endswith'"

I am trying to copy files (scripts and rpms) stored locally to a set of servers. I can copy the files when the names are hard coded, but not when I am using a variable.
ansible-lint comes back with no errors.
When use variable replacement I get the error:
TASK [Copy cpu_gov.sh]
***************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
In debug mode I can see that it is a Python error on a trailing "/". All other uses of the variable work fine, only when it is in the ""src:" field does it fail.
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 145, in run
res = self._execute()
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 650, in _execute
result = self._handler.run(task_vars=variables)
File "/usr/lib/python2.7/site-packages/ansible/plugins/action/copy.py", line 461, in run
trailing_slash = source.endswith(os.path.sep)
AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
---
### Test
#
- hosts: all
vars:
#isdct_rpm: foobar.txt
isdct_rpm: isdct-3.0.16-1.x86_64.rpm
cpu_gov: cpu_gov.sh
irq_bal: irq_balance.sh
root_dir: /root
bin_dir: /root/bin
files_dir: /root/projects/ansible/bootstrap/files
remote_user: root
tasks:
These work just fine -
- name: ISDCT rpm exists?
stat:
path: "{{ root_dir }}/{{ isdct_rpm }}"
register: isdct_rpm
tags:
- tools
- name: cpu_gov exists?
stat:
path: "{{ bin_dir }}/{{ cpu_gov }}"
register: cpu_gov
tags:
- tools
- name: irq_balance exists?
stat:
path: "{{ bin_dir }}/{{ irq_bal }}"
register: irq_bal
tags:
- tools
The first task is the failing one:
- name: Copy ISDCT rpm
copy:
remote_src: no
src: "{{ isdct_rpm }}"
dest: "{{ root_dir }}"
when: not isdct_rpm.stat.exists
These work fine:
- name: Copy rpm
copy:
remote_src: no
src: isdct-3.0.16-1.x86_64.rpm
dest: /root
when: not isdct_rpm.stat.exists
- name: Copy cpu_gov.sh
copy:
remote_src: no
src: cpu_gov.sh
# - fails - src: "{{ cpu_gov }}"
dest: "{{ bin_dir }}"
when: not cpu_gov.stat.exists
- name: Copy irq_balance.sh
copy:
remote_src: no
src: irq_balance.sh
dest: /root
when: not irq_bal.stat.exists
The full traceback is:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 145, in run
res = self._execute()
File "/usr/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 650, in _execute
result = self._handler.run(task_vars=variables)
File "/usr/lib/python2.7/site-packages/ansible/plugins/action/copy.py", line 461, in run
trailing_slash = source.endswith(os.path.sep)
AttributeError: 'dict' object has no attribute 'endswith'
fatal: [ceph3]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
You have a variable in your vars section named isdct_rpm which is a string, but you're registering a dictionary variable with the same name in your ISDCT rpm exists? task. This overrides the string value.
Stop trying to use the same variable name for two different purposes and I suspect things will work as expected.
#larsks Answered my question. I was using the same name for my variable and the register value.
This works:
#
###--- Copy the scripts over if needed
#
- name: Copy ISDCT rpm
copy:
remote_src: no
src: "{{ isdct_rpm }}"
dest: "{{ root_dir }}"
when: not isdctrpm.stat.exists
- name: Copy cpu_gov.sh
copy:
remote_src: no
#src: cpu_gov.sh
src: "{{ cpu_gov }}"
dest: "{{ bin_dir }}"
when: not cpugov.stat.exists
- name: Copy irq_balance.sh
copy:
remote_src: no
src: "{{ irq_bal }}"
dest: "{{ bin_dir }}"
when: not irqbal.stat.exists

win_find FAILED! => {"msg": "'dict object' has no attribute 'files'"}

I am trying to run win_find with variables for "paths" to find temp files (e.g. c:\users\public\appdata\local\temp) but when I pass it to debug I get the error message
"FAILED! => {"msg": "'dict object' has no attribute 'files'"}"
I have tried swapping the "register" and "with_items" lines but that seems to make no difference at all.
- hosts: windows-02
vars:
dir: \AppData\Local\Temp\
tasks:
- name: find user directories
win_find:
paths: c:\users
recurce: yes
file_type: directory
get_checksum: no
register: user_dir
- name: debug 1
debug:
msg: "{{ item.path + dir }}"
loop: "{{ user_dir.files }}"
- name: find temp files
win_find:
paths: "{{ item.path + dir }}"
recurce: yes
hidden: yes
get_checksum: no
register: files_to_delete
with_items: "{{ user_dir.files }}"
- name: debug
debug:
msg: "{{ item }}"
loop: "{{ files_to_delete.files }}"
- name: remove
win_file:
path: "{{ item.path }}"
state: absent
with_items: "{{ files_to_delete.files }}"
I expect to get a list of files to be deleted which will be passed to the "win_files" module. Instead I'm getting the error message
"FAILED! => {"msg": "'dict object' has no attribute 'files'"}"
There is a typo in win_find module, it is recurse: yes
Please find the below code whcih worked for me
---
- name: Find files
win_find:
paths: "{{paths}}"
age: "{{duration}}"
register: log_files
- name: Delete the files
win_file:
path: "{{item.path}}"
state: absent
with_items: "{{log_files.files}}"
Also files_to_delete will not have files_to_delete.files as it is in loop. It will have files_to_delete.results
So, it appears that win_find, at least in my case, does not return files when using "when_items". I got around this by creating a list of paths and passing it into the "paths" parameter of the module.
Here is my code:
- hosts: "{{ host }}"
vars:
dir: \AppData\Local\Temp\
temp_paths: []
line_break: \n
tasks:
- name: find user directories
win_find:
paths: c:\users
recurse: no
file_type: directory
get_checksum: no
register: user_dir
- name: debug 1
debug:
msg: "{{ item.path + dir }}"
loop: "{{ user_dir.files }}"
- name: set temp path
set_fact: temp_paths="{{temp_paths + [ item.path + dir ] }}"
when: item.path != 'C:\\users\\Public'
with_items: "{{ user_dir.files }}"
- name: find temp files
win_find:
paths: "{{ temp_paths }}"
recurse: True
patterns: '*'
hidden: False
get_checksum: False
register: files_to_delete
# ignore_errors: yes
- name: debug
debug:
msg: "{{ item.path }}"
loop: "{{ files_to_delete.files }}"
- name: remove
win_file:
path: "{{ item.path }}"
state: absent
with_items: "{{ files_to_delete.files }}"

Ansible: How to run command with shell output

Self explanatory. I want to link based on $(which {{ item }}).
Already saw the register function, but as I need to do a nested loop I'm not sure how to use it.
name: Link bins to user path
command: 'ln -s \$(which {{ item.1 }}) /home/{{ item.0 }}/bin/{{ item.1 }}'
with_nested:
- "{{ jail_users }}"
- "{{ jail_user_commands }}
Output:
failed: [rousertest] (item=[u'bob', u'date']) => {"changed": true,
"cmd": ["ln", "-s", "$(which", "date)", "/home/bob/bin/date"], "delta":
"0:00:00.011825", "end": "2019-07-11 08:17:32.921705", "item": ["bob", "date"], "msg": "non-zero return code", "rc": 1, "start": "2019-07-11
08:17:32.909880", "stderr": "ln: target ‘/home/bob/bin/date’ is not a
directory", "stderr_lines": ["ln: target ‘/home/bob/bin/date’ is not a
directory"], "stdout": "", "stdout_lines": []
Of course I was expecting something like this:
sudo ansible server -i inventory -m shell -a 'echo $(which date)'
rousertest | SUCCESS | rc=0 >>
/usr/bin/date
Below is the play. Avoid using command module for link. Use file module with state=link.
- name: Link binary
hosts: all
gather_facts: true
vars:
files:
- date
- ls
users:
- user1
- user2
tasks:
- name: Find paths
command: which {{ item }}
with_items:
- "{{ files }}"
register: result
- name: Link bins to user path
file:
src: "{{ item.1.stdout }}"
dest: "/home/{{ item.0 }}/bin/{{ item.1.item }}"
owner: "{{ item.0 }}"
group: "{{ item.0 }}"
state: link
with_nested:
- "{{ users }}"
- "{{ result.results }}"

Resources