Reinstall a custom installed package, based on its version

I want to decide whether to reinstall an existing minikube if it has a version smaller then x.
Target is Debian 12, but my example package (minikube) is not a repository package, but was installed manually. Therefore package_facts (bein my first idea) apparently is the wrong hammer here.

I can extract the current version with a bash command minikube version | head -n1 | tail -n1 | cut -d ' ' -f 3 | sed 's/v//'.

This is my first attempt to solve this:

$ cat package_facts.yml 
---
- name: recommend minikube upgrade
  hosts: "{{ targets | default('all') }}"

  tasks:

    - name: get minikube version
        ansible.builtin.shell:
          cmd: "minikube version | head -n1 | tail -n1 | cut -d ' ' -f 3 | sed 's/v//'" 
        register: minikube_version

    - name: debug
        debug:
          var: minikube_version.stdout

    - name: recommend new install
      debug:
        msg: "please upgrade minikube"
      when: minikube_version.stdout != '1.33.2'

this works, but I believe only based on comparing the strings 1.33.2 with the string 1.33.1 (which is the currently installed version).

Can anybody point me to how I can make this more ‘mathematical’ so I can say `when: minikube_version.stdout < ‘1.33.2’ (which does not work as is).


Edit:

I just realize that my whole idea is besides the fact that 1.33.2 is not a number even, so this gets even more inexplicable

You can use the ansible.builtin.version test:

    - name: recommend new install
      debug:
        msg: "please upgrade minikube"
      when: minikube_version.stdout is ansible.builtin.version('1.33.2', '<')
4 Likes

Another avenue you could pursue, check out DebianRepository/SetupWithReprepro - Debian Wiki (I currently use that for custom build Debs) or GitHub - rcrowley/freight: A modern take on the Debian archive. (this one is old, but it worked fine last I checked).

This will allow you to run your own APT based repo, if you then add the package version you wish to have and configure the repo on all your target hosts, you can use ‘normal’ update playbooks to update your systems.

Just to note, this tail is pointless; head -n1 only outputs one line.

Since you’re using sed anyway, you could also do all of this manipulation at once:

cmd: minikube version | sed -e 's/.*v//; q'

Or use awk to do likewise:

cmd: minikube version  | awk 'NR==1 {print substr($3, 2)}'

(Not that there’s anything really wrong with your multi-command pipeline.)

Or, of course, you can also do the manipulation in Ansible.

- hosts: minikube_hosts
  vars:
    minikube_installed_version: "{{ minikube_version.stdout_lines.0 | split | last | replace('v', '') }}"
    minikube_needs_upgrade: "{{ minikube_installed_version is ansible.builtin.version('1.33.2', '<') }}"
  tasks:
    - name: Get minikube version
      command:
        cmd: minikube version
      changed_when: false
      register: minikube_version

    - name: Upgrade minikube
      debug:
        msg: Upgrade task goes here (installed version is {{ minikube_installed_version }})
      when: minikube_needs_upgrade
TASK [Get minikube version] ****************************************************
ok: [amenable-dobyoshi.mx.x.mail.umich.edu]

TASK [Upgrade minikube] ********************************************************
ok: [amenable-dobyoshi.mx.x.mail.umich.edu] =>
    msg: Upgrade task goes here (installed version is 1.33.1)
2 Likes

A word of caution if you’re running shell pipelines with things like “… | head -n 1 | …” and you also “set -o pipefail” as one is supposed to do. Some programs (I’m looking at you, “tar -tvf”) will fail when a downstream “head” quits listening after having seen sufficient data. And that will cause your pipeline to fail (even though it does what you want it to), and that will cause your task to fail.

sed” on the other hand has the courtesy to absorb all the incoming data even if you’re only addressing the first line(s). We learned this the hard way, er, so you don’t have to.
You’re welcome!

2 Likes

true, those are much slicker, then the monster I created. thx