sandbox.sh utility to easily log into or execute commands in a sandbox, set hostname and SANDBOX env var to container name (#92)

This commit is contained in:
Olcan 2025-04-21 13:52:51 -07:00 committed by GitHub
parent ddaa21c750
commit 09973956ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 112 additions and 1 deletions

108
scripts/sandbox.sh Executable file
View File

@ -0,0 +1,108 @@
#!/bin/bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
# parse flags
interactive=false
while getopts "i" opt; do
case "$opt" in
\?)
echo "usage: sandbox.sh [-i] [sandbox-name-or-index = AUTO] [command... = bash -l]"
echo " -i: enable interactive mode for custom command (enabled by default for login shell)"
echo " (WARNING: interactive mode causes stderr to be redirected to stdout)"
exit 1
;;
i)
interactive=true
if [ ! -t 0 ]; then
echo "ERROR: interactive mode (-i) requested without a terminal attached"
exit 1
fi
;;
esac
done
shift $((OPTIND - 1))
IMAGE=gemini-code-sandbox
# use docker if installed, otherwise try to use podman instead
if command -v docker &> /dev/null; then
CMD=docker
elif command -v podman &> /dev/null; then
CMD=podman
else
echo "ERROR: missing docker or podman for sandboxing"
exit 1
fi
# list all containers running on sandbox image
sandboxes=()
while IFS= read -r line; do
sandboxes+=("$line")
done < <($CMD ps --filter "ancestor=$IMAGE" --format "{{.Names}}")
# take first argument as sandbox name if it starts with image name or is an integer
# otherwise require a unique sandbox to be running and take its name
if [[ "${1:-}" =~ ^$IMAGE(-[0-9]+)?$ ]]; then
SANDBOX=$1
shift
elif [[ "${1:-}" =~ ^[0-9]+$ ]]; then
SANDBOX=$IMAGE-$1
shift
else
# exit if no sandbox is running
if [ ${#sandboxes[@]} -eq 0 ]; then
echo "No sandboxes found. Are you running gemini-code with sandboxing enabled?"
exit 1
fi
# exit if multiple sandboxes are running
if [ ${#sandboxes[@]} -gt 1 ]; then
echo "Multiple sandboxes found:"
for sandbox in "${sandboxes[@]}"; do
echo " $sandbox"
done
echo "Sandbox name or index (0,1,...) must be specified as first argument"
exit 1
fi
SANDBOX=${sandboxes[0]}
fi
# check that sandbox exists
if ! [[ " ${sandboxes[*]} " == *" $SANDBOX "* ]]; then
echo "unknown sandbox $SANDBOX"
echo "known sandboxes:"
for sandbox in "${sandboxes[@]}"; do
echo " $sandbox"
done
exit 1
fi
# determine command and args for exec
if [ $# -gt 0 ]; then
cmd=(bash -l -c "$(printf '%q ' "$@")") # fixes quoting, e.g. bash -c 'echo $SANDBOX'
exec_args=()
if [ "$interactive" = true ]; then
exec_args=(-it)
fi
else
cmd=(bash -l)
exec_args=(-it)
fi
# run command in sandbox
exec_args+=("$SANDBOX" "${cmd[@]}")
$CMD exec "${exec_args[@]}"

View File

@ -41,7 +41,10 @@ INDEX=0
while $CMD ps -a --format "{{.Names}}" | grep -q "$IMAGE-$INDEX"; do
INDEX=$((INDEX + 1))
done
run_args+=(--name "$IMAGE-$INDEX")
run_args+=(--name "$IMAGE-$INDEX" --hostname "$IMAGE-$INDEX")
# also set SANDBOX environment variable as container name
run_args+=(--env "SANDBOX=$IMAGE-$INDEX")
# enable debugging via node --inspect-brk (and $DEBUG_PORT) if DEBUG is set
node_args=()