i-haidar
i-haidar

Reputation: 53

How to copy all the files resulting from an ansible find?

I need use ansible to ensure some files contain a particular pattern, and only copy those to a particular directory.

I'm very new to ansible, and my current idea was to use the find module to search for the pattern, then feed the resulting list of files into the copy module as a loop. However, I have no idea how to do this, and have been over the documentation for over an hour now but couldn't an find example of what im trying to do.

- name: "Ensure file contains pattern"
  find:
    paths: "/path/to/file.gz"
    use_regex: yes
    patterns: "-rev.*.gz"
  register: chosen_files

Now how to feed the chosen_files list to the copy module?

Edit:

I have tried the approach below but unfortunately it wouldn't work with how things are currently set up, due to the fact that the image names were constructed using a variable, so it would only grab the relevant image, while the approach using find find all images in my repo with that pattern.

archived_image_name: "{{ new_image.registry }}_{{ new_image.image | regex_replace('/', '_') }}_{{ new_image.version }}_image.tar"

I have created a variable that compares this regex pattern vs the pre-existing pattern, so only if it contains "-rev" it will proceed with the next steps.

archived_image_prod_name: "{{ archived_image_name | regex_search('.*-rev\\d.*')}}"

Now I have another problem, which is that my database images are not expected have this pattern in their version tags, and I need to create an exception for them somehow.Task fails when it tries to check if there is enough space in the filesystem for the image.

  - name: "Get {{ archived_image_prod_name }}.gz Size"
stat:
  path: "{{ tower_path }}/images/{{ archived_image_prod_name }}.gz"
register: image_archive
delegate_to: 127.0.0.1 

 - name: "Ensure There Is Enough Disk Space Filesystem"
assert:
  that:  available_disk_space.stdout | int > image_archive.stat.size
  msg: "Not enough disk space available for {{ archived_image_prod_name }}.gz"

The playbook stops here as some images don't match the pattern are so it fails to find their file size. I'm kinda pulling blanks on how to create an exception in this task particular images.

Upvotes: 1

Views: 1512

Answers (2)

Jack
Jack

Reputation: 6198

First, you need to run the find with delegate_to: localhost, and add run_once: yes because it won't change from one remote hosts to another. Also, your pattern needs, to start with .*.

  - name: "Ensure file contains pattern"
    find:
      paths: "/path/to/"
      use_regex: yes
      patterns: ".*-rev.*.gz"
    register: chosen_files
    delegate_to: localhost
    run_once: yes

I put a debug in so you can see what files are going to be copied, but you can drop this when you've got it working.

  - name: show files
    debug:
      var: item.path
    loop: "{{ chosen_files.files }}"
    delegate_to: localhost
    run_once: yes

The other answer assumes the copy is just internal to the managed hosts, and your comment says that it not the case, so we drop his remote_src line. Also, the src and loop were incorrect:

  - name: Copy files from local to remote
    copy:
      src: "{{ item.path }}"
      dest: /path/
    loop: "{{ chosen_files.files }}"

Upvotes: 0

sorin
sorin

Reputation: 170806

Add a second task like:

- name: Copy files
  copy:
    src: {{ item }}
    dest: /path/
    remote_src: true  # this tells ansible to perform action only on remote
  loop: chosen_files

Read entire: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/copy_module.html as copy module can be used in many ways across different hosts. The default behavior is to "push" files from controller towards the target machine. Still you can change its behaviour.

Upvotes: 1

Related Questions