feat(easy-docker): migrate sites after app install

This commit is contained in:
RocketQuack 2026-04-01 16:15:10 +02:00
parent da905fb1c4
commit 8d9b855ff4
4 changed files with 70 additions and 84 deletions

View file

@ -259,7 +259,6 @@ install_stack_apps_on_site() {
"${stack_dir}" \
"single-site" \
"${site_name}" \
"apps_installing" \
"${installed_app_lines}" \
"install-apps" \
"" \
@ -274,6 +273,26 @@ install_stack_apps_on_site() {
return 0
}
run_stack_site_migrate() {
local stack_dir="${1}"
local site_name="${2}"
local migrate_command=""
local migrate_output=""
migrate_command="$(
printf "bench --site %s migrate" \
"$(shell_quote_site_command_arg "${site_name}")"
)"
if ! run_stack_backend_bash_command_capture migrate_output "${stack_dir}" "${migrate_command}"; then
EASY_DOCKER_SITE_ERROR_DETAIL="$(printf "bench migrate failed for '%s'." "${site_name}")"
capture_stack_site_error_log "${stack_dir}" "site-migrate-error" "${migrate_output}" >/dev/null 2>&1 || true
return 64
fi
return 0
}
bootstrap_first_stack_site() {
local stack_dir="${1}"
local site_name="${2}"
@ -283,6 +302,7 @@ bootstrap_first_stack_site() {
local installed_app_lines=""
local site_create_status=0
local app_install_status=0
local site_migrate_status=0
local cleanup_status=0
if ! is_safe_stack_site_cleanup_name "${site_name}"; then
@ -315,7 +335,7 @@ bootstrap_first_stack_site() {
created_at="$(get_current_utc_timestamp)"
updated_at="${created_at}"
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "requested" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
return 58
fi
@ -339,7 +359,7 @@ bootstrap_first_stack_site() {
fi
updated_at="${created_at}"
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "creating" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
return 58
fi
@ -365,7 +385,7 @@ bootstrap_first_stack_site() {
fi
updated_at="$(get_current_utc_timestamp)"
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "created" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "" "create-site" "" "" "${created_at}" "${updated_at}"; then
return 58
fi
@ -400,8 +420,23 @@ bootstrap_first_stack_site() {
return "${app_install_status}"
fi
if run_stack_site_migrate "${stack_dir}" "${site_name}"; then
:
else
site_migrate_status=$?
case "${site_migrate_status}" in
64)
mark_stack_site_failed "${stack_dir}" "${site_name}" "${installed_app_lines}" "migrate-site" "${EASY_DOCKER_SITE_ERROR_DETAIL:-Site migration failed.}" "${EASY_DOCKER_SITE_ERROR_LOG_PATH}" "${created_at}" >/dev/null 2>&1 || true
;;
*)
mark_stack_site_failed "${stack_dir}" "${site_name}" "${installed_app_lines}" "migrate-site" "Unknown site migration failure." "${EASY_DOCKER_SITE_ERROR_LOG_PATH}" "${created_at}" >/dev/null 2>&1 || true
;;
esac
return "${site_migrate_status}"
fi
updated_at="$(get_current_utc_timestamp)"
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "ready" "${installed_app_lines}" "install-apps" "" "" "${created_at}" "${updated_at}"; then
if ! persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "${installed_app_lines}" "migrate-site" "" "" "${created_at}" "${updated_at}"; then
return 58
fi

View file

@ -75,10 +75,10 @@ get_stack_site_name() {
get_metadata_site_string_field "${stack_dir}/metadata.json" "name"
}
get_stack_site_state() {
get_stack_site_last_error() {
local stack_dir="${1}"
get_metadata_site_string_field "${stack_dir}/metadata.json" "state"
get_metadata_site_string_field "${stack_dir}/metadata.json" "last_error"
}
get_stack_site_created_at() {
@ -107,78 +107,29 @@ stack_has_site_record() {
stack_has_site_configured() {
local stack_dir="${1}"
local site_state=""
site_state="$(get_stack_site_state "${stack_dir}" || true)"
case "${site_state}" in
created | apps_installing | ready)
return 0
;;
*)
return 1
;;
esac
}
get_stack_site_status_label() {
local result_var="${1}"
local stack_dir="${2}"
local site_state=""
local site_name=""
local site_status_label=""
local last_error=""
site_state="$(get_stack_site_state "${stack_dir}" || true)"
site_name="$(get_stack_site_name "${stack_dir}" || true)"
last_error="$(get_stack_site_last_error "${stack_dir}" || true)"
case "${site_state}" in
"")
site_status_label="Not configured"
;;
requested)
site_status_label="Requested"
;;
creating)
site_status_label="Creating"
;;
created)
site_status_label="Created"
;;
apps_installing)
site_status_label="Installing apps"
;;
ready)
site_status_label="Ready"
;;
failed)
site_status_label="Failed"
;;
*)
site_status_label="${site_state}"
;;
esac
if [ -n "${site_name}" ]; then
site_status_label="${site_status_label} (${site_name})"
if [ -n "${site_name}" ] && [ -z "${last_error}" ]; then
return 0
fi
printf -v "${result_var}" "%s" "${site_status_label}"
return 0
return 1
}
get_stack_site_menu_entry() {
local result_var="${1}"
local stack_dir="${2}"
local site_name=""
local site_status_label=""
local menu_entry=""
site_name="$(get_stack_site_name "${stack_dir}" || true)"
if [ -z "${site_name}" ]; then
return 1
fi
get_stack_site_status_label site_status_label "${stack_dir}"
menu_entry="$(printf "%s | %s" "${site_name}" "${site_status_label}")"
printf -v "${result_var}" "%s" "${menu_entry}"
printf -v "${result_var}" "%s" "${site_name}"
return 0
}

