Finding file name in files section of current Ansible role

ansibleansible-playbook

I'm fairly new to Ansible and I'm trying to create a role that copies a file to a remote server. The local file can have a different name every time I'm running the playbook, but it needs to be copied to the same name remotely, something like this:

- name: copy file
  copy:
    src=*.txt
    dest=/path/to/fixedname.txt

Ansible doesn't allow wildcards, so when I wrote a simple playbook with the tasks in the main playbook I could do:

- name: find the filename
    connection: local
    shell: "ls -1 files/*.txt"
    register: myfile

- name: copy file
  copy:
    src="files/{{ item }}"
    dest=/path/to/fixedname.txt
  with_items:
   - myfile.stdout_lines

However, when I moved the tasks to a role, the first action didn't work anymore, because the relative path is relative to the role while the playbook executes in the root dir of the 'roles' directory. I could add the path to the role's files dir, but is there a more elegant way?

Best Answer

It looks like you need access to a task that looks up information locally, and then uses that information as input to the copy module.

There are two ways to get local information.

  • use local_action:. That's shorthand for running the task agains 127.0.0.1, more info found here. (this is what you've been using)

  • use a lookup. This is a plugin system specifically designed for getting information locally. More info here.

In your case, I would go for the second method, using lookup. You could set it up like this example:

vars:
  local_file_name: "{{ lookup('pipe', 'ls -1 files/*.txt') }}"

tasks:
  - name: copy file
    copy: src="{{ local_file_name }}" dest=/path/to/fixedname.txt    

Or, more directly:

tasks:
  - name: copy file
    copy: src="{{ lookup('pipe', 'ls -1 files/*.txt') }}" dest=/path/to/fixedname.txt    

With regards to paths

the lookup plugin is run from the context of the task (playbook vs role). This means that it will behave differently depending on where it's used.

In the setup above, the tasks are run directly from a playbook, so the working dir will be:

/path/to/project -- this is the folder where your playbook is.

If you where to add the task to a role, the working dir would be:

/path/to/project/roles/role_name/tasks

In addition, the file and pipe plugins run from within the role/files folder if it exists:

/path/to/project/roles/role_name/files -- this means your command is ls -1 *.txt

caveat:

The plugin is called every time you access the variable. This means you cannot trust debugging the variable in your playbook, and then relying on the variable to have the same value when used later in a role!

I do wonder though, about the use-case for a file that resides inside a projects ansible folders, but who's name is not known in advance. Where does such a file come from? Isn't it possible to add a layer in between the generation of the file and using it in Ansible... or having a fixed local path as a variable? Just curious ;)