Split parameter and use it as multiple arguments

Viewed 38

I'm trying to create a reusable role that does a synchronize where I pass in the src, dest and an exclude parameters.

I'd like to split that exclude parameter into multiple --exclude= parameters if it's defined.

So, effectively what would be running is:

With exclude undefined:

- name: Copy extracted files to remote
  synchronize:
    src: "{{ src }}"
    dest: "{{ dest }}"
    rsync_opts:
      - "--no-motd"

With exclude=logs,conf:

- name: Copy extracted files to remote
  synchronize:
    src: "{{ src }}"
    dest: "{{ dest }}"
    rsync_opts:
      - "--no-motd"
      - "--exclude=logs"
      - "--exclude=conf"

I figure I need to split the variable, but I'm not sure how to add the --exclude= to each one, whilst not adding any if there's nothing passed.

1 Answers

Given that you are passing the exclude parameter to your role via:

roles:
  - role: demo_role
    src: /path/to/src
    dest: /path/to/dest
    exclude:
      - logs
      - conf

Then, in your synchronize task, you could use a product filter, in order to construct the exclusions path along with the --exclude flag:

rsync_opts: >-
  {{
    ['--no-motd']
    + ['--exclude=']
      | product(exclude | default([]))
      | map('join')
  }}

From there:

  • when exclude is a list:

    exclude:
       - logs
       - conf
    

    rsync_opts will be:

    - --no-motd
    - --exclude=logs
    - --exclude=conf
    
  • when exclude is an empty list:

    exclude: []
    

    rsync_opts will be:

    - --no-motd
    
  • when exclude is undefined:

    - role: demo_role
      src: /path/to/src
      dest: /path/to/dest
    

    rsync_opts will be:

    - --no-motd
    

    thanks to the usage of the default filter

Related