Published on
·
Time to read
3 minute read

Ansible Struggles: Diff between my-dir and my-dir/

Blog post image
Authors

Ansible is a powerful automation tool that can be used to manage so many aspects of infrastructure, including file management. I've gotten the chance to play with it quite a bit here at Solvvy in building out our next-gen infrastructure.

One of the core modules used for file management is the copy module. The copy module allows you to copy files and directories from the local machine to a remote host, or from one remote host to another. It's pretty essential for moving configuration files around and getting machines into the state you want them to be in.

However, there is a very subtle difference in the behavior of the copy module when the destination directory ends with a trailing slash versus when it does not that differs from some common shell interpretations. This can really bite you in the ass, especially when the source is a directory and the copy is recursive.

When the source is a directory that ends with / and the destination directory ends with a trailing slash, Ansible will copy only the directory's contents into the specified directory, maintaining the original directory structure. For example, if you use the following command to copy a directory named source to a directory named destination, the source directory's contents will be placed in the destination directory and maintain the original directory structure.

- name: Copy directory's contents to destination
  copy:
    src: source/
    dest: /path/to/destination/

Result:

/path/to/destination/example.txt

On the other hand, if the source directory does not end with a trailing slash, Ansible will treat the destination as the parent directory, and will copy the source directory and its contents into that folder. For example, if you use the following command to copy the same source directory to the same destination directory, the source directory and its contents will be placed in a new directory named source.

- name: Copy directory and its contents to destination
  copy:
    src: source
    dest: /path/to/destination/

Result:

/path/to/destination/source/example.txt

This difference in behavior lead to some gnarly bugs and confusion why certain configurations weren't taking effect. For example, if you intend to mirror a directory to a destination directory and maintain the original directory structure, but you accidentally forget a trailing slash, you'll end up with a doubly nested structure.

When using the Ansible copy module to copy a directory and its contents, it is super important to be mindful of the trailing slash in the source directory. I hope this saves you some of the time I wasted 😅