From ac73e98ad4e02c63d0b362fe7c8d2ab9a1f88f7d Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:34:32 +0200 Subject: [PATCH 1/4] fix(exegol): per-engagement container, created non-interactively, no 120s hang dotsec new now CREATES the Exegol container instead of waiting on a non-existent shared 'exegol' one. Each engagement gets exegol- via 'exegol start free -w --accept-eula ; load_cmd sources /workspace/.env. --- lib/engagement.sh | 37 +++++++-------- lib/exegol.sh | 118 +++++++++++++++++++++++++--------------------- 2 files changed, 83 insertions(+), 72 deletions(-) diff --git a/lib/engagement.sh b/lib/engagement.sh index 898c762..eab5e8b 100644 --- a/lib/engagement.sh +++ b/lib/engagement.sh @@ -86,14 +86,14 @@ DOC printf '%b\n' " ${DIM}[4/6]${RESET} ${DIM}Starting mitmproxy...${RESET}" DOTSEC_WORKSPACE_ROOT="${ws_root}" TARGET="${target}" proxy_up - # 5. Ensure Exegol is running with workspace mounted - printf '%b\n' " ${DIM}[5/6]${RESET} ${DIM}Ensuring Exegol container...${RESET}" - __exegol_ensure_running "$target" "$ws_root" + # 5. Create the per-engagement Exegol container (workspace mounted, my-resources) + printf '%b\n' " ${DIM}[5/6]${RESET} ${DIM}Creating Exegol container...${RESET}" + __exegol_ensure_running "$target" "$ws" || true - # 6. Spawn tmux inside Exegol + # 6. Spawn tmux inside Exegol (engagement workspace is mounted at /workspace) printf '%b\n' " ${DIM}[6/6]${RESET} ${DIM}Creating tmux session in Exegol...${RESET}" - local container="${EXEGOL_CONTAINER:-exegol}" - local load_cmd="source /workspace/${target}/.env; [ -f /workspace/${target}/.env.secrets ] && source /workspace/${target}/.env.secrets; export TARGET=${target} DOMAIN=${domain}; clear" + local container; container="$(__exegol_name "$target")" + local load_cmd="source /workspace/.env; [ -f /workspace/.env.secrets ] && source /workspace/.env.secrets; export TARGET=${target} DOMAIN=${domain}; clear" __exegol_tmux_spawn "$container" "$target" "$load_cmd" echo "" @@ -206,7 +206,7 @@ cmd_archive() { exit 1 fi - local container="${EXEGOL_CONTAINER:-exegol}" + local container; container="$(__exegol_name "$target")" local timestamp timestamp=$(date '+%Y%m%d-%H%M%S') local archive_name="${target}-${timestamp}.tar.gz" @@ -288,9 +288,8 @@ cmd_rm() { [[ $do_archive -eq 1 ]] && cmd_archive "$target" - local container="${EXEGOL_CONTAINER:-exegol}" - docker rm -f "mitmproxy-${target}" "oob-${target}" >/dev/null 2>&1 || true - docker exec "$container" tmux kill-session -t "$target" >/dev/null 2>&1 || true + # Remove the per-engagement containers (never an externally forced one) + docker rm -f "mitmproxy-${target}" "oob-${target}" "exegol-${target}" >/dev/null 2>&1 || true rm -rf "$ws" 2>/dev/null || true if [[ -d "$ws" ]]; then @@ -313,7 +312,7 @@ cmd_stop() { printf '%b\n' "${RED}[!] Usage: dotsec stop ${RESET}" >&2 exit 1 fi - local container="${EXEGOL_CONTAINER:-exegol}" + local container="exegol-${target}" printf '%b\n' "${BOLD}${YELLOW}Stopping${RESET} ${CYAN}${target}${RESET}..." @@ -325,12 +324,12 @@ cmd_stop() { printf '%b\n' " ${DIM}Proxy: already stopped${RESET}" fi - # Kill tmux session in Exegol - if docker exec "$container" tmux has-session -t "$target" 2>/dev/null; then - printf '%b\n' " ${DIM}Tmux session...${RESET}" - docker exec "$container" tmux kill-session -t "$target" 2>/dev/null || true + # Stop the Exegol container + if docker ps --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then + printf '%b\n' " ${DIM}Exegol container...${RESET}" + docker stop "$container" >/dev/null 2>&1 || true else - printf '%b\n' " ${DIM}Tmux: no session${RESET}" + printf '%b\n' " ${DIM}Exegol: not running${RESET}" fi # Stop dashboard @@ -352,7 +351,7 @@ cmd_restart() { exit 1 fi local ws="${WORKSPACE_ROOT:-/workspace}/${target}" - local container="${EXEGOL_CONTAINER:-exegol}" + local container; container="$(__exegol_name "$target")" if [[ ! -d "$ws" ]] || [[ ! -f "${ws}/.env" ]]; then printf '%b\n' "${RED}[!] Engagement not found: ${target}${RESET}" >&2 @@ -375,11 +374,11 @@ cmd_restart() { # Ensure Exegol printf '%b\n' " ${DIM}Exegol...${RESET}" - __exegol_ensure_running "$target" + __exegol_ensure_running "$target" "$ws" || true # Recreate tmux session printf '%b\n' " ${DIM}Tmux session...${RESET}" - local load_cmd="source /workspace/${target}/.env; [ -f /workspace/${target}/.env.secrets ] && source /workspace/${target}/.env.secrets; export TARGET=${target} DOMAIN=${domain}; clear" + local load_cmd="source /workspace/.env; [ -f /workspace/.env.secrets ] && source /workspace/.env.secrets; export TARGET=${target} DOMAIN=${domain}; clear" __exegol_tmux_spawn "$container" "$target" "$load_cmd" printf '%b\n' " ${GREEN}Environment restarted${RESET}" diff --git a/lib/exegol.sh b/lib/exegol.sh index 4c566f4..f1c3bcf 100644 --- a/lib/exegol.sh +++ b/lib/exegol.sh @@ -1,54 +1,55 @@ #!/usr/bin/env bash # ─── lib/exegol.sh ─── Exegol container and tmux helpers ── -# ── Exegol helpers ─────────────────────────────────────── +# Per-engagement Exegol container name. EXEGOL_CONTAINER overrides it (use an +# already-running container instead of creating exegol-). +__exegol_name() { + echo "${EXEGOL_CONTAINER:-exegol-${1}}" +} + +# __exegol_ensure_running [engagement_workspace] +# Create the per-engagement Exegol container (exegol-) with the +# engagement workspace mounted as /workspace and my-resources deployed, or just +# start it if it already exists. Best-effort: returns non-zero only if it can't +# bring the container up. __exegol_ensure_running() { local target="${1}" - local ws_root="${2:-${WORKSPACE_ROOT}}" - local container="${EXEGOL_CONTAINER:-exegol}" + local ws="${2:-${WORKSPACE_ROOT}/${target}}" + local container; container="$(__exegol_name "$target")" - # Already running? Check mount and return + # Already running? if docker ps --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then - local mount_src - mount_src=$(docker inspect "$container" --format '{{range .Mounts}}{{if eq .Destination "/workspace"}}{{.Source}}{{end}}{{end}}' 2>/dev/null || echo "") - if [[ -n "$mount_src" ]] && [[ "$mount_src" = "${ws_root}" ]]; then - return 0 - fi + return 0 fi - - # Container exists (running or stopped)? Start it — fast + # Exists but stopped → start it. if docker ps -a --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then - # Stop if running with wrong mount - if docker ps --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then - docker stop "$container" >/dev/null 2>&1 - fi - # Recreate with correct mount if needed - local mount_src - mount_src=$(docker inspect "$container" --format '{{range .Mounts}}{{if eq .Destination "/workspace"}}{{.Source}}{{end}}{{end}}' 2>/dev/null || echo "") - if [[ -z "$mount_src" ]] || [[ "$mount_src" != "${ws_root}" ]]; then - docker rm "$container" >/dev/null 2>&1 - if command -v exegol &>/dev/null; then - exegol start -w "${ws_root}" "$container" &>/dev/null & - else - docker run -d --name "$container" -v "${ws_root}:/workspace" --network host "nwodtuhs/exegol:free" sleep infinity - fi - else - docker start "$container" >/dev/null 2>&1 - fi + docker start "$container" >/dev/null 2>&1 || true return 0 fi - - # Container doesn't exist — start in background (may take time) - printf '%b\n' " ${DIM}Exegol first launch (pulling image)...${RESET}" - if command -v exegol &>/dev/null; then - exegol start -w "${ws_root}" "$container" &>/dev/null & + # A forced EXEGOL_CONTAINER that doesn't exist: don't try to create it. + if [[ -n "${EXEGOL_CONTAINER:-}" ]]; then + printf '%b\n' " ${YELLOW}[!]${RESET} ${DIM}EXEGOL_CONTAINER=${EXEGOL_CONTAINER} not found — start it yourself${RESET}" >&2 + return 1 + fi + # Create it. Prefer the exegol CLI: it deploys my-resources and mounts the + # workspace. stdin=/dev/null makes the post-create auto-attach fail cleanly + # and leaves the container running detached (we connect via tmux instead). + if command -v exegol >/dev/null 2>&1; then + printf '%b\n' " ${DIM}Creating Exegol container ${container} (first run can take a moment)...${RESET}" + exegol start "${target}" "${EXEGOL_IMAGE:-free}" -w "${ws}" --accept-eula /dev/null 2>&1 || true else + printf '%b\n' " ${DIM}exegol CLI not found — using docker run fallback...${RESET}" docker run -d --name "$container" \ - -v "${ws_root}:/workspace" \ - -v /var/run/docker.sock:/var/run/docker.sock \ + -v "${ws}:/workspace" \ + -v "${HOME}/.exegol/my-resources:/opt/my-resources" \ --network host \ - "nwodtuhs/exegol:free" sleep infinity + nwodtuhs/exegol:free sleep infinity >/dev/null 2>&1 || true + fi + if docker ps --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then + return 0 fi + printf '%b\n' " ${YELLOW}[!]${RESET} ${DIM}Exegol container ${container} did not come up${RESET}" >&2 + return 1 } __exegol_tmux_spawn() { @@ -56,17 +57,22 @@ __exegol_tmux_spawn() { local session_name="${2}" local load_cmd="${3:-}" - # Wait for container to be ready (up to 120s for first pull) + # Container not present at all → skip without the long wait. + if ! docker ps -a --filter "name=^${container}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then + printf '%b\n' " ${YELLOW}[!]${RESET} ${DIM}No Exegol container ${container} — run${RESET} ${YELLOW}dotsec tmux create ${session_name}${RESET} ${DIM}once it's up${RESET}" >&2 + return 0 + fi + + # Wait for it to be exec-able (short: it was just created/started). printf '%b\n' " ${DIM}Waiting for Exegol container...${RESET}" local waited=0 - while ! docker exec "$container" true 2>/dev/null && [[ $waited -lt 120 ]]; do - sleep 3; ((waited+=3)) + while ! docker exec "$container" true 2>/dev/null && [[ $waited -lt 60 ]]; do + sleep 2; ((waited+=2)) || true printf '.' >&2 done - echo "" + echo "" >&2 if ! docker exec "$container" true 2>/dev/null; then - printf '%b\n' " ${YELLOW}[!]${RESET} ${DIM}Exegol not ready after 2min — tmux will be created later${RESET}" >&2 - printf '%b\n' " ${DIM}Run${RESET} ${YELLOW}dotsec tmux attach${RESET} ${DIM}once container is up${RESET}" >&2 + printf '%b\n' " ${YELLOW}[!]${RESET} ${DIM}Exegol not ready — ${RESET}${YELLOW}dotsec tmux create ${session_name}${RESET}" >&2 return 0 fi @@ -97,10 +103,16 @@ __exegol_tmux_spawn() { # ── Exegol ─────────────────────────────────────────────── cmd_exegol() { local action="${1:-shell}"; shift || true - local container="${EXEGOL_CONTAINER:-exegol}" + local target="${TARGET:-}" + local container; container="$(__exegol_name "$target")" __require_docker + if [[ -z "${EXEGOL_CONTAINER:-}" && -z "$target" ]]; then + printf '%b\n' "${RED}[!] No engagement loaded — ${RESET}${YELLOW}dotsec load ${RESET} ${DIM}first${RESET}" >&2 + exit 1 + fi + local docker_tty="" [[ -t 0 ]] && docker_tty="-it" @@ -115,7 +127,6 @@ cmd_exegol() { printf '%b\n' "${DIM}Running Exegol tool setup (uv + pnpm)...${RESET}" if ! docker ps --filter "name=^${container}$" --format '{{.Names}}' | grep -q .; then printf '%b\n' "${YELLOW}[!]${RESET} ${DIM}Container${RESET} ${YELLOW}${container}${RESET} ${DIM}not running.${RESET}" >&2 - printf '%b\n' " ${DIM}Start it with:${RESET} ${YELLOW}exegol start ${container}${RESET}" >&2 exit 1 fi docker exec ${docker_tty} "$container" bash /opt/my-resources/setup/load_user_setup.sh @@ -131,20 +142,20 @@ cmd_exegol() { # Instant pentest-ready tmux session, with or without engagement loaded cmd_spawn() { local session_name="${1:-${TARGET:-pentest}}" - local ws="${WORKSPACE:-}" + local target="${TARGET:-${session_name}}" + local ws="${WORKSPACE:-${WORKSPACE_ROOT}/${target}}" local envfile="${ws}/.env" - local container="${EXEGOL_CONTAINER:-exegol}" + local container; container="$(__exegol_name "$target")" __require_docker - # Check if target is an engagement with .env → use Exegol path + # Engagement with .env → source it inside (workspace is mounted at /workspace) local exegol_env="" - [[ -n "$ws" ]] && [[ -f "$envfile" ]] && exegol_env="/workspace/${TARGET:-${session_name}}/.env" + [[ -f "$envfile" ]] && exegol_env="/workspace/.env" printf '%b\n' "${DIM}Spawning tmux session in Exegol:${RESET} ${CYAN}${session_name}${RESET}" - # Ensure Exegol is running - __exegol_ensure_running "${TARGET:-${session_name}}" + __exegol_ensure_running "$target" "$ws" || true local load_cmd="" [[ -n "$exegol_env" ]] && load_cmd="source ${exegol_env}; clear" @@ -161,7 +172,7 @@ cmd_tmux() { local action="${1:-}"; shift || true local target="${TARGET:-}" [[ -z "$target" ]] && target="${1:-}" - local container="${EXEGOL_CONTAINER:-exegol}" + local container; container="$(__exegol_name "$target")" __require_docker @@ -172,8 +183,9 @@ cmd_tmux() { ;; create) [[ -z "$target" ]] && { printf '%b\n' "${RED}[!] Usage: dotsec tmux create ${RESET}" >&2; exit 1; } - __exegol_ensure_running "$target" - __exegol_tmux_spawn "$container" "$target" + __exegol_ensure_running "$target" "${WORKSPACE_ROOT}/${target}" || true + local load_cmd="source /workspace/.env 2>/dev/null; [ -f /workspace/.env.secrets ] && source /workspace/.env.secrets; export TARGET=${target}; clear" + __exegol_tmux_spawn "$container" "$target" "$load_cmd" printf '%b\n' "${GREEN}Session${RESET} ${CYAN}${target}${RESET} ${DIM}created in Exegol${RESET}" ;; kill|k) From b38f4f30fb6d847ce9376cd8303eeea9df581ec1 Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:35:58 +0200 Subject: [PATCH 2/4] fix(status): per-engagement exegol name; global shows count of running exegol containers --- lib/status.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/status.sh b/lib/status.sh index a9fb3dc..7fb2af9 100644 --- a/lib/status.sh +++ b/lib/status.sh @@ -2,12 +2,11 @@ # ─── lib/status.sh ─── engagement status overview ── __status_global() { - local exegol="${EXEGOL_CONTAINER:-exegol}" - local ex_state="stopped" db_state="down" - docker ps --filter "name=^${exegol}$" --format '{{.Names}}' 2>/dev/null | grep -q . && ex_state="running" + local db_state="down" ex_count + ex_count=$(docker ps --filter "name=exegol-" --format '{{.Names}}' 2>/dev/null | grep -c . || true) docker ps --filter "name=dotsec-homer" --format '{{.Names}}' 2>/dev/null | grep -q . \ && db_state="up (127.0.0.1:${HOMER_PORT:-9997})" - printf '%b\n' "${BOLD}${CYAN}Global${RESET} ${DIM}Exegol:${RESET} ${ex_state} ${DIM}Dashboard:${RESET} ${db_state}" + printf '%b\n' "${BOLD}${CYAN}Global${RESET} ${DIM}Exegol:${RESET} ${ex_count:-0} running ${DIM}Dashboard:${RESET} ${db_state}" return 0 } @@ -22,7 +21,7 @@ __status_engagement() { proxy="up 127.0.0.1:${pport} / ${wport}" fi tmuxs="—" - exegol="${EXEGOL_CONTAINER:-exegol}" + exegol="$(__exegol_name "$target")" if docker ps --filter "name=^${exegol}$" --format '{{.Names}}' 2>/dev/null | grep -q .; then docker exec "$exegol" tmux has-session -t "$target" 2>/dev/null && tmuxs="session present" fi From 9724646d0bf8d9e4e3789d029ab707feaccc9253 Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:58:37 +0200 Subject: [PATCH 3/4] feat(new): positional for workspace location + host-editable ACLs A path-like 2nd positional (., .., /dir, ./dir, ~/dir) sets where the workspace is created (dotsec new swiss_post .); resolved to an absolute path for Docker mounts. dotsec also lays default POSIX ACLs on the workspace so files the root Exegol/proxy containers create stay editable from the host (your user keeps rwx by inheritance), instead of being root-owned. --- lib/engagement.sh | 15 ++++++++++++++- lib/exegol.sh | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/engagement.sh b/lib/engagement.sh index eab5e8b..3d0ede2 100644 --- a/lib/engagement.sh +++ b/lib/engagement.sh @@ -21,6 +21,11 @@ cmd_new() { *) if [[ -z "$target" ]]; then target="$1" + elif [[ "$1" == "." || "$1" == ".." || "$1" == /* || "$1" == ./* || "$1" == ../* || "$1" == "~"/* ]]; then + # A path-like 2nd positional sets WHERE to create the workspace: + # dotsec new swiss_post . → ./swiss_post + # dotsec new swiss_post ~/bb/ywh → ~/bb/ywh/swiss_post + ws_root="$1" elif [[ -z "$domain" ]]; then domain="$1" fi @@ -31,11 +36,14 @@ cmd_new() { __require_docker if [[ -z "$target" ]]; then - printf '%b\n' "${RED}[!] Usage: dotsec new [-w ] [domain]${RESET}" >&2 + printf '%b\n' "${RED}[!] Usage: dotsec new [domain] [path|-w ]${RESET}" >&2 + printf '%b\n' " ${DIM}path: '.' or a dir → create the workspace there (e.g. dotsec new swiss_post .)${RESET}" >&2 exit 1 fi [[ -z "$domain" ]] && domain="${target}" + # Docker mounts (proxy, Exegol) need an absolute workspace root. + ws_root="$(realpath -m "$ws_root" 2>/dev/null || echo "$ws_root")" local ws="${ws_root}/${target}" printf '%b\n' "${BOLD}${GREEN}▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀${RESET}" @@ -45,6 +53,11 @@ cmd_new() { # 1. Workspace structure printf '%b\n' " ${DIM}[1/6]${RESET} ${DIM}Creating workspace...${RESET}" mkdir -p "${ws}"/{recon/{passive,active},scans/{ports,web,vuln},exploits/{pocs,payloads},loot/{credentials,data},logs,report/assets,replays/{recon,scan,exploit,post,report,monitor},keys} + # Default ACLs so files the root Exegol/proxy containers create in the + # workspace stay editable from the host (your user keeps rwx by inheritance). + if command -v setfacl >/dev/null 2>&1; then + setfacl -R -m "u:$(id -u):rwX" -m "d:u:$(id -u):rwX" "$ws" 2>/dev/null || true + fi # 2. Copy and fill .env printf '%b\n' " ${DIM}[2/6]${RESET} ${DIM}Setting up dotenv...${RESET}" diff --git a/lib/exegol.sh b/lib/exegol.sh index f1c3bcf..ad3509c 100644 --- a/lib/exegol.sh +++ b/lib/exegol.sh @@ -36,6 +36,8 @@ __exegol_ensure_running() { # and leaves the container running detached (we connect via tmux instead). if command -v exegol >/dev/null 2>&1; then printf '%b\n' " ${DIM}Creating Exegol container ${container} (first run can take a moment)...${RESET}" + # Host-side ACLs (set by dotsec at workspace creation) keep root-created + # files editable from the host, so --update-fs isn't needed here. exegol start "${target}" "${EXEGOL_IMAGE:-free}" -w "${ws}" --accept-eula /dev/null 2>&1 || true else printf '%b\n' " ${DIM}exegol CLI not found — using docker run fallback...${RESET}" From 88eb1b552782dd9bc468b094b949ae96e2f9a40c Mon Sep 17 00:00:00 2001 From: Dxsk <43427519+dxsk@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:58:37 +0200 Subject: [PATCH 4/4] fix(exegol): drop auto-detection that pinned every engagement to one running container __dotsec_load_global no longer scans for a running exegol-* and forces EXEGOL_CONTAINER: with per-engagement containers that pinned 'dotsec new X' to whatever exegol-* happened to be up. Name now comes from __exegol_name (exegol-); EXEGOL_CONTAINER only set if the user forces it. --- lib/core.sh | 15 ++++----------- tests/smoke.bats | 20 -------------------- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/lib/core.sh b/lib/core.sh index 0ec5271..700100d 100644 --- a/lib/core.sh +++ b/lib/core.sh @@ -17,17 +17,10 @@ __dotsec_load_global() { if [[ -f "${DOTSEC_CONFIG}/config" ]]; then source "${DOTSEC_CONFIG}/config" fi - # Resolve the Exegol container: detect when unset OR when the configured one - # no longer exists (e.g. removed/recreated) — so a stale config value never - # sticks. Prefer a running container, fall back to any. - if [[ -z "${EXEGOL_CONTAINER:-}" ]] || ! docker container inspect "${EXEGOL_CONTAINER}" >/dev/null 2>&1; then - local detected - detected=$(docker ps --filter "name=exegol" --format '{{.Names}}' 2>/dev/null | head -1) - [[ -z "$detected" ]] && detected=$(docker ps -a --filter "name=exegol" --format '{{.Names}}' 2>/dev/null | head -1) - [[ -n "$detected" ]] && EXEGOL_CONTAINER="$detected" - fi - # Last statement must not leak a non-zero status under `set -e` (this - # function runs top-level; a falsy [[ -n ]] above would otherwise abort dotsec). + # Exegol containers are per-engagement (exegol-, see __exegol_name). + # EXEGOL_CONTAINER stays unset unless the user forces one in their config — + # no auto-detection, which would otherwise pin every engagement to whichever + # exegol-* container happens to be running. return 0 } diff --git a/tests/smoke.bats b/tests/smoke.bats index 3936118..20f1950 100644 --- a/tests/smoke.bats +++ b/tests/smoke.bats @@ -34,26 +34,6 @@ load test_helper [[ "$output" == *REACHED* ]] } -@test "__dotsec_load_global re-detects when the configured container is gone" { - run env DOTSEC_HOME="$DOTSEC_HOME" bash -euo pipefail -c ' - DOTSEC_CONFIG=$(mktemp -d) - docker() { - case "$1" in - container) [[ "$2" == "inspect" ]] && return 1 ;; # configured one gone - ps) echo "exegol-a" ;; # a running exegol exists - esac - return 0 - } - source "$DOTSEC_HOME/lib/ui.sh" - source "$DOTSEC_HOME/lib/core.sh" - EXEGOL_CONTAINER="exegol-dead" - __dotsec_load_global - echo "GOT=$EXEGOL_CONTAINER" - ' - [ "$status" -eq 0 ] - [[ "$output" == *"GOT=exegol-a"* ]] -} - @test "dotsec list exits 0 when engagements exist" { local ws cfg ws="$(mktemp -d)"; cfg="$(mktemp -d)"