akash
akash

Reputation: 1024

Ansible - How to zip files in localhost before copying to remote

I am trying to copy large sets of files (in 100's) to my remote server. However, using 'copy' command this task is taking considerably long time. Searching a bit, I understood the 'synchronize' is a good suit for this. Unfortunately my current remote servers do not have 'rsync' and so I am not able to use the 'synchronize' option as well.

As a workaround, I wanted to zip the folder in ansible host and then transfer it to the remote server by using the 'unarchive' module.

- name: Archive the folder
  shell: zip <dest-zip-path> <path-to-folder>
  delegate_to: localhost

However, doing this I am getting the following error: "module_stderr": "sudo: a password is required\n"

Is there a simpler to zip the folder locally on the ansible host before transfering?

Upvotes: 5

Views: 5266

Answers (3)

ronnyworm
ronnyworm

Reputation: 51

I wouldn't use zip, but the default (which is gz) to not be forced to check for unzip being present on the target.

This is a complete replacement of copying from local to remote with an archive.

Before (plain copying a folder)

  vars:
      target_folder: /var/www/my-data
      local_folder: my-data
  ...

  - name: ensures {{ target_folder }} exists on server
    file: 
      path: "{{ target_folder }}"
      state: directory
      recurse: true

  - name: Move to server
    copy:
      src: "{{ local_folder }}/"
      dest: "{{ target_folder }}"
      force: yes

After (achieving the same result by archiving, unarchiving and removing the traces)

  vars:
      target_folder: /var/www/my-data
      local_folder: my-data
  ...

  - name: ensures {{ target_folder }} exists on server
    file: 
      path: "{{ target_folder }}"
      state: directory
      recurse: true

  - name: Archive first
    archive:
      path: "{{ local_folder }}/"
      dest: "{{ local_folder }}.gz"
    delegate_to: localhost
    become: false

  - name: Move the archive to server
    copy:
      src: "{{ local_folder }}.gz"
      dest: "{{ target_folder }}/.."
      force: yes

  - name: Unarchive on server
    unarchive:
      src: "{{ target_folder }}/../{{ local_folder }}.gz"
      dest: "{{ target_folder }}"
      remote_src: yes

  - name: Delete archive on server
    file:
      path: "{{ target_folder }}/../{{ local_folder }}.gz"
      state: absent

  - name: Delete archive locally
    file:
      path: "{{ local_folder }}.gz"
      state: absent
    delegate_to: localhost
    become: false

Upvotes: 0

akash
akash

Reputation: 1024

Based on the solution posted by Zeitounator, this was the Ansible code I used to solve the issue:

- name: Archive the files
  archive:
    path: <path-to-folder>
    dest: <dest-zip-path>
    format: zip
  delegate_to: localhost
  become: false

Upvotes: 6

Zeitounator
Zeitounator

Reputation: 44645

You are probably using become: true on your play. This also applies when delegating to localhost. But it requires a password on your local machine.

Since you probably don't need this, simply apply become: false to this specific task. Else you will have to configure privilege escalation on localhost or provide a become_password.

Moreover, you should consider using the archive module rather than using shell.

Upvotes: 3

Related Questions