You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.9 KiB

#!/usr/bin/env bash
# CONSTANTS
BASEDIR=$(dirname "$0")
MIAOU_IMAGE=images:debian/13
APT_ARCHIVES=/var/cache/apt/archives
PROJECT_SANDBOX=sandbox
TEMPLATE_SANDBOX=miaou-debian13-template
TEMPLATE_REFRESH_DELAY="7 days"
CONTAINER=
# FUNCTIONS
function usage {
echo "$(basename "$0") <CONTAINER_NAME>"
}
function humanize_ago {
local seconds=$(($(date +%s) - $(date -d "$1" +%s)))
local days=$((seconds / 86400))
local hours=$(((seconds % 86400) / 3600))
local minutes=$(((seconds % 3600) / 60))
if ((days > 365)); then
echo "$((days / 365)) year(s) ago"
elif ((days > 30)); then
echo "$((days / 30)) month(s) ago"
elif ((days > 0)); then
echo "$days day(s) ago"
elif ((hours > 0)); then
echo "$hours hour(s) ago"
elif ((minutes > 0)); then
echo "$minutes minute(s) ago"
else
echo "$seconds second(s) ago"
fi
}
function parse_options {
while [[ $# -gt 0 ]]; do
case "$1" in
--help | -h)
usage && exit 0
;;
*)
if [[ -z $CONTAINER ]]; then
CONTAINER=$1
else
echo >&2 "Unknown option: $1" && usage && exit 2
fi
;;
esac
shift 1 # Move to the next argument
done
[[ -n $CONTAINER ]] || (usage && exit 1)
}
function create {
incus --project "$PROJECT_SANDBOX" copy "$TEMPLATE_SANDBOX" "$CONTAINER" --target-project $(incus project get-current)
incus file delete "$CONTAINER/etc/machine-id"
incus start "$CONTAINER"
customize_host "$CONTAINER"
}
function mount_miaou_bash {
[[ -v MIAOU_BASH_DIR ]] && echo >&2 "Warn: variable MIAOU_BASH_DIR missing!" && return
local target="$1"
local optional_project=${2:-}
[[ -n $optional_project ]] && optional_project="--project $optional_project"
incus $optional_project config device add $target MIAOU-BASH disk source=$MIAOU_BASH_DIR path=/opt/miaou-bash readonly=true | grep -q 'Device MIAOU-BASH added'
incus $optional_project config set $target environment.PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/miaou-bash/tools
}
function build_sandbox_project {
incus project show $PROJECT_SANDBOX > /dev/null || incus project create $PROJECT_SANDBOX
}
function refresh_template {
incus --project "$PROJECT_SANDBOX" start "$TEMPLATE_SANDBOX"
incus --project "$PROJECT_SANDBOX" exec "$TEMPLATE_SANDBOX" -- bash << EOF
apt-get update
apt-get dist-upgrade -y
apt-get install -y curl
/opt/miaou-bash/install.sh
EOF
incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX"
local image_date=$(incus --project "$PROJECT_SANDBOX" list "$TEMPLATE_SANDBOX" -f compact,noheader -cl)
echo "template refreshed at: $image_date"
}
function build_template_from_scratch {
build_sandbox_project
echo "building image from scratch..."
incus --project "$PROJECT_SANDBOX" file delete "$TEMPLATE_SANDBOX"/etc/apt/sources.list
incus --project "$PROJECT_SANDBOX" file push --uid 0 --gid 0 --mode 644 --create-dirs /etc/apt/sources.list.d/debian.sources "$TEMPLATE_SANDBOX"/etc/apt/sources.list.d/debian.sources
cat << EOF | incus --project "$PROJECT_SANDBOX" file push --uid 0 --gid 0 --mode 644 --create-dirs - "$TEMPLATE_SANDBOX"/etc/systemd/resolved.conf.d/10-disable-ipv4-listener.conf
[Resolve]
LLMNR=no
DNSStubListener=no
EOF
mount_miaou_bash "$TEMPLATE_SANDBOX" "$PROJECT_SANDBOX"
incus --project "$PROJECT_SANDBOX" create "$MIAOU_IMAGE" "$TEMPLATE_SANDBOX"
refresh_template
echo "image:"$TEMPLATE_SANDBOX" from project:$PROJECT_SANDBOX built successfully!"
}
function prepare_template_for_quick_creation {
local image_date=$(incus list "$TEMPLATE_SANDBOX" -f compact,noheader -cl --project "$PROJECT_SANDBOX")
if [[ -z $image_date ]]; then
build_template_from_scratch
else
local true_date=$(date -d "$image_date" +%s)
local expiration_date=$(date -d "$TEMPLATE_REFRESH_DELAY ago" +%s)
if ((true_date < expiration_date)); then
echo "template exists $(humanize_ago "$image_date"), needs a refresh..."
refresh_template
else
:
# echo "template already exists $(humanize_ago "$image_date")!"
fi
fi
}
function customize_host {
local target="$1"
local domain=$(incus network get incusbr0 dns.domain)
domain=${domain:-incus}
cat << EOF | incus file push --uid 0 --gid 0 --mode 644 --create-dirs - $target/etc/hosts
127.0.1.1 $target.$domain $target
127.0.0.1 localhost
EOF
}
function assert_not_sandboxing {
[[ $(incus project get-current) == "$PROJECT_SANDBOX" ]] \
&& echo ERROR: actual sandboxing project, please switch back to your 'default' project >&2 \
&& exit 30 \
|| true
}
# MAIN
set -Eue
parse_options "$@"
assert_not_sandboxing
prepare_template_for_quick_creation
create
echo Success