Add Mattermost OIDC plugin installer

This commit is contained in:
2026-09-29 01:24:25 +02:00
parent da911ff607
commit 8ea53f6372
+977
View File
@@ -0,0 +1,977 @@
#!/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