Support for device environment variables

@WillFG the SSL error is caused when you are trying to control your openBalena install which has a self-signed CA certificate. This is how it is setup by default, so I would expect that this is the case here.

To circumvent this, you need to export the variable NODE_EXTRA_CA_CERTS with the path to the CA certificate generated during the openBalena setup; usually in the ./open-balena/config/certs/ca directory.

An example of this is provided in the Getting Started guide found here: https://www.balena.io/open/docs/getting-started/

I hope this helps.

Rich

@richbayliss - I fixed the error using the same method as described but with Python via REQUESTS_CA_BUNDLE

However, getting a 404 using the Python SDK at /v4/device so I’ll try using the CLI again as @imrehg described, having checked I’m using the correct version.

@imrehg - getting the below using the CLI - can confirm version is 9.0.2
balena env add WIBBLE 1 --device xxxxx
BalenaRequestError: Request error: Database error

I will update to 9.0.3 and also see if I can dig up some logs on the server and report back.

Currently my server only has port 443 exposed to the outside, do the remainder as per:

ports:
  - "80:80"
  - "222:222"
  - "443:443"
  - "5432:5432"
  - "6379:6379"

also need to be accessible?
Otherwise I have not found much within the containers running on the server to diagnose the error.

Found the error, will see why the constraint is an issue:

2018-11-08 13:44:35.005 UTC [28] ERROR: null value in column “env var name” violates not-null constraint
2018-11-08 13:44:35.005 UTC [28] DETAIL: Failing row contains (2018-11-08 13:44:34.995467, 1, null, 4, woo).
2018-11-08 13:44:35.005 UTC [28] STATEMENT: INSERT INTO “device environment variable” (“device”, “value”)
VALUES ($1, $2) RETURNING “id”;
2018-11-08 13:44:45.522 UTC [31] ERROR: null value in column “env var name” violates not-null constraint
2018-11-08 13:44:45.522 UTC [31] DETAIL: Failing row contains (2018-11-08 13:44:45.515905, 1, null, 5, woo).
2018-11-08 13:44:45.522 UTC [31] STATEMENT: INSERT INTO “device environment variable” (“device”, “value”)
VALUES ($1, $2) RETURNING “id”;

Edit: key being set to null for some reason
Edit: happening for 9.0.2, 9.0.3 and 9.1.0

@WillFG you should be good only exposing 443 for now. Note that we’ll soon require 3128 as well for device SSH.

The Python SDK currently cannot target an open-balena instance – it still assumes the full balenaCloud API.

Regarding the env vars issue you’re seeing, can you please make sure you completely remove previous CLI versions before updating – NPM might not pick up new versions of dependencies.

@dfunckt I have tried on a few different machines and get the same result, including standalone installs.
I’m wondering whether the api_version in ~/.resin/resin.cfg should still be v4?
I took the cfg file from previous install of CLI when working against balenaCloud and just updated URLs, so wondering if that could be an issue.

In case this sheds light on this, adding journal entries from api for completeness.

Nov 09 12:22:04 dad477126c02 api[862]: resin: Parsing POST /resin/device_environment_variable
Nov 09 12:22:04 dad477126c02 api[862]: resin: Running POST /resin/device_environment_variable
Nov 09 12:22:04 dad477126c02 api[862]: resin: Parsing GET /resin/device?$select=id&$filter=id eq 1
Nov 09 12:22:04 dad477126c02 api[862]: resin: Running GET /resin/device?$select=id&$filter=id eq 1
Nov 09 12:22:04 dad477126c02 api[862]: resin: SELECT “device”.“id”
Nov 09 12:22:04 dad477126c02 api[862]: FROM “device”
Nov 09 12:22:04 dad477126c02 api[862]: WHERE “device”.“id” = $1 [ 1 ]
Nov 09 12:22:04 dad477126c02 api[862]: resin: INSERT INTO “device environment variable” (“device”, “value”)
Nov 09 12:22:04 dad477126c02 api[862]: VALUES ($1, $2) [ 1, ‘testval’ ]

@WillFG indeed, that could be the issue – openBalena API is at v5, it does not expose any earlier version.

Are these last logs after you switched to v5? Did you get it working?

@dfunckt I just looked at env-vars.ts and thought maybe it was a whitelisting problem.

I then tried BALENA_SOMETHING and RESIN_SOMETHING and it worked

Nov 09 14:51:14 dad477126c02 api[862]: resin: INSERT INTO “device config variable” (“device”, “name”, “value”)
Nov 09 14:51:14 dad477126c02 api[862]: VALUES ($1, $2, $3) [ 1, ‘BALENA_NAME’, ‘TEST’ ]
Nov 09 14:51:14 dad477126c02 api[862]: resin: Parsing GET /resin/device?$select=id&$filter=((is_connected_to_vpn eq true) and (vpn_address ne null)) and (id in (1))
Nov 09 14:51:14 dad477126c02 api[862]: resin: Running GET /resin/device?$select=id&$filter=((is_connected_to_vpn eq true) and (vpn_address ne null)) and (id in (1))

Edit: just realised that’s adding into config variables rather than device environment variables but it is passing it through in the POST at least.

Edit2: I removed the resin.cfg so will reinstate and set to v5 to see if that helps

Just to confirm, I:

  1. removed ~/.resin/resin.cfg
  2. tried setting env vars, which failed as per above
  3. Tried setting with reserved names, which appeared to work, although I have not checked whether they are retrievable
  4. reinstated resin.cfg with explicit api_version = v5 and the behaviour is the same

