Commit 5e065f15 authored by Ivan Mazhukin's avatar Ivan Mazhukin

add "--exec" for executing custom commands inside containers

parent 902cbfd2
......@@ -39,6 +39,15 @@
./epm-docker-test.sh ayugram --preset all
```
Выполнить произвольную команду в контейнере:
```bash
./epm-docker-test.sh --exec "cat /etc/os-release | head -3" fedora alt:p11
./epm-docker-test.sh --exec "epm install wget && wget --version" --preset main
```
При использовании `--exec` имя приложения не указывается — позиционные аргументы трактуются как системы.
Параллельный запуск:
```bash
......@@ -106,6 +115,7 @@
- `--builder-path <path>`: явный builder64-путь вместо дефолта
- `--preset <all|russian|main>`: добавить набор систем
- `--latest`: передать `--latest` в `epm play` (принудительно последняя версия)
- `--exec <cmd>`: выполнить произвольную shell-команду вместо `epm play` (bootstrap системы выполняется как обычно)
- `--parallel`: запустить все тесты параллельно
- `-j <N>`: запустить не более N тестов одновременно
- `--log-root <path>`: каталог для логов
......
......@@ -10,6 +10,7 @@ DEFAULT_LOG_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test"
COMMAND="play"
PLAY_FLAGS=()
EXEC_COMMAND=""
APP_NAME=""
SYSTEM_IMAGE=""
RUN_MODE="auto"
......@@ -59,6 +60,7 @@ Usage:
epm-docker-test.sh [options] play <app> <system> [<system> ...]
epm-docker-test.sh [options] <app> <system> [<system> ...]
epm-docker-test.sh [options] <app> --preset <name>
epm-docker-test.sh --exec <cmd> [options] <system> [<system> ...]
Options:
--mode <auto|local|remote> Runner mode. Default: auto
......@@ -74,6 +76,7 @@ Options:
--preset <all|russian|main>
Add a named system preset
--latest Pass --latest to epm play
--exec <cmd> Run arbitrary shell command instead of epm play
--parallel Run tests in parallel (all at once)
-j <N> Run up to N tests in parallel
--log-root <path> Directory for saved logs
......@@ -85,6 +88,7 @@ Examples:
epm-docker-test.sh telegram --preset main
epm-docker-test.sh play telegram Fedora/43
epm-docker-test.sh --remote-user builder-robot --eepm-source builder64 telegram fedora:43
epm-docker-test.sh --exec "epm install wget && wget --version" fedora alt:p11
EOF
}
......@@ -387,7 +391,7 @@ create_log_file() {
[[ -w "$log_root" ]] || fatal "Could not write to log root: $log_root"
fi
safe_app="$(sanitize_name "$APP_NAME")"
safe_app="$(sanitize_name "${APP_NAME:-exec}")"
safe_system="$(sanitize_name "$SYSTEM_IMAGE")"
timestamp="$(date +%Y%m%d-%H%M%S)"
log_name="${safe_app}-${safe_system}-${timestamp}.log"
......@@ -474,9 +478,7 @@ build_container_script() {
set -eu
TEST_COMMAND="$1"
APP_NAME="$2"
shift 2
EXTRA_FLAGS="$*"
shift
SOURCE_DIR="/work/eepm"
run_eepm() {
......@@ -531,7 +533,12 @@ esac
case "$TEST_COMMAND" in
play)
exec bash ./bin/eepm play --auto $EXTRA_FLAGS "$APP_NAME"
APP_NAME="$1"
shift
exec bash ./bin/eepm play --auto "$@" "$APP_NAME"
;;
exec)
exec bash -c "$1"
;;
*)
printf '[container] unsupported test command: %s\n' "$TEST_COMMAND" >&2
......@@ -548,13 +555,20 @@ run_container_locally() {
local inner_script container_name
local current_user
local status
local -a inner_args
require_command docker
inner_script="$(mktemp "${TMPDIR:-/tmp}/epm-docker-test-inner.XXXXXX.sh")"
build_container_script "$inner_script"
container_name="epm-test-$(sanitize_name "$APP_NAME")-$(sanitize_name "$SYSTEM_IMAGE")-$$"
if [[ -n "$EXEC_COMMAND" ]]; then
inner_args=(exec "$EXEC_COMMAND")
container_name="epm-test-exec-$(sanitize_name "$SYSTEM_IMAGE")-$$"
else
inner_args=(play "$APP_NAME" "${PLAY_FLAGS[@]}")
container_name="epm-test-$(sanitize_name "$APP_NAME")-$(sanitize_name "$SYSTEM_IMAGE")-$$"
fi
info "Using eepm tree: $resolved_source"
info "Target image: $SYSTEM_IMAGE"
......@@ -572,7 +586,7 @@ run_container_locally() {
--volume "$resolved_source:/work/eepm:ro" \
--volume "$inner_script:/tmp/epm-docker-test-inner.sh:ro" \
"$SYSTEM_IMAGE" \
sh /tmp/epm-docker-test-inner.sh "$COMMAND" "$APP_NAME" "${PLAY_FLAGS[@]}"; then
sh /tmp/epm-docker-test-inner.sh "${inner_args[@]}"; then
status=0
else
status=$?
......@@ -610,7 +624,11 @@ build_remote_args() {
[[ -n "$BUILDER_PATH" ]] && REMOTE_ARGS+=(--builder-path "$BUILDER_PATH")
fi
REMOTE_ARGS+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE")
if [[ -n "$EXEC_COMMAND" ]]; then
REMOTE_ARGS+=(--exec "$EXEC_COMMAND" "$SYSTEM_IMAGE")
else
REMOTE_ARGS+=("$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE")
fi
}
run_container_via_ssh() {
......@@ -633,7 +651,13 @@ run_container_via_ssh() {
bash -s --
)
if ssh "${ssh_args[@]}" "${REMOTE_ARGS[@]}" <"$SCRIPT_PATH"; then
local -a escaped_args
local arg
for arg in "${REMOTE_ARGS[@]}"; do
escaped_args+=("$(printf '%q' "$arg")")
done
if ssh "${ssh_args[@]}" "${escaped_args[@]}" <"$SCRIPT_PATH"; then
status=0
else
status=$?
......@@ -674,29 +698,39 @@ run_once() {
esac
}
test_description() {
if [[ -n "$EXEC_COMMAND" ]]; then
printf 'exec: %s' "$EXEC_COMMAND"
else
printf 'epm %s %s' "$COMMAND" "$APP_NAME"
fi
}
run_for_system() {
local system_image="$1"
local index="$2"
local total="$3"
local status
local desc
SYSTEM_IMAGE="$system_image"
LOG_FILE="$(create_log_file)"
desc="$(test_description)"
if ((total > 1)); then
info "Run [$index/$total]: epm $COMMAND $APP_NAME on $SYSTEM_IMAGE"
info "Run [$index/$total]: $desc on $SYSTEM_IMAGE"
fi
info "Log file: $LOG_FILE"
info "Normalized system: $SYSTEM_IMAGE"
info "Test command: epm $COMMAND $APP_NAME"
info "Test command: $desc"
run_once 2>&1 | tee "$LOG_FILE" && status=0 || status=$?
if ((status == 0)); then
printf '\nTest passed: epm %s %s on %s\n' "$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE"
printf '\nTest passed: %s on %s\n' "$desc" "$SYSTEM_IMAGE"
printf 'Log: %s\n' "$LOG_FILE"
else
printf '\nTest failed: epm %s %s on %s\n' "$COMMAND" "$APP_NAME" "$SYSTEM_IMAGE" >&2
printf '\nTest failed: %s on %s\n' "$desc" "$SYSTEM_IMAGE" >&2
printf 'Log: %s\n' "$LOG_FILE" >&2
print_failure_excerpt
fi
......@@ -802,6 +836,11 @@ parse_args() {
PLAY_FLAGS+=(--latest)
shift
;;
--exec)
[[ $# -ge 2 ]] || fatal "--exec requires a value"
EXEC_COMMAND="$2"
shift 2
;;
--log-root)
[[ $# -ge 2 ]] || fatal "--log-root requires a value"
LOG_ROOT="$2"
......@@ -832,14 +871,17 @@ parse_args() {
esac
done
if ((${#positional[@]} < 1)); then
usage >&2
exit 1
if [[ -n "$EXEC_COMMAND" ]]; then
SYSTEM_INPUTS=("${positional[@]}")
else
if ((${#positional[@]} < 1)); then
usage >&2
exit 1
fi
APP_NAME="${positional[0]}"
SYSTEM_INPUTS=("${positional[@]:1}")
fi
APP_NAME="${positional[0]}"
SYSTEM_INPUTS=("${positional[@]:1}")
if ((${#SYSTEM_INPUTS[@]} == 0 && ${#PRESET_NAMES[@]} == 0)); then
fatal "At least one target system or --preset is required"
fi
......
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