Automate Installation of Multiple Binary packages


As a ParaView developer it is useful to keep multiple version of ParaView installed so that testing for regressions becomes quick and easy. I used to just drop the binaries from https://www.paraview.org/download/ right into an ~/opt directory, and add custom launchers with menulibre. To differentiate between versions I would edit the icon with Gimp so that it includes the corresponding ParaView version.

Since I started using ansible to set up different VMs and machines it became natural to look for an opportunity to use it everywhere. In this case the goal is:

  • Use common ansible roles to download (and verify) the tarballs.
  • Use imagemagick to embed text into the icon.
  • Setup .desktop files in an appropriate directory.

In this case we have something like this:

---
- name: Install ParaView Binary releases
  hosts: localhost
  become: no
  vars:
    opt: "{{ ansible_env.HOME }}/opt"
    paraview:
      - file: "ParaView-5.11.2-MPI-Linux-Python3.9-x86_64.tar.gz"
        base_version: "5.11"
        version: "5.11.2"
        checksum: "sha256:3454f6d92cda9469590e9746e212b52cad0d90869901d63ac955fa76c8bce887"
      - file: "ParaView-5.11.1-MPI-Linux-Python3.9-x86_64.tar.gz"
        base_version: "5.11"
        version: "5.11.1"
        checksum: "sha256:be8920d15bf54b457ffb3cdce43e598c0e53a051592135440d916b0effbf8593"
      - file: "ParaView-5.11.0-MPI-Linux-Python3.9-x86_64.tar.gz"
        base_version: "5.11"
        version: "5.11.0"
        checksum: "sha256:1fbbff211e3c10c02cd1f994ed7b36eb8d2270091f8a43aa5ed866fa905fe5d4"

  tasks:

    # not required but makes code cleaner
    - name: Create a list of installation paths
      ansible.builtin.set_fact:
        installation_paths: "{{ installation_paths|default({}) | combine( {item.version:   opt + '/' + (item.file | regex_replace('\\.tar\\.gz$', ''))  } ) }}"
      loop: "{{ paraview }}"

    - name: Download ParaView Binaries
      ansible.builtin.get_url:
        url: "https://www.paraview.org/paraview-downloads/download.php?submit=Download&version=v{{item.base_version}}&type=binary&os=Linux&downloadFile={{item.file}}"
        dest: "{{ ansible_env.HOME }}/Downloads/{{item.file}}"
        checksum: "{{item.checksum}}"
      loop: "{{ paraview }}"

    - name: Extract ParaView Binaries
      ansible.builtin.unarchive:
        src: "{{ ansible_env.HOME }}/Downloads/{{item.file}}"
        dest: "{{ opt }}"
        creates: "{{ installation_paths[ item.version] }}"
      loop: "{{ paraview }}"

    - name: Modify icons
      ansible.builtin.command:
        chdir: "{{ installation_paths[item.version] }}/share/icons/hicolor/96x96/apps"
        cmd: "convert paraview.png -gravity Center -fill white  -pointsize 30 -annotate 1 {{item.version}}  paraview-version.png "
        creates: "paraview-version.png"
      loop: "{{ paraview }}"

    - name: Create desktop entries
      ansible.builtin.template:
        src: ./paraview.desktop.j2
        dest: "{{ansible_env.HOME}}/.local/share/applications/paraview-{{item.version}}.desktop"
      vars:
        app_name: ParaView {{item.version}}
        executable: "{{ installation_paths[item.version] }}/bin/paraview"
        icon: "{{ installation_paths[item.version] }}/share/icons/hicolor/96x96/apps/paraview-version.png"
        version: "{{item.version}}"
      loop: "{{ paraview }}"

The associated paraview.desktop.j2 is based on the one that ParaView ships with but we have templated the interesting parts.

[Desktop Entry]
Version=1.0

Type=Application

Name={{app_name}}

Comment=ParaView {{version}}

Exec={{executable}} %f

TryExec={{executable}}

Icon={{icon}}

# This needs to be ParaView, otherwise the icon is not used  see https://askubuntu.com/questions/367396/what-does-the-startupwmclass-field-of-a-desktop-file-represent

StartupWMClass=ParaView

Categories=Qt;Science;DataVisualization;

Let’s hope this saves me more time in the future than the effort I spent creating it :).