mirror of https://github.com/rapenne-s/bento
libs: allow flakes to have multiple systems, if so, use the flakes output as directory and user names
This commit is contained in:
parent
69abe73000
commit
7fd5558111
85
libs.sh
85
libs.sh
|
@ -1,3 +1,12 @@
|
|||
user_exists() {
|
||||
user="$1"
|
||||
if ! id "${user}" >/dev/null 2>/dev/null
|
||||
then
|
||||
echo "you need a system user in your fleet for ${user}"
|
||||
exit 3
|
||||
fi
|
||||
}
|
||||
|
||||
build_config()
|
||||
{
|
||||
SOURCES=$1
|
||||
|
@ -5,6 +14,8 @@ build_config()
|
|||
SUDO="$3"
|
||||
NAME="$4"
|
||||
|
||||
user_exists "${NAME}"
|
||||
|
||||
SUCCESS=0
|
||||
TMP="$(mktemp -d /tmp/bento-build.XXXXXXXXXXXX)"
|
||||
TMPLOG="$(mktemp /tmp/bento-build-log.XXXXXXXXXXXX)"
|
||||
|
@ -19,7 +30,7 @@ build_config()
|
|||
test -d .git || git init >/dev/null 2>/dev/null
|
||||
git add . >/dev/null
|
||||
|
||||
$SUDO nixos-rebuild "${COMMAND}" --flake .#bento-machine 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
$SUDO nixos-rebuild "${COMMAND}" --flake ".#${NAME}" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
else
|
||||
$SUDO nixos-rebuild "${COMMAND}" --no-flake -I nixos-config="$TMP/configuration.nix" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
fi
|
||||
|
@ -46,8 +57,19 @@ build_config()
|
|||
}
|
||||
|
||||
deploy_files() {
|
||||
i="$1"
|
||||
printf "Copying $i: "
|
||||
sources="$1"
|
||||
user="$2"
|
||||
config="$3"
|
||||
if [ -n "${config}" ]
|
||||
then
|
||||
dest="${config}"
|
||||
else
|
||||
dest="${sources}"
|
||||
fi
|
||||
|
||||
user_exists "${dest}"
|
||||
|
||||
printf "Copying ${dest}: "
|
||||
|
||||
# we only want directories
|
||||
if [ -d "$i" ]
|
||||
|
@ -57,15 +79,15 @@ deploy_files() {
|
|||
|
||||
# sftp chroot requires the home directory to be owned by root
|
||||
install -d -o root -g sftp_users -m 755 "${STAGING_DIR}"
|
||||
install -d -o root -g sftp_users -m 755 "${STAGING_DIR}/${i}"
|
||||
install -d -o root -g sftp_users -m 755 "${STAGING_DIR}/${i}/config"
|
||||
install -d -o "${i}" -g sftp_users -m 755 "${STAGING_DIR}/${i}/logs"
|
||||
install -d -o root -g sftp_users -m 755 "${STAGING_DIR}/${sources}"
|
||||
install -d -o root -g sftp_users -m 755 "${STAGING_DIR}/${sources}/config"
|
||||
install -d -o "${user}" -g sftp_users -m 755 "${STAGING_DIR}/${sources}/logs"
|
||||
|
||||
# copy files in the chroot
|
||||
rsync --delete -rltgoDL "$i/" "${STAGING_DIR}/${i}/config/"
|
||||
rsync --delete -rltgoDL "$sources/" "${STAGING_DIR}/${sources}/config/"
|
||||
|
||||
# create the script that will check for updates
|
||||
cat > "${STAGING_DIR}/${i}/config/update.sh" <<EOF
|
||||
cat > "${STAGING_DIR}/${sources}/config/update.sh" <<EOF
|
||||
#!/bin/sh
|
||||
|
||||
install -d -o root -g root -m 700 /var/bento
|
||||
|
@ -76,7 +98,7 @@ touch .state
|
|||
ssh-keygen -F "${REMOTE_IP}" >/dev/null || ssh-keyscan "${REMOTE_IP}" >> /root/.ssh/known_hosts
|
||||
|
||||
STATEFILE="\$(mktemp /tmp/bento-state.XXXXXXXXXXXXXXXX)"
|
||||
echo "ls -l last_change_date" | sftp ${i}@${REMOTE_IP} >"\${STATEFILE}"
|
||||
echo "ls -l last_change_date" | sftp ${user}@${REMOTE_IP} >"\${STATEFILE}"
|
||||
|
||||
if [ \$? -ne 0 ]
|
||||
then
|
||||
|
@ -94,7 +116,7 @@ then
|
|||
echo "no update required"
|
||||
else
|
||||
echo "update required"
|
||||
sftp ${i}@${REMOTE_IP}:/config/bootstrap.sh .
|
||||
sftp ${user}@${REMOTE_IP}:/config/bootstrap.sh .
|
||||
/bin/sh bootstrap.sh
|
||||
echo "\${STATE}" > "/var/bento/.state"
|
||||
fi
|
||||
|
@ -103,7 +125,7 @@ EOF
|
|||
|
||||
# script used to download changes and rebuild
|
||||
# also used to run it manually the first time to configure the system
|
||||
cat > "${STAGING_DIR}/${i}/config/bootstrap.sh" <<EOF
|
||||
cat > "${STAGING_DIR}/${sources}/config/bootstrap.sh" <<EOF
|
||||
#!/bin/sh
|
||||
|
||||
# accept the remote ssh fingerprint if not already known
|
||||
|
@ -115,7 +137,7 @@ cd /var/bento || exit 5
|
|||
find . -maxdepth 1 -type d -exec rm -fr {} \;
|
||||
find . -maxdepth 1 -type f -not -name .state -and -not -name update.sh -and -not -name bootstrap.sh -exec rm {} \;
|
||||
|
||||
printf "%s\n" "cd config" "get -R ." | sftp -r ${i}@${REMOTE_IP}:
|
||||
printf "%s\n" "cd config" "get -R ." | sftp -r ${user}@${REMOTE_IP}:
|
||||
|
||||
# required by flakes
|
||||
test -d .git || git init
|
||||
|
@ -129,7 +151,7 @@ LOGFILE=\$(mktemp /tmp/build-log.XXXXXXXXXXXXXXXXXXXX)
|
|||
SUCCESS=2
|
||||
if test -f flake.nix
|
||||
then
|
||||
nixos-rebuild build --flake .#bento-machine
|
||||
nixos-rebuild build --flake .#${dest}
|
||||
else
|
||||
export NIX_PATH=/root/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/var/bento/configuration.nix:/nix/var/nix/profiles/per-user/root/channels
|
||||
nixos-rebuild build --no-flake --upgrade 2>&1 | tee \$LOGFILE
|
||||
|
@ -142,7 +164,7 @@ then
|
|||
then
|
||||
if test -f flake.nix
|
||||
then
|
||||
nixos-rebuild switch --flake .#bento-machine 2>&1 | tee \$LOGFILE
|
||||
nixos-rebuild switch --flake .#${dest} 2>&1 | tee \$LOGFILE
|
||||
else
|
||||
nixos-rebuild switch --no-flake --upgrade 2>&1 | tee -a \$LOGFILE
|
||||
fi
|
||||
|
@ -177,7 +199,7 @@ fi
|
|||
|
||||
# rollback if something is wrong
|
||||
# we test connection to the sftp server
|
||||
echo "ls -l last_change_date" | sftp ${i}@${REMOTE_IP} >"\${LOGFILE}"
|
||||
echo "ls -l last_change_date" | sftp ${user}@${REMOTE_IP} >"\${LOGFILE}"
|
||||
if [ "\$?" -ne 0 ];
|
||||
then
|
||||
nixos-rebuild --rollback switch
|
||||
|
@ -188,14 +210,14 @@ fi
|
|||
gzip -9 \$LOGFILE
|
||||
if [ "\$SUCCESS" -eq 0 ]
|
||||
then
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_success.log.gz" | sftp ${i}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_success.log.gz" | sftp ${user}@${REMOTE_IP}:
|
||||
else
|
||||
# check if we did a rollback
|
||||
if [ "\$SUCCESS" -eq 255 ]
|
||||
then
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_rollback.log.gz" | sftp ${i}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_rollback.log.gz" | sftp ${user}@${REMOTE_IP}:
|
||||
else
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_failure.log.gz" | sftp ${i}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_failure.log.gz" | sftp ${user}@${REMOTE_IP}:
|
||||
fi
|
||||
fi
|
||||
rm "\${LOGFILE}.gz"
|
||||
|
@ -203,7 +225,7 @@ EOF
|
|||
|
||||
# to make flakes using caching, we must avoid repositories to change everytime
|
||||
# we must ignore files that change everytime
|
||||
cat > "${STAGING_DIR}/${i}/config/.gitignore" <<EOF
|
||||
cat > "${STAGING_DIR}/${sources}/config/.gitignore" <<EOF
|
||||
bootstrap.sh
|
||||
update.sh
|
||||
.state
|
||||
|
@ -213,25 +235,26 @@ EOF
|
|||
|
||||
# only distribute changes if they changed
|
||||
# this avoids bumping the time and trigger a rebuild for nothing
|
||||
diff -r "${STAGING_DIR}/${i}/config/" "${CHROOT_DIR}/${i}/config/" >/dev/null
|
||||
|
||||
diff -r "${STAGING_DIR}/${sources}/config/" "${CHROOT_DIR}/${dest}/config/" >/dev/null
|
||||
CHANGES=$?
|
||||
|
||||
if [ "$CHANGES" -ne 0 ]
|
||||
then
|
||||
build_config "${STAGING_DIR}/${i}/config/" "build" "" "${i}"
|
||||
if [ $? -eq 0 ]
|
||||
if [ -n "${config}" ]
|
||||
then
|
||||
echo " update required"
|
||||
# copy files in the chroot
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}"
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}/${i}"
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}/${i}/config"
|
||||
install -d -o "${i}" -g sftp_users -m 755 "${CHROOT_DIR}/${i}/logs"
|
||||
rsync --delete -rltgoDL "${STAGING_DIR}/${i}/config/" "${CHROOT_DIR}/${i}/config/"
|
||||
touch "${CHROOT_DIR}/${i}/last_change_date"
|
||||
build_config "${STAGING_DIR}/${sources}/config/" "build" "" "${config}"
|
||||
else
|
||||
echo " an error occured"
|
||||
build_config "${STAGING_DIR}/${sources}/config/" "build" "" "${sources}"
|
||||
fi
|
||||
echo " update required"
|
||||
# copy files in the chroot
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}"
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}/${dest}"
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}/${dest}/config"
|
||||
install -d -o "${dest}" -g sftp_users -m 755 "${CHROOT_DIR}/${dest}/logs"
|
||||
rsync --delete -rltgoDL "${STAGING_DIR}/${sources}/config/" "${CHROOT_DIR}/${dest}/config/"
|
||||
touch "${CHROOT_DIR}/${dest}/last_change_date"
|
||||
else
|
||||
echo " no changes"
|
||||
fi
|
||||
|
|
|
@ -10,25 +10,112 @@ fi
|
|||
|
||||
. ./libs.sh
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]
|
||||
then
|
||||
echo "you need to be root to run this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd hosts
|
||||
|
||||
# load all hosts or the one defined in environment variable NAME
|
||||
if [ -z "$NAME" ]
|
||||
FLAKES=$(
|
||||
for flakes in $(find . -name flake.nix)
|
||||
do
|
||||
TARGET="$(dirname $flakes)"
|
||||
nix flake show --json "path:$TARGET" | jq -r '.nixosConfigurations | keys[]'
|
||||
done
|
||||
)
|
||||
|
||||
if [ -z "${NAME}" ]
|
||||
then
|
||||
NAME=*
|
||||
NAME=*
|
||||
PRETTY_OUT_COLUMN=$( ( ls -1 ; echo $FLAKES ) | awk '{ if(length($1) > max) { max = length($1) }} END { print max }')
|
||||
else
|
||||
MATCH=$(echo "$FLAKES" | awk -v name="${NAME}" 'BEGIN { sum = 0 } name == $1 { sum=sum+1 } END { print sum }')
|
||||
if [ "$MATCH" -ne 1 ]
|
||||
then
|
||||
echo "Found ${MATCH} system with this name"
|
||||
exit 2
|
||||
else
|
||||
for flakes in $(find . -name flake.nix)
|
||||
do
|
||||
TARGET="$(dirname $flakes)"
|
||||
FLAKES_IN_DIR=$(nix flake show --json "path:$TARGET" | jq -r '.nixosConfigurations | keys[]')
|
||||
if echo "${FLAKES_IN_DIR}" | grep "^${NAME}$" >/dev/null
|
||||
then
|
||||
# store the configuration name
|
||||
SINGLE_FLAKE="${NAME}"
|
||||
# store the directory containing it
|
||||
NAME="$(basename ${TARGET})"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
for i in $NAME
|
||||
do
|
||||
deploy_files "$i"
|
||||
if [ "$1" = "build" ]
|
||||
then
|
||||
if [ -z "$2" ]
|
||||
then
|
||||
COMMAND="dry-build"
|
||||
else
|
||||
COMMAND="$2"
|
||||
fi
|
||||
|
||||
if [ "$COMMAND" = "switch" ] || [ "$COMMAND" = "test" ]
|
||||
then
|
||||
|
||||
# we only allow these commands if you have only one name
|
||||
if [ -n "$NAME" ]
|
||||
then
|
||||
SUDO="sudo"
|
||||
echo "you are about to $COMMAND $NAME, are you sure? Ctrl+C to abort"
|
||||
read a
|
||||
else
|
||||
echo "you can't use $COMMAND without giving a single configuration to use with variable NAME"
|
||||
fi
|
||||
|
||||
else # not using switch or test
|
||||
SUDO=""
|
||||
fi
|
||||
for i in $NAME
|
||||
do
|
||||
test -d "$i" || continue
|
||||
if [ -f "$i/flake.nix" ]
|
||||
then
|
||||
for host in $(nix flake show --json "path:${i}" | jq -r '.nixosConfigurations | keys[]')
|
||||
do
|
||||
test -n "${SINGLE_FLAKE}" && ! [ "$host" = "${SINGLE_FLAKE}" ] && continue
|
||||
printf "%${PRETTY_OUT_COLUMN}s " "${host}"
|
||||
build_config "$i" "$COMMAND" "$SUDO" "$host"
|
||||
done
|
||||
else
|
||||
printf "%${PRETTY_OUT_COLUMN}s " "${i}"
|
||||
build_config "$i" "$COMMAND" "$SUDO" "$i"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "deploy" ]
|
||||
then
|
||||
if [ "$(id -u)" -ne 0 ]
|
||||
then
|
||||
echo "you need to be root to run this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in $NAME
|
||||
do
|
||||
if [ -f "$i/flake.nix" ]
|
||||
then
|
||||
for host in $(nix flake show --json "path:${i}" | jq -r '.nixosConfigurations | keys[]')
|
||||
do
|
||||
test -n "${SINGLE_FLAKE}" && ! [ "$host" = "${SINGLE_FLAKE}" ] && continue
|
||||
deploy_files "$i" "${host}" "${host}"
|
||||
done
|
||||
else
|
||||
deploy_files "$i" "$i"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [ -f ../states.txt ]
|
||||
then
|
||||
cp ../states.txt "${CHROOT_DIR}/states.txt"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue