mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 13:55:08 +00:00
445 lines
14 KiB
Bash
Executable file
445 lines
14 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
easy_docker_test_repo_root() {
|
|
local helper_dir=""
|
|
|
|
helper_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
(cd "${helper_dir}/../.." && pwd)
|
|
}
|
|
|
|
easy_docker_test_begin() {
|
|
EASY_DOCKER_TEST_TMPDIR="$(mktemp -d)"
|
|
export EASY_DOCKER_TEST_TMPDIR
|
|
unset EASY_DOCKER_REPO_ROOT_OVERRIDE
|
|
}
|
|
|
|
easy_docker_test_end() {
|
|
if [ -n "${EASY_DOCKER_TEST_TMPDIR:-}" ] && [ -d "${EASY_DOCKER_TEST_TMPDIR}" ]; then
|
|
rm -rf "${EASY_DOCKER_TEST_TMPDIR}"
|
|
fi
|
|
}
|
|
|
|
easy_docker_test_bin_dir() {
|
|
printf '%s/bin\n' "${EASY_DOCKER_TEST_TMPDIR}"
|
|
}
|
|
|
|
easy_docker_test_write_executable() {
|
|
local target_path="${1}"
|
|
local system_bash=""
|
|
shift
|
|
|
|
system_bash="$(command -v bash)"
|
|
mkdir -p "$(dirname "${target_path}")"
|
|
|
|
{
|
|
printf '#!%s\n' "${system_bash}"
|
|
printf '%s\n' "$@"
|
|
} >"${target_path}"
|
|
chmod +x "${target_path}"
|
|
}
|
|
|
|
easy_docker_test_write_bin_command() {
|
|
local command_name="${1}"
|
|
local target_path=""
|
|
shift
|
|
|
|
target_path="$(easy_docker_test_bin_dir)/${command_name}"
|
|
easy_docker_test_write_executable "${target_path}" "$@"
|
|
}
|
|
|
|
easy_docker_test_prepend_bin_dir() {
|
|
PATH="$(easy_docker_test_bin_dir):${PATH}"
|
|
export PATH
|
|
}
|
|
|
|
easy_docker_test_source_common_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/core/commands.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/core/commands.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/core/messages.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/core/messages.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/core/json.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/core/json.sh"
|
|
}
|
|
|
|
easy_docker_test_source_core_render_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/core.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/core.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/compose/render.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/compose/render.sh"
|
|
}
|
|
|
|
easy_docker_test_source_apps_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/core.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/core.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/helpers.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/helpers.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/apps/metadata.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/apps/metadata.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/apps/persistence.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/apps/persistence.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/apps/catalog.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/apps/catalog.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/app/wizard/common/compose/build.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/wizard/common/compose/build.sh"
|
|
}
|
|
|
|
easy_docker_test_source_docker_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/checks/docker.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/checks/docker.sh"
|
|
}
|
|
|
|
easy_docker_test_source_jq_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/checks/jq.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/checks/jq.sh"
|
|
}
|
|
|
|
easy_docker_test_source_gum_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/install/gum/package_manager.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/install/gum/package_manager.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/install/gum/github_release.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/install/gum/github_release.sh"
|
|
# shellcheck source=scripts/easy-docker/lib/install/gum/ensure.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/install/gum/ensure.sh"
|
|
}
|
|
|
|
easy_docker_test_source_screen_modules() {
|
|
local repo_root=""
|
|
|
|
repo_root="$(easy_docker_test_repo_root)"
|
|
|
|
easy_docker_test_source_common_modules
|
|
|
|
# shellcheck source=scripts/easy-docker/lib/app/screen.sh
|
|
source "${repo_root}/scripts/easy-docker/lib/app/screen.sh"
|
|
}
|
|
|
|
easy_docker_test_source_screen_modules_with_tty_stdout() {
|
|
easy_docker_test_source_screen_modules
|
|
|
|
# shellcheck disable=SC2317
|
|
stdout_is_terminal() {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
easy_docker_test_create_repo_sandbox() {
|
|
local sandbox_name="${1}"
|
|
local sandbox_root=""
|
|
|
|
sandbox_root="${EASY_DOCKER_TEST_TMPDIR}/repo-${sandbox_name}"
|
|
mkdir -p "${sandbox_root}/.easy-docker/stacks" "${sandbox_root}/overrides"
|
|
printf '%s\n' "${sandbox_root}"
|
|
}
|
|
|
|
easy_docker_test_override_repo_root() {
|
|
EASY_DOCKER_REPO_ROOT_OVERRIDE="${1}"
|
|
export EASY_DOCKER_REPO_ROOT_OVERRIDE
|
|
}
|
|
|
|
easy_docker_test_stack_dir() {
|
|
local stack_name="${1}"
|
|
|
|
printf '%s/.easy-docker/stacks/%s\n' "${EASY_DOCKER_REPO_ROOT_OVERRIDE}" "${stack_name}"
|
|
}
|
|
|
|
easy_docker_test_install_docker_stub() {
|
|
local log_file=""
|
|
|
|
log_file="${EASY_DOCKER_TEST_TMPDIR}/docker.invocations"
|
|
|
|
# shellcheck disable=SC2016
|
|
easy_docker_test_write_bin_command docker \
|
|
'set -euo pipefail' \
|
|
"log_file=\"${log_file}\"" \
|
|
'printf '"'"'%s\n'"'"' "docker $*" >>"${log_file}"' \
|
|
'if [ "${1:-}" != "compose" ]; then' \
|
|
' echo "unexpected docker subcommand: ${1:-}" >&2' \
|
|
' exit 64' \
|
|
'fi' \
|
|
'if [ "${!#}" != "config" ]; then' \
|
|
' echo "expected docker compose config invocation" >&2' \
|
|
' exit 65' \
|
|
'fi' \
|
|
'printf '"'"'invocation=%s\n'"'"' "docker $*"' \
|
|
'printf '"'"'erpnext=%s\n'"'"' "${ERPNEXT_VERSION:-}"'
|
|
|
|
easy_docker_test_prepend_bin_dir
|
|
}
|
|
|
|
easy_docker_test_install_jq_stub() {
|
|
# shellcheck disable=SC2016
|
|
easy_docker_test_write_bin_command jq \
|
|
'set -euo pipefail' \
|
|
'raw_output=0' \
|
|
'exit_status=0' \
|
|
'filter_expr=""' \
|
|
'file_path=""' \
|
|
'arg_field_name=""' \
|
|
'arg_key=""' \
|
|
'arg_app_id=""' \
|
|
'while [ "$#" -gt 0 ]; do' \
|
|
' case "${1}" in' \
|
|
' -r)' \
|
|
' raw_output=1' \
|
|
' shift' \
|
|
' ;;' \
|
|
' -e)' \
|
|
' exit_status=1' \
|
|
' shift' \
|
|
' ;;' \
|
|
' --arg)' \
|
|
' case "${2}" in' \
|
|
' field_name) arg_field_name="${3}" ;;' \
|
|
' key) arg_key="${3}" ;;' \
|
|
' app_id) arg_app_id="${3}" ;;' \
|
|
' esac' \
|
|
' shift 3' \
|
|
' ;;' \
|
|
' --indent)' \
|
|
' shift 2' \
|
|
' ;;' \
|
|
' -*)' \
|
|
' shift' \
|
|
' ;;' \
|
|
' *)' \
|
|
' if [ -z "${filter_expr}" ]; then' \
|
|
' filter_expr="${1}"' \
|
|
' elif [ -z "${file_path}" ]; then' \
|
|
' file_path="${1}"' \
|
|
' else' \
|
|
' echo "unsupported jq stub arguments" >&2' \
|
|
' exit 2' \
|
|
' fi' \
|
|
' shift' \
|
|
' ;;' \
|
|
' esac' \
|
|
'done' \
|
|
'if [ -z "${filter_expr}" ]; then' \
|
|
' echo "missing jq filter" >&2' \
|
|
' exit 2' \
|
|
'fi' \
|
|
'cleanup_file=""' \
|
|
'if [ -n "${file_path}" ] && [ "${file_path}" != "-" ]; then' \
|
|
' payload_path="${file_path}"' \
|
|
'else' \
|
|
' payload_path="$(mktemp)"' \
|
|
' cleanup_file="${payload_path}"' \
|
|
' cat >"${payload_path}"' \
|
|
'fi' \
|
|
'jq_stub_cleanup() {' \
|
|
' if [ -n "${cleanup_file}" ] && [ -f "${cleanup_file}" ]; then' \
|
|
' rm -f "${cleanup_file}"' \
|
|
' fi' \
|
|
'}' \
|
|
'trap jq_stub_cleanup EXIT' \
|
|
'jq_stub_is_object() {' \
|
|
' awk '"'"'BEGIN { found=0 } /^[[:space:]]*$/ { next } { if ($0 ~ /^[[:space:]]*{/) found=1; exit } END { exit(found ? 0 : 1) }'"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_first_string_field() {' \
|
|
' local field_name="${1}"' \
|
|
' awk -v field_name="${field_name}" '"'"'match($0, "\"" field_name "\"[[:space:]]*:[[:space:]]*\"([^\"]*)\"", parts) { print parts[1]; exit }'"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_array_strings() {' \
|
|
' local key="${1}"' \
|
|
' awk -v key="${key}" '"'"'' \
|
|
' function emit_matches(segment, parts) {' \
|
|
' while (match(segment, /"([^"]+)"/, parts)) {' \
|
|
' print parts[1]' \
|
|
' segment = substr(segment, RSTART + RLENGTH)' \
|
|
' }' \
|
|
' }' \
|
|
' $0 ~ "\"" key "\"[[:space:]]*:[[:space:]]*\\[" {' \
|
|
' segment = $0' \
|
|
' sub(/^.*\[[[:space:]]*/, "", segment)' \
|
|
' emit_matches(segment)' \
|
|
' if (segment ~ /\]/) {' \
|
|
' exit' \
|
|
' }' \
|
|
' in_array = 1' \
|
|
' next' \
|
|
' }' \
|
|
' in_array {' \
|
|
' emit_matches($0)' \
|
|
' if ($0 ~ /\]/) {' \
|
|
' exit' \
|
|
' }' \
|
|
' }' \
|
|
' '"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_object_entries() {' \
|
|
' local key="${1}"' \
|
|
' awk -v key="${key}" '"'"'' \
|
|
' $0 ~ "\"" key "\"[[:space:]]*:[[:space:]]*\\{" { in_object = 1; next }' \
|
|
' in_object && /^[[:space:]]*}/ { exit }' \
|
|
' in_object && match($0, /"([^"]+)"[[:space:]]*:[[:space:]]*"([^"]+)"/, parts) { print parts[1] "|" parts[2] }' \
|
|
' '"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_lookup_object_value() {' \
|
|
' local object_key="${1}"' \
|
|
' local lookup_key="${2}"' \
|
|
' awk -v object_key="${object_key}" -v lookup_key="${lookup_key}" '"'"'' \
|
|
' $0 ~ "\"" object_key "\"[[:space:]]*:[[:space:]]*\\{" { in_object = 1; next }' \
|
|
' in_object && /^[[:space:]]*}/ { exit }' \
|
|
' in_object && match($0, /"([^"]+)"[[:space:]]*:[[:space:]]*"([^"]+)"/, parts) {' \
|
|
' if (parts[1] == lookup_key) {' \
|
|
' print parts[2]' \
|
|
' exit' \
|
|
' }' \
|
|
' }' \
|
|
' '"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_top_level_keys() {' \
|
|
' awk '"'"'match($0, /^ "([^"]+)":/, parts) { print parts[1] }'"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_count_delta() {' \
|
|
' local line="${1}"' \
|
|
' local opens=0' \
|
|
' local closes=0' \
|
|
' local tmp=""' \
|
|
' tmp="${line//[^\{]/}"' \
|
|
' opens=$((opens + ${#tmp}))' \
|
|
' tmp="${line//[^\[]/}"' \
|
|
' opens=$((opens + ${#tmp}))' \
|
|
' tmp="${line//[^\}]/}"' \
|
|
' closes=$((closes + ${#tmp}))' \
|
|
' tmp="${line//[^\]]/}"' \
|
|
' closes=$((closes + ${#tmp}))' \
|
|
' printf "%s\n" "$((opens - closes))"' \
|
|
'}' \
|
|
'jq_stub_top_level_value() {' \
|
|
' local key="${1}"' \
|
|
' local line=""' \
|
|
' local value=""' \
|
|
' local in_block=0' \
|
|
' local depth=0' \
|
|
' local delta=0' \
|
|
' while IFS= read -r line || [ -n "${line}" ]; do' \
|
|
' if [ "${in_block}" -eq 0 ]; then' \
|
|
' case "${line}" in' \
|
|
' " \"${key}\":"*)' \
|
|
' value="${line#*: }"' \
|
|
' if [[ "${value}" == \{* || "${value}" == \[* ]]; then' \
|
|
' printf "%s\n" "${value}"' \
|
|
' depth="$(jq_stub_count_delta "${value}")"' \
|
|
' if [ "${depth}" -le 0 ]; then' \
|
|
' return 0' \
|
|
' fi' \
|
|
' in_block=1' \
|
|
' else' \
|
|
' value="${value%,}"' \
|
|
' printf "%s\n" "${value}"' \
|
|
' return 0' \
|
|
' fi' \
|
|
' ;;' \
|
|
' esac' \
|
|
' else' \
|
|
' delta="$(jq_stub_count_delta "${line}")"' \
|
|
' if [ $((depth + delta)) -le 0 ]; then' \
|
|
' printf "%s\n" "${line%,}"' \
|
|
' return 0' \
|
|
' fi' \
|
|
' printf "%s\n" "${line}"' \
|
|
' depth=$((depth + delta))' \
|
|
' fi' \
|
|
' done <"${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_apps_custom_lines() {' \
|
|
' local repo=""' \
|
|
' local branch=""' \
|
|
' awk '"'"'' \
|
|
' /"custom"[[:space:]]*:[[:space:]]*\[/ { in_custom = 1; next }' \
|
|
' in_custom && /\]/ { exit }' \
|
|
' in_custom && match($0, /"repo"[[:space:]]*:[[:space:]]*"([^"]+)"/, parts) { repo = parts[1] }' \
|
|
' in_custom && match($0, /"branch"[[:space:]]*:[[:space:]]*"([^"]+)"/, parts) { branch = parts[1] }' \
|
|
' in_custom && repo != "" && branch != "" { print repo "|" branch; repo = ""; branch = "" }' \
|
|
' '"'"' "${payload_path}"' \
|
|
'}' \
|
|
'jq_stub_apps_json_refs() {' \
|
|
' awk '"'"'match($0, /"url"[[:space:]]*:[[:space:]]*"([^"]+)".*"branch"[[:space:]]*:[[:space:]]*"([^"]+)"/, parts) { print parts[1] "|" parts[2] }'"'"' "${payload_path}"' \
|
|
'}' \
|
|
'case "${filter_expr}" in' \
|
|
' "(.apps.predefined // []) | join(\",\")")' \
|
|
' output="$(jq_stub_array_strings "predefined" | paste -sd, -)"' \
|
|
' [ -n "${output}" ] && printf "%s\n" "${output}"' \
|
|
' ;;' \
|
|
' "(.apps.custom // [])[]? | select(has(\"repo\") and has(\"branch\")) | \"\\(.repo)|\\(.branch)\"")' \
|
|
' jq_stub_apps_custom_lines' \
|
|
' ;;' \
|
|
' "(.apps.predefined_branches // {}) | to_entries[]? | \"\\(.key)|\\(.value)\"")' \
|
|
' jq_stub_object_entries "predefined_branches"' \
|
|
' ;;' \
|
|
' ".apps.predefined_branches[\$app_id] // empty")' \
|
|
' jq_stub_lookup_object_value "predefined_branches" "${arg_app_id}"' \
|
|
' ;;' \
|
|
' "[.. | objects | .[\$field_name]? | select(type == \"string\")][0] // empty")' \
|
|
' jq_stub_first_string_field "${arg_field_name}"' \
|
|
' ;;' \
|
|
' "([.. | objects | .compose_files? | select(type == \"array\")] | .[0] // [])[]?")' \
|
|
' jq_stub_array_strings "compose_files"' \
|
|
' ;;' \
|
|
' ".site[\$field_name] // empty")' \
|
|
' jq_stub_first_string_field "${arg_field_name}"' \
|
|
' ;;' \
|
|
' "(.site.apps_installed // [])[]? | select(type == \"string\")")' \
|
|
' jq_stub_array_strings "apps_installed"' \
|
|
' ;;' \
|
|
' "type == \"object\"")' \
|
|
' if jq_stub_is_object; then' \
|
|
' [ "${exit_status}" -eq 0 ] && printf "true\n"' \
|
|
' exit 0' \
|
|
' fi' \
|
|
' [ "${exit_status}" -eq 1 ] && exit 1' \
|
|
' printf "false\n"' \
|
|
' exit 0' \
|
|
' ;;' \
|
|
' "keys_unsorted[]")' \
|
|
' jq_stub_top_level_keys' \
|
|
' ;;' \
|
|
' ".[\$key]")' \
|
|
' jq_stub_top_level_value "${arg_key}"' \
|
|
' ;;' \
|
|
' ".[]? | select((.url // \"\") != \"\" and (.branch // \"\") != \"\") | \"\\(.url)|\\(.branch)\"")' \
|
|
' jq_stub_apps_json_refs' \
|
|
' ;;' \
|
|
' *)' \
|
|
' echo "unsupported jq filter in stub: ${filter_expr}" >&2' \
|
|
' exit 2' \
|
|
' ;;' \
|
|
'esac'
|
|
|
|
easy_docker_test_prepend_bin_dir
|
|
}
|