Commit e57a7a77 authored by Ivan Mazhukin's avatar Ivan Mazhukin

implement build_container_script; resolve_builder_source_path

parent 8d9bdd72
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
set -euo pipefail set -euo pipefail
SCRIPT_NAME="$(basename "$0")" SCRIPT_REF="${BASH_SOURCE[0]-$0}"
SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")" SCRIPT_NAME="$(basename "$SCRIPT_REF")"
DEFAULT_REMOTE_HOST="${EPM_DOCKER_TEST_REMOTE_HOST:-localhost}" SCRIPT_PATH="$(realpath "$SCRIPT_REF" 2>/dev/null || printf '%s\n' "$SCRIPT_REF")"
DEFAULT_REMOTE_HOST="${EPM_DOCKER_TEST_REMOTE_HOST:-builder64}"
DEFAULT_REMOTE_USER="${EPM_DOCKER_TEST_REMOTE_USER:-builder-robot}"
DEFAULT_LOG_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test" DEFAULT_LOG_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test"
COMMAND="play" COMMAND="play"
...@@ -13,7 +15,7 @@ SYSTEM_INPUT="" ...@@ -13,7 +15,7 @@ SYSTEM_INPUT=""
SYSTEM_IMAGE="" SYSTEM_IMAGE=""
RUN_MODE="auto" RUN_MODE="auto"
REMOTE_HOST="$DEFAULT_REMOTE_HOST" REMOTE_HOST="$DEFAULT_REMOTE_HOST"
REMOTE_USER="" REMOTE_USER="$DEFAULT_REMOTE_USER"
SOURCE_KIND="local" SOURCE_KIND="local"
SOURCE_PATH="" SOURCE_PATH=""
BUILDER_USER="" BUILDER_USER=""
...@@ -21,6 +23,7 @@ BUILDER_PATH="" ...@@ -21,6 +23,7 @@ BUILDER_PATH=""
INTERNAL_LOCAL_RUN=0 INTERNAL_LOCAL_RUN=0
LOG_ROOT="$DEFAULT_LOG_ROOT" LOG_ROOT="$DEFAULT_LOG_ROOT"
LOG_FILE="" LOG_FILE=""
REMOTE_ARGS=()
usage() { usage() {
cat <<'EOF' cat <<'EOF'
...@@ -32,8 +35,8 @@ Options: ...@@ -32,8 +35,8 @@ Options:
--mode <auto|local|remote> Runner mode. Default: auto --mode <auto|local|remote> Runner mode. Default: auto
--remote Shortcut for --mode remote --remote Shortcut for --mode remote
--local Shortcut for --mode local --local Shortcut for --mode local
--remote-host <host> SSH host for fallback runner. Default: localhost --remote-host <host> SSH host for fallback runner. Default: builder64
--remote-user <user> SSH user with Docker access --remote-user <user> SSH user for fallback runner. Default: builder-robot
--eepm-source <local|builder64> --eepm-source <local|builder64>
eepm source selector. Default: local eepm source selector. Default: local
--eepm-dir <path> Explicit eepm tree path --eepm-dir <path> Explicit eepm tree path
...@@ -45,7 +48,7 @@ Options: ...@@ -45,7 +48,7 @@ Options:
Examples: Examples:
epm-docker-test.sh nginx fedora epm-docker-test.sh nginx fedora
epm-docker-test.sh play nginx Fedora/43 epm-docker-test.sh play nginx Fedora/43
epm-docker-test.sh --remote-user dockerbot --eepm-source builder64 nginx fedora:43 epm-docker-test.sh --remote-user builder-robot --eepm-source builder64 nginx fedora:43
EOF EOF
} }
...@@ -102,11 +105,6 @@ can_use_local_docker() { ...@@ -102,11 +105,6 @@ can_use_local_docker() {
docker info >/dev/null 2>&1 docker info >/dev/null 2>&1
} }
discover_remote_user() {
# TODO: implement remote user discovery for docker access.
return 1
}
user_home_dir() { user_home_dir() {
local user="$1" local user="$1"
local passwd_line local passwd_line
...@@ -137,9 +135,22 @@ project_suffix_from_pwd() { ...@@ -137,9 +135,22 @@ project_suffix_from_pwd() {
verify_eepm_tree() { verify_eepm_tree() {
local tree="$1" local tree="$1"
local epm_path
[[ -d "$tree" ]] || fatal "eepm tree is not a directory: $tree" [[ -d "$tree" ]] || fatal "eepm tree is not a directory: $tree"
[[ -f "$tree/epm" ]] || fatal "eepm tree does not contain ./epm: $tree"
epm_path="$tree/bin/eepm"
if [[ ! -e "$epm_path" ]]; then
fatal "eepm tree does not contain ./bin/eepm: $tree"
fi
if [[ ! -f "$epm_path" ]]; then
fatal "eepm entrypoint is not a regular file: $epm_path"
fi
if [[ ! -r "$epm_path" ]]; then
fatal "eepm entrypoint is not readable: $epm_path"
fi
} }
resolve_local_source_path() { resolve_local_source_path() {
...@@ -152,8 +163,14 @@ resolve_local_source_path() { ...@@ -152,8 +163,14 @@ resolve_local_source_path() {
} }
resolve_builder_source_path() { resolve_builder_source_path() {
# TODO: implement builder64 source discovery. local current_user source_user candidate
fatal "TODO: resolve_builder_source_path is not implemented yet"
current_user="$(id -un)"
source_user="${BUILDER_USER:-$current_user}"
candidate="${BUILDER_PATH:-/srv/$source_user/Projects/eepm}"
candidate="$(realpath "$candidate" 2>/dev/null || printf '%s\n' "$candidate")"
verify_eepm_tree "$candidate"
printf '%s\n' "$candidate"
} }
resolve_source_path() { resolve_source_path() {
...@@ -213,70 +230,142 @@ print_failure_excerpt() { ...@@ -213,70 +230,142 @@ print_failure_excerpt() {
build_container_script() { build_container_script() {
local script_path="$1" local script_path="$1"
# TODO: generate container bootstrap/run script.
fatal "TODO: build_container_script is not implemented yet" cat >"$script_path" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
TEST_COMMAND="$1"
APP_NAME="$2"
SOURCE_DIR="/work/eepm"
run_eepm() {
bash ./bin/eepm "$@"
}
os_id="unknown"
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
. /etc/os-release
os_id="${ID:-unknown}"
fi
printf '[container] bootstrap: os_id=%s\n' "$os_id" >&2
[[ -f "$SOURCE_DIR/bin/eepm" ]] || {
printf '[container] eepm tree does not contain ./bin/eepm\n' >&2
exit 3
}
export HOME="/tmp/epm-home"
mkdir -p "$HOME"
export PATH="$SOURCE_DIR/bin:$PATH"
cd "$SOURCE_DIR"
case "$os_id" in
altlinux|alt)
run_eepm --auto repo set etersoft
run_eepm update
run_eepm --auto install wget glibc-pthread file
;;
debian|ubuntu)
run_eepm update
run_eepm --auto install bash wget ca-certificates coreutils file
;;
*)
run_eepm --auto install wget file bash
;;
esac
case "$TEST_COMMAND" in
play)
exec bash ./bin/eepm play --auto "$APP_NAME"
;;
*)
printf '[container] unsupported test command: %s\n' "$TEST_COMMAND" >&2
exit 64
;;
esac
EOF
chmod +x "$script_path"
} }
run_container_locally() { run_container_locally() {
local resolved_source="$1" local resolved_source="$1"
local inner_script container_name local inner_script container_name
local current_user
local status
require_command docker require_command docker
inner_script="$(mktemp "${TMPDIR:-/tmp}/epm-docker-test-inner.XXXXXX.sh")" inner_script="$(mktemp "${TMPDIR:-/tmp}/epm-docker-test-inner.XXXXXX.sh")"
trap 'rm -f "$inner_script"' RETURN
build_container_script "$inner_script" build_container_script "$inner_script"
container_name="epm-test-$(slugify "$APP_NAME")-$(slugify "$SYSTEM_IMAGE")-$$" container_name="epm-test-$(slugify "$APP_NAME")-$(slugify "$SYSTEM_IMAGE")-$$"
info "Using eepm tree: $resolved_source" info "Using eepm tree: $resolved_source"
info "Target image: $SYSTEM_IMAGE" info "Target image: $SYSTEM_IMAGE"
info "Runner: local docker" current_user="$(id -un)"
if ((INTERNAL_LOCAL_RUN)); then
info "Runner: local docker (inside ssh session, user: $current_user)"
else
info "Runner: local docker"
fi
docker run --rm \ if docker run --rm \
--name "$container_name" \ --name "$container_name" \
--hostname epm-docker-test \ --hostname epm-docker-test \
--workdir /work/eepm \ --workdir /work/eepm \
--volume "$resolved_source:/work/eepm:ro" \ --volume "$resolved_source:/work/eepm:ro" \
--volume "$inner_script:/tmp/epm-docker-test-inner.sh:ro" \ --volume "$inner_script:/tmp/epm-docker-test-inner.sh:ro" \
"$SYSTEM_IMAGE" \ "$SYSTEM_IMAGE" \
bash /tmp/epm-docker-test-inner.sh "$COMMAND" "$APP_NAME" bash /tmp/epm-docker-test-inner.sh "$COMMAND" "$APP_NAME"; then
status=0
else
status=$?
fi
rm -f "$inner_script"
return "$status"
} }
build_remote_args() { build_remote_args() {
local -a args local explicit_source
local explicit_local_source
REMOTE_ARGS=(--internal-local-run --mode local)
args=(--internal-local-run --mode local)
if [[ "$SOURCE_KIND" == "local" ]]; then
if [[ "$SOURCE_KIND" == "local" || "$SOURCE_KIND" == "explicit" ]]; then explicit_source="${SOURCE_PATH:-$(pwd -P)}"
explicit_local_source="$(resolve_local_source_path)" explicit_source="$(realpath "$explicit_source")"
args+=(--eepm-source explicit --eepm-dir "$explicit_local_source") verify_eepm_tree "$explicit_source"
REMOTE_ARGS+=(--eepm-source explicit --eepm-dir "$explicit_source")
elif [[ "$SOURCE_KIND" == "explicit" ]]; then
[[ -n "$SOURCE_PATH" ]] || fatal "Explicit source path is empty"
explicit_source="$(realpath "$SOURCE_PATH" 2>/dev/null || printf '%s\n' "$SOURCE_PATH")"
verify_eepm_tree "$explicit_source"
REMOTE_ARGS+=(--eepm-source explicit --eepm-dir "$explicit_source")
else else
args+=(--eepm-source "$SOURCE_KIND") REMOTE_ARGS+=(--eepm-source "$SOURCE_KIND")
[[ -n "$BUILDER_USER" ]] && args+=(--builder-user "$BUILDER_USER") [[ -n "$BUILDER_USER" ]] && REMOTE_ARGS+=(--builder-user "$BUILDER_USER")
[[ -n "$BUILDER_PATH" ]] && args+=(--builder-path "$BUILDER_PATH") [[ -n "$BUILDER_PATH" ]] && REMOTE_ARGS+=(--builder-path "$BUILDER_PATH")
fi fi
args+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE") REMOTE_ARGS+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE")
printf '%s\0' "${args[@]}"
} }
run_container_via_ssh() { run_container_via_ssh() {
local target_user target local target
local -a ssh_args forwarded_args local -a ssh_args
require_command ssh require_command ssh
target_user="${REMOTE_USER:-$(discover_remote_user || true)}" [[ -n "$REMOTE_USER" ]] || fatal "Remote user is empty"
[[ -n "$target_user" ]] || fatal "Could not determine remote user with Docker access; use --remote-user" target="${REMOTE_USER}@${REMOTE_HOST}"
target="${target_user}@${REMOTE_HOST}"
info "Runner: ssh -> $target" info "Runner: ssh -> $target"
while IFS= read -r -d '' arg; do build_remote_args
forwarded_args+=("$arg")
done < <(build_remote_args)
ssh_args=( ssh_args=(
-o BatchMode=yes -o BatchMode=yes
...@@ -285,7 +374,7 @@ run_container_via_ssh() { ...@@ -285,7 +374,7 @@ run_container_via_ssh() {
bash -s -- bash -s --
) )
ssh "${ssh_args[@]}" "${forwarded_args[@]}" <"$SCRIPT_PATH" ssh "${ssh_args[@]}" "${REMOTE_ARGS[@]}" <"$SCRIPT_PATH"
} }
run_once() { run_once() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment