From 9e52bb33ac931a035b4cd0fd80173bf10db771c0 Mon Sep 17 00:00:00 2001 From: Pagan Gazzard Date: Thu, 29 Apr 2021 13:14:18 +0000 Subject: [PATCH] Update balena-register-device and send extra info at provision time This extra info will mean the API is able to immediately set default config vars based on the os/supervisor version so that they are available on the first target state fetch rather than having a delay whilst waiting for the supervisor to report them as part of a state patch Update balena-register-device from 6.1.6 to 7.2.0 Change-type: patch --- package-lock.json | 38 ++++++++++++++++++----------- package.json | 2 +- repo.yml | 2 ++ src/config/functions.ts | 8 ++++++ src/config/schema-type.ts | 4 +++ src/lib/api-helper.ts | 24 +++++++++++++++++- src/lib/errors.ts | 3 +-- src/lib/register-device.ts | 12 ++++----- test/10-api-binder.spec.ts | 5 ++++ typings/balena-register-device.d.ts | 19 --------------- 10 files changed, 73 insertions(+), 44 deletions(-) delete mode 100644 typings/balena-register-device.d.ts diff --git a/package-lock.json b/package-lock.json index 646a7d0d..71d48859 100644 --- a/package-lock.json +++ b/package-lock.json @@ -798,6 +798,12 @@ "source-map": "^0.6.1" } }, + "@types/uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", + "dev": true + }, "@types/webpack": { "version": "4.41.21", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.21.tgz", @@ -1425,24 +1431,28 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "balena-register-device": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/balena-register-device/-/balena-register-device-6.1.6.tgz", - "integrity": "sha512-kS8JZoLyucZ9oUFicspN/k3jRrvdtQ4UYXVCHHyw91C3y2Z1T5CQpwfMBSqA8dp5wQKyP527K/0+lMUa2ncLhA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/balena-register-device/-/balena-register-device-7.2.0.tgz", + "integrity": "sha512-Uo8iceob2Zg8gBedZKzSZWTyr5XoDkUN+2oSyyuKVuhZYcZS623Lsj/+I8QdJQutlObgVHjD2k3mM1Pa6loFxA==", "dev": true, "requires": { - "bluebird": "^3.7.2", - "randomstring": "^1.1.5", - "typed-error": "^2.0.0" + "@types/uuid": "^8.3.0", + "tslib": "^2.2.0", + "typed-error": "^3.2.1", + "uuid": "^8.3.2" }, "dependencies": { - "typed-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/typed-error/-/typed-error-2.0.0.tgz", - "integrity": "sha1-05j9hin8K3nIOfm30b/Ay7ZSYBI=", - "dev": true, - "requires": { - "tslib": "^1.7.1" - } + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true } } }, diff --git a/package.json b/package.json index 2bd51ad3..258a10d8 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "@types/tmp": "^0.1.0", "@types/webpack": "^4.41.21", "@types/yargs": "^15.0.12", - "balena-register-device": "^6.1.6", + "balena-register-device": "^7.2.0", "blinking": "^0.0.4", "bluebird": "^3.7.2", "chai-as-promised": "^7.1.1", diff --git a/repo.yml b/repo.yml index 49035bf3..f3033072 100644 --- a/repo.yml +++ b/repo.yml @@ -6,6 +6,8 @@ backports: sunset: 10.3.x upstream: + - repo: 'balena-register-device' + url: 'https://github.com/balena-io-modules/balena-register-device' - repo: 'docker-delta' url: 'https://github.com/balena-io-modules/node-docker-delta' - repo: 'docker-progress' diff --git a/src/config/functions.ts b/src/config/functions.ts index 520372a9..3002bdac 100644 --- a/src/config/functions.ts +++ b/src/config/functions.ts @@ -90,6 +90,10 @@ export const fnSchema = { 'apiTimeout', 'registered_at', 'deviceId', + 'version', + 'osVersion', + 'osVariant', + 'macAddress', ]) .then((conf) => { return { @@ -103,6 +107,10 @@ export const fnSchema = { apiTimeout: conf.apiTimeout, registered_at: conf.registered_at, deviceId: conf.deviceId, + supervisorVersion: conf.version, + osVersion: conf.osVersion, + osVariant: conf.osVariant, + macAddress: conf.macAddress, }; }); }, diff --git a/src/config/schema-type.ts b/src/config/schema-type.ts index de0b0fe6..308681f8 100644 --- a/src/config/schema-type.ts +++ b/src/config/schema-type.ts @@ -211,6 +211,10 @@ export const schemaTypes = { apiTimeout: PermissiveNumber, registered_at: t.union([PermissiveNumber, NullOrUndefined]), deviceId: t.union([PermissiveNumber, NullOrUndefined]), + supervisorVersion: t.union([t.string, t.undefined]), + osVersion: t.union([t.string, t.undefined]), + osVariant: t.union([t.string, t.undefined]), + macAddress: t.union([t.string, t.undefined]), }), default: t.never, }, diff --git a/src/lib/api-helper.ts b/src/lib/api-helper.ts index a0335aa9..6b91bbe7 100644 --- a/src/lib/api-helper.ts +++ b/src/lib/api-helper.ts @@ -170,9 +170,31 @@ export const provision = async ( device = await exchangeKeyAndGetDeviceOrRegenerate(balenaApi, opts); } else if (opts.registered_at == null) { + if (opts.provisioningApiKey == null) { + throw new Error('Cannot provision without a provisioning api key'); + } + if (opts.applicationId == null) { + throw new Error('Cannot provision without an application id'); + } + if (opts.uuid == null) { + throw new Error('Cannot provision without a uuid'); + } log.info('New device detected. Provisioning...'); try { - device = await deviceRegister.register(opts).timeout(opts.apiTimeout); + device = await Bluebird.resolve( + deviceRegister.register({ + applicationId: opts.applicationId, + uuid: opts.uuid, + deviceType: opts.deviceType, + deviceApiKey: opts.deviceApiKey, + provisioningApiKey: opts.provisioningApiKey, + apiEndpoint: opts.apiEndpoint, + supervisorVersion: opts.supervisorVersion, + osVersion: opts.osVersion, + osVariant: opts.osVariant, + macAddress: opts.macAddress, + }), + ).timeout(opts.apiTimeout); } catch (err) { if ( err instanceof deviceRegister.ApiError && diff --git a/src/lib/errors.ts b/src/lib/errors.ts index 02c455b9..d1cf01e8 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -1,5 +1,4 @@ import { endsWith, map } from 'lodash'; -import { Response } from 'request'; import { TypedError } from 'typed-error'; import { checkInt } from './validation'; @@ -48,7 +47,7 @@ export class InvalidAppIdError extends TypedError { export class UpdatesLockedError extends TypedError {} -export function isHttpConflictError(err: StatusCodeError | Response): boolean { +export function isHttpConflictError(err: { statusCode: number }): boolean { return checkInt(err.statusCode) === 409; } diff --git a/src/lib/register-device.ts b/src/lib/register-device.ts index 6415b046..5f635879 100644 --- a/src/lib/register-device.ts +++ b/src/lib/register-device.ts @@ -1,15 +1,13 @@ -import factory = require('balena-register-device'); -import * as Bluebird from 'bluebird'; +import { getRegisterDevice } from 'balena-register-device'; +export { ApiError } from 'balena-register-device'; import { getRequestInstance } from './request'; -export const { ApiError } = factory; - -export const { generateUniqueKey, register } = factory({ +export const { generateUniqueKey, register } = getRegisterDevice({ request: { - send: Bluebird.method(async (options: {}) => { + send: async (options: {}) => { const request = await getRequestInstance(); const [response] = await request.postAsync({ ...options, json: true }); return response; - }), + }, }, }); diff --git a/test/10-api-binder.spec.ts b/test/10-api-binder.spec.ts index 979afbd9..fa5b77b8 100644 --- a/test/10-api-binder.spec.ts +++ b/test/10-api-binder.spec.ts @@ -15,6 +15,7 @@ import * as TargetState from '../src/device-state/target-state'; import { DeviceStatus } from '../src/types/state'; import * as CurrentState from '../src/device-state/current-state'; import * as ApiHelper from '../src/lib/api-helper'; +import supervisorVersion = require('../src/lib/supervisor-version'); import { TypedError } from 'typed-error'; import { DeviceNotFoundError } from '../src/lib/errors'; @@ -166,6 +167,10 @@ describe('ApiBinder', () => { uuid: conf.uuid, device_type: conf.deviceType, api_key: conf.deviceApiKey, + mac_address: '00:11:22:33:44:55 66:77:88:99:AA:BB', + os_variant: 'dev', + os_version: 'balenaOS 2.0.6+rev1', + supervisor_version: supervisorVersion, }, }); }); diff --git a/typings/balena-register-device.d.ts b/typings/balena-register-device.d.ts deleted file mode 100644 index 3c019524..00000000 --- a/typings/balena-register-device.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Typings (incomplete) for balena-register-device@v6.0.1 - -// TODO: Upstream types to the repo -declare module 'balena-register-device' { - import { Response } from 'request'; - import { TypedError } from 'typed-error'; - - function factory({ - request, - }): { - generateUniqueKey: () => string; - register: (opts: Dictionary) => Bluebird<{ id: string }>; - }; - - factory.ApiError = class ApiError extends TypedError { - public response: Response; - }; - export = factory; -}