2016-07-05 17:48:14 +00:00
#!/bin/bash
2020-05-07 09:16:24 +00:00
set -e
2017-07-07 21:49:41 +00:00
#
# This script can be used to facilitate supervisor development. Its core feature is allowing
# faster development iterations by bind-mounting the local './dist' directly into the running
# supervisor container.
#
2017-07-10 16:37:36 +00:00
# Setting the '--mount-nm' flag in either 'run' or 'buildrun' action will bind-mount
2017-07-07 21:49:41 +00:00
# './node_modules/' into the running supervisor. In this case, it's up to the developer
# to make sure that the correct dependencies are installed.
#
# Usage: dindctl action [options]
#
# Actions:
2018-12-07 17:54:16 +00:00
# build build local supervisor image. By default it will be balena/amd64-supervisor:master, you can override the tag with --tag.
# run [options] build dind host container, run it (with name balena_supervisor_1), which will include the specified supervisor image and run it.
# buildrun [options] run 'build' and then immediately 'run' the built container.
# refresh recompile sources in './src' and restart supervisor container on dind host - requires --mount-dist in order to work properly.
# logs [-f] print out supervisor log files - use '-f' to follow instead, or any other arguments you'd send to journalctl.
# stop stop dind supervisor host container.
2017-07-07 21:49:41 +00:00
# Options:
2018-12-07 17:54:16 +00:00
# --arch | -a [arch] architecture of the supervisor to build (default: amd64 )
# --image | -i [image] image name for supervisor image to build/use ( default: balena/$ARCH-supervisor:master )
2019-11-12 11:47:07 +00:00
# --dind-image [image] image to use for the balenaos-in-container host (default: resin/resinos:2.12.5_rev1-intel-nuc)
# --dind-container [name] container name suffix for the dind host container ( default: "supervisor", which will produce a container named balena-container-supervisor)
2018-12-07 17:54:16 +00:00
# --mount-dist bind-mount './dist/' (where webpack stores the built js) from local development environment into supervisor container.
# --mount-nm bind-mount './node_modules/' from local development environment into supervisor container.
# --mount-backup bind-mount './tools/dind/backup.tgz' to simulate a migration backup.
# --preload | -p use tools/dind/apps.json to preload an application image into the dind host.
# --config | -c [file] path to config.json, relative to tools/dind ( default: config.json )
# --tag | -t [tag] for the "build" action, specify the tag to build (default: master)
# --no-clean for the "stop" action, skip removing the data, boot and state volumes
2017-07-07 21:49:41 +00:00
#
# See README.md for examples.
#
# The script requires make and docker.
#
THIS_FILE=$0
2016-07-05 17:48:14 +00:00
set -o errexit
set -o pipefail
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
2017-07-14 17:19:33 +00:00
SUPERVISOR_BASE_DIR="${DIR}"
2020-05-07 09:16:24 +00:00
DIND_DIR="${SUPERVISOR_BASE_DIR}/tools/dind/"
2016-07-05 17:48:14 +00:00
2017-07-07 21:49:41 +00:00
ARCH="amd64"
2018-10-18 18:52:35 +00:00
SUPERVISOR_IMAGE="balena/${ARCH}-supervisor:master"
2020-05-07 09:16:24 +00:00
DIND_IMAGE="resin/resinos:2.48.0_rev3-intel-nuc"
2018-02-09 19:30:15 +00:00
MOUNT_DIST="false"
MOUNT_NODE_MODULES="false"
CONTAINER_NAME="supervisor"
2017-07-07 21:49:41 +00:00
PRELOADED_IMAGE=""
2017-07-26 18:43:44 +00:00
OPTIMIZE="true"
2020-05-07 09:16:24 +00:00
CONFIG_FILENAME="${DIND_DIR}config.json"
2017-11-10 20:01:49 +00:00
TAG="master"
2018-02-09 19:30:15 +00:00
CLEAN_VOLUMES="true"
2018-12-07 17:54:16 +00:00
MOUNT_BACKUP="false"
2016-07-05 17:48:14 +00:00
function showHelp {
2017-07-07 21:49:41 +00:00
cat $THIS_FILE | awk '{if(/^#/)print;else exit}' | tail -n +2 | sed 's/\#//' | sed 's|dindctl|'$THIS_FILE'|'
2016-07-05 17:48:14 +00:00
}
2017-07-07 21:49:41 +00:00
function parseOptions {
2017-07-26 17:44:09 +00:00
while [[ $# -ge 1 ]]
2016-07-05 17:48:14 +00:00
do
2017-07-07 21:49:41 +00:00
case $1 in
--mount-dist)
2018-02-09 19:30:15 +00:00
MOUNT_DIST="true"
2016-07-05 17:48:14 +00:00
;;
--mount-nm)
2018-02-09 19:30:15 +00:00
MOUNT_NODE_MODULES="true"
2017-07-07 21:49:41 +00:00
;;
2018-12-07 17:54:16 +00:00
--mount-backup)
MOUNT_BACKUP="true"
;;
2017-07-07 21:49:41 +00:00
-p|--preload)
PRELOADED_IMAGE="true"
;;
-i|--image)
SUPERVISOR_IMAGE="$2"
shift || { echo "--image provided not specified" && exit 1; }
;;
2017-10-10 17:21:21 +00:00
-c|--config)
CONFIG_FILENAME="$2"
shift || { echo "--config provided not specified" && exit 1; }
;;
2017-07-07 21:49:41 +00:00
--dind-image)
DIND_IMAGE="$2"
shift || { echo "--dind-image provided not specified" && exit 1; }
;;
2017-10-10 17:01:31 +00:00
--dind-container)
CONTAINER_NAME="$2"
shift || { echo "--dind-container provided not specified" && exit 1; }
;;
2017-07-07 21:49:41 +00:00
-a|--arch)
ARCH="$2"
shift || { echo "--arch provided not specified" && exit 1; }
2016-07-05 17:48:14 +00:00
;;
2017-11-10 20:01:49 +00:00
-t|--tag)
TAG="$2"
shift || { echo "--tag provided not specified" && exit 1; }
;;
-n|--no-optimize)
2017-07-26 18:43:44 +00:00
OPTIMIZE="false"
;;
2018-02-09 19:30:15 +00:00
--no-clean)
CLEAN_VOLUMES="false"
;;
2016-07-05 17:48:14 +00:00
*)
2019-11-11 23:34:59 +00:00
echo "Warning: unknown argument: $1"
2016-07-05 17:48:14 +00:00
;;
esac
2017-07-07 21:49:41 +00:00
shift
2016-07-05 17:48:14 +00:00
done
2017-07-07 21:49:41 +00:00
}
2016-07-05 17:48:14 +00:00
2020-05-07 09:16:24 +00:00
SUPERVISOR_DIND_MOUNTS="-v ${DIND_DIR}/config/supervisor-image.tar:/usr/src/supervisor-image.tar:ro"
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/config/supervisor.conf:/etc/resin-supervisor/supervisor.conf"
if [ "${MOUNT_DIST}" == "true" ]; then
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/../../dist:/resin-supervisor/dist"
fi
if [ "${PRELOADED_IMAGE}" == "true" ]; then
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/apps.json:/mnt/data/apps.json"
fi
if [ "${MOUNT_NODE_MODULES}" == "true" ]; then
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/../../node_modules:/resin-supervisor/node_modules"
fi
if [ "${MOUNT_BACKUP}" == "true" ]; then
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/backup.tgz:/mnt/data/backup.tgz.mounted"
fi
if [ "${PRELOADED_IMAGE}" == "true" ]; then
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/apps.json:/mnt/data/apps.json"
fi
2017-07-10 16:37:36 +00:00
function buildSupervisor {
2018-02-09 19:30:15 +00:00
echo "Building supervisor image for architecture $ARCH and tagging as $TAG"
2017-11-10 20:01:49 +00:00
ARCH="$ARCH" TAG="$TAG" bash automation/build.sh
2017-07-07 21:49:41 +00:00
}
function buildSupervisorSrc {
2017-07-26 18:43:44 +00:00
if [ "$OPTIMIZE" = "true" ]; then
echo "Rebuilding supervisor source"
( cd "$SUPERVISOR_BASE_DIR" && npm install && npm run build )
else
echo "Rebuilding supervisor source without optimizations"
2017-11-09 00:06:28 +00:00
( cd "$SUPERVISOR_BASE_DIR" && npm install && npm run build -- --env.noOptimize )
2017-07-26 18:43:44 +00:00
fi
2017-07-07 21:49:41 +00:00
}
function refreshSupervisorSrc {
buildSupervisorSrc
echo "Restarting the supervisor container"
2019-11-12 11:47:07 +00:00
docker exec -ti balena-container-$CONTAINER_NAME systemctl restart resin-supervisor
2017-07-07 21:49:41 +00:00
}
function runDind {
2020-05-07 09:16:24 +00:00
if [ ! -f "${DIND_DIR}/balenaos-in-container/balenaos-in-container.sh" ]; then
2019-11-11 23:51:47 +00:00
(cd $SUPERVISOR_BASE_DIR; git submodule update --init)
2018-02-09 19:30:15 +00:00
fi
if [ "$MOUNT_DIST" = "true" ]; then
2017-07-07 21:49:41 +00:00
buildSupervisorSrc
echo "Running with mounted dist folder"
fi
if [ "$PRELOADED_IMAGE" = "true" ]; then
echo "Running with preloaded apps"
fi
2017-07-26 18:20:06 +00:00
if ! ( docker inspect $SUPERVISOR_IMAGE &> /dev/null ); then
echo "$SUPERVISOR_IMAGE not available locally, pulling"
docker pull $SUPERVISOR_IMAGE
fi
2020-05-07 09:16:24 +00:00
# Save the requested image into a tar file
mkdir -p "${DIND_DIR}/config" && docker save --output "${DIND_DIR}/config/supervisor-image.tar" "${SUPERVISOR_IMAGE}"
echo "${SUPERVISOR_IMAGE}" | awk -F: '{print "SUPERVISOR_IMAGE="$1"\nSUPERVISOR_TAG="$2"\nLED_FILE=/dev/null"}' > "${DIND_DIR}/config/supervisor.conf"
2017-07-07 21:49:41 +00:00
echo "Starting dind supervisor"
2020-05-07 09:16:24 +00:00
"${DIND_DIR}/balenaos-in-container/balenaos-in-container.sh" \
--detach \
--config "${CONFIG_FILENAME}" \
--image "${DIND_IMAGE}" \
--id "${CONTAINER_NAME}" \
--extra-args "${SUPERVISOR_DIND_MOUNTS}"
2016-07-05 17:48:14 +00:00
}
2017-07-07 21:49:41 +00:00
function stopDind {
echo "Stopping dind supervisor"
2020-05-07 09:16:24 +00:00
docker stop balena-container-${CONTAINER_NAME} > /dev/null 2>&1 || true
docker rm -f --volumes balena-container-${CONTAINER_NAME} > /dev/null 2>&1 || true
2018-02-09 19:30:15 +00:00
if [ "$CLEAN_VOLUMES" = "true" ]; then
cleanDind
fi
}
function cleanDind {
echo "Cleaning dind supervisor volumes"
docker volume rm "resin-boot-$CONTAINER_NAME" "resin-state-$CONTAINER_NAME" "resin-data-$CONTAINER_NAME" &> /dev/null || true
2017-07-07 21:49:41 +00:00
}
2016-07-06 09:25:48 +00:00
function logs {
2019-11-12 11:47:07 +00:00
docker exec -ti balena-container-$CONTAINER_NAME journalctl $@
2016-07-06 09:25:48 +00:00
}
action="$1"
shift || true
2017-07-07 21:49:41 +00:00
if [ "$action" = "logs" ]; then
logs "$@"
else
parseOptions "$@"
case $action in
2017-07-10 16:37:36 +00:00
build)
buildSupervisor
2017-07-07 21:49:41 +00:00
;;
run)
2018-02-09 19:30:15 +00:00
stopDind
2017-07-07 21:49:41 +00:00
runDind
;;
2017-07-10 16:37:36 +00:00
buildrun)
buildSupervisor && runDind
2017-07-07 21:49:41 +00:00
;;
refresh)
refreshSupervisorSrc
;;
stop)
stopDind
;;
*)
showHelp
2017-07-26 17:44:09 +00:00
;;
2017-07-07 21:49:41 +00:00
esac
fi