Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ GO_LDFLAGS ?= -s -w \

## Shipped binaries under cmd/, and the build-tagged harnesses under test/ (one tag per directory)
BINARIES := sandbox-apiserver sandbox-envd-proxy sandbox-e2b
TAGGED_HARNESSES := l3bench envdproxysmoke meshinventorysmoke
TAGGED_HARNESSES := l3bench envdproxysmoke meshinventorysmoke envdsmoke

## Target OSes for vet / lint
GOOSES ?= linux darwin
Expand Down
18 changes: 18 additions & 0 deletions docs/e2b-compat.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,24 @@ own start, and a publish that deletes an older holder removes a record its
siblings still advertise; a create of one fails over to the next advertiser, and
the template list lags until those nodes restart.

## Proving envd on hardware

`scripts/envd-e2e.sh` runs the guest half on a node: it starts a sandboxd with
an e2b flavor pool whose warmup gates on envd's `/health`, then drives
`test/envdsmoke` (`go build -tags envdsmoke ./test/envdsmoke`), which claims a
sandbox through `pkg/sandboxd` and reaches the real envd through the node's
guest-port relay: health, the version the compat API reports, `POST`/`GET
/files`, a ConnectRPC unary, a `process.Process/Start` whose output comes back
over the Connect server stream, the `user` account with passwordless sudo, and
that envd serves HTTP/1.1 only. `CODE_INTERPRETER=1` also gates warmup on 49999
and runs `1+1` the way the SDK's `runCode` does; `-hold` keeps the sandbox for
an out-of-tree harness that puts an edge proxy in front of it.

```bash
K=<kit> TEMPLATE=ghcr.io/cocoonstack/sandbox/e2b-rt:24.04 bash scripts/envd-e2e.sh
K=<kit> TEMPLATE=ghcr.io/cocoonstack/sandbox/e2b-ci:24.04 SIZE=medium CODE_INTERPRETER=1 bash scripts/envd-e2e.sh
```

## Limits worth knowing

- **Reaching `envd` (the in-sandbox data plane).** The SDK derives the sandbox
Expand Down
56 changes: 56 additions & 0 deletions scripts/envd-e2e.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Bare-metal proof for the e2b image flavor: envd inside a cocoon microVM,
# reached only through sandboxd's guest-port relay. The pool's warmup gates a
# warm clone on envd answering, so a claim never hands out a sandbox whose data
# plane is still starting.
# Run as root on a node with cocoon; K names a kit holding bin/sandboxd,
# bin/envdsmoke (go build -tags envdsmoke ./test/envdsmoke), bin/jq and a cocoon on PATH.
set -uo pipefail
K=${K:?kit dir}
ADDR=${ADDR:-127.0.0.1:7996}
TOKEN=${TOKEN:-e2benvd}
TEMPLATE=${TEMPLATE:-e2b-rt:24.04}
ENVD_VERSION=${ENVD_VERSION:-0.8.0}
# CODE_INTERPRETER=1 is the e2b-ci pass: warmup also gates on the interpreter API, and envdsmoke drives it.
CODE_INTERPRETER=${CODE_INTERPRETER:-}
SIZE=${SIZE:-small}
HEALTH="curl -sf -m 1 -o /dev/null http://127.0.0.1:49983/health"
[[ -n $CODE_INTERPRETER ]] && HEALTH="$HEALTH && curl -sf -m 1 -o /dev/null http://127.0.0.1:49999/health"
export PATH=$K/bin:$PATH
DATA=$(mktemp -d /tmp/envd-e2e.XXXXXX); DAEMON_PID=""
cleanup() {
status=$?
echo "== daemon log tail"; tail -25 "$DATA/daemon.log" 2>/dev/null
[[ -n $DAEMON_PID ]] && kill "$DAEMON_PID" 2>/dev/null
wait 2>/dev/null
cocoon vm list --format json 2>/dev/null |
jq -r '.[] | select(.config.name | startswith("sbx-")) | .config.name' |
while read -r vm; do
cocoon vm stop --force "$vm" >/dev/null 2>&1
cocoon vm rm --force "$vm" >/dev/null 2>&1
done
rm -rf "$DATA"; exit "$status"
}
trap cleanup EXIT
# warmup gates a warm clone on envd answering: a clone that hands out a sandbox
# whose data plane is not up yet is worse than a slower clone.
cat >"$DATA/config.json" <<EOF
{"listen":"$ADDR","data_dir":"$DATA/state","api_token":"$TOKEN",
"pools":[{"template":"$TEMPLATE","net":"none","size":"$SIZE","warm":2,
"warmup":["sh","-c","for i in \$(seq 1 1200); do $HEALTH && exit 0; sleep 0.05; done; exit 1"]}]}
EOF
echo "== start sandboxd $("$K/bin/sandboxd" -version 2>/dev/null)"
"$K/bin/sandboxd" -config "$DATA/config.json" >>"$DATA/daemon.log" 2>&1 &
DAEMON_PID=$!
for _ in $(seq 1 40); do curl -sf "http://$ADDR/healthz" >/dev/null && break; sleep 0.5; done
curl -sf "http://$ADDR/healthz" >/dev/null || { echo "daemon never came up"; exit 1; }
echo "== wait for golden + warm (warmup gates on envd /health)"
for i in $(seq 1 300); do
curl -sf -H "Authorization: Bearer $TOKEN" "http://$ADDR/v1/info" |
jq -e '(.pools|length)>0 and all(.pools[]; .golden and .warm >= .target)' >/dev/null 2>&1 && break
[[ $i == 300 ]] && { echo "pools never became ready"; curl -sf -H "Authorization: Bearer $TOKEN" "http://$ADDR/v1/info" | jq .; exit 1; }
sleep 1
done
curl -sf -H "Authorization: Bearer $TOKEN" "http://$ADDR/v1/info" | jq -c '.pools'
echo "== envdsmoke"
"$K/bin/envdsmoke" -addr "$ADDR" -token "$TOKEN" -template "$TEMPLATE" -envd-version "$ENVD_VERSION" -size "$SIZE" ${HOLD:+-hold "$HOLD"} ${CODE_INTERPRETER:+-code-interpreter}
Loading
Loading