Often in Ansible I find myself needing to download an artifact. Whether it is a piece of software from GitHub or a build of some internal application that needs to be installed. One thing that is often important in these cases is speed of rollback. If something goes wrong with a new version I want the rollback to be fast, and preferable using preexisting files, and not downloading everything again.

Here is an example of an application that has binaries and needs to be extracted. It assumes that the version is already set.

---
- name: Calculate Settings
set_fact:
release_dir:   "{{ base_dir }}/releases/{{ app_version }}"
binary_dir:    "/usr/local/bin"


Here we are simply calculating the variables we will use later. This makes each step simpler. I use pattern this often when there are lots of paths to deal with.

- name: Create Directories
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ release_dir }}"


Create the directories for the downloaded artifacts and releases. Ansible will create all the sub directories required on the way to these.

- name: Download the Artifact
get_url:
dest: "{{ artifact_file }}"


Here we do the actual download of the artifact. You might want to add owner, group and mode to here to choose the mode of the downloaded files.

- name: Extract Artifact to Release Directory
unarchive:
copy: no
src: "{{ artifact_file }}"
dest: "{{ release_dir }}"


Extract the artifact, because we downloaded it on the remote host we set copy to no to prevent Ansible trying to find the file locally and copy it to the managed host. You may want to add other options to the unachive module to set the permissions you want.

- name: Update the Link to the Latest Release
file:
src: "{{ release_dir }}"


Here we atomically change the binaries that are in use. If anything before this step fails, we wont run this step, and once this step runs all the binaries change to the new version immediately. When rolling back to an existing version this is the only step that will need to run.

- name: Make the Link to the latest binaries
file:
src: "{{ latest_link }}/bin/{{ item }}"
dest: "{{ binary_dir }}/{{ item }}"