opticyclic
opticyclic

Reputation: 8106

Find Remote File Using Wildcard In Ansible

I run a java command using the shell module which creates a file with a random string suffixed to this.

I need to subsequently POST this file using the uri module.

I am trying to find the file using the stat module and a wildcard but it isn't finding it.

- stat:
    path: "{{ my_dir }}/info-*"
  register: info

- debug:
    msg: "info isn't defined (path doesn't exist)"
  when: info.stat.exists == False

How else can I find the filename?

Upvotes: 3

Views: 5332

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67959

The stat module requires a full path. Use the find module instead. Quoting:

paths List of paths of directories to search.

patterns One or more (shell or regex) patterns, which type is controlled by use_regex option. The patterns restrict the list of files to be returned to those whose basenames match at least one of the patterns specified. Multiple patterns can be specified using a list. This parameter expects a list, ...

For example, find the info-* files in the directory /tmp/test and display the list of files

    - find:
        paths: /tmp/test
        patterns:
          - "info-*"
      register: info

    - debug:
        var: info.files

Q: "I run a java command using the shell module which creates a file with a random string suffixed to this. I need to subsequently POST this file using the uri module."

A: It is possible to use the first file from the list

  my_file: "{{ info.files.0.path }}"

, but there might be more files matching the pattern info-*. A robust solution would be to make the java command ... which creates a file with a random string suffixed to return the filename. Or, it might be possible to use the tempfile module instead.

Update

There is the creation time attribute ctime in each of the files from the list info.files. You can sort the list by ctime and take the last one created

  my_files: "{{ info.files|sort(attribute='ctime')|map(attribute='path') }}"
  my_file: "{{ my_files|last }}"

Be careful because this creates a race condition. Other processes may create newer matching files.


Given the tree

shell> tree /tmp/test
/tmp/test
├── info-1
├── info-2
└── info-3

and the example of a complete playbook for testing

- hosts: localhost

  vars:

    my_files: "{{ info.files|sort(attribute='ctime')|map(attribute='path') }}"
    my_file: "{{ my_files|last }}"

  tasks:

    - find:
        paths: /tmp/test
        patterns:
          - "info-*"
      register: info

    - debug:
        var: my_files

    - debug:
        var: my_file

gives

PLAY [localhost] *****************************************************************************

TASK [find] **********************************************************************************
ok: [localhost]

TASK [debug] *********************************************************************************
ok: [localhost] => 
  my_files:
  - /tmp/test/info-1
  - /tmp/test/info-2
  - /tmp/test/info-3

TASK [debug] *********************************************************************************
ok: [localhost] => 
  my_file: /tmp/test/info-3

PLAY RECAP ***********************************************************************************
localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 3

Related Questions