dobu/functions.sh

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'
}