frappe_docker/scripts/easy-docker/lib/app/wizard/flows/manage/stack.sh

451 lines
17 KiB
Bash
Executable file

#!/usr/bin/env bash
handle_manage_selected_stack_flow() {
local stack_name="${1}"
local stack_dir=""
local stack_action=""
local apps_action=""
local updates_action=""
local stack_metadata_path=""
local stack_apps_path=""
local stack_env_path=""
local custom_apps_update_status=0
local compose_start_status=0
local stack_runtime_status=""
local stack_frappe_branch=""
local stack_custom_image_ref=""
local stack_custom_tag=""
local custom_tag_prompt_status=0
local custom_tag_update_status=0
local missing_custom_image_action=""
local delete_stack_confirmation_action=""
local delete_stack_keyword=""
stack_dir="$(get_stack_dir_by_name "${stack_name}" || true)"
if [ -z "${stack_dir}" ]; then
show_warning_and_wait "Could not resolve stack directory for '${stack_name}'." 2
return "${FLOW_CONTINUE}"
fi
while true; do
get_stack_compose_runtime_status_label stack_runtime_status "${stack_dir}"
stack_frappe_branch="$(get_stack_frappe_branch "${stack_dir}" || true)"
stack_custom_image_ref="$(get_stack_custom_image_ref "${stack_dir}" || true)"
stack_action="$(show_manage_stack_actions_menu "${stack_name}" "${stack_dir}" "${stack_runtime_status}" || true)"
case "${stack_action}" in
"Apps")
while true; do
apps_action="$(show_manage_stack_apps_menu "${stack_name}" "${stack_dir}" "${stack_frappe_branch}" || true)"
case "${apps_action}" in
"Select apps and branches")
if update_stack_custom_modular_apps "${stack_dir}"; then
:
else
custom_apps_update_status=$?
case "${custom_apps_update_status}" in
2 | 130)
continue
;;
3)
stack_metadata_path="${stack_dir}/metadata.json"
show_warning_and_wait "Cannot update app selection because metadata is missing: ${stack_metadata_path}" 3
continue
;;
*)
show_warning_and_wait "Could not update app selection (${custom_apps_update_status}) for stack: ${stack_name}" 3
continue
;;
esac
fi
stack_apps_path="${stack_dir}/apps.json"
show_warning_and_wait "App selection updated in ${stack_dir}/metadata.json and ${stack_apps_path}." 3
;;
"Back" | "")
break
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown apps action: ${apps_action}"
;;
esac
done
;;
"Updates")
while true; do
stack_custom_image_ref="$(get_stack_custom_image_ref "${stack_dir}" || true)"
updates_action="$(show_manage_stack_updates_menu "${stack_name}" "${stack_dir}" "${stack_frappe_branch}" "${stack_custom_image_ref}" || true)"
case "${updates_action}" in
"Update selected app branches")
if update_stack_selected_app_branches "${stack_dir}"; then
stack_apps_path="${stack_dir}/apps.json"
show_warning_and_wait "Selected app branches updated in ${stack_dir}/metadata.json and ${stack_apps_path}. Set the next custom image tag, build the updated image, restart the stack, and migrate the site to apply the update." 6
else
custom_apps_update_status=$?
case "${custom_apps_update_status}" in
2 | 130)
continue
;;
3)
stack_metadata_path="${stack_dir}/metadata.json"
show_warning_and_wait "Cannot update selected app branches because metadata is missing: ${stack_metadata_path}" 3
continue
;;
4)
show_warning_and_wait "No selected stack apps were found for branch updates. Select apps for the stack first." 4
continue
;;
*)
show_warning_and_wait "Could not update selected app branches (${custom_apps_update_status}) for stack: ${stack_name}" 3
continue
;;
esac
fi
;;
"Set next custom image tag")
stack_env_path="$(get_stack_env_path "${stack_dir}")"
if [ ! -f "${stack_env_path}" ]; then
show_warning_and_wait "Cannot update CUSTOM_TAG because the stack env file is missing: ${stack_env_path}" 4
continue
fi
if [ -z "$(get_stack_custom_image_name "${stack_dir}" || true)" ]; then
show_warning_and_wait "Cannot update CUSTOM_TAG because CUSTOM_IMAGE is missing in the stack env file." 4
continue
fi
if prompt_stack_custom_image_tag_with_cancel stack_custom_tag "${stack_dir}"; then
:
else
custom_tag_prompt_status=$?
case "${custom_tag_prompt_status}" in
2 | 130)
continue
;;
*)
show_warning_and_wait "Could not collect the next custom image tag (${custom_tag_prompt_status})." 3
continue
;;
esac
fi
if set_stack_custom_image_tag "${stack_dir}" "${stack_custom_tag}"; then
stack_custom_image_ref="$(get_stack_custom_image_ref "${stack_dir}" || true)"
show_warning_message "Custom image tag updated successfully: ${stack_custom_image_ref:-${stack_custom_tag}}"
if run_build_stack_custom_image_with_feedback "${stack_name}" "${stack_dir}"; then
:
else
continue
fi
else
custom_tag_update_status=$?
case "${custom_tag_update_status}" in
31)
show_warning_and_wait "Cannot update CUSTOM_TAG because the stack env file is missing: ${stack_env_path}" 4
;;
32)
show_warning_and_wait "Cannot update CUSTOM_TAG because the value is not a valid Docker image tag." 4
;;
33)
show_warning_and_wait "Cannot update CUSTOM_TAG because CUSTOM_IMAGE is missing in the stack env file." 4
;;
34)
show_warning_and_wait "Could not write the updated CUSTOM_TAG to ${stack_env_path}." 4
;;
*)
show_warning_and_wait "Could not update CUSTOM_TAG (${custom_tag_update_status})." 4
;;
esac
fi
;;
"Build updated image")
if run_build_stack_custom_image_with_feedback "${stack_name}" "${stack_dir}"; then
:
else
continue
fi
;;
"Back" | "")
break
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown update action: ${updates_action}"
;;
esac
done
;;
"Start stack in Docker Compose")
while true; do
show_warning_message "Starting stack with docker compose: ${stack_name}"
if start_stack_with_compose_from_metadata "${stack_dir}"; then
show_warning_and_wait "Stack started successfully with docker compose: ${stack_name}" 3
break
else
compose_start_status=$?
fi
case "${compose_start_status}" in
31)
show_warning_and_wait "Cannot start stack: metadata.json is missing in ${stack_dir}." 4
break
;;
32)
show_warning_and_wait "Cannot start stack: stack env file not found in ${stack_dir}." 4
break
;;
33)
show_warning_and_wait "Cannot start stack: topology is missing in metadata.json. Re-run the topology wizard for this stack." 4
break
;;
34)
show_warning_and_wait "Cannot start stack via docker compose for topology '${EASY_DOCKER_COMPOSE_ERROR_DETAIL}'. Use the topology-specific runbook path." 5
break
;;
35)
show_warning_and_wait "Cannot start stack: no compose files configured in metadata.json." 4
break
;;
36)
show_warning_and_wait "Cannot start stack: compose file is missing -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 4
break
;;
37)
show_warning_and_wait "docker compose up failed. Check the output above for details." 4
break
;;
38)
missing_custom_image_action="$(
show_missing_custom_image_start_menu "${stack_name}" "${stack_dir}" "${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" || true
)"
case "${missing_custom_image_action}" in
"Build custom image now")
if run_build_stack_custom_image_with_feedback "${stack_name}" "${stack_dir}"; then
continue
fi
break
;;
"Back" | "")
break
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown missing-image action: ${missing_custom_image_action}" 2
break
;;
esac
;;
39)
show_warning_and_wait "Cannot inspect custom image before start. Check Docker and try again. Details: ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 5
break
;;
*)
show_warning_and_wait "Cannot start stack with docker compose (${compose_start_status})." 4
break
;;
esac
done
;;
"Restart stack in Docker Compose")
while true; do
show_warning_message "Restarting stack with docker compose: ${stack_name}"
if restart_stack_with_compose_from_metadata "${stack_dir}"; then
show_warning_and_wait "Stack restarted successfully with docker compose: ${stack_name}" 3
break
else
compose_start_status=$?
fi
case "${compose_start_status}" in
57)
show_warning_and_wait "Cannot restart stack: metadata.json is missing in ${stack_dir}." 4
break
;;
58)
show_warning_and_wait "Cannot restart stack: stack env file not found in ${stack_dir}." 4
break
;;
59)
show_warning_and_wait "Cannot restart stack: topology is missing in metadata.json. Re-run the topology wizard for this stack." 4
break
;;
60)
show_warning_and_wait "Cannot restart stack via docker compose for topology '${EASY_DOCKER_COMPOSE_ERROR_DETAIL}'. Use the topology-specific runbook path." 5
break
;;
61)
show_warning_and_wait "Cannot restart stack: no compose files configured in metadata.json." 4
break
;;
62)
show_warning_and_wait "Cannot restart stack: compose file is missing -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 4
break
;;
63)
show_warning_and_wait "docker compose restart failed. Check the output above for details." 4
break
;;
64)
missing_custom_image_action="$(
show_missing_custom_image_start_menu "${stack_name}" "${stack_dir}" "${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" || true
)"
case "${missing_custom_image_action}" in
"Build custom image now")
if run_build_stack_custom_image_with_feedback "${stack_name}" "${stack_dir}"; then
continue
fi
break
;;
"Back" | "")
break
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown missing-image action: ${missing_custom_image_action}" 2
break
;;
esac
;;
65)
show_warning_and_wait "Cannot inspect custom image before restart. Check Docker and try again. Details: ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 5
break
;;
*)
show_warning_and_wait "Cannot restart stack with docker compose (${compose_start_status})." 4
break
;;
esac
done
;;
"Stop stack in Docker Compose")
show_warning_message "Stopping stack with docker compose: ${stack_name}"
if stop_stack_with_compose_from_metadata "${stack_dir}"; then
show_warning_and_wait "Stack stopped successfully with docker compose: ${stack_name}" 3
continue
else
compose_start_status=$?
fi
case "${compose_start_status}" in
41)
show_warning_and_wait "Cannot stop stack: metadata.json is missing in ${stack_dir}." 4
;;
42)
show_warning_and_wait "Cannot stop stack: stack env file not found in ${stack_dir}." 4
;;
43)
show_warning_and_wait "Cannot stop stack: topology is missing in metadata.json. Re-run the topology wizard for this stack." 4
;;
44)
show_warning_and_wait "Cannot stop stack via docker compose for topology '${EASY_DOCKER_COMPOSE_ERROR_DETAIL}'. Use the topology-specific runbook path." 5
;;
45)
show_warning_and_wait "Cannot stop stack: no compose files configured in metadata.json." 4
;;
46)
show_warning_and_wait "Cannot stop stack: compose file is missing -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 4
;;
47)
show_warning_and_wait "docker compose stop failed. Check the output above for details." 4
;;
*)
show_warning_and_wait "Cannot stop stack with docker compose (${compose_start_status})." 4
;;
esac
;;
"Delete stack")
delete_stack_confirmation_action="$(
show_manage_stack_delete_confirmation "${stack_name}" "${stack_dir}" || true
)"
case "${delete_stack_confirmation_action}" in
"Yes")
if ! prompt_manage_stack_delete_keyword_with_cancel delete_stack_keyword "${stack_name}"; then
continue
fi
if [ "${delete_stack_keyword}" != "delete" ]; then
continue
fi
show_warning_message "Deleting stack with docker compose resources: ${stack_name}"
if delete_stack_with_compose_from_metadata "${stack_dir}"; then
show_warning_and_wait "Stack deleted successfully with containers, networks, volumes, image, and stack directory: ${stack_name}" 5
return "${FLOW_CONTINUE}"
else
compose_start_status=$?
fi
case "${compose_start_status}" in
48)
show_warning_and_wait "Cannot delete stack: metadata.json is missing in ${stack_dir}." 4
;;
49)
show_warning_and_wait "Cannot delete stack: stack env file not found in ${stack_dir}." 4
;;
50)
show_warning_and_wait "Cannot delete stack: topology is missing in metadata.json. Re-run the topology wizard for this stack." 4
;;
51)
show_warning_and_wait "Cannot delete stack via docker compose for topology '${EASY_DOCKER_COMPOSE_ERROR_DETAIL}'. Use the topology-specific runbook path." 5
;;
52)
show_warning_and_wait "Cannot delete stack: no compose files configured in metadata.json." 4
;;
53)
show_warning_and_wait "Cannot delete stack: compose file is missing -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 4
;;
54)
show_warning_and_wait "docker compose down failed. Check the output above for details." 4
;;
55)
show_warning_and_wait "Stack resources were removed, but the configured custom image could not be deleted -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 5
;;
56)
show_warning_and_wait "Docker resources were removed, but the stack directory could not be deleted -> ${EASY_DOCKER_COMPOSE_ERROR_DETAIL}" 5
;;
*)
show_warning_and_wait "Cannot delete stack with docker compose (${compose_start_status})." 4
;;
esac
;;
"No" | "")
continue
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown delete-stack action: ${delete_stack_confirmation_action}" 2
;;
esac
;;
"Site")
if handle_manage_stack_site_flow "${stack_name}" "${stack_dir}"; then
:
else
compose_start_status=$?
case "${compose_start_status}" in
"${FLOW_EXIT_APP}")
return "${FLOW_EXIT_APP}"
;;
*)
continue
;;
esac
fi
;;
"Back" | "")
return "${FLOW_CONTINUE}"
;;
"Exit and close easy-docker")
return "${FLOW_EXIT_APP}"
;;
*)
show_warning_and_wait "Unknown stack action: ${stack_action}"
;;
esac
done
}