I expect it is something obvious that I am doing wrong…will look into env-vars.ts and see how it handles the POSTS. Apologies for the very long thread, I think I will have it figured out reasonably soon!

Try removing the whole ~/.resin and ~/.balena folders to start fresh. Then login again with the CLI and try setting a non-reserved env var – i.e. something not prefixed with RESIN_ or BALENA_ (I think these are automatically saved as config vars as you found out).

@dfunckt - still no joy

Please ignore my comment below if it is clearly wrong. I will fork and see if I can fix it.

This is a complete stab in the dark but I’m wondering whether this method should not have name rather than env_var_name in it:

addEnvHooks(
‘device_environment_variable’,
’env_var_name’,
checkEnvVarValidity,
(
args: sbvrUtils.HookArgs & {
tx: Tx;
},
) => {
if (args.req.body.device != null) {
// If we have a device passed in the body (ie POST) then we can use that as ID filter.
return Promise.resolve({ id: args.req.body.device });
}

What is the exact CLI command you run?

Can you try npm -g ls | grep balena-sdk and npm -g ls | grep balena-cli please and paste the output here?

The snippet you pasted above is correct – the key on device_environment_variables is stored on env_var_name, as per https://github.com/balena-io/open-balena-api/blob/master/src/resin.sbvr#L277-L279

balena env add TEST TEST --device ccaed85

will@MAVEN-MINT:~$ npm -g ls | grep balena-sdk
│ │ └─┬ balena-sdk@11.0.0
│ ├─┬ balena-sdk@11.1.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! error in /usr/local/lib/node_modules/resin-cli: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/package.json'
npm ERR! extraneous: aws-sdk /usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk/package.json'
npm ERR! extraneous: degenerator /usr/local/lib/node_modules/resin-cli/node_modules/degenerator
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/degenerator: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/degenerator/package.json'
npm ERR! extraneous: docker-modem /usr/local/lib/node_modules/resin-cli/node_modules/docker-modem
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/docker-modem: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/docker-modem/package.json'
npm ERR! extraneous: escodegen /usr/local/lib/node_modules/resin-cli/node_modules/escodegen
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/escodegen: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/escodegen/package.json'
npm ERR! extraneous: resin-cli-visuals /usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals/package.json'
npm ERR! extraneous: resin-device-config /usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config/package.json'
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
will@MAVEN-MINT:~$ npm -g ls | grep balena-cli
├─┬ balena-cli@9.1.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! error in /usr/local/lib/node_modules/resin-cli: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/package.json'
npm ERR! extraneous: aws-sdk /usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/aws-sdk/package.json'
npm ERR! extraneous: degenerator /usr/local/lib/node_modules/resin-cli/node_modules/degenerator
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/degenerator: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/degenerator/package.json'
npm ERR! extraneous: docker-modem /usr/local/lib/node_modules/resin-cli/node_modules/docker-modem
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/docker-modem: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/docker-modem/package.json'
npm ERR! extraneous: escodegen /usr/local/lib/node_modules/resin-cli/node_modules/escodegen
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/escodegen: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/escodegen/package.json'
npm ERR! extraneous: resin-cli-visuals /usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/resin-cli-visuals/package.json'
npm ERR! extraneous: resin-device-config /usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config
npm ERR! error in /usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config: ENOENT: no such file or directory, open '/usr/local/lib/node_modules/resin-cli/node_modules/resin-device-config/package.json'
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0

I believe the missing peer dependencies are fine but the references to resin-cli are puzzling. Can you try the following to clean things up a bit? (I’m assuming rm -rf /usr/local/lib/node_modules/* && npm -g cache clean --force is not an option).

$ npm uninstall -g resin-cli balena-cli
$ npm prune -g
$ npm cache clean --force
$ npm install -g balena-cli

Here’s what I get on a clean install:

$ npm -g ls | grep balena-cli
├─┬ balena-cli@9.1.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
$ npm -g ls | grep balena-sdk
│ │ ├─┬ balena-sdk@11.0.0
│ │ ├── balena-sdk@11.1.0 deduped
│ │ ├── balena-sdk@11.1.0 deduped
│ ├─┬ balena-sdk@11.1.0
│ │ ├── balena-sdk@11.1.0 deduped
│ │ ├── balena-sdk@11.1.0 deduped
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0

Ran the above inc. removing node modules and get the below now.
Still same database error as previously so will see how easy it is to remote debug the API.

will@MAVEN-MINT:~$ npm -g ls | grep balena-cli
└─┬ balena-cli@9.1.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0

will@MAVEN-MINT:~$ npm -g ls | grep balena-sdk
│ └─┬ balena-sdk@11.0.0
├─┬ balena-sdk@11.1.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: balena-auth@^2.0.0, required by balena-request@10.0.0
npm ERR! peer dep missing: resin-request@^9.0.2, required by resin-register-device@5.0.0

This is really weird. Can you please follow the steps below to get a fresh installation up?

Pull the latest version of all services, with:

$ cd open-balena
$ ./scripts/compose pull

Then reset the current deployment (note the following will delete all data, including the database):

$ ./scripts/compose kill
$ ./scripts/compose down
$ docker volume rm openbalena_s3 openbalena_redis openbalena_db openbalena_registry

Pull the latest open-balena:

$ cd open-balena
$ git pull

Run the quickstart again:

$ ./scripts/quickstart

@WillFG I managed to reproduce the database error :slight_smile: I’m now looking to fix this.

@dfunckt - great! I thought I was doing something stupid and / or going mad…

1 Like