#!/usr/bin/env bash script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" LOCK_DIR="/tmp/$(basename $0).$$.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" backup_date="$(date +%Y-%m-%d-%H%M%S)" MM_OIDC_REPOSITORY="https://github.com/server-camp/mattermost-oidc-plugin.git" MM_OIDC_RELEASE_BASE="https://github.com/server-camp/mattermost-oidc-plugin/releases/download" MM_OIDC_PLUGIN_ID="mattermost-oidc" MM_SOURCE_BASE="/usr/local/src/mattermost" MM_INSTALL_DIR="/opt/mattermost" MM_BIN="${MM_INSTALL_DIR}/bin/mattermost" MMCTL="${MM_INSTALL_DIR}/bin/mmctl" MM_CONFIG_FILE="${MM_INSTALL_DIR}/config/config.json" MM_LOCAL_SOCKET="/var/tmp/mattermost_local.socket" MM_SERVICE="mattermost.service" MM_USER="mattermost" MM_GROUP="mattermost" INSTALLATION_MODE="" MM_CURRENT_VERSION="" MM_NEW_VERSION="" MM_LATEST_VERSION="" MM_MIN_SERVER_VERSION="" MM_SERVER_VERSION="" MM_BUNDLE="" MM_BUNDLE_BACKUP="" MM_ROLLBACK_BUNDLE="" MM_PREVIOUS_PLUGIN_ENABLED=false MM_ROLLBACK_REQUIRED=false # ---------- # Base Function(s) # ---------- clean_up() { rm -rf "$LOCK_DIR" blank_line exit $1 } echononl(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n " $*\\c" 1>&2 else echo -e -n " $*" 1>&2 fi rm /tmp/shprompt$$ fi } fatal(){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mFatal\033[m ] $*" else echo -e " [ Fatal ] $*" fi echo "" if $terminal ; then echo -e " \033[1mScript terminated\033[m.." else echo -e " Script terminated.." fi echo "" clean_up 1 } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ] $*" else echo " [ Error ] $*" fi echo "" } warn (){ echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarning\033[m ] $*" else echo " [ Warning ] $*" fi echo "" } info (){ if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ] $*" echo "" fi } echo_ok() { if $terminal ; then echo -e "\033[85G[ \033[32mok\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[85G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[85G[ \033[33m\033[1mskipped\033[m ]" fi } blank_line() { if $terminal ; then echo "" fi } ask_yes_no() { local question="$1" local default_answer="${2:-no}" local answer="" local prompt="[yes/no]" if [[ "$default_answer" = "yes" ]]; then prompt="[yes/no, default: yes]" elif [[ "$default_answer" = "no" ]]; then prompt="[yes/no, default: no]" fi while true ; do echononl "$question $prompt: " read answer answer="${answer,,}" [[ -z "$answer" ]] && answer="$default_answer" case "$answer" in yes) return 0 ;; no) return 1 ;; *) warn "Wrong entry! Please enter 'yes' or 'no'." ;; esac done } version_ge() { [[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -1)" = "$2" ]] } plugin_state_json() { "$MMCTL" --local --json plugin list 2>> "$log_file" } installed_plugin_version() { plugin_state_json | python3 -c ' import json, sys plugin_id = sys.argv[1] try: data = json.load(sys.stdin) except Exception: raise SystemExit(1) if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict): data = data[0] def walk(obj): if isinstance(obj, dict): if obj.get("id") == plugin_id and obj.get("version"): print(obj["version"]) raise SystemExit(0) for value in obj.values(): walk(value) elif isinstance(obj, list): for value in obj: walk(value) walk(data) raise SystemExit(2) ' "$MM_OIDC_PLUGIN_ID" } plugin_is_enabled() { plugin_state_json | python3 -c ' import json, sys plugin_id = sys.argv[1] try: data = json.load(sys.stdin) except Exception: raise SystemExit(1) if isinstance(data, list) and len(data) == 1 and isinstance(data[0], dict): data = data[0] if not isinstance(data, dict): raise SystemExit(1) active = data.get("active") inactive = data.get("inactive") if not isinstance(active, list) or not isinstance(inactive, list): raise SystemExit(1) for plugin in active: if isinstance(plugin, dict) and plugin.get("id") == plugin_id: raise SystemExit(0) for plugin in inactive: if isinstance(plugin, dict) and plugin.get("id") == plugin_id: raise SystemExit(2) raise SystemExit(1) ' "$MM_OIDC_PLUGIN_ID" } restore_release_bundle() { if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then rm -f "$MM_BUNDLE" if mv "$MM_BUNDLE_BACKUP" "$MM_BUNDLE" > "$log_file" 2>&1 ; then MM_BUNDLE_BACKUP="" return 0 fi return 1 fi rm -f "$MM_BUNDLE" return 0 } cleanup_prepared_bundles() { if [[ -n "$MM_ROLLBACK_BUNDLE" ]]; then rm -f "$MM_ROLLBACK_BUNDLE" fi restore_release_bundle } rollback_plugin() { local rollback_failed=false local restore_command_failed=false local _rollback_version="" local _rollback_rc local _plugin_enabled_rc blank_line warn "Mattermost OIDC Plugin installation failed. Trying to restore the previous plugin state." if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then echononl "Restore Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.." if [[ -f "$MM_ROLLBACK_BUNDLE" ]] && "$MMCTL" --local plugin add --force "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else echo_failed restore_command_failed=true fi if $MM_PREVIOUS_PLUGIN_ENABLED ; then echononl "Restore previous plugin state 'enabled'.." if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then echo_ok else echo_failed restore_command_failed=true fi else echononl "Restore previous plugin state 'disabled'.." if "$MMCTL" --local plugin disable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then echo_ok else echo_failed restore_command_failed=true fi fi echononl "Verify restored plugin version '${MM_CURRENT_VERSION}'.." _rollback_version="$(installed_plugin_version 2>/dev/null)" if [[ "$_rollback_version" = "$MM_CURRENT_VERSION" ]]; then echo_ok else echo_failed rollback_failed=true fi echononl "Verify restored plugin state.." plugin_is_enabled _plugin_enabled_rc=$? if $MM_PREVIOUS_PLUGIN_ENABLED ; then if [[ $_plugin_enabled_rc -eq 0 ]]; then echo_ok else echo_failed rollback_failed=true fi else if [[ $_plugin_enabled_rc -eq 2 ]]; then echo_ok else echo_failed rollback_failed=true fi fi elif [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then installed_plugin_version > /dev/null 2>&1 _rollback_rc=$? echononl "Remove newly installed Mattermost OIDC Plugin.." if [[ $_rollback_rc -eq 2 ]]; then echo_ok elif [[ $_rollback_rc -eq 0 ]]; then if "$MMCTL" --local plugin delete "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then echo_ok else echo_failed restore_command_failed=true fi else echo_failed restore_command_failed=true fi echononl "Verify Mattermost OIDC Plugin was removed.." installed_plugin_version > /dev/null 2>&1 _rollback_rc=$? if [[ $_rollback_rc -eq 2 ]]; then echo_ok else echo_failed rollback_failed=true fi else rollback_failed=true fi if $rollback_failed ; then error "Automatic plugin rollback could not fully restore the previous state." return 1 fi if $restore_command_failed ; then warn "One or more rollback commands reported an error, but the previous plugin state was successfully verified." fi info "Previous Mattermost OIDC Plugin state was successfully restored." return 0 } fatal_with_plugin_rollback() { local failure_message="$1" if $MM_ROLLBACK_REQUIRED ; then if rollback_plugin ; then MM_ROLLBACK_REQUIRED=false if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then echononl "Remove temporary rollback bundle.." if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else echo_failed warn "Plugin rollback was successful, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed." fi fi if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then echononl "Remove previous release bundle backup.." if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then MM_BUNDLE_BACKUP="" echo_ok else echo_failed warn "Plugin rollback was successful, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed." fi fi fatal "${failure_message} The previous plugin state was successfully restored." else fatal "${failure_message} Automatic rollback could not fully restore the previous state. Manual intervention is required." fi fi fatal "$failure_message" } handle_signal() { trap - SIGHUP SIGINT SIGTERM blank_line warn "Installation interrupted by signal." if $MM_ROLLBACK_REQUIRED ; then if rollback_plugin ; then MM_ROLLBACK_REQUIRED=false cleanup_prepared_bundles || warn "Plugin rollback was successful, but previous release bundle state could not be fully restored." else error "Automatic rollback could not fully restore the previous plugin state. Manual intervention is required." fi else cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state." fi clean_up 1 } # ---------- # Jobhandling # ---------- trap 'handle_signal' SIGHUP SIGINT SIGTERM if ! mkdir "$LOCK_DIR" 2>/dev/null ; then echo "Cannot create lock directory '$LOCK_DIR'." exit 1 fi if [[ -t 1 ]] ; then terminal=true else fatal "Script must run in a terminal." fi # ========== # Begin Main Script # ========== if $terminal ; then echo "" echo -e "\033[1m----------\033[m" echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m" echo -e "\033[1m----------\033[m" fi blank_line # ---------- # Some checks # ---------- echononl "Check if script is running as root.." if [[ "$(id -u)" -eq 0 ]]; then echo_ok else echo_failed fatal "This script must be run as root." fi for _cmd in git curl tar awk grep sed sort python3 systemctl stat uname mv cp mkdir ; do echononl "Check for command '${_cmd}'.." if command -v "$_cmd" > /dev/null 2>&1 ; then echo_ok else echo_failed fatal "Required command '${_cmd}' was not found." fi done echononl "Check Mattermost binary.." if [[ -x "$MM_BIN" ]]; then echo_ok else echo_failed fatal "Mattermost binary '${MM_BIN}' was not found." fi echononl "Check mmctl binary.." if [[ -x "$MMCTL" ]]; then echo_ok else echo_failed fatal "mmctl binary '${MMCTL}' was not found." fi echononl "Check Mattermost service '${MM_SERVICE}'.." if systemctl is-active --quiet "$MM_SERVICE" ; then echo_ok else echo_failed fatal "Mattermost service '${MM_SERVICE}' is not active." fi echononl "Check Mattermost user '${MM_USER}'.." if id "$MM_USER" > /dev/null 2>&1 ; then echo_ok else echo_failed fatal "Mattermost user '${MM_USER}' does not exist." fi echononl "Check Mattermost group '${MM_GROUP}'.." if getent group "$MM_GROUP" > /dev/null 2>&1 ; then echo_ok else echo_failed fatal "Mattermost group '${MM_GROUP}' does not exist." fi echononl "Check Mattermost configuration '${MM_CONFIG_FILE}'.." if [[ -r "$MM_CONFIG_FILE" ]]; then echo_ok else echo_failed fatal "Mattermost configuration '${MM_CONFIG_FILE}' is not readable." fi echononl "Check Mattermost Local Mode configuration.." _local_data="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF' import json, sys with open(sys.argv[1], encoding="utf-8") as f: data = json.load(f) s = data.get("ServiceSettings", {}) print("true" if s.get("EnableLocalMode") is True else "false") print(s.get("LocalModeSocketLocation") or "/var/tmp/mattermost_local.socket") PY_EOF )" || { echo_failed fatal "Could not parse '${MM_CONFIG_FILE}'." } _local_enabled="$(printf '%s\n' "$_local_data" | sed -n '1p')" _local_socket="$(printf '%s\n' "$_local_data" | sed -n '2p')" if [[ "$_local_enabled" = "true" ]]; then MM_LOCAL_SOCKET="$_local_socket" echo_ok else echo_failed fatal "Mattermost Local Mode is disabled. Set ServiceSettings.EnableLocalMode to true and restart Mattermost first." fi echononl "Check Mattermost Local Mode socket '${MM_LOCAL_SOCKET}'.." if [[ -S "$MM_LOCAL_SOCKET" ]]; then echo_ok else echo_failed fatal "Mattermost Local Mode socket '${MM_LOCAL_SOCKET}' does not exist." fi echononl "Test mmctl Local Mode connection.." if "$MMCTL" --local plugin list > "$log_file" 2>&1 ; then echo_ok else echo_failed fatal "mmctl Local Mode connection failed. $(cat "$log_file")" fi echononl "Check Mattermost plugin configuration.." _plugin_settings="$(python3 - "$MM_CONFIG_FILE" <<'PY_EOF' import json, sys with open(sys.argv[1], encoding="utf-8") as f: data = json.load(f) s = data.get("PluginSettings", {}) print("true" if s.get("Enable") is True else "false") print("true" if s.get("EnableUploads") is True else "false") PY_EOF )" || { echo_failed fatal "Could not parse Mattermost plugin settings in '${MM_CONFIG_FILE}'." } _plugins_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '1p')" _plugin_uploads_enabled="$(printf '%s\n' "$_plugin_settings" | sed -n '2p')" if [[ "$_plugins_enabled" != "true" ]]; then echo_failed fatal "Mattermost plugins are disabled. Set PluginSettings.Enable to true and restart Mattermost first." elif [[ "$_plugin_uploads_enabled" != "true" ]]; then echo_failed fatal "Mattermost plugin uploads are disabled. Set PluginSettings.EnableUploads to true and restart Mattermost first." else echo_ok fi MM_SERVER_VERSION="$("$MM_BIN" version 2>/dev/null | awk -F': ' '$1 == "Version" {print $2; exit}')" [[ -n "$MM_SERVER_VERSION" ]] || fatal "Could not determine installed Mattermost version." # ---------- # Detect installation mode # ---------- echononl "Detect existing Mattermost OIDC plugin installation.." MM_CURRENT_VERSION="$(installed_plugin_version 2>/dev/null)" _plugin_version_rc=$? if [[ $_plugin_version_rc -eq 0 && -n "$MM_CURRENT_VERSION" ]]; then INSTALLATION_MODE="upgrade" plugin_is_enabled _plugin_enabled_rc=$? if [[ $_plugin_enabled_rc -eq 0 ]]; then MM_PREVIOUS_PLUGIN_ENABLED=true elif [[ $_plugin_enabled_rc -eq 2 ]]; then MM_PREVIOUS_PLUGIN_ENABLED=false else echo_failed fatal "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled or disabled." fi echo_ok elif [[ $_plugin_version_rc -eq 2 ]]; then INSTALLATION_MODE="initial-installation" MM_CURRENT_VERSION="" echo_ok else echo_failed fatal "Could not determine current Mattermost OIDC plugin state." fi # ---------- # Determine latest stable release # ---------- echononl "Determine latest stable Mattermost OIDC release.." MM_LATEST_VERSION="$(git ls-remote --tags --refs "$MM_OIDC_REPOSITORY" 2> "$log_file" \ | awk '{print $2}' \ | sed -nE 's#refs/tags/v([0-9]+\.[0-9]+\.[0-9]+)$#\1#p' \ | sort -V \ | tail -1)" if [[ -n "$MM_LATEST_VERSION" ]]; then echo_ok else echo_failed fatal "Could not determine latest stable release from '${MM_OIDC_REPOSITORY}'. $(cat "$log_file")" fi blank_line if [[ "$INSTALLATION_MODE" = "initial-installation" ]]; then echo " Installation mode....................: Initial installation" else echo " Installation mode....................: Upgrade" echo " Currently installed version.........: ${MM_CURRENT_VERSION}" fi echo " Installed Mattermost version........: ${MM_SERVER_VERSION}" echo " Latest stable OIDC version..........: ${MM_LATEST_VERSION}" blank_line while true ; do echononl "New Mattermost OIDC Plugin Version [${MM_LATEST_VERSION}]: " read MM_NEW_VERSION MM_NEW_VERSION="${MM_NEW_VERSION#v}" [[ -z "$MM_NEW_VERSION" ]] && MM_NEW_VERSION="$MM_LATEST_VERSION" echononl "Check release tag 'v${MM_NEW_VERSION}'.." if git ls-remote --exit-code --tags "$MM_OIDC_REPOSITORY" \ "refs/tags/v${MM_NEW_VERSION}" "refs/tags/v${MM_NEW_VERSION}^{}" \ > /dev/null 2> "$log_file" ; then echo_ok break else echo_failed warn "Tag 'v${MM_NEW_VERSION}' does not exist in the upstream repository." fi done if [[ "$INSTALLATION_MODE" = "upgrade" && "$MM_NEW_VERSION" = "$MM_CURRENT_VERSION" ]]; then blank_line warn "Mattermost OIDC Plugin ${MM_CURRENT_VERSION} is already installed." if ! ask_yes_no "Reinstall version ${MM_NEW_VERSION}" "no" ; then info "Version ${MM_CURRENT_VERSION} is already installed. Nothing to do." clean_up 0 fi fi MM_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz" # ---------- # Summary # ---------- blank_line echo -e "\033[37m\033[1mMattermost OIDC Plugin installation settings:\033[m" blank_line echo " Installation mode....................: ${INSTALLATION_MODE}" [[ -n "$MM_CURRENT_VERSION" ]] && echo " Current plugin version...............: ${MM_CURRENT_VERSION}" echo " New plugin version...................: ${MM_NEW_VERSION}" echo " Latest stable version...............: ${MM_LATEST_VERSION}" echo " Installed Mattermost version........: ${MM_SERVER_VERSION}" echo " Repository...........................: ${MM_OIDC_REPOSITORY}" echo " Release bundle.......................: ${MM_BUNDLE}" echo " Plugin ID............................: ${MM_OIDC_PLUGIN_ID}" echo " Local Mode socket....................: ${MM_LOCAL_SOCKET}" blank_line if ! ask_yes_no "einverstanden" "no" ; then fatal "Stopped by user" fi # ---------- # Prepare source directory # ---------- blank_line # ---------- # Download release bundle # ---------- blank_line echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin release bundle..\033[m" blank_line echononl "Create source directory '${MM_SOURCE_BASE}'.." if mkdir -p "$MM_SOURCE_BASE" > "$log_file" 2>&1 ; then echo_ok else echo_failed fatal "$(cat "$log_file")" fi if [[ -e "$MM_BUNDLE" ]]; then MM_BUNDLE_BACKUP="${MM_BUNDLE}.${backup_date}" echononl "Backup existing release bundle.." if mv "$MM_BUNDLE" "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then echo_ok else echo_failed fatal "$(cat "$log_file")" fi else echononl "Backup existing release bundle.." echo_skipped fi echononl "Download Mattermost OIDC Plugin ${MM_NEW_VERSION}.." _release_url="${MM_OIDC_RELEASE_BASE}/v${MM_NEW_VERSION}/mattermost-oidc-${MM_NEW_VERSION}.tar.gz" if curl -fL --retry 2 --connect-timeout 15 -o "$MM_BUNDLE" "$_release_url" > "$log_file" 2>&1 ; then echo_ok else _download_error="$(cat "$log_file")" echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Could not download '${_release_url}'. ${_download_error}" fi echononl "Check release bundle archive.." if tar tzf "$MM_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Downloaded release bundle is not a valid gzip-compressed tar archive." fi echononl "Read and verify plugin metadata.." _plugin_json="$(tar xOf "$MM_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || { echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Could not read mattermost-oidc/plugin.json from release bundle." } _metadata="$(printf '%s' "$_plugin_json" | python3 -c ' import json, sys expected_id, expected_version = sys.argv[1:3] try: data = json.load(sys.stdin) except Exception: raise SystemExit(1) if data.get("id") != expected_id: raise SystemExit(2) if data.get("version") != expected_version: raise SystemExit(3) print(data.get("min_server_version", "")) ' "$MM_OIDC_PLUGIN_ID" "$MM_NEW_VERSION")" _metadata_rc=$? if [[ $_metadata_rc -eq 0 ]]; then MM_MIN_SERVER_VERSION="$_metadata" echo_ok else echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Plugin metadata does not match expected ID '${MM_OIDC_PLUGIN_ID}' and version '${MM_NEW_VERSION}'." fi if [[ -n "$MM_MIN_SERVER_VERSION" ]]; then echononl "Check Mattermost version (installed: ${MM_SERVER_VERSION}, required: ${MM_MIN_SERVER_VERSION}).." if version_ge "$MM_SERVER_VERSION" "$MM_MIN_SERVER_VERSION" ; then echo_ok else echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Mattermost ${MM_NEW_VERSION} requires Mattermost ${MM_MIN_SERVER_VERSION} or newer. Installed version is ${MM_SERVER_VERSION}." fi fi _arch="$(uname -m)" case "$_arch" in x86_64|amd64) _bundle_arch="amd64" ;; aarch64|arm64) _bundle_arch="arm64" ;; *) restore_release_bundle || warn "Could not restore previous release bundle." fatal "Unsupported system architecture '${_arch}'." ;; esac echononl "Check Linux server binary for architecture '${_bundle_arch}'.." if tar tzf "$MM_BUNDLE" | grep -qx "mattermost-oidc/server/dist/plugin-linux-${_bundle_arch}" ; then echo_ok else echo_failed restore_release_bundle || warn "Could not restore previous release bundle." fatal "Release bundle does not contain plugin-linux-${_bundle_arch}." fi # ---------- # Prepare rollback bundle # ---------- if [[ "$INSTALLATION_MODE" = "upgrade" ]]; then MM_ROLLBACK_BUNDLE="${MM_SOURCE_BASE}/mattermost-oidc-${MM_CURRENT_VERSION}.rollback-${backup_date}.tar.gz" blank_line echo -e "\033[37m\033[1mPrepare Mattermost OIDC Plugin rollback bundle..\033[m" blank_line echononl "Download rollback bundle for Mattermost OIDC Plugin ${MM_CURRENT_VERSION}.." _rollback_url="${MM_OIDC_RELEASE_BASE}/v${MM_CURRENT_VERSION}/mattermost-oidc-${MM_CURRENT_VERSION}.tar.gz" if curl -fL --retry 2 --connect-timeout 15 -o "$MM_ROLLBACK_BUNDLE" "$_rollback_url" > "$log_file" 2>&1 ; then echo_ok else _rollback_download_error="$(cat "$log_file")" echo_failed cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state." fatal "Could not prepare rollback bundle '${_rollback_url}'. No changes were made to the installed plugin. ${_rollback_download_error}" fi echononl "Check rollback bundle archive.." if tar tzf "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else echo_failed cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state." fatal "Rollback bundle for version '${MM_CURRENT_VERSION}' is not a valid gzip-compressed tar archive." fi echononl "Verify rollback bundle metadata.." _rollback_plugin_json="$(tar xOf "$MM_ROLLBACK_BUNDLE" mattermost-oidc/plugin.json 2> "$log_file")" || { echo_failed cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state." fatal "Could not read plugin metadata from rollback bundle." } if printf '%s' "$_rollback_plugin_json" | python3 -c ' import json, sys expected_id, expected_version = sys.argv[1:3] try: data = json.load(sys.stdin) except Exception: raise SystemExit(1) if data.get("id") != expected_id or data.get("version") != expected_version: raise SystemExit(1) ' "$MM_OIDC_PLUGIN_ID" "$MM_CURRENT_VERSION" ; then echo_ok else echo_failed cleanup_prepared_bundles || warn "Could not fully restore previous release bundle state." fatal "Rollback bundle metadata does not match plugin '${MM_OIDC_PLUGIN_ID}' version '${MM_CURRENT_VERSION}'." fi fi # ---------- # Install/upgrade plugin # ---------- blank_line echo -e "\033[37m\033[1mInstall Mattermost OIDC Plugin..\033[m" blank_line echononl "Install Mattermost OIDC Plugin ${MM_NEW_VERSION}.." MM_ROLLBACK_REQUIRED=true if "$MMCTL" --local plugin add --force "$MM_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else _install_error="$(cat "$log_file")" echo_failed fatal_with_plugin_rollback "Plugin installation failed. ${_install_error}" fi echononl "Enable Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}'.." if "$MMCTL" --local plugin enable "$MM_OIDC_PLUGIN_ID" > "$log_file" 2>&1 ; then echo_ok else _enable_error="$(cat "$log_file")" echo_failed fatal_with_plugin_rollback "Plugin was installed but could not be enabled. ${_enable_error}" fi # ---------- # Verify installation # ---------- blank_line echo -e "\033[37m\033[1mVerify Mattermost OIDC Plugin installation..\033[m" blank_line sleep 1 echononl "Verify installed plugin version '${MM_NEW_VERSION}'.." _verified_version="$(installed_plugin_version 2>/dev/null)" if [[ "$_verified_version" = "$MM_NEW_VERSION" ]]; then echo_ok else echo_failed fatal_with_plugin_rollback "Installed plugin version is '${_verified_version:-unknown}', expected '${MM_NEW_VERSION}'." fi echononl "Verify plugin is enabled.." plugin_is_enabled _plugin_enabled_rc=$? if [[ $_plugin_enabled_rc -eq 0 ]]; then echo_ok MM_ROLLBACK_REQUIRED=false elif [[ $_plugin_enabled_rc -eq 2 ]]; then echo_failed fatal_with_plugin_rollback "Plugin '${MM_OIDC_PLUGIN_ID}' is installed but not enabled." else echo_failed fatal_with_plugin_rollback "Could not determine whether Mattermost OIDC Plugin '${MM_OIDC_PLUGIN_ID}' is enabled." fi if [[ -n "$MM_ROLLBACK_BUNDLE" && -f "$MM_ROLLBACK_BUNDLE" ]]; then echononl "Remove temporary rollback bundle.." if rm -f "$MM_ROLLBACK_BUNDLE" > "$log_file" 2>&1 ; then echo_ok else echo_failed warn "Mattermost OIDC Plugin was successfully installed, but temporary rollback bundle '${MM_ROLLBACK_BUNDLE}' could not be removed." fi fi if [[ -n "$MM_BUNDLE_BACKUP" && -f "$MM_BUNDLE_BACKUP" ]]; then echononl "Remove previous release bundle backup.." if rm -f "$MM_BUNDLE_BACKUP" > "$log_file" 2>&1 ; then MM_BUNDLE_BACKUP="" echo_ok else echo_failed warn "Mattermost OIDC Plugin was successfully installed, but previous release bundle backup '${MM_BUNDLE_BACKUP}' could not be removed." fi fi # ---------- # Final information # ---------- blank_line echo -e "\033[37m\033[1mMattermost OIDC Plugin successfully installed.\033[m" blank_line echo " Installed version.....................: ${MM_NEW_VERSION}" echo " Plugin ID.............................: ${MM_OIDC_PLUGIN_ID}" echo " Release bundle........................: ${MM_BUNDLE}" echo " Mattermost version....................: ${MM_SERVER_VERSION}" echo " Minimum Mattermost version............: ${MM_MIN_SERVER_VERSION:-not specified}" echo " Status................................: enabled" blank_line clean_up 0