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
5.3 KiB
154 lines
5.3 KiB
#!/bin/bash
|
|
|
|
## Init is run on host
|
|
## For now it is run every time the script is launched, but
|
|
## it should be launched only once after build.
|
|
|
|
## Accessible variables are:
|
|
## - SERVICE_NAME Name of current service
|
|
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
|
|
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
|
|
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
|
|
|
|
|
|
set -e
|
|
|
|
service_def=$(get_compose_service_def "$SERVICE_NAME")
|
|
|
|
admin_keys=$(echo "$service_def" | shyaml -y get-value options.admin 2>/dev/null) || {
|
|
err "You must specify a ${WHITE}admin${NORMAL} struct in ${DARKYELLOW}$SERVICE_NAME${NORMAL}'s options"
|
|
exit 1
|
|
}
|
|
|
|
[ "$(echo "$admin_keys" | shyaml -y get-type 2>/dev/null)" == "struct" ] || {
|
|
err "Invalid value type for ${WHITE}admin${NORMAL} in" \
|
|
"${DARKYELLOW}$SERVICE_NAME${NORMAL}'s options, please provide a struct"
|
|
exit 1
|
|
}
|
|
|
|
|
|
rebuild-config() {
|
|
|
|
rm -rf "$SERVICE_CONFIGSTORE/etc/rsync/keys/admin"
|
|
mkdir -p "$host_path_key"
|
|
|
|
while read-0 ident keys; do
|
|
ident=$(e "$ident" | shyaml get-value)
|
|
if ! [[ "$ident" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
|
err "Invalid identifier '$ident'," \
|
|
"please use only alphanumerical char, dots, dash or underscores."
|
|
exit 1
|
|
fi
|
|
debug "Setting access keys for ${ident}"
|
|
[ "$(echo "$keys" | shyaml -y get-type 2>/dev/null)" == "sequence" ] || {
|
|
err "Invalid value type for ${WHITE}admin.$ident${NORMAL}, please provide a sequence"
|
|
echo " Received: '$keys'" >&2
|
|
exit 1
|
|
}
|
|
|
|
while read-0 key; do
|
|
echo "command=\"/usr/local/sbin/ssh-admin-cmd-validate \\\"$ident\\\"\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty $key"
|
|
done < <(echo "$keys" | shyaml get-values-0) | file_put "$host_path_key/$ident/.ssh/authorized_keys"
|
|
done < <(echo "$admin_keys" | shyaml -y key-values-0)
|
|
|
|
mkdir -p "${CONTROL_USERS_FILE%/*}" || return 1
|
|
e "$control_users" > "$CONTROL_USERS_FILE"
|
|
}
|
|
|
|
is_btrfs_subvolume() {
|
|
local dir=$1
|
|
[ "$(stat -f --format="%T" "$dir")" == "btrfs" ] || return 1
|
|
inode="$(stat --format="%i" "$dir")"
|
|
case "$inode" in
|
|
2|256)
|
|
return 0;;
|
|
*)
|
|
return 1;;
|
|
esac
|
|
}
|
|
|
|
|
|
local_path_key=/etc/rsync/keys/admin
|
|
host_path_key="$SERVICE_CONFIGSTORE${local_path_key}"
|
|
|
|
|
|
CONTROL_USERS_FILE="$SERVICE_DATASTORE/.control-pass"
|
|
## Was it already properly propagated to database ?
|
|
control_users=$(H "${admin_keys}" "$(declare -f "rebuild-config")")
|
|
|
|
if ! out=$(stat -f -c %T "$SERVICE_DATASTORE"/var/log 2>&1); then
|
|
err "Command 'stat' failed with error:"
|
|
echo "$out" | prefix " ${GRAY}|${NORMAL} " >&2
|
|
exit 1
|
|
fi
|
|
|
|
compose_fragments=""
|
|
if [ "$out" == "btrfs" ]; then
|
|
## We'll need to add SYS_ADMIN capability to the container to
|
|
## allow it to delete snapshots
|
|
compose_fragments+="\
|
|
cap_add:
|
|
- SYS_ADMIN
|
|
"
|
|
|
|
RSYNC_LOG_PATH="$SERVICE_DATASTORE/var/log/rsync"
|
|
if ! is_btrfs_subvolume "$RSYNC_LOG_PATH"; then
|
|
previous_contents=
|
|
if [ -e "$RSYNC_LOG_PATH" ]; then
|
|
previous_contents=1
|
|
info "Directory '$RSYNC_LOG_PATH' exists but is not a btrfs subvolume."
|
|
## we want to keep the data, so we'll move it to a temporary location
|
|
mv "$RSYNC_LOG_PATH" "${RSYNC_LOG_PATH}.bak"
|
|
fi
|
|
if ! out=$(btrfs subvolume create "$RSYNC_LOG_PATH" 2>&1); then
|
|
err "Command 'btrfs subvolume create' failed with error:"
|
|
echo "$out" | prefix " ${GRAY}|${NORMAL} " >&2
|
|
if [ -n "$previous_contents" ]; then
|
|
info "Restoring previous contents of '$RSYNC_LOG_PATH'"
|
|
mv "${RSYNC_LOG_PATH}.bak" "$RSYNC_LOG_PATH" || exit 1
|
|
fi
|
|
exit 1
|
|
fi
|
|
if [ -n "$previous_contents" ]; then
|
|
info "Moving previous contents of '$RSYNC_LOG_PATH' into the new subvolume."
|
|
(
|
|
## avoid sending our env to find,
|
|
## to prevent any "The environment is too large for exec" error
|
|
env -i PATH=/bin:/usr/bin \
|
|
find "${RSYNC_LOG_PATH}.bak" \
|
|
-mindepth 1 -maxdepth 1 \
|
|
-exec cp -a {} "$RSYNC_LOG_PATH/" \;
|
|
) && rm -rf "${RSYNC_LOG_PATH}.bak" || {
|
|
err "Failed to copy previous contents of '$RSYNC_LOG_PATH' into the new subvolume."
|
|
rmdir "$RSYNC_LOG_PATH" || {
|
|
err "Failed to delete the newly created subvolume."
|
|
echo " Couldn't restore previous state !!" >&2
|
|
exit 1
|
|
}
|
|
mv "${RSYNC_LOG_PATH}.bak" "$RSYNC_LOG_PATH" || {
|
|
err "Failed to restore previous contents of '$RSYNC_LOG_PATH'."
|
|
echo " Couldn't restore previous state !!" >&2
|
|
exit 1
|
|
}
|
|
exit 1
|
|
}
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
|
|
init-config-add "\
|
|
$SERVICE_NAME:
|
|
volumes:
|
|
- $host_path_key:$local_path_key
|
|
labels:
|
|
- compose.config_hash=$control_users
|
|
$compose_fragments
|
|
"
|
|
|
|
if [ -e "$CONTROL_USERS_FILE" ] && [ "$control_users" == "$(cat "$CONTROL_USERS_FILE")" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
|
|
rebuild-config
|