Rename most of the documentation and variable names from resin to balena

Change-type: minor
Signed-off-by: Pablo Carranza Velez <pablo@balena.io>
This commit is contained in:
Pablo Carranza Velez 2018-10-18 20:52:35 +02:00
parent 94ebc67839
commit 8298487a88
17 changed files with 113 additions and 111 deletions

View File

@ -1,4 +1,4 @@
# Changelog for resin-supervisor # Changelog for balena-supervisor
All notable changes to this project will be documented in this file All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY! automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!

View File

@ -1,22 +1,22 @@
# resin-supervisor [![Tickets in Progress](https://badge.waffle.io/resin-io/resin-supervisor.svg?label=flow/in-progress&title=Tickets%20in%20progress)](https://waffle.io/resin-io/resin-supervisor) # balena-supervisor [![Tickets in Progress](https://badge.waffle.io/resin-io/resin-supervisor.svg?label=flow/in-progress&title=Tickets%20in%20progress)](https://waffle.io/resin-io/resin-supervisor)
Join our online chat at [![Gitter chat](https://badges.gitter.im/resin-io/chat.png)](https://gitter.im/resin-io/chat) Join our online chat at [![Gitter chat](https://badges.gitter.im/resin-io/chat.png)](https://gitter.im/resin-io/chat)
This is [resin.io](https://resin.io)'s supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as resin.io's API informs it to. This is [balena](https://balena.io)'s supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as the balena API informs it to.
The supervisor is a Node.js program. The supervisor is a Node.js program.
## Running a supervisor locally ## Running a supervisor locally
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. 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 resinOS instance running in a container, so effectively it's a Docker-in-Docker instance (or more precisely, [balena](https://github.com/resin-os/balena)-in-Docker). The supervisor is run inside a resinOS 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` ### 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: 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 [resin dashboard](https://dashboard.resin.io), create or select an application, 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 application, for example Intel NUC. * Log in to the [balenaCloud dashboard](https://dashboard.balena-cloud.com), create or select an application, 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 application, for example Intel NUC.
* Install the resin CLI with `npm install -g resin-cli`, then login with `resin login` and finally run `resin config generate --app <appName> -o config.json` (choose the default settings whenever prompted). * Install the balena CLI with `npm install -g balena-cli`, then login with `balena login` and finally run `balena config generate --app <appName> -o config.json` (choose the default settings whenever prompted).
The `config.json` file should look something like this: The `config.json` file should look something like this:
@ -25,36 +25,36 @@ The `config.json` file should look something like this:
``` ```
{ {
"applicationId": "2167", /* Id of the app this supervisor will run */ "applicationId": "2167", /* Id of the app this supervisor will run */
"apiKey": "supersecretapikey", /* The API key to provision the device on the resin.io API */ "apiKey": "supersecretapikey", /* The API key to provision the device on the balena API */
"userId": "141", /* User ID for the user who owns the app */ "userId": "141", /* User ID for the user who owns the app */
"username": "gh_pcarranzav", /* User name for the user who owns the app */ "username": "gh_pcarranzav", /* User name for the user who owns the app */
"deviceType": "intel-nuc", /* The device type corresponding to the test application */ "deviceType": "intel-nuc", /* The device type corresponding to the test application */
"apiEndpoint": "https://api.resinstaging.io", /* Endpoint for the resin.io API */ "apiEndpoint": "https://api.balena-cloud.com", /* Endpoint for the balena API */
"deltaEndpoint": "https://delta.resinstaging.io", /* Endpoint for the delta server to download Docker binary diffs */ "deltaEndpoint": "https://delta.balena-cloud.com", /* Endpoint for the delta server to download Docker binary diffs */
"vpnEndpoint": "vpn.resinstaging.io", /* Endpoint for the resin.io VPN server */ "vpnEndpoint": "vpn.balena-cloud.com", /* Endpoint for the balena VPN server */
"listenPort": 48484, /* Listen port for the supervisor API */ "listenPort": 48484, /* Listen port for the supervisor API */
"mixpanelToken": "aaaaaaaaaaaaaaaaaaaaaaaaaa", /* Mixpanel token to report events */ "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 resin 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. 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 ### 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`). 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`).
```bash ```bash
./dindctl run --image resin/amd64-supervisor:master ./dindctl run --image balena/amd64-supervisor:master
``` ```
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/resin/amd64-supervisor/tags/)) to run 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 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. local Docker instance.
If you want to develop and test your changes, you can run: If you want to develop and test your changes, you can run:
```bash ```bash
./dindctl run --image resin/amd64-supervisor:master --mount-dist ./dindctl run --image balena/amd64-supervisor:master --mount-dist
``` ```
Note: Using `--mount-dist` requires a Node.js 6.x installed on your computer. Note: Using `--mount-dist` requires a Node.js 6.x installed on your computer.
@ -67,19 +67,19 @@ This will mount the ./dist folder into the supervisor container and build the co
### Testing with preloaded apps ### Testing with preloaded apps
To test preloaded apps, run `resin preload` (see the [resin CLI docs](https://docs.resin.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`. 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 resin API. 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. 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: Then run the supervisor like this:
```bash ```bash
./dindctl run --image resin/amd64-supervisor:master --preload ./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 resinOS image. 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 ### View the supervisor's logs
@ -91,7 +91,7 @@ This will show the output of `journalctl` inside the Docker-in-Docker container.
additional options, for instance, to see the logs from the supervisor service: additional options, for instance, to see the logs from the supervisor service:
```bash ```bash
./dindctl logs -fn 100 -u resin-supervisor-dind ./dindctl logs -fn 100 -u resin-supervisor
``` ```
### Stop the supervisor ### Stop the supervisor
@ -102,10 +102,10 @@ additional options, for instance, to see the logs from the supervisor service:
This will stop the container and remove it, also removing its volumes. This will stop the container and remove it, also removing its volumes.
## Developing with a resinOS device ## Developing with a balenaOS device
If you want to test local changes (only changes to the Node.js code are supported) on a real resinOS device, provision If you want to test local changes (only changes to the Node.js code are supported) on a real balenaOS device, provision
a [development OS image](https://docs.resin.io/understanding/understanding-devices/2.0.0/#dev-vs-prod-images) and power up the device. On the resin.io dashboard, take note of the device's IP address. Then run: a [development OS image](https://docs.balena.io/understanding/understanding-devices/2.0.0/#dev-vs-prod-images) and power up the device. On the balenaCloud dashboard, take note of the device's IP address. Then run:
``` ```
./sync.js <device IP> ./sync.js <device IP>

View File

@ -11,15 +11,15 @@
# Usage: dindctl action [options] # Usage: dindctl action [options]
# #
# Actions: # Actions:
# build build local supervisor image. By default it will be resin/amd64-supervisor:master, you can override the tag with --tag. # 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 resin_supervisor_1), which will include the specified supervisor image and run it. # 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. # 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. # 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. # 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. # stop stop dind supervisor host container.
# Options: # Options:
# --arch | -a [arch] architecture of the supervisor to build (default: amd64 ) # --arch | -a [arch] architecture of the supervisor to build (default: amd64 )
# --image | -i [image] image name for supervisor image to build/use ( default: resin/$ARCH-supervisor:master ) # --image | -i [image] image name for supervisor image to build/use ( default: balena/$ARCH-supervisor:master )
# --dind-image [image] image to use for the resinos-in-container host (default: resin/resinos:2.12.5_rev1-intel-nuc) # --dind-image [image] image to use for the resinos-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 resinos-in-container-supervisor) # --dind-container [name] container name suffix for the dind host container ( default: "supervisor", which will produce a container named resinos-in-container-supervisor)
# --mount-dist bind-mount './dist/' (where webpack stores the built js) from local development environment into supervisor container. # --mount-dist bind-mount './dist/' (where webpack stores the built js) from local development environment into supervisor container.
@ -43,7 +43,7 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
SUPERVISOR_BASE_DIR="${DIR}" SUPERVISOR_BASE_DIR="${DIR}"
ARCH="amd64" ARCH="amd64"
SUPERVISOR_IMAGE="resin/${ARCH}-supervisor:master" SUPERVISOR_IMAGE="balena/${ARCH}-supervisor:master"
DIND_IMAGE="resin/resinos:2.12.5_rev1-intel-nuc" DIND_IMAGE="resin/resinos:2.12.5_rev1-intel-nuc"
MOUNT_DIST="false" MOUNT_DIST="false"
MOUNT_NODE_MODULES="false" MOUNT_NODE_MODULES="false"

View File

@ -482,7 +482,7 @@ Added in supervisor v6.6.0.
This endpoint allows setting some configuration values for the host OS. Currently it supports This endpoint allows setting some configuration values for the host OS. Currently it supports
proxy and hostname configuration. proxy and hostname configuration.
For proxy configuration, resinOS 2.0.7 and higher provides a transparent proxy redirector (redsocks) that makes all connections be routed to a SOCKS or HTTP proxy. This endpoint allows user applications to modify these proxy settings at runtime. For proxy configuration, balenaOS 2.0.7 and higher provides a transparent proxy redirector (redsocks) that makes all connections be routed to a SOCKS or HTTP proxy. This endpoint allows user applications to modify these proxy settings at runtime.
#### Request body #### Request body
@ -513,7 +513,7 @@ guaranteed to work, especially if they block connections that the balena service
Keep in mind that, even if transparent proxy redirection will take effect immediately after the API call (i.e. all new connections will go through the proxy), open connections will not be closed. So, if for example, the device has managed to connect to the balenaCloud VPN without the proxy, it will stay connected directly without trying to reconnect through the proxy, unless the connection breaks - any reconnection attempts will then go through the proxy. To force *all* connections to go through the proxy, the best way is to reboot the device (see the /v1/reboot endpoint). In most networks were no connections to the Internet can be made if not through a proxy, this should not be necessary (as there will be no open connections before configuring the proxy settings). Keep in mind that, even if transparent proxy redirection will take effect immediately after the API call (i.e. all new connections will go through the proxy), open connections will not be closed. So, if for example, the device has managed to connect to the balenaCloud VPN without the proxy, it will stay connected directly without trying to reconnect through the proxy, unless the connection breaks - any reconnection attempts will then go through the proxy. To force *all* connections to go through the proxy, the best way is to reboot the device (see the /v1/reboot endpoint). In most networks were no connections to the Internet can be made if not through a proxy, this should not be necessary (as there will be no open connections before configuring the proxy settings).
The "noProxy" setting for the proxy is an optional array of IP addresses/subnets that should not be routed through the The "noProxy" setting for the proxy is an optional array of IP addresses/subnets that should not be routed through the
proxy. Keep in mind that local/reserved subnets are already [excluded by resinOS automatically](https://github.com/resin-os/meta-resin/blob/master/meta-resin-common/recipes-connectivity/resin-proxy-config/resin-proxy-config/resin-proxy-config#L48). proxy. Keep in mind that local/reserved subnets are already [excluded by balenaOS automatically](https://github.com/resin-os/meta-resin/blob/master/meta-resin-common/recipes-connectivity/resin-proxy-config/resin-proxy-config/resin-proxy-config#L48).
If either "proxy" or "hostname" are null or empty values (i.e. `{}` for proxy or an empty string for hostname), they will be cleared to their default values (i.e. not using a proxy, and a hostname equal to the first 7 characters of the device's uuid, respectively). If either "proxy" or "hostname" are null or empty values (i.e. `{}` for proxy or an empty string for hostname), they will be cleared to their default values (i.e. not using a proxy, and a hostname equal to the first 7 characters of the device's uuid, respectively).

View File

@ -1,25 +1,25 @@
# Using the Resin Supervisor to manage dependent applications # Using the balena Supervisor to manage dependent applications
Since version 2.5.0 the Resin Supervisor can act as a proxy for dependent apps. Since version 2.5.0 the balena Supervisor can act as a proxy for dependent apps.
Only Supervisors after version 2.5.0 have this functionality, and some of the endpoints appeared in later versions (we've noted it down where this is the case). Only Supervisors after version 2.5.0 have this functionality, and some of the endpoints appeared in later versions (we've noted it down where this is the case).
## What is a dependent application ## What is a dependent application
A **dependent application** is a resin application that targets devices not capable of interacting directly with the Resin API - the reasons can be several, the most common are: A **dependent application** is a balena application that targets devices not capable of interacting directly with the balena API - the reasons can be several, the most common are:
- no direct Internet capabilities - no direct Internet capabilities
- not able to run Resin OS (being a microcontroller, for example) - not able to run balenaOS (being a microcontroller, for example)
The **dependent application** is scoped under a resin application, which gets the definition of **gateway application**. The **dependent application** is scoped under a balena application, which gets the definition of **gateway application**.
The **gateway application** is responsible for detecting, provisioning and managing **dependent devices** belonging to one of its **dependent applications**. This is possible leveraging a new set of endpoints exposed by the Resin Supervisor. The **gateway application** is responsible for detecting, provisioning and managing **dependent devices** belonging to one of its **dependent applications**. This is possible leveraging a new set of endpoints exposed by the balena Supervisor.
When a new version of the dependent application is git pushed, the supervisor will download the docker image and expose the assets in one of the endpoints detailed below. It is then the gateway application (i.e. the user app that is run by the supervisor) that is responsible for ensuring those assets get deployed to the dependent devices, using the provided endpoints to perform the management. When a new version of the dependent application is git pushed, the supervisor will download the docker image and expose the assets in one of the endpoints detailed below. It is then the gateway application (i.e. the user app that is run by the supervisor) that is responsible for ensuring those assets get deployed to the dependent devices, using the provided endpoints to perform the management.
A dependent application follows the same development cycle of a conventional resin application: A dependent application follows the same development cycle of a conventional balena application:
- it binds to your git workspace via the **resin remote** - it binds to your git workspace via the **balena remote**
- it consists in a Docker application - it consists in a Docker application
- it offers the same environment and configuration variables management - it offers the same environment and configuration variables management
@ -29,13 +29,13 @@ There are some differences:
- the Dockerfile must target either an `x86` or `amd64` base image - the Dockerfile must target either an `x86` or `amd64` base image
- the actual firmware/business logic must be stored in the `/assets` folder within the built docker image. - the actual firmware/business logic must be stored in the `/assets` folder within the built docker image.
- You can either just `COPY` a pre-built artifact in that folder, or build your artifact at push time and then store it in the `/assets` folder. - You can either just `COPY` a pre-built artifact in that folder, or build your artifact at push time and then store it in the `/assets` folder.
- **a dependent application Docker image is only used to build, package and deliver the firmware on the dependent device via resin-supervisor - it won't be run at any point.** - **a dependent application Docker image is only used to build, package and deliver the firmware on the dependent device via balena-supervisor - it won't be run at any point.**
## How a dependent application works ## How a dependent application works
### Endpoints ### Endpoints
The supervisor exposes a REST API to interact with the dependent applications and dependent devices models that come from the Resin API - it also allows using a set of hooks to have push functionality, both documented below. The supervisor exposes a REST API to interact with the dependent applications and dependent devices models that come from the balena API - it also allows using a set of hooks to have push functionality, both documented below.
# HTTP API reference # HTTP API reference
@ -47,7 +47,7 @@ Dependent Applications List
**Example** **Example**
```bash ```bash
curl -X GET $RESIN_SUPERVISOR_ADDRESS/v1/dependent-apps?apikey=$RESIN_SUPERVISOR_API_KEY curl -X GET $BALENA_SUPERVISOR_ADDRESS/v1/dependent-apps?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -76,7 +76,7 @@ Dependent Application Updates Registry
**Example** **Example**
```bash ```bash
curl -X GET $RESIN_SUPERVISOR_ADDRESS/v1/dependent-apps/<appId>/assets/<commit>?apikey=$RESIN_SUPERVISOR_API_KEY curl -X GET $BALENA_SUPERVISOR_ADDRESS/v1/dependent-apps/<appId>/assets/<commit>?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -95,7 +95,7 @@ Dependent Devices List
**Example** **Example**
```bash ```bash
curl -X GET $RESIN_SUPERVISOR_ADDRESS/v1/devices?apikey=$RESIN_SUPERVISOR_API_KEY curl -X GET $BALENA_SUPERVISOR_ADDRESS/v1/devices?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -155,7 +155,7 @@ application with the deprecated `edge` device type.
```bash ```bash
curl -H "Content-Type: application/json" -X POST --data '{"appId": <appId>, curl -H "Content-Type: application/json" -X POST --data '{"appId": <appId>,
"device_type": "edge"}' / "device_type": "edge"}' /
$RESIN_SUPERVISOR_ADDRESS/v1/devices?apikey=$RESIN_SUPERVISOR_API_KEY $BALENA_SUPERVISOR_ADDRESS/v1/devices?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -178,7 +178,7 @@ Dependent Device Information
**Example** **Example**
```bash ```bash
curl -X GET $RESIN_SUPERVISOR_ADDRESS/v1/devices/<uuid>?apikey=$RESIN_SUPERVISOR_API_KEY curl -X GET $BALENA_SUPERVISOR_ADDRESS/v1/devices/<uuid>?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -211,7 +211,7 @@ Dependent Device Information Update
```bash ```bash
curl -H "Content-Type: application/json" -X PUT --data / curl -H "Content-Type: application/json" -X PUT --data /
'{"is_online":true, "status": "Updating", "commit": "339125a7529cb2c2a8c93a0bbd8af69f2d96286ab4f4552cb5cfe99b0d3ee9"}' / '{"is_online":true, "status": "Updating", "commit": "339125a7529cb2c2a8c93a0bbd8af69f2d96286ab4f4552cb5cfe99b0d3ee9"}' /
$RESIN_SUPERVISOR_ADDRESS/v1/devices/<uuid>?apikey=$RESIN_SUPERVISOR_API_KEY $BALENA_SUPERVISOR_ADDRESS/v1/devices/<uuid>?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
@ -243,18 +243,18 @@ Dependent Device Log
```bash ```bash
curl -H "Content-Type: application/json" -X POST --data '{"message":"detected movement","timestamp":1472142960}' / curl -H "Content-Type: application/json" -X POST --data '{"message":"detected movement","timestamp":1472142960}' /
$RESIN_SUPERVISOR_ADDRESS/v1/devices/<uuid>/logs?apikey=$RESIN_SUPERVISOR_API_KEY $BALENA_SUPERVISOR_ADDRESS/v1/devices/<uuid>/logs?apikey=$BALENA_SUPERVISOR_API_KEY
``` ```
**Response** **Response**
`HTTP/1.1 202 ACCEPTED` `HTTP/1.1 202 ACCEPTED`
## Hooks (the requests the Resin Supervisor performs) ## Hooks (the requests the balena Supervisor performs)
### Hook configuration ### Hook configuration
You can point the supervisor where to find the hook server via a configuration variable. You can point the supervisor where to find the hook server via a configuration variable.
- `RESIN_DEPENDENT_DEVICES_HOOK_ADDRESS` _(defaults to `http://0.0.0.0:1337/v1/devices/`)_ - `BALENA_DEPENDENT_DEVICES_HOOK_ADDRESS` _(defaults to `http://0.0.0.0:1337/v1/devices/`)_
It's worth mentioning (as described below) that the supervisor will append the dependent device uuid (`<uuid>` in the hook descriptions) to every hook request URL It's worth mentioning (as described below) that the supervisor will append the dependent device uuid (`<uuid>` in the hook descriptions) to every hook request URL

View File

@ -1,6 +1,6 @@
{ {
"name": "resin-supervisor", "name": "balena-supervisor",
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.", "description": "This is balena's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as the balena API informs it to.",
"version": "8.1.0", "version": "8.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {

View File

@ -38,8 +38,8 @@ createAPIBinderRouter = (apiBinder) ->
module.exports = class APIBinder module.exports = class APIBinder
constructor: ({ @config, @db, @deviceState, @eventTracker }) -> constructor: ({ @config, @db, @deviceState, @eventTracker }) ->
@resinApi = null @balenaApi = null
@cachedResinApi = null @cachedBalenaApi = null
@lastReportedState = { local: {}, dependent: {} } @lastReportedState = { local: {}, dependent: {} }
@stateForReport = { local: {}, dependent: {} } @stateForReport = { local: {}, dependent: {} }
@lastTarget = {} @lastTarget = {}
@ -78,10 +78,10 @@ module.exports = class APIBinder
passthrough = _.cloneDeep(requestOpts) passthrough = _.cloneDeep(requestOpts)
passthrough.headers ?= {} passthrough.headers ?= {}
passthrough.headers.Authorization = "Bearer #{currentApiKey}" passthrough.headers.Authorization = "Bearer #{currentApiKey}"
@resinApi = new PinejsClient @balenaApi = new PinejsClient
apiPrefix: baseUrl apiPrefix: baseUrl
passthrough: passthrough passthrough: passthrough
@cachedResinApi = @resinApi.clone({}, cache: {}) @cachedBalenaApi = @balenaApi.clone({}, cache: {})
start: => start: =>
@config.getMany([ 'apiEndpoint', 'offlineMode', 'bootstrapRetryDelay' ]) @config.getMany([ 'apiEndpoint', 'offlineMode', 'bootstrapRetryDelay' ])
@ -124,7 +124,7 @@ module.exports = class APIBinder
passthrough: passthrough:
headers: Authorization: "Bearer #{apiKey}" headers: Authorization: "Bearer #{apiKey}"
} }
@resinApi.get(reqOpts) @balenaApi.get(reqOpts)
.get(0) .get(0)
.catchReturn(null) .catchReturn(null)
.timeout(timeout) .timeout(timeout)
@ -191,7 +191,7 @@ module.exports = class APIBinder
console.log('Device is registered but we still have an apiKey, attempting key exchange') console.log('Device is registered but we still have an apiKey, attempting key exchange')
@_exchangeKeyAndGetDevice(opts) @_exchangeKeyAndGetDevice(opts)
.then ({ id }) => .then ({ id }) =>
@resinApi.passthrough.headers.Authorization = "Bearer #{opts.deviceApiKey}" @balenaApi.passthrough.headers.Authorization = "Bearer #{opts.deviceApiKey}"
configToUpdate = { configToUpdate = {
registered_at: opts.registered_at registered_at: opts.registered_at
deviceId: id deviceId: id
@ -224,7 +224,7 @@ module.exports = class APIBinder
@_provisionOrRetry(retryDelay) @_provisionOrRetry(retryDelay)
provisionDevice: => provisionDevice: =>
if !@resinApi? if !@balenaApi?
throw new Error('Trying to provision device without initializing API client') throw new Error('Trying to provision device without initializing API client')
@config.getMany([ @config.getMany([
'provisioned' 'provisioned'
@ -256,7 +256,7 @@ module.exports = class APIBinder
uuid: deviceRegister.generateUniqueKey() uuid: deviceRegister.generateUniqueKey()
registered_at: Math.floor(Date.now() / 1000) registered_at: Math.floor(Date.now() / 1000)
}) })
@resinApi.post @balenaApi.post
resource: 'device' resource: 'device'
body: device body: device
.timeout(conf.apiTimeout) .timeout(conf.apiTimeout)
@ -272,7 +272,7 @@ module.exports = class APIBinder
throw new Error('Cannot update dependent device in offline mode') throw new Error('Cannot update dependent device in offline mode')
if !conf.provisioned if !conf.provisioned
throw new Error('Device must be provisioned to update a dependent device') throw new Error('Device must be provisioned to update a dependent device')
@resinApi.patch @balenaApi.patch
resource: 'device' resource: 'device'
id: id id: id
body: updatedFields body: updatedFields
@ -281,7 +281,7 @@ module.exports = class APIBinder
pinDevice: ({ app, commit }) => pinDevice: ({ app, commit }) =>
@config.get('deviceId') @config.get('deviceId')
.then (deviceId) => .then (deviceId) =>
@resinApi.get @balenaApi.get
resource: 'release' resource: 'release'
options: options:
filter: filter:
@ -293,7 +293,7 @@ module.exports = class APIBinder
releaseId = _.get(release, '[0].id') releaseId = _.get(release, '[0].id')
if !releaseId? if !releaseId?
throw new Error('Cannot continue pinning preloaded device! No release found!') throw new Error('Cannot continue pinning preloaded device! No release found!')
@resinApi.patch @balenaApi.patch
resource: 'device' resource: 'device'
id: deviceId id: deviceId
body: body:
@ -329,7 +329,7 @@ module.exports = class APIBinder
device: deviceId device: deviceId
name: 'RESIN_' + key name: 'RESIN_' + key
} }
@resinApi.post @balenaApi.post
resource: 'device_config_variable' resource: 'device_config_variable'
body: envVar body: envVar
) )
@ -352,9 +352,9 @@ module.exports = class APIBinder
requestParams = _.extend requestParams = _.extend
method: 'GET' method: 'GET'
url: "#{endpoint}" url: "#{endpoint}"
, @cachedResinApi.passthrough , @cachedBalenaApi.passthrough
@cachedResinApi._request(requestParams) @cachedBalenaApi._request(requestParams)
.timeout(apiTimeout) .timeout(apiTimeout)
# Get target state from API, set it on @deviceState and trigger a state application # Get target state from API, set it on @deviceState and trigger a state application
@ -388,7 +388,7 @@ module.exports = class APIBinder
startTargetStatePoll: => startTargetStatePoll: =>
Promise.try => Promise.try =>
if !@resinApi? if !@balenaApi?
throw new Error('Trying to start poll without initializing API client') throw new Error('Trying to start poll without initializing API client')
@_pollTargetState() @_pollTargetState()
return null return null
@ -412,9 +412,9 @@ module.exports = class APIBinder
method: 'PATCH' method: 'PATCH'
url: "#{endpoint}" url: "#{endpoint}"
body: stateDiff body: stateDiff
, @cachedResinApi.passthrough , @cachedBalenaApi.passthrough
@cachedResinApi._request(requestParams) @cachedBalenaApi._request(requestParams)
_report: => _report: =>
@config.getMany([ 'deviceId', 'apiTimeout', 'apiEndpoint', 'uuid', 'localMode' ]) @config.getMany([ 'deviceId', 'apiTimeout', 'apiEndpoint', 'uuid', 'localMode' ])
@ -454,7 +454,7 @@ module.exports = class APIBinder
return null return null
startCurrentStateReport: => startCurrentStateReport: =>
if !@resinApi? if !@balenaApi?
throw new Error('Trying to start state reporting without initializing API client') throw new Error('Trying to start state reporting without initializing API client')
# patch to the device(id) endpoint # patch to the device(id) endpoint
@deviceState.on 'change', => @deviceState.on 'change', =>

View File

@ -12,7 +12,7 @@ validation = require '../lib/validation'
# appId # appId
# serviceId # serviceId
# serviceName # serviceName
# imageId (from resin API) # imageId (from balena API)
# releaseId # releaseId
# dependent # dependent
# dockerImageId # dockerImageId

View File

@ -245,7 +245,7 @@ export class ExtlinuxConfigBackend extends DeviceConfigBackend {
} }
public setBootConfig(opts: ConfigOptions): Promise<void> { public setBootConfig(opts: ConfigOptions): Promise<void> {
// First get a representation of the configuration file, with all resin-supported configuration removed // First get a representation of the configuration file, with all balena-supported configuration removed
return Promise.resolve(fs.readFile(ExtlinuxConfigBackend.bootConfigPath)) return Promise.resolve(fs.readFile(ExtlinuxConfigBackend.bootConfigPath))
.then((data) => { .then((data) => {
const extlinuxFile = ExtlinuxConfigBackend.parseExtlinuxFile(data.toString()); const extlinuxFile = ExtlinuxConfigBackend.parseExtlinuxFile(data.toString());

View File

@ -10,7 +10,7 @@ import {
LocalLogBackend, LocalLogBackend,
LogBackend, LogBackend,
LogMessage, LogMessage,
ResinLogBackend, BalenaLogBackend,
} from './logging-backends'; } from './logging-backends';
interface LoggerSetupOptions { interface LoggerSetupOptions {
@ -39,7 +39,7 @@ export class Logger {
); );
private backend: LogBackend | null = null; private backend: LogBackend | null = null;
private resinBackend: ResinLogBackend | null = null; private balenaBackend: BalenaLogBackend | null = null;
private localBackend: LocalLogBackend | null = null; private localBackend: LocalLogBackend | null = null;
private eventTracker: EventTracker; private eventTracker: EventTracker;
@ -64,10 +64,10 @@ export class Logger {
localMode, localMode,
}: LoggerSetupOptions, }: LoggerSetupOptions,
) { ) {
this.resinBackend = new ResinLogBackend(apiEndpoint, uuid, deviceApiKey); this.balenaBackend = new BalenaLogBackend(apiEndpoint, uuid, deviceApiKey);
this.localBackend = new LocalLogBackend(); this.localBackend = new LocalLogBackend();
this.backend = localMode ? this.localBackend : this.resinBackend; this.backend = localMode ? this.localBackend : this.balenaBackend;
this.backend.offlineMode = offlineMode; this.backend.offlineMode = offlineMode;
this.backend.publishEnabled = enableLogs; this.backend.publishEnabled = enableLogs;
@ -79,9 +79,9 @@ export class Logger {
this.backend = this.localBackend; this.backend = this.localBackend;
console.log('Switching logging backend to LocalLogBackend'); console.log('Switching logging backend to LocalLogBackend');
} else { } else {
// Use the resin backend // Use the balena backend
this.backend = this.resinBackend; this.backend = this.balenaBackend;
console.log('Switching logging backend to ResinLogBackend'); console.log('Switching logging backend to BalenaLogBackend');
} }
} }

View File

@ -20,7 +20,7 @@ interface Options extends url.UrlWithParsedQuery {
headers: Dictionary<string>; headers: Dictionary<string>;
} }
export class ResinLogBackend extends LogBackend { export class BalenaLogBackend extends LogBackend {
private req: ClientRequest | null = null; private req: ClientRequest | null = null;
private dropCount: number = 0; private dropCount: number = 0;

View File

@ -1,10 +1,10 @@
import { LocalLogBackend } from './local-backend'; import { LocalLogBackend } from './local-backend';
import { LogBackend, LogMessage } from './log-backend'; import { LogBackend, LogMessage } from './log-backend';
import { ResinLogBackend } from './resin-backend'; import { BalenaLogBackend } from './balena-backend';
export { export {
LocalLogBackend, LocalLogBackend,
LogBackend, LogBackend,
LogMessage, LogMessage,
ResinLogBackend, BalenaLogBackend,
}; };

View File

@ -583,11 +583,13 @@ module.exports = class Proxyvisor
.then (parentApp) => .then (parentApp) =>
Promise.map parentApp?.services ? [], (service) => Promise.map parentApp?.services ? [], (service) =>
@docker.getImageEnv(service.image) @docker.getImageEnv(service.image)
.get('RESIN_DEPENDENT_DEVICES_HOOK_ADDRESS') .then (imageEnvs) ->
.then (imageHookAddresses) -> imageHookAddresses = _.map imageEnvs, (env) ->
return env.BALENA_DEPENDENT_DEVICES_HOOK_ADDRESS ? env.RESIN_DEPENDENT_DEVICES_HOOK_ADDRESS
for addr in imageHookAddresses for addr in imageHookAddresses
return addr if addr? return addr if addr?
return parentApp?.config?.RESIN_DEPENDENT_DEVICES_HOOK_ADDRESS ? return parentApp?.config?.BALENA_DEPENDENT_DEVICES_HOOK_ADDRESS ?
parentApp?.config?.RESIN_DEPENDENT_DEVICES_HOOK_ADDRESS ?
"#{constants.proxyvisorHookReceiver}/v1/devices/" "#{constants.proxyvisorHookReceiver}/v1/devices/"
sendUpdate: (device, timeout, endpoint) => sendUpdate: (device, timeout, endpoint) =>

View File

@ -54,7 +54,7 @@ module.exports = class SupervisorAPI
res.sendStatus(200) res.sendStatus(200)
# Expires the supervisor's API key and generates a new one. # Expires the supervisor's API key and generates a new one.
# It also communicates the new key to the Resin API. # It also communicates the new key to the balena API.
@_api.post '/v1/regenerate-api-key', (req, res) => @_api.post '/v1/regenerate-api-key', (req, res) =>
@config.newUniqueKey() @config.newUniqueKey()
.then (secret) => .then (secret) =>

View File

@ -7,7 +7,7 @@
// //
// The script will first build a non-optimized version of the js code and sync the resulting app.js // 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. // onto the supervisor container at the specified IP. It will also restart the supervisor container.
// The device must be a development variant of Resin OS and the supervisor must be running. // The device must be a development variant of balenaOS and the supervisor must be running.
fs = require('fs'); fs = require('fs');

View File

@ -1,6 +1,6 @@
prepare = require './lib/prepare' prepare = require './lib/prepare'
Promise = require 'bluebird' Promise = require 'bluebird'
resinAPI = require './lib/mocked-resin-api' balenaAPI = require './lib/mocked-balena-api'
fs = Promise.promisifyAll(require('fs')) fs = Promise.promisifyAll(require('fs'))
m = require 'mochainon' m = require 'mochainon'
@ -39,10 +39,10 @@ mockProvisioningOpts = {
describe 'APIBinder', -> describe 'APIBinder', ->
before -> before ->
spy(resinAPI.resinBackend, 'registerHandler') spy(balenaAPI.balenaBackend, 'registerHandler')
@server = resinAPI.listen(3000) @server = balenaAPI.listen(3000)
after -> after ->
resinAPI.resinBackend.registerHandler.restore() balenaAPI.balenaBackend.registerHandler.restore()
try try
@server.close() @server.close()
@ -55,8 +55,8 @@ describe 'APIBinder', ->
promise = @apiBinder.provisionDevice() promise = @apiBinder.provisionDevice()
expect(promise).to.be.fulfilled expect(promise).to.be.fulfilled
.then => .then =>
expect(resinAPI.resinBackend.registerHandler).to.be.calledOnce expect(balenaAPI.balenaBackend.registerHandler).to.be.calledOnce
resinAPI.resinBackend.registerHandler.reset() balenaAPI.balenaBackend.registerHandler.reset()
expect(@eventTracker.track).to.be.calledWith('Device bootstrap success') expect(@eventTracker.track).to.be.calledWith('Device bootstrap success')
it 'deletes the provisioning key', -> it 'deletes the provisioning key', ->
@ -66,7 +66,7 @@ describe 'APIBinder', ->
fs.readFileAsync('./test/data/config-apibinder.json') fs.readFileAsync('./test/data/config-apibinder.json')
.then(JSON.parse) .then(JSON.parse)
.then (conf) -> .then (conf) ->
expect(resinAPI.resinBackend.devices).to.deep.equal({ expect(balenaAPI.balenaBackend.devices).to.deep.equal({
'1': { '1': {
id: 1 id: 1
user: conf.userId user: conf.userId
@ -81,9 +81,9 @@ describe 'APIBinder', ->
before -> before ->
initModels.call(this, '/config-apibinder.json') initModels.call(this, '/config-apibinder.json')
it 'gets a device by its uuid from the Resin API', -> it 'gets a device by its uuid from the balena API', ->
# Manually add a device to the mocked API # Manually add a device to the mocked API
resinAPI.resinBackend.devices[3] = { balenaAPI.balenaBackend.devices[3] = {
id: 3 id: 3
user: 'foo' user: 'foo'
application: 1337 application: 1337
@ -93,48 +93,48 @@ describe 'APIBinder', ->
} }
@apiBinder.fetchDevice('abcd', 'someApiKey', 30000) @apiBinder.fetchDevice('abcd', 'someApiKey', 30000)
.then (theDevice) -> .then (theDevice) ->
expect(theDevice).to.deep.equal(resinAPI.resinBackend.devices[3]) expect(theDevice).to.deep.equal(balenaAPI.balenaBackend.devices[3])
describe '_exchangeKeyAndGetDevice', -> describe '_exchangeKeyAndGetDevice', ->
before -> before ->
initModels.call(this, '/config-apibinder.json') initModels.call(this, '/config-apibinder.json')
it 'returns the device if it can fetch it with the deviceApiKey', -> it 'returns the device if it can fetch it with the deviceApiKey', ->
spy(resinAPI.resinBackend, 'deviceKeyHandler') spy(balenaAPI.balenaBackend, 'deviceKeyHandler')
fetchDeviceStub = stub(@apiBinder, 'fetchDevice') fetchDeviceStub = stub(@apiBinder, 'fetchDevice')
fetchDeviceStub.onCall(0).resolves({ id: 1 }) fetchDeviceStub.onCall(0).resolves({ id: 1 })
@apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts) @apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts)
.then (device) => .then (device) =>
expect(resinAPI.resinBackend.deviceKeyHandler).to.not.be.called expect(balenaAPI.balenaBackend.deviceKeyHandler).to.not.be.called
expect(device).to.deep.equal({ id: 1 }) expect(device).to.deep.equal({ id: 1 })
expect(@apiBinder.fetchDevice).to.be.calledOnce expect(@apiBinder.fetchDevice).to.be.calledOnce
@apiBinder.fetchDevice.restore() @apiBinder.fetchDevice.restore()
resinAPI.resinBackend.deviceKeyHandler.restore() balenaAPI.balenaBackend.deviceKeyHandler.restore()
it 'throws if it cannot get the device with any of the keys', -> it 'throws if it cannot get the device with any of the keys', ->
spy(resinAPI.resinBackend, 'deviceKeyHandler') spy(balenaAPI.balenaBackend, 'deviceKeyHandler')
stub(@apiBinder, 'fetchDevice').returns(Promise.resolve(null)) stub(@apiBinder, 'fetchDevice').returns(Promise.resolve(null))
promise = @apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts) promise = @apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts)
promise.catch(->) promise.catch(->)
expect(promise).to.be.rejected expect(promise).to.be.rejected
.then => .then =>
expect(resinAPI.resinBackend.deviceKeyHandler).to.not.be.called expect(balenaAPI.balenaBackend.deviceKeyHandler).to.not.be.called
expect(@apiBinder.fetchDevice).to.be.calledTwice expect(@apiBinder.fetchDevice).to.be.calledTwice
@apiBinder.fetchDevice.restore() @apiBinder.fetchDevice.restore()
resinAPI.resinBackend.deviceKeyHandler.restore() balenaAPI.balenaBackend.deviceKeyHandler.restore()
it 'exchanges the key and returns the device if the provisioning key is valid', -> it 'exchanges the key and returns the device if the provisioning key is valid', ->
spy(resinAPI.resinBackend, 'deviceKeyHandler') spy(balenaAPI.balenaBackend, 'deviceKeyHandler')
fetchDeviceStub = stub(@apiBinder, 'fetchDevice') fetchDeviceStub = stub(@apiBinder, 'fetchDevice')
fetchDeviceStub.onCall(0).returns(Promise.resolve(null)) fetchDeviceStub.onCall(0).returns(Promise.resolve(null))
fetchDeviceStub.onCall(1).returns(Promise.resolve({ id: 1 })) fetchDeviceStub.onCall(1).returns(Promise.resolve({ id: 1 }))
@apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts) @apiBinder._exchangeKeyAndGetDevice(mockProvisioningOpts)
.then (device) => .then (device) =>
expect(resinAPI.resinBackend.deviceKeyHandler).to.be.calledOnce expect(balenaAPI.balenaBackend.deviceKeyHandler).to.be.calledOnce
expect(device).to.deep.equal({ id: 1 }) expect(device).to.deep.equal({ id: 1 })
expect(@apiBinder.fetchDevice).to.be.calledTwice expect(@apiBinder.fetchDevice).to.be.calledTwice
@apiBinder.fetchDevice.restore() @apiBinder.fetchDevice.restore()
resinAPI.resinBackend.deviceKeyHandler.restore() balenaAPI.balenaBackend.deviceKeyHandler.restore()
describe 'offline mode', -> describe 'offline mode', ->
before -> before ->

View File

@ -3,19 +3,19 @@ _ = require 'lodash'
api = express() api = express()
api.use(require('body-parser').json()) api.use(require('body-parser').json())
api.resinBackend = { api.balenaBackend = {
currentId: 1 currentId: 1
devices: {} devices: {}
registerHandler: (req, res) -> registerHandler: (req, res) ->
console.log('/device/register called with ', req.body) console.log('/device/register called with ', req.body)
device = req.body device = req.body
device.id = api.resinBackend.currentId++ device.id = api.balenaBackend.currentId++
api.resinBackend.devices[device.id] = device api.balenaBackend.devices[device.id] = device
res.status(201).json(device) res.status(201).json(device)
getDeviceHandler: (req, res) -> getDeviceHandler: (req, res) ->
uuid = req.query['$filter']?.match(/uuid eq '(.*)'/)?[1] uuid = req.query['$filter']?.match(/uuid eq '(.*)'/)?[1]
if uuid? if uuid?
res.json({ d: _.filter(api.resinBackend.devices, (dev) -> dev.uuid is uuid ) }) res.json({ d: _.filter(api.balenaBackend.devices, (dev) -> dev.uuid is uuid ) })
else else
res.json({ d: [] }) res.json({ d: [] })
deviceKeyHandler: (req, res) -> deviceKeyHandler: (req, res) ->
@ -24,12 +24,12 @@ api.resinBackend = {
api.post '/device/register', (req, res) -> api.post '/device/register', (req, res) ->
api.resinBackend.registerHandler(req, res) api.balenaBackend.registerHandler(req, res)
api.get '/v5/device', (req, res) -> api.get '/v5/device', (req, res) ->
api.resinBackend.getDeviceHandler(req, res) api.balenaBackend.getDeviceHandler(req, res)
api.post '/api-key/device/:deviceId/device-key', (req, res) -> api.post '/api-key/device/:deviceId/device-key', (req, res) ->
api.resinBackend.deviceKeyHandler(req, res) api.balenaBackend.deviceKeyHandler(req, res)
module.exports = api module.exports = api