Commit e57a7a77 authored by Ivan Mazhukin's avatar Ivan Mazhukin

implement build_container_script; resolve_builder_source_path

parent 8d9bdd72
......@@ -2,9 +2,11 @@
set -euo pipefail
SCRIPT_NAME="$(basename "$0")"
SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")"
DEFAULT_REMOTE_HOST="${EPM_DOCKER_TEST_REMOTE_HOST:-localhost}"
SCRIPT_REF="${BASH_SOURCE[0]-$0}"
SCRIPT_NAME="$(basename "$SCRIPT_REF")"
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"
COMMAND="play"
......@@ -13,7 +15,7 @@ SYSTEM_INPUT=""
SYSTEM_IMAGE=""
RUN_MODE="auto"
REMOTE_HOST="$DEFAULT_REMOTE_HOST"
REMOTE_USER=""
REMOTE_USER="$DEFAULT_REMOTE_USER"
SOURCE_KIND="local"
SOURCE_PATH=""
BUILDER_USER=""
......@@ -21,6 +23,7 @@ BUILDER_PATH=""
INTERNAL_LOCAL_RUN=0
LOG_ROOT="$DEFAULT_LOG_ROOT"
LOG_FILE=""
REMOTE_ARGS=()
usage() {
cat <<'EOF'
......@@ -32,8 +35,8 @@ Options:
--mode <auto|local|remote> Runner mode. Default: auto
--remote Shortcut for --mode remote
--local Shortcut for --mode local
--remote-host <host> SSH host for fallback runner. Default: localhost
--remote-user <user> SSH user with Docker access
--remote-host <host> SSH host for fallback runner. Default: builder64
--remote-user <user> SSH user for fallback runner. Default: builder-robot
--eepm-source <local|builder64>
eepm source selector. Default: local
--eepm-dir <path> Explicit eepm tree path
......@@ -45,7 +48,7 @@ Options:
Examples:
epm-docker-test.sh nginx fedora
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
}
......@@ -102,11 +105,6 @@ can_use_local_docker() {
docker info >/dev/null 2>&1
}
discover_remote_user() {
# TODO: implement remote user discovery for docker access.
return 1
}
user_home_dir() {
local user="$1"
local passwd_line
......@@ -137,9 +135,22 @@ project_suffix_from_pwd() {
verify_eepm_tree() {
local tree="$1"
local epm_path
[[ -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() {
......@@ -152,8 +163,14 @@ resolve_local_source_path() {
}
resolve_builder_source_path() {
# TODO: implement builder64 source discovery.
fatal "TODO: resolve_builder_source_path is not implemented yet"
local current_user source_user candidate
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() {
......@@ -213,70 +230,142 @@ print_failure_excerpt() {
build_container_script() {
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() {
local resolved_source="$1"
local inner_script container_name
local current_user
local status
require_command docker
inner_script="$(mktemp "${TMPDIR:-/tmp}/epm-docker-test-inner.XXXXXX.sh")"
trap 'rm -f "$inner_script"' RETURN
build_container_script "$inner_script"
container_name="epm-test-$(slugify "$APP_NAME")-$(slugify "$SYSTEM_IMAGE")-$$"
info "Using eepm tree: $resolved_source"
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" \
--hostname epm-docker-test \
--workdir /work/eepm \
--volume "$resolved_source:/work/eepm:ro" \
--volume "$inner_script:/tmp/epm-docker-test-inner.sh:ro" \
"$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() {
local -a args
local explicit_local_source
args=(--internal-local-run --mode local)
if [[ "$SOURCE_KIND" == "local" || "$SOURCE_KIND" == "explicit" ]]; then
explicit_local_source="$(resolve_local_source_path)"
args+=(--eepm-source explicit --eepm-dir "$explicit_local_source")
local explicit_source
REMOTE_ARGS=(--internal-local-run --mode local)
if [[ "$SOURCE_KIND" == "local" ]]; then
explicit_source="${SOURCE_PATH:-$(pwd -P)}"
explicit_source="$(realpath "$explicit_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
args+=(--eepm-source "$SOURCE_KIND")
[[ -n "$BUILDER_USER" ]] && args+=(--builder-user "$BUILDER_USER")
[[ -n "$BUILDER_PATH" ]] && args+=(--builder-path "$BUILDER_PATH")
REMOTE_ARGS+=(--eepm-source "$SOURCE_KIND")
[[ -n "$BUILDER_USER" ]] && REMOTE_ARGS+=(--builder-user "$BUILDER_USER")
[[ -n "$BUILDER_PATH" ]] && REMOTE_ARGS+=(--builder-path "$BUILDER_PATH")
fi
args+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE")
printf '%s\0' "${args[@]}"
REMOTE_ARGS+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE")
}
run_container_via_ssh() {
local target_user target
local -a ssh_args forwarded_args
local target
local -a ssh_args
require_command ssh
target_user="${REMOTE_USER:-$(discover_remote_user || true)}"
[[ -n "$target_user" ]] || fatal "Could not determine remote user with Docker access; use --remote-user"
target="${target_user}@${REMOTE_HOST}"
[[ -n "$REMOTE_USER" ]] || fatal "Remote user is empty"
target="${REMOTE_USER}@${REMOTE_HOST}"
info "Runner: ssh -> $target"
while IFS= read -r -d '' arg; do
forwarded_args+=("$arg")
done < <(build_remote_args)
build_remote_args
ssh_args=(
-o BatchMode=yes
......@@ -285,7 +374,7 @@ run_container_via_ssh() {
bash -s --
)
ssh "${ssh_args[@]}" "${forwarded_args[@]}" <"$SCRIPT_PATH"
ssh "${ssh_args[@]}" "${REMOTE_ARGS[@]}" <"$SCRIPT_PATH"
}
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