You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
4.4 KiB
113 lines
4.4 KiB
#!/bin/bash
|
|
|
|
# -------------------------------------------------------------------------------
|
|
# This script listens to an MQTT topic to receive image update notifications
|
|
# and triggers the system update process via bootc if the new digest is
|
|
# different from the one currently deployed.
|
|
#
|
|
# Dependencies:
|
|
# - bootc
|
|
# - jq
|
|
# - mosquitto_sub (from the mosquitto-clients package)
|
|
#
|
|
# Required environment variables:
|
|
# - MQTT_URL: The MQTT url.
|
|
# - MOSQUITTO_OPTS: The extra options to pass to mosquitto.
|
|
#
|
|
# -------------------------------------------------------------------------------
|
|
|
|
MQTT_URL="mqtts://mosquitto-build-multiarch.apps.nmasse-q2-2025.sandbox1038.opentlc.com:443/bootc/updates"
|
|
MOSQUITTO_OPTS="--insecure --cafile service-ca.crt -k 15"
|
|
|
|
# Exit immediately if a command fails, if an unset variable is used,
|
|
# or if a command in a pipeline fails.
|
|
set -Eeuo pipefail
|
|
|
|
# --- Log a message to stderr ----
|
|
function _log () {
|
|
echo "$@" >&2
|
|
}
|
|
|
|
_log "✅ Update script started."
|
|
|
|
# --- Function to run mosquitto ----
|
|
function get_mqtt_message () {
|
|
_log "ℹ️ Mosquitto command: mosquitto_sub $mosquitto_opts $MOSQUITTO_OPTS -L "$MQTT_URL" -C 1"
|
|
local return_code=0
|
|
mosquitto_sub $mosquitto_opts $MOSQUITTO_OPTS -L "$MQTT_URL" -C 1 || return_code=$?
|
|
_log "ℹ️ Mosquitto command returned with code: $return_code"
|
|
if [[ $? -ne 27 ]] && [[ $? -ne 0 ]]; then # 27 is the exit code for a timeout, which we can ignore
|
|
_log "❗️ Error: Mosquitto connection failed. Please check the MQTT URL and network connectivity."
|
|
return $?
|
|
fi
|
|
}
|
|
|
|
# 1. Get the current image and digest
|
|
_log "🔍 Checking the current image..."
|
|
CURRENT_IMAGE_REF=$(bootc status --format json | jq -r '.spec.image.image')
|
|
|
|
# Extracts the digest and the base image (e.g., registry/path/image)
|
|
# Handles the case where the image is tagged by digest (with '@')
|
|
if [[ "$CURRENT_IMAGE_REF" == *"@sha256:"* ]]; then
|
|
CURRENT_IMAGE_BASE=$(echo "$CURRENT_IMAGE_REF" | cut -d'@' -f1)
|
|
CURRENT_DIGEST=$(echo "$CURRENT_IMAGE_REF" | cut -d'@' -f2)
|
|
_log "ℹ️ Current image: $CURRENT_IMAGE_BASE"
|
|
_log "ℹ️ Current digest : $CURRENT_DIGEST"
|
|
elif [[ "$CURRENT_IMAGE_REF" == *":"* ]]; then
|
|
# If the image is tagged by a tag (e.g., :latest), we cannot compare the digest.
|
|
# The script will continue but will trigger an update on the first digest received.
|
|
CURRENT_IMAGE_BASE=$(echo "$CURRENT_IMAGE_REF" | cut -d':' -f1)
|
|
CURRENT_DIGEST=""
|
|
_log "⚠️ The current image ($CURRENT_IMAGE_REF) is using a tag. Any new digest notification will trigger an update."
|
|
else
|
|
CURRENT_IMAGE_BASE="$CURRENT_IMAGE_REF"
|
|
CURRENT_DIGEST=""
|
|
_log "⚠️ The current image ($CURRENT_IMAGE_REF) has neither digest nor tag. Any new digest notification will trigger an update."
|
|
fi
|
|
|
|
# --- Main Loop ---
|
|
mosquitto_opts="-W 10 --retained-only"
|
|
stale="1"
|
|
_log "♻️ Processing stale update triggers..."
|
|
while true; do
|
|
# 2. Wait for an MQTT message containing the new digest
|
|
_log "📡 Waiting for a message..."
|
|
# The `-C 1` flag makes mosquitto_sub exit after receiving one message.
|
|
NEW_DIGEST=$(get_mqtt_message)
|
|
|
|
if [[ -z "$NEW_DIGEST" ]]; then
|
|
_log "⚠️ No message received from the MQTT broker. Delaying for 10 seconds before retrying..."
|
|
sleep 10 # Short pause before retrying
|
|
else
|
|
_log "📩 New digest received: $NEW_DIGEST"
|
|
|
|
# 3. Compare the digests and act accordingly
|
|
if [[ "$NEW_DIGEST" != "$CURRENT_DIGEST" ]]; then
|
|
_log "✨ New digest detected! Starting the update process."
|
|
|
|
# Build the new full image reference
|
|
NEW_IMAGE_REF="${CURRENT_IMAGE_BASE}@${NEW_DIGEST}"
|
|
_log "ℹ️ New target image: $NEW_IMAGE_REF"
|
|
|
|
# Running update commands
|
|
_log "🚀 Executing 'bootc switch'..."
|
|
bootc switch "$NEW_IMAGE_REF"
|
|
|
|
_log "🔄 Rebooting the system to apply the update..."
|
|
reboot
|
|
|
|
# The script stops here due to the reboot
|
|
exit 0
|
|
else
|
|
_log "👍 The received digest is identical to the current one. No action required."
|
|
_log "😴 Returning to listening mode..."
|
|
fi
|
|
fi
|
|
|
|
# Up frow now, process only fresh messages
|
|
if [[ "$stale" -eq "1" ]]; then
|
|
_log "✨ Processing fresh update triggers only from now on."
|
|
mosquitto_opts="-R"
|
|
stale="0"
|
|
fi
|
|
done
|
|
|