How to copy files with ansible relatively to the role? - ansible

I have a copy task inside a role and I was expecting that the src location would be relative to the role itself, not the playbook that calls the roles.
How do I make this work and use the files from myfrole/files from a task inside myrole/tasks, I don't want to include the role name as part of the path as it does not make much sense. If I do it will break if I duplicate the role.

If you do not provide any path at all, just the filename, Ansible will pick it automatically from the files directory of the role.
- copy:
src: foo.conf
dest: /etc/foo.conf
Additionally, since Ansible 1.8, there is the variable role_path which you could use in your copy task.
- copy:
src: "{{ role_path }}/files/foo.conf"
dest: /etc/foo.conf

You wouldn't need to specify the path of the file to copy, as long as it is stored in files directory.
Here's how your role should look like:
my-awesome-role
├───files
│ my-awesome-file
└───tasks
main.yml
And here's the way to call copy in the tasks/main.yml:
- copy:
src: my-awesome-file
dest: '{{ some_destination }}'

Related

ansible.builtin.copy:: how to multiple file copy

So, this is ansible 2.10, and i'm trying to copy multiple files using with_items and it seems that it does not work. My tryout are more or less on the form of (this is a task):
---
- name: Sync md tools
ansible.builtin.copy:
dest: /root/bin/
src: "{{ playbook_dir }}/../additions/mdraid/{{ item }}"
with_items:
- mdadm_readd_dev
- md_check
owner: root
group: root
mode: '0700'
force: yes
I'm aware of ansible.posix.synchronize and of src_dir/ dst_dir/ format, but i would like to be able so specify a list. Is there a way to copy a specific list of multiple files with ansible.builtin.copy?
Bad syntax, ie. bad indentation. ansible-lint or ansible-playbook <playbook> -C would tell you more.

Ansible copy files with wildcard?

In my files directory I have various files, with a similar name structure:
data-example.zip
data-precise.zip
data-arbitrary.zip
data-collected.zip
I would like to transfer all of these files in the /tmp directory of my remote machine using Ansible without specifying each file name explicitly.
In other words I would like to transfer every file that stars with "data-".
What is the correct way to do that? In a similar thread, someone suggested the with_fileglob keyword, - but I couldn't get that to work.
Can someone provide me an example on how to accomplish said task?
Method 1: Find all files, store them in a variable and copy them to destination.
- hosts: lnx
tasks:
- find: paths="/source/path" recurse=yes patterns="data*"
register: file_to_copy
- copy: src={{ item.path }} dest=/dear/dir
owner: root
mode: 0775
with_items: "{{ files_to_copy.files }}"
Use remote_src: yes to copy file in remote machine from one path to another.
Ansible documentation
Method 2: Fileglob
- name: Copy each file over that matches the given pattern
copy:
src: "{{ item }}"
dest: "/etc/fooapp/"
owner: "root"
mode: 0600
with_fileglob:
- "/playbooks/files/fooapp/*"
Ansible documentation
Shortly after posting the question I actually figured it out myself. The with_fileglob keyword is the way to do it.
- name: "Transferring all data files"
copy:
src: "{{ item }}"
dest: /tmp/
with_fileglob: "data-*"

Ansible with host specific files, but fallback to default files

I'm currently trying to get used to Ansible but I'm failing to achieve what seems to be a common use-case:
Lets say I have have a role nginx in roles/nginx and and one task is to setup a custom default page:
- name: install nginx default page
copy:
src: "index.html"
dest: /var/www/html/
owner: root
mode: 0644
Ansible will look for the file in:
roles/nginx/files
roles/nginx
roles/nginx/tasks/files
roles/nginx/tasks
files
./
Now for some reason a single host should receive a completely different file.
I know I could alter the file src path to src: "{{ inventory_hostname }}/index.html" but then it would search in host-specific directories only.
Is there a way to alter the search paths so that Ansible will look for files in host-specific directories first but fall-back to common directories?
I don't want to decide if files might need to be host-specific when writing roles. I'd rather like to overwrite the role default files without altering the base role at all.
Q: "Is there a way to alter the search paths so that Ansible will look for files in host-specific directories first but fall back to common directories?"
A: In general, it is not possible to change the search paths. But, with first_found it is possible to define how a specific file shall be searched. For example,
- copy:
src: "{{ lookup('first_found', findme) }}"
dest: /scratch/tmp/
owner: root
mode: 0644
vars:
findme:
- "{{ inventory_hostname }}/index.html"
- "{{ role_path }}/files/index.html"
- "{{ role_path }}/files/defaults/index.html"

Copy folder content with Ansible

For some weird reasons I'm having troubles with a simple task which is copying a content of the folder myfiles (few files in there) to the dist/myfiles location. Task looks like this:
name: Deploy config files like there is no tomorrow
copy:
src: "{{ item }}"
dest: "/home/{{ ansible_user_id }}/dist/{{ item }}"
with_items:
- 'config'
- 'myfiles/'
myfiles folder exist under the dist and config file is copied to the dist folder.
Is this possible in Ansible or I should copy each file separately? Am I doing it completely wrong?
Your task copies both: the config file and the myfiles on Debian and CentOS targets properly.
If for some reason you have a problem, you might have a look at Looping over Fileglobs.
You need to split the task into two, with the second one looking like:
- name: Deploy multiple config files
copy:
src: "{{ item }}"
dest: "/home/{{ ansible_user_id }}/dist/myfiles/{{ item | basename }}"
with_fileglob:
- /path/to/myfiles/*
For a recursive copy, check this question on SeverFault
Alternatively, you could use the synchronize module, but pay special attention when using become. See this question on SuperUser.

Ansible: extract archive to user's dir

I'm trying to build an ansible playbook which extracts an archive (available through http) under a folder to be created in the user's home directory.
So far I've come up with:
- name: Extract archive
unarchive:
creates: wildfly
src: "http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.zip"
dest: "{{ ansible_user_dir }}"/wildfly
remote_src: yes
However by running it, I get a syntax error: here is the offending line:
dest: "{{ ansible_user_dir }}"/wildfly
^ here
I've tried also without quotes, but the issue stays the same.
By hardcoding the user's home dir it works- except that no folder "wildfly" is created. Any help ?
Quote the whole expression:
dest: "{{ ansible_user_dir }}/wildfly"

Resources