Austin Pray
Austin Pray

Reputation: 4936

Ansible best practice to copy directories

In my playbook I have

- name: Grab h5bp/server-configs-nginx
  git:  repo=https://github.com/h5bp/server-configs-nginx.git
        dest=/tmp/server-configs-nginx
        version="3db5d61f81d7229d12b89e0355629249a49ee4ac"
        force=yes

- name: Copy over h5bp configuration
  command: cp -r /tmp/server-configs-nginx/{{ item }} /etc/nginx/{{ item }}
  with_items:
    - "mime.types"
    - "h5bp/"

Which raises the warning in ansible-lint:

[ANSIBLE0006] cp used in place of copy module
/Users/austinpray/Dropbox/DEV/opensauce/bedrock-ansible/roles/nginx/tasks/main.yml:0
Task/Handler: Copy over h5bp configuration

So this raises the question: is there a better way to do this with ansible modules rather than a command?

Upvotes: 20

Views: 56540

Answers (6)

Vijay Samanthapuri
Vijay Samanthapuri

Reputation: 11

  • copy: src={{ item }} dest=/etc/fooapp/ directory_mode=yes

user directory_mode field.

Upvotes: 1

ant31
ant31

Reputation: 4780

You can use the synchronize module with mode='pull'

- name: Copy over h5bp configuration
 synchronize: mode=pull src=/tmp/server-configs-nginx/{{ item }} dest=/etc/nginx/{{ item }} 
 with_items:
   - "mime.types"
   - "h5bp/"

Note: To copy remote-to-remote, use the same command and add delegate_to (as remote source) and current inventory_host (as remote dest)

Upvotes: 16

Hassan Boutougha
Hassan Boutougha

Reputation: 3919

Another way is to zip your folder before and use the unarchive ansible module:

- name: copy your folder using a work around
  unarchive: src=your.zip dest=/destinationfolder
  become: yes

This will unzip your folder on your destination so you have a folder copy ;-) but don't forget to have unzip package on your target machine.

RHEL :

yum install unzip -y


Debian :

apt install unzip

Upvotes: 5

user3773243
user3773243

Reputation: 29

You could use with_fileglob: http://docs.ansible.com/ansible/playbooks_loops.html#id4

# copy each file over that matches the given pattern
- copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
  with_fileglob:
    - /playbooks/files/fooapp/*

Upvotes: 0

Pricey
Pricey

Reputation: 538

Ansible 2.0 brings the remote_src parameter to the copy module: http://docs.ansible.com/ansible/copy_module.html

Now you just need to do something like:

- name: Copy over h5bp configuration
  copy: src=/tmp/server-configs-nginx/{{ item }} dest=/etc/nginx/{{ item }} remote_src=yes
  with_items:
    - "mime.types"
    - "h5bp"

Upvotes: 7

300D7309EF17
300D7309EF17

Reputation: 24653

Currently, command is your best option. There's no remote-to-remote option. Here's a thread about it: How to move/rename a file using an Ansible task on a remote system

You have a couple other options:

  • you could use the file module to make a symlink (by setting src, path, and state=link.
  • you could check out the repo on the Ansible server and then use copy. This is a more common model for deploying code.
  • you can keep using command but wrap it with a stat conditional so it only overwrites once. This is especially helpful if you use notify to restart nginx.

Finally, it looks like you might be doing a "deploy by git". That isn't always the best choice, especially if you don't "own" that repo. But it could be fine- just a bit of code smell.

Upvotes: 9

Related Questions