142 lines
4.2 KiB
Bash
142 lines
4.2 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -e
|
|
|
|
script_path="$(dirname "$(realpath "$0")")"
|
|
|
|
DOBU_TMP=/tmp/dobu
|
|
|
|
. "$script_path/config-default.sh"
|
|
[ -f "$script_path/config.sh" ] && . "$script_path/config.sh"
|
|
|
|
# This function exists so that we can update the seccomp profile used
|
|
update_podman_security_args() {
|
|
local seccomp_profile="$1"
|
|
[ -z "$seccomp_profile" ] && seccomp_profile="seccomp.json"
|
|
# Default security-related arguments ALWAYS passed to podman
|
|
# Install a seccomp filter that disallows sub-namespaces which could lead to exploits
|
|
# and use the keep-id mode of userns, such that the user 1100 is mapped to the
|
|
# current host user, and the root user inside the namespace is mapped to an unrelated
|
|
# large uid on the host.
|
|
podman_security_args=(
|
|
--security-opt
|
|
seccomp="$script_path/assets/$seccomp_profile"
|
|
--userns=keep-id:uid=1100,gid=1100
|
|
)
|
|
}
|
|
|
|
update_podman_security_args
|
|
|
|
assert_prerequisites() {
|
|
command -v podman >/dev/null 2>&1 || die "Podman is required"
|
|
command -v jq >/dev/null 2>&1 || die "jq is required"
|
|
[ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ] || die "Dobu must be run under a compliant Wayland compositor"
|
|
}
|
|
|
|
die() {
|
|
echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu][error] $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
log() {
|
|
echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu] $1"
|
|
}
|
|
|
|
is_in_array() {
|
|
local e match="$1"
|
|
shift
|
|
for e; do [[ "$e" == "$match" ]] && return 0; done
|
|
return 1
|
|
}
|
|
|
|
relative_path_to_image_name() {
|
|
local context_path="$script_path/$1"
|
|
|
|
[ -d "$context_path" ] || die "$context_path does not exist"
|
|
|
|
local relative_path="$(realpath --relative-to="$script_path" "$context_path")"
|
|
|
|
if [[ "$relative_path" =~ \.\. ]]; then
|
|
die "Image path must be a subdirectory of the dobu project"
|
|
fi
|
|
|
|
local image_name="dobu/${relative_path/\//-}"
|
|
echo "$image_name"
|
|
}
|
|
|
|
assert_image_exists() {
|
|
podman inspect "$1" > /dev/null 2>&1 || die "Image $1 does not exist; please build the image first"
|
|
}
|
|
|
|
container_exists() {
|
|
podman container exists $1 > /dev/null 2>&1
|
|
}
|
|
|
|
get_image_label() {
|
|
assert_image_exists "$1"
|
|
podman inspect "$1" | jq -r ".[0].Labels.\"$2\""
|
|
}
|
|
|
|
remove_stale_container() {
|
|
container_exists "$1" || return 0
|
|
local is_running="$(podman inspect "$1" | jq -r '.[0].State.Running')"
|
|
if [ "$is_running" == "false" ]; then
|
|
podman rm -f "$1"
|
|
fi
|
|
}
|
|
|
|
# Note: this works with __containers__, not images
|
|
container_entrypoint() {
|
|
podman inspect $1 | jq -r '.[0].Config.Entrypoint'
|
|
}
|
|
|
|
ensure_sommelier() {
|
|
assert_image_exists dobu/deps-sommelier
|
|
remove_stale_container dobu-deps-sommelier
|
|
if container_exists dobu-deps-sommelier; then
|
|
[ -S "$DOBU_TMP/X11-unix/X1" ] && [ -S "$DOBU_TMP/xdg_runtime/wayland-1" ] && return
|
|
log "Killing non-functional Sommelier container"
|
|
podman kill dobu-deps-sommelier
|
|
podman rm -f dobu-deps-sommelier
|
|
fi
|
|
|
|
rm -rf "$DOBU_TMP/xdg_runtime" || true
|
|
rm -rf "$DOBU_TMP/X11-unix" || true
|
|
mkdir -p "$DOBU_TMP/xdg_runtime"
|
|
mkdir -p "$DOBU_TMP/X11-unix"
|
|
|
|
log "Starting Sommelier as a nested compositor..."
|
|
|
|
podman run --rm -d "${podman_security_args[@]}" --name dobu-deps-sommelier \
|
|
-v "$DOBU_TMP/xdg_runtime":/xdg_runtime \
|
|
`# Pass through host wayland display for Sommelier always as wayland-0` \
|
|
-v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY":/xdg_runtime/wayland-0 \
|
|
`# X11-unix uses hard-coded path` \
|
|
-v "$DOBU_TMP/X11-unix":/tmp/.X11-unix \
|
|
`# DRM render nodes` \
|
|
-v /dev/dri:/dev/dri \
|
|
dobu/deps-sommelier
|
|
while [ ! -S "$DOBU_TMP/xdg_runtime/wayland-1" ] || [ ! -S "$DOBU_TMP/X11-unix/X1" ]; do
|
|
|
|
sleep 0.5
|
|
done
|
|
}
|
|
|
|
get_archlinux_pkg_ver() {
|
|
curl https://archlinux.org/packages/$1/json/ 2>/dev/null | jq -r '. | .pkgver + "-" + .pkgrel'
|
|
}
|
|
|
|
get_aur_pkg_ver() {
|
|
curl "https://aur.archlinux.org/rpc/v5/info?arg[]=$1" 2>/dev/null | jq -r '.results[0].Version'
|
|
}
|
|
|
|
# Note: this does not specify which version of Ubuntu to use, because we don't actually care
|
|
# this version can and will only used to invalidate Docker cache, and we only need a vague
|
|
# idea of whether this package has been updated upstream.
|
|
get_ubuntu_pkg_ver() {
|
|
curl "https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=$1&exact_match=true" | jq -r '.entries[0].source_package_version'
|
|
}
|
|
|
|
get_github_pkg_ver() {
|
|
curl "https://api.github.com/repos/$1/tags" | jq -r '.[0].name'
|
|
}
|