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.
 
 

293 lines
9.8 KiB

#!/bin/bash
## compose: no-hooks
if [ -z "$SERVICE_DATASTORE" ]; then
echo "This script is meant to be run through 'compose' to work properly." >&2
exit 1
fi
version=0.1
usage="$exname [-h|--help] [--force|-f] [TARGET_VERSION]"
help="
USAGE:
$usage
DESCRIPTION:
Migrate the current nextcloud service to given target version. Don't
forget to change your =compose.yml= accordingly afterwards.
EXAMPLES:
$exname 21.0.0
"
no_hint=
force=
target=
while [ "$1" ]; do
case "$1" in
"--help"|"-h")
print_help >&2
exit 0
;;
"--force"|"-f")
force=yes
;;
"--no-hint")
no_hint=yes
;;
--*|-*)
err "Unexpected optional argument '$1'"
print_usage >&2
exit 1
;;
*)
[ -z "$target" ] && { target=$1 ; shift ; continue ; }
err "Unexpected positional argument '$1'"
print_usage >&2
exit 1
;;
esac
shift
done
. lib/common
nextcloud:code:version() {
cat "$SERVICE_DATASTORE/var/www/html/version.php" |
grep 'VersionString =' |
cut -f 3 -d ' ' |
cut -f 2 -d \'
}
current_image_version="${DOCKER_BASE_IMAGE#*:}"
current_image_version="${current_image_version%-myc}"
if ! [[ "$current_image_version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then
err "Current nextcloud version '$current_image_version' is unsupported yet."
exit 1
fi
if ! [ -e "$SERVICE_DATASTORE/var/www/html/version.php" ]; then
err "No code seem to have been deployed yet in datastore." \
"This is not supported yet."
exit 1
fi
current_code_version=$(nextcloud:code:version)
if [ "$current_code_version" != "$current_image_version" ]; then
err "Current code version ${WHITE}$current_code_version${NORMAL}" \
"mismatch with current image version" \
"${WHITE}$current_image_version${NORMAL}"
exit 1
fi
current_config_version=$(nextcloud:config:version)
info "Current config version: ${WHITE}$current_config_version${NORMAL}"
if [ "$current_config_version" != "$current_code_version" ]; then
warn "Current config version ${WHITE}$current_config_version${NORMAL}" \
"mismatch with current code version" \
"${WHITE}$current_code_version${NORMAL}"
echo " Will use the config version as reference for upgrade." >&2
fi
last_available_versions=(
$(DEBUG= docker:tags:fetch docker.0k.io/nextcloud 30 '[0-9]+\.[0-9+]\.[0-9]+-myc$' |
sed -r 's/-myc$//g' |
sort -rV)
)
## XXXvlab: put this in kal-shlib-common
version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
last_upgradable_versions=()
for v in "${last_available_versions[@]}"; do
if version_gt "$v" "$current_config_version"; then
last_upgradable_versions+=("$v")
fi
done
docker_version=$(docker info --format '{{.ServerVersion}}')
last_compatible_versions=()
for v in "${last_upgradable_versions[@]}"; do
if version_gt "$docker_version" 20.10.0; then
last_compatible_versions+=("$v")
continue
fi
if version_gt "26.99.99" "$v"; then
last_compatible_versions+=("$v")
fi
done
if [ "${#last_upgradable_versions[@]}" == 0 ]; then
info "${DARKYELLOW}nextcloud${NORMAL} is already ${GREEN}up-to-date${NORMAL}."
exit 0
fi
if [ -z "$target" ]; then
info "Target latest version: ${WHITE}${last_available_versions[0]}${NORMAL}"
target=${last_upgradable_versions[0]}
else
if [[ " ${last_available_versions[*]} " != *" $target "* ]]; then
err "Invalid version ${WHITE}$target${NORMAL} selected, please specify one of:"
for v in "${last_upgradable_versions[@]}"; do
echo " - $v"
done >&2
exit 1
fi
info "Target version ${WHITE}$target${NORMAL}"
fi
if [[ " ${last_compatible_versions[*]} " != *" $target "* ]]; then
err "Sorry, ${DARKYELLOW}$SERVICE_NAME${NORMAL} ${WHITE}$target${NORMAL}" \
"require docker version >= ${WHITE}20.10${NORMAL} (current: $docker_version)"
echo " Nextcloud versions <= ${WHITE}27${NORMAL} are still supported." >&2
echo " You can specify one of:" >&2
for v in "${last_compatible_versions[@]}"; do
echo " - $v" >&2
done
exit 1
fi
upgrade_path=($(echo "${last_upgradable_versions[*]}" | tr ' ' '\n' | uniq -w 3 | sort -V))
containers="$(get_running_containers_for_service "$SERVICE_NAME")"
container_stopped=()
if [ -n "$containers" ]; then
#err "Running container(s) for $DARKYELLOW$SERVICE_NAME$NORMAL are still running:"
for container in $containers; do
docker stop "$container" >/dev/null || {
err "Failed to stop container '$container'."
exit 1
}
docker rm "$container" > /dev/null || {
err "Couldn't delete container '$container'."
}
container_stopped+=("$container")
done
fi
## XXXvlab: taking first container is probably not a good idea
container="$(echo "$containers" | head -n 1)"
settmpdir MIGRATION_TMPDIR
set -o pipefail
for image_version in "${upgrade_path[@]}"; do
while true; do
patched=()
current_code_version=$(nextcloud:code:version)
current_config_version=$(nextcloud:config:version)
if [ "$current_config_version" == "$image_version" ]; then
err "Unexpected step where config version ${WHITE}$current_config_version${NORMAL} is same than image version"
exit 1
fi
if ! version_gt "$image_version" "$current_config_version"; then
err "Unexpected step where config version ${WHITE}$current_config_version${NORMAL} is greater than image version ${WHITE}$image_version${NORMAL}"
exit 1
fi
if (( ${image_version%%.*} - ${current_config_version%%.*} > 1 )); then
err "Unexpected step where config version ${WHITE}$current_config_version${NORMAL} is more than one major version less than image version ${WHITE}$image_version${NORMAL}"
exit 1
fi
docker rmi "docker.0k.io/nextcloud:${current_config_version}-myc" >/dev/null 2>&1 || true
if [ "$current_code_version" == "$image_version" ]; then
## Code already setup, we need to call ``occ upgrade`` by our selves
info "Upgrading ${WHITE}$current_config_version${NORMAL} => ${WHITE}$image_version${NORMAL} (db)"
compose --no-hooks \
--add-compose-content="$SERVICE_NAME:
docker-compose:
image: docker.0k.io/nextcloud:${image_version}-myc" \
run --rm \
-u www-data --entrypoint /var/www/html/occ "$SERVICE_NAME" \
upgrade 2>&1 |
tee "$MIGRATION_TMPDIR/migration.log"
errlvl="$?"
else
## Code will be upgraded
info "Upgrading ${WHITE}$current_config_version${NORMAL} => ${WHITE}$image_version${NORMAL} (code, db)"
compose --no-hooks \
--add-compose-content="$SERVICE_NAME:
docker-compose:
image: docker.0k.io/nextcloud:${image_version}-myc" \
run --rm \
-v "$CHARM_PATH"/src/fake-apache:/usr/bin/apache \
--entrypoint /entrypoint.sh "$SERVICE_NAME" apache 2>&1 |
tee "$MIGRATION_TMPDIR/migration.log"
errlvl="$?"
fi
[ "$errlvl" == 0 ] && continue 2
##
## Damage control, there are some things we can solve
##
if grep "^Update failed" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1; then
## XXXvlab: this comes from and should move to onlyoffice charm in
## some way.
if grep "Update app onlyoffice" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1 && (
grep "SQLSTATE" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1 ||
grep "^Database error when running migration latest for app onlyoffice" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1 ); then
if [ -e "$DATASTORE"/"$SERVICE_NAME/var/www/html/custom_apps/onlyoffice/lib/Migration/Version070400Date20220607111111.php" ]; then
patch="$CHARM_PATH/../onlyoffice/src/patch/00-onlyoffice-nextcloud.patch"
if ! [[ " ${patched[*]} " == *" $patch "* ]]; then
if (
cd "$DATASTORE"/"$SERVICE_NAME/var/www/html/custom_apps/onlyoffice/";
patch -Np1 --dry-run < "$patch" ); then
info "Found OnlyOffice issue, correcting it, and retrying."
(
cd "$DATASTORE"/"$SERVICE_NAME/var/www/html/custom_apps/onlyoffice/";
patch -Np1 < "$patch"
) || exit 1
patched+=("$patch")
continue
fi
fi
fi
fi
fi
err "Upgrade to ${WHITE}$image_version${NORMAL} ${DARKRED}failed${NORMAL}. Aborting."
exit 1
done
done
if grep "^Nextcloud is in maintenance mode" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1; then
info "Forcing maintenance mode off"
compose --no-hooks \
--add-compose-content="$SERVICE_NAME:
docker-compose:
image: docker.0k.io/nextcloud:${target}-myc" \
run --rm \
-u www-data --entrypoint /var/www/html/occ "$SERVICE_NAME" \
maintenance:mode --off
fi
info "Successfully upgraded from ${WHITE}$current_config_version${NORMAL} to ${WHITE}$target${NORMAL}"
if [ -z "$no_hint" ]; then
cat <<EOF >&2
Don't forget to force the version in your \`\`compose.yml\`\`. For instance:
${DARKYELLOW}$SERVICE_NAME${NORMAL}:
${DARKGRAY}# ...${NORMAL}
${WHITE}docker-compose${NORMAL}:
${WHITE}image${NORMAL}: docker.0k.io/nextcloud:${target}-myc
${DARKGRAY}# ...${NORMAL}
EOF
fi