mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-18 21:27:54 +00:00
Remove legacy build methods
Removes dindctl and `tools/sync.js` in favor of balenaos-in-container and SSH tunneling respectively. Change-type: patch
This commit is contained in:
parent
175d14258b
commit
515b6297a0
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "tools/dind/balenaos-in-container"]
|
||||
path = tools/dind/balenaos-in-container
|
||||
url = https://github.com/balena-os/balenaos-in-container.git
|
171
README.md
171
README.md
@ -74,7 +74,8 @@ These steps are detailed below.
|
||||
Example:
|
||||
|
||||
```bash
|
||||
$ npm run sync -- d19baeb.local
|
||||
# Replace amd64 with your device architecture
|
||||
$ npm run sync -- d19baeb.local -a amd64
|
||||
|
||||
> balena-supervisor@10.11.3 sync /home/cameron/Balena/modules/balena-supervisor
|
||||
> ts-node --project tsconfig.json sync/sync.ts "d19baeb.local"
|
||||
@ -83,7 +84,6 @@ Step 1/23 : ARG ARCH=amd64
|
||||
Step 2/23 : ARG NODE_VERSION=10.19.0
|
||||
Step 3/23 : FROM balenalib/$ARCH-alpine-supervisor-base:3.11 as BUILD
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
> Note: For .local resolution to work you must have installed
|
||||
@ -106,136 +106,74 @@ restarted, or let nodemon handle the changes.
|
||||
This process will allow you to run a development instance of the supervisor on your local computer. It is not recommended for production scenarios, but allows someone developing on the supervisor to test changes quickly.
|
||||
The supervisor is run inside a balenaOS instance running in a container, so effectively it's a Docker-in-Docker instance (or more precisely, [balenaEngine](https://github.com/resin-os/balena-engine)-in-Docker).
|
||||
|
||||
#### Set up `config.json`
|
||||
|
||||
To configure the supervisor, you'll need a `tools/dind/config.json` file. There's two options on how to get this file:
|
||||
|
||||
- Log in to the [balenaCloud dashboard](https://dashboard.balena-cloud.com), create or select a fleet, click "Add device" and on the Advanced section select "Download configuration file only". Make sure you use an x86 or amd64 device type for your fleet, for example Intel NUC.
|
||||
- Install the balena CLI with `npm install -g balena-cli`, then login with `balena login` and finally run `balena config generate --fleet <appName> -o config.json` (choose the default settings whenever prompted).
|
||||
|
||||
The `config.json` file should look something like this:
|
||||
|
||||
(Please note we've added comments to the JSON for better explanation - the actual file should be valid json _without_ such comments)
|
||||
|
||||
```
|
||||
{
|
||||
"applicationId": "2167", /* Id of the app this supervisor will run */
|
||||
"apiKey": "supersecretapikey", /* The API key to provision the device on the balena API */
|
||||
"deviceType": "intel-nuc", /* The device type corresponding to the test fleet */
|
||||
"apiEndpoint": "https://api.balena-cloud.com", /* Endpoint for the balena API */
|
||||
"deltaEndpoint": "https://delta.balena-cloud.com", /* Endpoint for the delta server to download Docker binary diffs */
|
||||
"listenPort": 48484, /* Listen port for the supervisor API */
|
||||
"mixpanelToken": "aaaaaaaaaaaaaaaaaaaaaaaaaa", /* Mixpanel token to report events */
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, the `uuid`, `registered_at` and `deviceId` fields will be added by the supervisor upon registration with the balena API. Other fields may be present (the format has evolved over time and will likely continue to do so) but they are not used by the supervisor.
|
||||
|
||||
#### Start the supervisor instance
|
||||
|
||||
Ensure your kernel supports aufs (in Ubuntu, install `linux-image-extra-$(uname -r)`) and the `aufs` module is loaded (if necessary, run `sudo modprobe aufs`).
|
||||
To run the supervisor in a balenaOS-in-container instance, first follow the installation instructions on the [balenaOS-in-container repository](https://github.com/balena-os/balenaos-in-container/). Make sure
|
||||
you have the image configured in [development mode](https://www.balena.io/docs/reference/OS/overview/#development-vs-production-mode). After the image starts you should be able to use the [sync](#Sync) method described above for running a livepush Supervisor on the docker container.
|
||||
|
||||
```bash
|
||||
./dindctl run --image balena/amd64-supervisor:master
|
||||
# Replace d19baeb.local with the container address.
|
||||
$ npm run sync -- d19baeb.local -a amd64
|
||||
|
||||
> balena-supervisor@10.11.3 sync /home/cameron/Balena/modules/balena-supervisor
|
||||
> ts-node --project tsconfig.json sync/sync.ts "d19baeb.local"
|
||||
```
|
||||
|
||||
This will setup a Docker-in-Docker instance with an image that runs the supervisor image. You can replace `:master` for a specific tag (see the [tags in Dockerhub](https://hub.docker.com/r/balena/amd64-supervisor/tags/)) to run
|
||||
a supervisor from a branch or specific version. The script will pull the image if it is not already available in your
|
||||
local Docker instance.
|
||||
|
||||
If you want to develop and test your changes, you can run:
|
||||
|
||||
```bash
|
||||
./dindctl run --image balena/amd64-supervisor:master --mount-dist
|
||||
```
|
||||
|
||||
Note: Using `--mount-dist` requires a Node.js 6.x installed on your computer.
|
||||
|
||||
This will mount the ./dist folder into the supervisor container and build the code before starting the instance, so that any changes you make can be added to the running supervisor with:
|
||||
|
||||
```bash
|
||||
./dindctl refresh
|
||||
```
|
||||
|
||||
#### Testing with preloaded apps
|
||||
|
||||
To test preloaded apps, run `balena preload` (see the [balena CLI docs](https://docs.balena.io/tools/cli/#preload-60-image-62-) on an OS image for the app you are testing with. Then copy the `apps.json` file from the `resin-data` partition into `tools/dind/apps.json`.
|
||||
|
||||
This file has a format equivalent to the `local` part of the target state endpoint on the balena API.
|
||||
|
||||
Make sure the `config.json` file doesn't have uuid, registered_at or deviceId populated from a previous run.
|
||||
|
||||
Then run the supervisor like this:
|
||||
|
||||
```bash
|
||||
./dindctl run --image balena/amd64-supervisor:master --preload
|
||||
```
|
||||
|
||||
This will make the Docker-in-Docker instance pull the image specified in `apps.json` before running the supervisor, simulating a preloaded balenaOS image.
|
||||
|
||||
#### View the supervisor's logs
|
||||
|
||||
```bash
|
||||
./dindctl logs
|
||||
```
|
||||
|
||||
This will show the output of `journalctl` inside the Docker-in-Docker container. You can pass
|
||||
additional options, for instance, to see the logs from the supervisor service:
|
||||
|
||||
```bash
|
||||
./dindctl logs -fn 100 -u balena-supervisor
|
||||
```
|
||||
|
||||
#### Stop the supervisor
|
||||
|
||||
```bash
|
||||
./dindctl stop
|
||||
```
|
||||
|
||||
This will stop the container and remove it, also removing
|
||||
its volumes.
|
||||
|
||||
## Developing using a production image or device
|
||||
|
||||
A production balena image does not have an open docker
|
||||
socket, required for livepush to work. In this situation,
|
||||
the `tools/sync.js` script can be used. Note that this
|
||||
process is no longer actively developed, so your mileage may
|
||||
vary.
|
||||
socket, required for livepush to work. In this situation, [balena tunnel](https://www.balena.io/docs/reference/balena-cli/#tunnel-deviceorfleet)
|
||||
can be used to tunnel the necessary ports to the local development machine.
|
||||
|
||||
Bug reports and pull requests are still accepted for changes
|
||||
to `sync.js`, but the balenaSupervisor team will focus on
|
||||
`npm run sync` in the future.
|
||||
For a balena device on a different network:
|
||||
|
||||
```bash
|
||||
# Open tunnel using the device uuid
|
||||
balena tunnel <uuid> -p 22222
|
||||
# Tunnel device ports to the local machine
|
||||
ssh -ACN -p 22222 \
|
||||
-L 2375:/var/run/balena-engine.sock \
|
||||
-L 48484:127.0.0.1:48484 \
|
||||
root@localhost
|
||||
# On another terminal
|
||||
npm run sync -- 127.0.0.1 -a amd64
|
||||
```
|
||||
|
||||
For a balena device on the local network, the `balena tunnel` step is not necessary.
|
||||
|
||||
```bash
|
||||
# Tunnel device ports to the local machine
|
||||
# replace d19baeb.local below with the local network address
|
||||
# of the balena device
|
||||
ssh -ACN -p 22222 \
|
||||
-L 2375:/var/run/balena-engine.sock \
|
||||
-L 48484:127.0.0.1:48484 \
|
||||
-L 22222:127.0.0.1:22222 \
|
||||
root@d19baeb.local
|
||||
# On another terminal
|
||||
npm run sync -- 127.0.0.1 -a amd64
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
### Docker images
|
||||
The supervisor is built automatically by the CI system, but a docker image can be also be built locally using the [balena CLI](https://www.balena.io/docs/reference/balena-cli/#build-source).
|
||||
|
||||
To build a docker image for amd64 targets, it's as simple
|
||||
as:
|
||||
To build a docker image for amd64 targets, it's as simple as:
|
||||
|
||||
```bash
|
||||
docker build . -t my-supervisor
|
||||
balena build -d genericx86-64-ext -A amd64
|
||||
```
|
||||
|
||||
For other architectures, one must use the script
|
||||
`automation/build.sh`. This is because of emulation specific
|
||||
changes we have made to our base images to allow
|
||||
cross-compilation.
|
||||
|
||||
For example, to build for the raspberry pi 3:
|
||||
|
||||
```sh
|
||||
ARCH=armv7hf automation/build.sh
|
||||
```
|
||||
|
||||
This will produce an image `balena/armv7hf-supervisor:<git branch name>`.
|
||||
To avoid using the branch name, you can set a `TAG` variable
|
||||
in your shell, before using the build script.
|
||||
For other architectures, the argument to `-A` must be replaced with the proper architecture and the correct device type must be
|
||||
passed using `-d`.
|
||||
|
||||
> Available architectures: `amd64`, `i386`, `aarch64`,
|
||||
> `armv7hf` and `rpi`
|
||||
|
||||
For instance to build for raspberrypi4:
|
||||
|
||||
```bash
|
||||
balena build -d raspberrypi4-64 -A aarch64
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
You can run some unit tests with:
|
||||
@ -256,11 +194,11 @@ which ensures that the environment is exactly the same.
|
||||
You can run specific tests quickly with the `test:fast` script by matching with test suites (describe) or test cases (it) using a string or regexp:
|
||||
|
||||
```sh
|
||||
npm run test:fast -- --grep spawnJournalctl
|
||||
npm run test:fast -- -g spawnJournalctl
|
||||
|
||||
npm run test:fast -- --grep "detect a V2 delta"
|
||||
npm run test:fast -- -g "detect a V2 delta"
|
||||
|
||||
npm run test:fast -- --grep (GET|POST|PUT|DELETE)
|
||||
npm run test:fast -- -g (GET|POST|PUT|DELETE)
|
||||
```
|
||||
|
||||
The --grep option, when specified, will trigger mocha to only run tests matching the given pattern which is internally compiled to a RegExp.
|
||||
@ -274,10 +212,13 @@ node -v # >= 12.16.2
|
||||
npm -v # >= 6.14.4
|
||||
git --version # >= 2.13.0
|
||||
```
|
||||
|
||||
Also, ensure you're installing dependencies with `npm ci` as this will perform a clean install and guarantee the module versions specified are downloaded rather then installed which might attempt to upgrade!
|
||||
|
||||
### DBus
|
||||
|
||||
When developing on macOS you may need to install DBus on the development host.
|
||||
|
||||
1. `brew install dbus`
|
||||
2. `npm ci`
|
||||
|
||||
|
236
dindctl
236
dindctl
@ -1,236 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Setting the '--mount-nm' flag in either 'run' or 'buildrun' action will bind-mount
|
||||
# './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:
|
||||
# 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.
|
||||
# Options:
|
||||
# --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 )
|
||||
# --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)
|
||||
# --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
|
||||
#
|
||||
# See README.md for examples.
|
||||
#
|
||||
# The script requires make and docker.
|
||||
#
|
||||
|
||||
THIS_FILE=$0
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
SUPERVISOR_BASE_DIR="${DIR}"
|
||||
DIND_DIR="${SUPERVISOR_BASE_DIR}/tools/dind/"
|
||||
|
||||
ARCH="amd64"
|
||||
SUPERVISOR_IMAGE="balena/${ARCH}-supervisor:master"
|
||||
DIND_IMAGE="resin/resinos:2.48.0_rev3-intel-nuc"
|
||||
MOUNT_DIST="false"
|
||||
MOUNT_NODE_MODULES="false"
|
||||
CONTAINER_NAME="supervisor"
|
||||
PRELOADED_IMAGE=""
|
||||
OPTIMIZE="true"
|
||||
CONFIG_FILENAME="${DIND_DIR}config.json"
|
||||
TAG="master"
|
||||
CLEAN_VOLUMES="true"
|
||||
MOUNT_BACKUP="false"
|
||||
|
||||
function showHelp {
|
||||
cat $THIS_FILE | awk '{if(/^#/)print;else exit}' | tail -n +2 | sed 's/\#//' | sed 's|dindctl|'$THIS_FILE'|'
|
||||
}
|
||||
|
||||
function parseOptions {
|
||||
while [[ $# -ge 1 ]]
|
||||
do
|
||||
case $1 in
|
||||
--mount-dist)
|
||||
MOUNT_DIST="true"
|
||||
;;
|
||||
--mount-nm)
|
||||
MOUNT_NODE_MODULES="true"
|
||||
;;
|
||||
--mount-backup)
|
||||
MOUNT_BACKUP="true"
|
||||
;;
|
||||
-p|--preload)
|
||||
PRELOADED_IMAGE="true"
|
||||
;;
|
||||
-i|--image)
|
||||
SUPERVISOR_IMAGE="$2"
|
||||
shift || { echo "--image provided not specified" && exit 1; }
|
||||
;;
|
||||
-c|--config)
|
||||
CONFIG_FILENAME="$2"
|
||||
shift || { echo "--config provided not specified" && exit 1; }
|
||||
;;
|
||||
--dind-image)
|
||||
DIND_IMAGE="$2"
|
||||
shift || { echo "--dind-image provided not specified" && exit 1; }
|
||||
;;
|
||||
--dind-container)
|
||||
CONTAINER_NAME="$2"
|
||||
shift || { echo "--dind-container provided not specified" && exit 1; }
|
||||
;;
|
||||
-a|--arch)
|
||||
ARCH="$2"
|
||||
shift || { echo "--arch provided not specified" && exit 1; }
|
||||
;;
|
||||
-t|--tag)
|
||||
TAG="$2"
|
||||
shift || { echo "--tag provided not specified" && exit 1; }
|
||||
;;
|
||||
-n|--no-optimize)
|
||||
OPTIMIZE="false"
|
||||
;;
|
||||
--no-clean)
|
||||
CLEAN_VOLUMES="false"
|
||||
;;
|
||||
*)
|
||||
echo "Warning: unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
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/balena-supervisor/supervisor.conf"
|
||||
|
||||
if [ "${MOUNT_DIST}" == "true" ]; then
|
||||
SUPERVISOR_DIND_MOUNTS="${SUPERVISOR_DIND_MOUNTS} -v ${DIND_DIR}/../../dist:/balena-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:/balena-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
|
||||
|
||||
function buildSupervisor {
|
||||
echo "Building supervisor image for architecture $ARCH and tagging as $TAG"
|
||||
ARCH="$ARCH" TAG="$TAG" bash automation/build.sh
|
||||
}
|
||||
|
||||
function buildSupervisorSrc {
|
||||
if [ "$OPTIMIZE" = "true" ]; then
|
||||
echo "Rebuilding supervisor source"
|
||||
( cd "$SUPERVISOR_BASE_DIR" && npm install && npm run build )
|
||||
else
|
||||
echo "Rebuilding supervisor source without optimizations"
|
||||
( cd "$SUPERVISOR_BASE_DIR" && npm install && npm run build -- --env.noOptimize )
|
||||
fi
|
||||
}
|
||||
|
||||
function refreshSupervisorSrc {
|
||||
buildSupervisorSrc
|
||||
echo "Restarting the supervisor container"
|
||||
docker exec -ti balena-container-$CONTAINER_NAME systemctl restart balena-supervisor
|
||||
}
|
||||
|
||||
function runDind {
|
||||
if [ ! -f "${DIND_DIR}/balenaos-in-container/balenaos-in-container.sh" ]; then
|
||||
(cd $SUPERVISOR_BASE_DIR; git submodule update --init)
|
||||
fi
|
||||
if [ "$MOUNT_DIST" = "true" ]; then
|
||||
buildSupervisorSrc
|
||||
echo "Running with mounted dist folder"
|
||||
fi
|
||||
if [ "$PRELOADED_IMAGE" = "true" ]; then
|
||||
echo "Running with preloaded apps"
|
||||
fi
|
||||
if ! ( docker inspect $SUPERVISOR_IMAGE &> /dev/null ); then
|
||||
echo "$SUPERVISOR_IMAGE not available locally, pulling"
|
||||
docker pull $SUPERVISOR_IMAGE
|
||||
fi
|
||||
|
||||
# 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"
|
||||
|
||||
echo "Starting dind supervisor"
|
||||
"${DIND_DIR}/balenaos-in-container/balenaos-in-container.sh" \
|
||||
--detach \
|
||||
--config "${CONFIG_FILENAME}" \
|
||||
--image "${DIND_IMAGE}" \
|
||||
--id "${CONTAINER_NAME}" \
|
||||
--extra-args "${SUPERVISOR_DIND_MOUNTS}"
|
||||
|
||||
}
|
||||
|
||||
function stopDind {
|
||||
echo "Stopping dind supervisor"
|
||||
docker stop balena-container-${CONTAINER_NAME} > /dev/null 2>&1 || true
|
||||
docker rm -f --volumes balena-container-${CONTAINER_NAME} > /dev/null 2>&1 || true
|
||||
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
|
||||
}
|
||||
|
||||
function logs {
|
||||
docker exec -ti balena-container-$CONTAINER_NAME journalctl $@
|
||||
}
|
||||
|
||||
action="$1"
|
||||
shift || true
|
||||
|
||||
if [ "$action" = "logs" ]; then
|
||||
logs "$@"
|
||||
else
|
||||
parseOptions "$@"
|
||||
case $action in
|
||||
build)
|
||||
buildSupervisor
|
||||
;;
|
||||
run)
|
||||
stopDind
|
||||
runDind
|
||||
;;
|
||||
buildrun)
|
||||
buildSupervisor && runDind
|
||||
;;
|
||||
refresh)
|
||||
refreshSupervisorSrc
|
||||
;;
|
||||
stop)
|
||||
stopDind
|
||||
;;
|
||||
*)
|
||||
showHelp
|
||||
;;
|
||||
esac
|
||||
fi
|
@ -1 +0,0 @@
|
||||
Subproject commit adf4f77385ef12203c2603b8ba262ee08fbf10a0
|
@ -1,122 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Adapted from: https://github.com/balena-os/meta-balena/blob/v2.45.0/meta-balena-common/recipes-containers/balena-supervisor/balena-supervisor/start-balena-supervisor
|
||||
|
||||
# We still need to include resin-vars on legacy systems
|
||||
if [ -f /usr/sbin/resin-vars ]; then
|
||||
# shellcheck disable=SC1091
|
||||
. /usr/sbin/resin-vars
|
||||
else
|
||||
# shellcheck disable=SC1091
|
||||
. /usr/sbin/balena-config-vars
|
||||
fi
|
||||
|
||||
if ! balena inspect $SUPERVISOR_IMAGE:$SUPERVISOR_TAG > /dev/null; then
|
||||
balena load --input /usr/src/supervisor-image.tar
|
||||
fi
|
||||
|
||||
if [ -f /mnt/data/backup.tgz.mounted ]; then
|
||||
cp /mnt/data/backup.tgz.mounted /mnt/data/backup.tgz
|
||||
fi
|
||||
|
||||
# Handle apps.json existence
|
||||
# Keep this before computing SUPERVISOR_CONTAINER_IMAGE_ID
|
||||
APPSJSON=/mnt/data/apps.json
|
||||
if [ ! -f "$APPSJSON" ]; then
|
||||
if [ -d "$APPSJSON" ]; then
|
||||
rm -rf "$APPSJSON"
|
||||
balena rm -f balena_supervisor || true
|
||||
echo '{}' > "$APPSJSON"
|
||||
elif [ ! -e "$APPSJSON" ]; then
|
||||
echo '{}' > "$APPSJSON"
|
||||
fi
|
||||
fi
|
||||
|
||||
SUPERVISOR_IMAGE_ID=$(balena inspect --format='{{.Id}}' "$SUPERVISOR_IMAGE:$SUPERVISOR_TAG")
|
||||
SUPERVISOR_CONTAINER_IMAGE_ID=$(balena inspect --format='{{.Image}}' balena_supervisor || echo "")
|
||||
|
||||
# If self-signed root CA exists, add the CA for the specified registry
|
||||
if [ -n "$BALENA_ROOT_CA" ]; then
|
||||
BALENA_DECODED_ROOT_CA="$(echo "${BALENA_ROOT_CA}" | base64 -d -w0)"
|
||||
NODE_EXTRA_CA_CERTS="/etc/ssl/certs/balenaRootCA.pem"
|
||||
CERT_DIR="/mnt/state/root-overlay/etc/docker/certs.d/${REGISTRY_ENDPOINT}"
|
||||
CERT_FILE="${CERT_DIR}/ca.crt"
|
||||
CERT_CONTENTS=$(if [ -e "$CERT_FILE" ]; then echo $(cat "$CERT_FILE"); fi)
|
||||
|
||||
# Ensure that the contents is correct, install otherwise
|
||||
if [ "$BALENA_DECODED_ROOT_CA" != "$CERT_CONTENTS" ]; then
|
||||
mkdir -p "$CERT_DIR"
|
||||
echo "$BALENA_DECODED_ROOT_CA" > "$CERT_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
hasValueChanged() {
|
||||
KEY="$1"
|
||||
NEW_VALUE="$2"
|
||||
COLLECTION="$3"
|
||||
CURRENT_VALUE=$(echo "$COLLECTION" | jq -r ".$KEY")
|
||||
|
||||
if [ "$CURRENT_VALUE" != "$NEW_VALUE" ];then
|
||||
echo "$KEY has changed!"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
configIsUnchanged() {
|
||||
|
||||
SUPERVISOR_CONTAINER_ENV_JSON="$(balena inspect balena_supervisor | jq '.[0].Config.Env | map(.| { (.[0:index("=")]): .[index("=")+1:] }) | add')"
|
||||
|
||||
if hasValueChanged "BOOT_MOUNTPOINT" "$BOOT_MOUNTPOINT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "REGISTRY_ENDPOINT" "$REGISTRY_ENDPOINT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "MIXPANEL_TOKEN" "$MIXPANEL_TOKEN" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "LED_FILE" "${LED_FILE}" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "LISTEN_PORT" "$LISTEN_PORT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "SUPERVISOR_IMAGE" "${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "BALENA_ROOT_CA" "$BALENA_DECODED_ROOT_CA" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
|
||||
hasValueChanged "NODE_EXTRA_CA_CERTS" "$NODE_EXTRA_CA_CERTS" "$SUPERVISOR_CONTAINER_ENV_JSON"; then
|
||||
echo "Container config has changed!"
|
||||
return 1
|
||||
else
|
||||
echo "Container config has not changed"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
runSupervisor() {
|
||||
balena rm --force balena_supervisor || true
|
||||
balena run --privileged --name balena_supervisor \
|
||||
--restart=always \
|
||||
--net=host \
|
||||
--cidenv=SUPERVISOR_CONTAINER_ID \
|
||||
-v /var/run/balena-engine.sock:/var/run/balena-engine.sock \
|
||||
-v "$CONFIG_PATH:/boot/config.json" \
|
||||
-v /mnt/data/apps.json:/boot/apps.json \
|
||||
-v /resin-data/balena-supervisor:/data \
|
||||
-v /proc/net/fib_trie:/mnt/fib_trie \
|
||||
-v /var/log/supervisor-log:/var/log \
|
||||
-v /:/mnt/root \
|
||||
-e DOCKER_ROOT=/mnt/root/var/lib/docker \
|
||||
-e DOCKER_SOCKET=/var/run/balena-engine.sock \
|
||||
-e "BOOT_MOUNTPOINT=$BOOT_MOUNTPOINT" \
|
||||
-e "REGISTRY_ENDPOINT=$REGISTRY_ENDPOINT" \
|
||||
-e "MIXPANEL_TOKEN=$MIXPANEL_TOKEN" \
|
||||
-e "LED_FILE=${LED_FILE}" \
|
||||
-e "LISTEN_PORT=$LISTEN_PORT" \
|
||||
-e "SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" \
|
||||
-e "BALENA_ROOT_CA=$BALENA_DECODED_ROOT_CA" \
|
||||
-e "NODE_EXTRA_CA_CERTS=$NODE_EXTRA_CA_CERTS" \
|
||||
"${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" \
|
||||
node /usr/src/app/dist/app.js --inspect-brk
|
||||
}
|
||||
|
||||
if [ -z "$SUPERVISOR_IMAGE_ID" ]; then
|
||||
# No supervisor image exists on the device, try to pull it
|
||||
systemctl start update-balena-supervisor
|
||||
elif [ "$SUPERVISOR_IMAGE_ID" = "$SUPERVISOR_CONTAINER_IMAGE_ID" ] && configIsUnchanged; then
|
||||
# Supervisor image exists, and the current supervisor container is created from
|
||||
balena start --attach balena_supervisor
|
||||
else
|
||||
# No supervisor container exists or there's a different supervisor image to run
|
||||
runSupervisor
|
||||
fi
|
@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
if (!process.argv[2] || ['help', '-h', '--help'].includes(process.argv[2])) {
|
||||
console.log(`
|
||||
Sync changes in the javascript code to a running supervisor on a device in the local network
|
||||
|
||||
Usage:
|
||||
./sync.js <device IP>
|
||||
|
||||
The script will first build a non-optimized version of the js code and sync the resulting app.js
|
||||
onto the supervisor container at the specified IP. It will also restart the supervisor container.
|
||||
The device must be a development variant of balenaOS and the supervisor must be running.
|
||||
`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const childProcess = require('child_process');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const webpackConfig = require('./webpack.config');
|
||||
const compiler = webpack(webpackConfig({ noOptimize: true }));
|
||||
|
||||
const doSync = require('balena-sync').sync('local-balena-os-device').sync;
|
||||
|
||||
const syncOpts = {
|
||||
deviceIp: process.argv[2],
|
||||
baseDir: __dirname + '/dist',
|
||||
destination: '/usr/src/app/dist',
|
||||
appName: 'balena_supervisor',
|
||||
skipGitignore: true,
|
||||
};
|
||||
|
||||
childProcess.execSync('npm install', { stdio: 'inherit' });
|
||||
|
||||
compiler.watch(
|
||||
{
|
||||
ignored: /node_modules/,
|
||||
},
|
||||
(err, stats) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
console.log(stats.toString({ colors: true }));
|
||||
if (stats.hasErrors()) {
|
||||
console.error('Skipping sync due to errors');
|
||||
return;
|
||||
}
|
||||
doSync(syncOpts);
|
||||
},
|
||||
);
|
Loading…
Reference in New Issue
Block a user