diff --git a/update-outpost-images.sh b/update-outpost-images.sh new file mode 100644 index 0000000..2ed6921 --- /dev/null +++ b/update-outpost-images.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +set -eu + +if [ "$(kubectl config current-context)" != 'kubernetes-admin@kubernetes' ]; then + echo 'Expected the homelab Kubernetes context; refusing to update outposts.' >&2 + exit 1 +fi + +# Authentik stores managed outpost image pins in its database. Keep them on +# the same release as the server; changing the Helm chart alone does not do so. +for entry in \ + 'ldap ghcr.io/goauthentik/ldap:2026.8.3' \ + 'radius ghcr.io/goauthentik/radius:2026.8.3' \ + 'rac ghcr.io/goauthentik/rac:2026.8.3' +do + name=${entry%% *} + image=${entry#* } + kubectl --namespace authentik exec deployment/authentik-worker -- \ + ak shell --command "from authentik.outposts.models import Outpost; o = Outpost.objects.get(name='$name', type='$name'); c = o.config; old = c.container_image; c.container_image = '$image'; o.config = c; o.save() if old != c.container_image else None; print('Outpost image:', o.name, c.container_image)" + attempt=0 + while [ "$(kubectl --namespace authentik get "deployment/ak-outpost-$name" --output='jsonpath={.spec.template.spec.containers[0].image}')" != "$image" ]; do + attempt=$((attempt + 1)) + if [ "$attempt" -ge 60 ]; then + echo "Timed out waiting for Authentik to update the $name deployment image." >&2 + exit 1 + fi + sleep 5 + done + # The outpost controller may recreate the Deployment during reconciliation, + # which makes `kubectl rollout status` fail with "object has been deleted". + attempt=0 + while [ "$(kubectl --namespace authentik get "deployment/ak-outpost-$name" --output='jsonpath={.status.availableReplicas}' 2>/dev/null)" != '1' ]; do + attempt=$((attempt + 1)) + if [ "$attempt" -ge 180 ]; then + echo "Timed out waiting for the $name outpost to become available." >&2 + exit 1 + fi + sleep 5 + done + echo "Outpost $name is available on $image" +done