cscan
cscan

Reputation: 3850

Ansible Synchronize With Wildcard

I'm trying to synchronize a file with a wildcard:

- name: Install Services jar
  synchronize: src="{{repo}}/target/all-services-*.jar" dest=/opt/company

I'm doing this so that I don't have to update ansible every time our version number gets bumped. However, this throws a file not found exception when it is run. Does ansible support this? And if so, how can I do it?

Upvotes: 7

Views: 6679

Answers (4)

scrutari
scrutari

Reputation: 1628

Ansible module synchronize uses rsync and supports custom options for rsync through parameter rsync_opts (since 1.6) which could be used to filter file.

Example:

- name: sync source code
  synchronize:
  src: "/path/to/local/src"
  dest: "{{lookup('env','HOME')}}/remote/src"
  rsync_opts:
  - "--include=*.py"
  - "--exclude=*.pyc"
  - "--delete"

Upvotes: 4

Cody A. Ray
Cody A. Ray

Reputation: 6027

If you're already using a with_items or related, then you might not be able to use with_lines instead. For example, if you're trying to run

- name: Install Services jar
  synchronize: src="{{repo}}/target/{{ item }}-*.jar" dest=/opt/company
  with_items:
    - service1
    - service2

When synchronize invokes rsync, it wraps the src and dest in quotes which breaks the wildcard/glob expansion.

I've been able to shell out to rsync directly to bypass this behavior.

- name: Install Services jar
  shell: rsync -azPihv {{repo}}/target/{{ item }}-*.jar {{ inventory_hostname }}:/opt/company
  register: rsync_cmd
  changed_when: rsync_cmd.stdout.find('xfer') != -1
  with_items:
    - service1
    - service2

(You may need to use xfr instead of xfer depending on your rsync.)

Upvotes: 1

cscan
cscan

Reputation: 3850

This can be done with ansible's with_lines:

- name: Install services jar
  synchronize: src="{{item}}" dest=/opt/company/
  with_lines: "find {{ core_repo }}/service-packaging/target/ -name all-services*.jar | grep -v original"

Upvotes: 2

tphummel
tphummel

Reputation: 166

If the file name changes automatically and isn't set explicitly in an ansible variable, you'll want to identify the name of the file by some other means. I've seen patterns in which you download the "latest" version of a package (many repositories provide this ability). Then once you have the file, you always name it the same thing locally and you can synchronize that - no need for the wildcard pattern.

Another option could be to look up the latest version of a library in some machine readable registry. Then use that to reference the file by its full name and drive the tasks that require the exact file name.

If I'm misunderstanding your question and you are intending to synchronize multiple files that match your wildcard pattern, you could synchronize the entire directory containing your src pattern ({{repo}}/target/), then pass arguments directly to rsync to filter using a pattern. Via synchronize module docs I see you can pass arguments directly to rsync by setting rsync-opts. In the rsync docs I found online you can pass a flag like --include=all-services-*.jar to limit the files you send to just those that match a pattern.

I hope this helps!

Upvotes: 0

Related Questions