1
0
Fork 0
env/.local/bin/contain

235 lines
4.3 KiB
Plaintext
Raw Normal View History

2021-03-16 19:21:41 +08:00
#!/bin/sh
2021-03-16 19:34:17 +08:00
set -eo pipefail
2021-03-16 19:21:41 +08:00
# snippet from https://github.com/mkropat/sh-realpath
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
resolve_symlinks() {
_resolve_symlinks "$1"
}
_resolve_symlinks() {
_assert_no_path_cycles "$@" || return
local dir_context path
path=$(readlink -- "$1")
if [ $? -eq 0 ]; then
dir_context=$(dirname -- "$1")
_resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@"
else
printf '%s\n' "$1"
fi
}
_prepend_dir_context_if_necessary() {
if [ "$1" = . ]; then
printf '%s\n' "$2"
else
_prepend_path_if_relative "$1" "$2"
fi
}
_prepend_path_if_relative() {
case "$2" in
/* ) printf '%s\n' "$2" ;;
* ) printf '%s\n' "$1/$2" ;;
esac
}
_assert_no_path_cycles() {
local target path
target=$1
shift
for path in "$@"; do
if [ "$path" = "$target" ]; then
return 1
fi
done
}
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
local dir file
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
2021-03-16 19:34:17 +08:00
. ~/.config/contain
2021-03-16 19:21:41 +08:00
if [[ -f "$(which docker 2>/dev/null)" ]]; then
2021-03-16 19:51:10 +08:00
runtime=docker
2021-03-16 19:21:41 +08:00
elif [[ -f "$(which podman 2>/dev/null)" ]]; then
2021-03-16 19:51:10 +08:00
runtime=podman
runtime_extra_opts="$runtime_extra_opts--userns=keep-id "
2021-03-16 19:21:41 +08:00
fi
2021-03-16 19:51:10 +08:00
if $runtime info | grep -iq selinux; then
selinux_enabled=true
2021-03-16 19:21:41 +08:00
else
2021-03-16 19:51:10 +08:00
selinux_enabled=false
2021-03-16 19:21:41 +08:00
fi
OPTIND=1
2021-03-16 19:51:10 +08:00
label="${0##*/}=true"
2021-03-17 02:14:22 +08:00
labels="--label $label "
env="--env TERM --env CONTAIN=true "
2021-03-16 19:21:41 +08:00
workdir=""
delete=""
name=""
2021-03-17 02:53:43 +08:00
ports=""
2021-03-16 19:21:41 +08:00
host=""
volumes=""
image="$DEFAULT_IMAGE"
tag="$DEFAULT_TAG"
show_help() {
cat << EOF
Usage: ${0##*/} [-xwo] [-n NAME] [-p PORT]... [-v LIST]... [-i IMAGE] [-t TAG] [CMD]...
${0##*/} -l
${0##*/} -a NAME
${0##*/} -e NAME [CMD]...
${0##*/} -h
Starts an environment container. If CMD is specified, starts CMD instead of a shell.
-x delete Docker container after exit. will loose data
2021-03-16 19:34:17 +08:00
-w forward \$PWD into $CONTAIN_HOME/src, and start there
2021-03-16 19:21:41 +08:00
-o use host networking instead
-n NAME give container a NAME
-p PORT forward host PORT to container PORT
-v LIST mount volume LIST. specify as LOCAL:MOUNT
-i IMAGE use IMAGE as container image instead
-t TAG use TAG as container tag instead
-l list running containers and exit
2021-03-17 02:53:43 +08:00
-u pull image and exit
2021-03-16 19:21:41 +08:00
-a NAME attach to a running container
-e NAME execute zsh or CMD on a running container
-h display this help and exit
EOF
}
list_running() {
2021-03-16 19:51:10 +08:00
$runtime ps --all \
--filter label="$label" \
--format "table {{.Names}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Command}}"
2021-03-16 19:21:41 +08:00
}
2021-03-17 02:53:43 +08:00
pull_image() {
$runtime pull \
$image:$tag
}
while getopts "xwon:p:v:i:t:lua:e:h" opt; do
2021-03-16 19:21:41 +08:00
case "$opt" in
x)
delete="--rm "
;;
w)
2021-03-17 02:53:43 +08:00
workdir="--workdir $CONTAIN_HOME/src/ "
2021-03-16 19:51:10 +08:00
if $selinux_enabled; then
volume_opts=":z"
fi
2021-03-17 02:53:43 +08:00
mount="$(realpath "$PWD")"
volumes="$volumes--volume \"$mount:$CONTAIN_HOME/src/$volume_opts\" "
2021-03-16 19:21:41 +08:00
;;
o)
host="--net host "
;;
n)
2021-03-17 02:14:22 +08:00
name="--name $OPTARG --hostname $OPTARG "
2021-03-16 19:21:41 +08:00
;;
p)
2021-03-17 02:14:22 +08:00
ports="$ports--publish $OPTARG:$OPTARG "
2021-03-16 19:21:41 +08:00
;;
v)
2021-03-16 19:51:10 +08:00
if $selinux_enabled; then
volume_opts=":z"
fi
2021-03-17 02:53:43 +08:00
volumes="$volumes--volume $OPTARG$volume_opts "
2021-03-16 19:21:41 +08:00
;;
i)
image="$OPTARG"
;;
t)
tag="$OPTARG"
;;
l)
list_running
exit 0
;;
2021-03-17 02:53:43 +08:00
u)
pull_image
exit 0
;;
2021-03-16 19:21:41 +08:00
a)
mode_attach="true"
name="$OPTARG"
;;
e)
mode_execute="true"
name="$OPTARG"
;;
h)
show_help
exit 0
;;
:)
echo "Option -$OPTARG requires an argument." >&2
show_help
exit 1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
show_help
exit 1
;;
esac
done
shift $((OPTIND-1))
[ "$1" = "--" ] && shift
if [ "$ports" = "\n\t" ]; then
ports=""
fi
if [ "$mode_attach" = "true" ]; then
2021-03-16 19:51:10 +08:00
$runtime attach \
2021-03-16 19:21:41 +08:00
$name
exit 0
fi
if [ "$mode_execute" = "true" ]; then
cmd="$@"
if [ -z "$@" ]; then
cmd="/bin/zsh"
fi
2021-03-17 02:53:43 +08:00
$runtime exec --interactive --tty \
2021-03-16 19:21:41 +08:00
$name \
$cmd
exit 0
fi
2021-03-17 02:53:43 +08:00
cmd="\
$runtime run --interactive --tty \
$runtime_extra_opts\
$labels$env\
$delete\
$name\
$ports$host\
$workdir$volumes\
$image:$tag\
$@ \
"
echo Running: $cmd
exec sh -c "exec $cmd"