View file

@ -33,21 +33,19 @@ build_stack_site_metadata_json_object() {
local result_var="${1}"
local site_mode="${2:-single-site}"
local site_name="${3:-}"
local site_state="${4:-not_created}"
local apps_installed_lines="${5:-}"
local last_action="${6:-}"
local last_error="${7:-}"
local error_log_path="${8:-}"
local created_at="${9:-}"
local updated_at="${10:-}"
local apps_installed_lines="${4:-}"
local last_action="${5:-}"
local last_error="${6:-}"
local error_log_path="${7:-}"
local created_at="${8:-}"
local updated_at="${9:-}"
local apps_installed_json_array=""
build_stack_site_apps_installed_json_array apps_installed_json_array "${apps_installed_lines}"
printf -v "${result_var}" '{\n "mode": "%s",\n "name": "%s",\n "state": "%s",\n "apps_installed": %s,\n "last_action": "%s",\n "last_error": "%s",\n "error_log_path": "%s",\n "created_at": "%s",\n "updated_at": "%s"\n }' \
printf -v "${result_var}" '{\n "mode": "%s",\n "name": "%s",\n "apps_installed": %s,\n "last_action": "%s",\n "last_error": "%s",\n "error_log_path": "%s",\n "created_at": "%s",\n "updated_at": "%s"\n }' \
"$(json_escape_string "${site_mode}")" \
"$(json_escape_string "${site_name}")" \
"$(json_escape_string "${site_state}")" \
"${apps_installed_json_array}" \
"$(json_escape_string "${last_action}")" \
"$(json_escape_string "${last_error}")" \
@ -60,13 +58,12 @@ persist_stack_site_metadata() {
local stack_dir="${1}"
local site_mode="${2:-single-site}"
local site_name="${3:-}"
local site_state="${4:-not_created}"
local apps_installed_lines="${5:-}"
local last_action="${6:-}"
local last_error="${7:-}"
local error_log_path="${8:-}"
local created_at="${9:-}"
local updated_at="${10:-}"
local apps_installed_lines="${4:-}"
local last_action="${5:-}"
local last_error="${6:-}"
local error_log_path="${7:-}"
local created_at="${8:-}"
local updated_at="${9:-}"
local metadata_path=""
local metadata_tmp_path=""
local site_json_object=""
@ -77,7 +74,7 @@ persist_stack_site_metadata() {
return 1
fi
build_stack_site_metadata_json_object site_json_object "${site_mode}" "${site_name}" "${site_state}" "${apps_installed_lines}" "${last_action}" "${last_error}" "${error_log_path}" "${created_at}" "${updated_at}"
build_stack_site_metadata_json_object site_json_object "${site_mode}" "${site_name}" "${apps_installed_lines}" "${last_action}" "${last_error}" "${error_log_path}" "${created_at}" "${updated_at}"
if ! awk -v site_object="${site_json_object}" '
BEGIN {
@ -167,7 +164,7 @@ mark_stack_site_failed() {
local updated_at=""
updated_at="$(get_current_utc_timestamp)"
persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "failed" "${apps_installed_lines}" "${last_action}" "${last_error}" "${error_log_path}" "${created_at}" "${updated_at}"
persist_stack_site_metadata "${stack_dir}" "single-site" "${site_name}" "${apps_installed_lines}" "${last_action}" "${last_error}" "${error_log_path}" "${created_at}" "${updated_at}"
}
clear_stack_site_metadata() {
@ -175,5 +172,5 @@ clear_stack_site_metadata() {
local updated_at=""
updated_at="$(get_current_utc_timestamp)"
persist_stack_site_metadata "${stack_dir}" "single-site" "" "not_created" "" "delete-site" "" "" "" "${updated_at}"
persist_stack_site_metadata "${stack_dir}" "single-site" "" "" "delete-site" "" "" "" "${updated_at}"
}

View file

@ -32,7 +32,7 @@ handle_manage_stack_site_flow() {
show_warning_message "Creating the first site for stack: ${stack_name}"
if bootstrap_first_stack_site "${stack_dir}" "${site_name}" "${admin_password}"; then
show_warning_and_wait "Site created successfully and selected stack apps were installed: ${site_name}" 3
show_warning_and_wait "Site created successfully, selected stack apps were installed, and bench migrate completed: ${site_name}" 3
continue
else
site_flow_status=$?
@ -61,7 +61,7 @@ handle_manage_stack_site_flow() {
show_warning_and_wait "Site bootstrap currently supports only MariaDB-backed single-host stacks." 4
;;
58)
show_warning_and_wait "The site state could not be written to metadata.json." 4
show_warning_and_wait "The site metadata could not be written to metadata.json." 4
;;
59)
show_warning_and_wait "Cannot create site: stack services are not ready yet. Wait and try again." 4
@ -78,6 +78,9 @@ handle_manage_stack_site_flow() {
63)
show_warning_and_wait "Cannot install the selected stack apps because at least one app is missing from the backend image. ${EASY_DOCKER_SITE_ERROR_DETAIL} ${EASY_DOCKER_SITE_ERROR_LOG_PATH:+See ${stack_dir}/${EASY_DOCKER_SITE_ERROR_LOG_PATH}}" 7
;;
64)
show_warning_and_wait "The site was created and apps were installed, but bench migrate failed. ${EASY_DOCKER_SITE_ERROR_DETAIL:-Check the output above.} ${EASY_DOCKER_SITE_ERROR_LOG_PATH:+See ${stack_dir}/${EASY_DOCKER_SITE_ERROR_LOG_PATH}}" 7
;;
*)
show_warning_and_wait "Site bootstrap failed (${site_flow_status})." 4
;;
@ -139,7 +142,7 @@ handle_manage_stack_site_flow() {
show_warning_and_wait "Cannot delete site because stack metadata, env, or compose inputs are incomplete." 4
;;
58)
show_warning_and_wait "The cleared site state could not be written to metadata.json." 4
show_warning_and_wait "The cleared site metadata could not be written to metadata.json." 4
;;
60)
show_warning_and_wait "Site deletion could not remove all site or database data automatically. Manual cleanup is required." 5