mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-06-21 09:23:58 +00:00
Update balena-sdk to 14.x
Update balena-sdk from 13.6.0 to 14.8.0 Change-type: patch
This commit is contained in:
@ -86,6 +86,7 @@ export default class AppCreateCmd extends Command {
|
|||||||
application = await balena.models.application.create({
|
application = await balena.models.application.create({
|
||||||
name: params.name,
|
name: params.name,
|
||||||
deviceType,
|
deviceType,
|
||||||
|
organization: (await balena.auth.whoami())!,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// BalenaRequestError: Request error: Unique key constraint violated
|
// BalenaRequestError: Request error: Unique key constraint violated
|
||||||
@ -97,7 +98,7 @@ export default class AppCreateCmd extends Command {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
console.info(
|
console.info(
|
||||||
`Application created: ${application.slug} (${application.device_type}, id ${application.id})`,
|
`Application created: ${application.slug} (${deviceType}, id ${application.id})`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import Command from '../../command';
|
|||||||
import * as cf from '../../utils/common-flags';
|
import * as cf from '../../utils/common-flags';
|
||||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||||
import { tryAsInteger } from '../../utils/validation';
|
import { tryAsInteger } from '../../utils/validation';
|
||||||
|
import { Release } from 'balena-sdk';
|
||||||
|
|
||||||
interface FlagsDef {
|
interface FlagsDef {
|
||||||
help: void;
|
help: void;
|
||||||
@ -57,10 +58,22 @@ export default class AppCmd extends Command {
|
|||||||
public async run() {
|
public async run() {
|
||||||
const { args: params } = this.parse<FlagsDef, ArgsDef>(AppCmd);
|
const { args: params } = this.parse<FlagsDef, ArgsDef>(AppCmd);
|
||||||
|
|
||||||
const application = await getBalenaSdk().models.application.get(
|
const application = (await getBalenaSdk().models.application.get(
|
||||||
tryAsInteger(params.name),
|
tryAsInteger(params.name),
|
||||||
);
|
{
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
should_be_running__release: { $select: 'commit' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)) as ApplicationWithDeviceType & {
|
||||||
|
should_be_running__release: [Release?];
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
|
application.device_type = application.is_for__device_type[0].slug;
|
||||||
|
// @ts-expect-error
|
||||||
|
application.commit = application.should_be_running__release[0]?.commit;
|
||||||
console.log(
|
console.log(
|
||||||
getVisuals().table.vertical(application, [
|
getVisuals().table.vertical(application, [
|
||||||
`$${application.app_name}$`,
|
`$${application.app_name}$`,
|
||||||
|
@ -16,13 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { flags } from '@oclif/command';
|
import { flags } from '@oclif/command';
|
||||||
import type { Application } from 'balena-sdk';
|
|
||||||
import Command from '../command';
|
import Command from '../command';
|
||||||
import * as cf from '../utils/common-flags';
|
import * as cf from '../utils/common-flags';
|
||||||
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
|
import { getBalenaSdk, getVisuals, stripIndent } from '../utils/lazy';
|
||||||
import { isV12 } from '../utils/version';
|
import { isV12 } from '../utils/version';
|
||||||
|
|
||||||
interface ExtendedApplication extends Application {
|
interface ExtendedApplication extends ApplicationWithDeviceType {
|
||||||
device_count?: number;
|
device_count?: number;
|
||||||
online_devices?: number;
|
online_devices?: number;
|
||||||
}
|
}
|
||||||
@ -64,12 +63,13 @@ export default class AppsCmd extends Command {
|
|||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
|
|
||||||
// Get applications
|
// Get applications
|
||||||
const applications: ExtendedApplication[] = await balena.models.application.getAll(
|
const applications = (await balena.models.application.getAll({
|
||||||
{
|
$select: ['id', 'app_name', 'slug'],
|
||||||
$select: ['id', 'app_name', 'slug', 'device_type'],
|
$expand: {
|
||||||
$expand: { owns__device: { $select: 'is_online' } },
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
owns__device: { $select: 'is_online' },
|
||||||
},
|
},
|
||||||
);
|
})) as ExtendedApplication[];
|
||||||
|
|
||||||
const _ = await import('lodash');
|
const _ = await import('lodash');
|
||||||
// Add extended properties
|
// Add extended properties
|
||||||
@ -78,6 +78,8 @@ export default class AppsCmd extends Command {
|
|||||||
application.online_devices = _.sumBy(application.owns__device, (d) =>
|
application.online_devices = _.sumBy(application.owns__device, (d) =>
|
||||||
d.is_online === true ? 1 : 0,
|
d.is_online === true ? 1 : 0,
|
||||||
);
|
);
|
||||||
|
// @ts-expect-error
|
||||||
|
application.device_type = application.is_for__device_type[0].slug;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
|
@ -189,7 +189,7 @@ ${dockerignoreHelp}
|
|||||||
const { getAppWithArch } = await import('../utils/helpers');
|
const { getAppWithArch } = await import('../utils/helpers');
|
||||||
const app = await getAppWithArch(opts.application);
|
const app = await getAppWithArch(opts.application);
|
||||||
opts.arch = app.arch;
|
opts.arch = app.arch;
|
||||||
opts.deviceType = app.device_type;
|
opts.deviceType = app.is_for__device_type[0].slug;
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import { flags } from '@oclif/command';
|
|||||||
import Command from '../../command';
|
import Command from '../../command';
|
||||||
import * as cf from '../../utils/common-flags';
|
import * as cf from '../../utils/common-flags';
|
||||||
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
|
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
|
||||||
import type { Device, Application, PineDeferred } from 'balena-sdk';
|
import type { Application, PineDeferred } from 'balena-sdk';
|
||||||
|
|
||||||
interface FlagsDef {
|
interface FlagsDef {
|
||||||
version: string; // OS version
|
version: string; // OS version
|
||||||
@ -130,27 +130,34 @@ export default class ConfigGenerateCmd extends Command {
|
|||||||
|
|
||||||
await this.validateOptions(options);
|
await this.validateOptions(options);
|
||||||
|
|
||||||
|
let deviceType = options.deviceType;
|
||||||
// Get device | application
|
// Get device | application
|
||||||
let resource;
|
let resource;
|
||||||
if (options.device != null) {
|
if (options.device != null) {
|
||||||
const { tryAsInteger } = await import('../../utils/validation');
|
const { tryAsInteger } = await import('../../utils/validation');
|
||||||
resource = (await balena.models.device.get(
|
resource = (await balena.models.device.get(tryAsInteger(options.device), {
|
||||||
tryAsInteger(options.device),
|
$expand: {
|
||||||
)) as Device & { belongs_to__application: PineDeferred };
|
is_of__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
})) as DeviceWithDeviceType & { belongs_to__application: PineDeferred };
|
||||||
|
deviceType = deviceType || resource.is_of__device_type[0].slug;
|
||||||
} else {
|
} else {
|
||||||
resource = await balena.models.application.get(options.application!);
|
resource = (await balena.models.application.get(options.application!, {
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
})) as ApplicationWithDeviceType;
|
||||||
|
deviceType = deviceType || resource.is_for__device_type[0].slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
const deviceType = options.deviceType || resource.device_type;
|
|
||||||
|
|
||||||
const deviceManifest = await balena.models.device.getManifestBySlug(
|
const deviceManifest = await balena.models.device.getManifestBySlug(
|
||||||
deviceType,
|
deviceType!,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check compatibility if application and deviceType provided
|
// Check compatibility if application and deviceType provided
|
||||||
if (options.application && options.deviceType) {
|
if (options.application && options.deviceType) {
|
||||||
const appDeviceManifest = await balena.models.device.getManifestBySlug(
|
const appDeviceManifest = await balena.models.device.getManifestBySlug(
|
||||||
resource.device_type,
|
deviceType!,
|
||||||
);
|
);
|
||||||
|
|
||||||
const helpers = await import('../../utils/helpers');
|
const helpers = await import('../../utils/helpers');
|
||||||
|
@ -22,11 +22,12 @@ import * as cf from '../../utils/common-flags';
|
|||||||
import { expandForAppName } from '../../utils/helpers';
|
import { expandForAppName } from '../../utils/helpers';
|
||||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||||
import { tryAsInteger } from '../../utils/validation';
|
import { tryAsInteger } from '../../utils/validation';
|
||||||
import type { Application, Device } from 'balena-sdk';
|
import type { Application, Release } from 'balena-sdk';
|
||||||
|
|
||||||
interface ExtendedDevice extends Device {
|
interface ExtendedDevice extends DeviceWithDeviceType {
|
||||||
dashboard_url?: string;
|
dashboard_url?: string;
|
||||||
application_name?: string;
|
application_name?: string;
|
||||||
|
device_type?: string;
|
||||||
commit?: string;
|
commit?: string;
|
||||||
last_seen?: string;
|
last_seen?: string;
|
||||||
}
|
}
|
||||||
@ -70,25 +71,23 @@ export default class DeviceCmd extends Command {
|
|||||||
|
|
||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
|
|
||||||
const device: ExtendedDevice = await balena.models.device.get(params.uuid, {
|
const device = (await balena.models.device.get(params.uuid, {
|
||||||
$select: [
|
$select: [
|
||||||
'device_name',
|
'device_name',
|
||||||
'id',
|
'id',
|
||||||
'device_type',
|
|
||||||
'overall_status',
|
'overall_status',
|
||||||
'is_online',
|
'is_online',
|
||||||
'ip_address',
|
'ip_address',
|
||||||
'mac_address',
|
'mac_address',
|
||||||
'last_connectivity_event',
|
'last_connectivity_event',
|
||||||
'uuid',
|
'uuid',
|
||||||
'is_on__commit',
|
|
||||||
'supervisor_version',
|
'supervisor_version',
|
||||||
'is_web_accessible',
|
'is_web_accessible',
|
||||||
'note',
|
'note',
|
||||||
'os_version',
|
'os_version',
|
||||||
],
|
],
|
||||||
...expandForAppName,
|
...expandForAppName,
|
||||||
});
|
})) as ExtendedDevice;
|
||||||
device.status = device.overall_status;
|
device.status = device.overall_status;
|
||||||
|
|
||||||
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid);
|
device.dashboard_url = balena.models.device.getDashboardUrl(device.uuid);
|
||||||
@ -98,8 +97,9 @@ export default class DeviceCmd extends Command {
|
|||||||
? belongsToApplication[0].app_name
|
? belongsToApplication[0].app_name
|
||||||
: 'N/a';
|
: 'N/a';
|
||||||
|
|
||||||
device.commit = device.is_on__commit;
|
device.device_type = device.is_of__device_type[0].slug;
|
||||||
device.last_seen = device.last_connectivity_event;
|
device.commit = (device.is_running__release as Release[])[0].commit;
|
||||||
|
device.last_seen = device.last_connectivity_event ?? undefined;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
getVisuals().table.vertical(device, [
|
getVisuals().table.vertical(device, [
|
||||||
|
@ -95,10 +95,17 @@ export default class DeviceInitCmd extends Command {
|
|||||||
delete options.app;
|
delete options.app;
|
||||||
|
|
||||||
// Get application and
|
// Get application and
|
||||||
const application = await balena.models.application.get(
|
const application = (await balena.models.application.get(
|
||||||
options['application'] ||
|
options['application'] ||
|
||||||
(await (await import('../../utils/patterns')).selectApplication()),
|
(await (await import('../../utils/patterns')).selectApplication()),
|
||||||
);
|
{
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: {
|
||||||
|
$select: 'slug',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)) as ApplicationWithDeviceType;
|
||||||
|
|
||||||
// Register new device
|
// Register new device
|
||||||
const deviceUuid = balena.models.device.generateUniqueKey();
|
const deviceUuid = balena.models.device.generateUniqueKey();
|
||||||
@ -111,13 +118,14 @@ export default class DeviceInitCmd extends Command {
|
|||||||
try {
|
try {
|
||||||
logger.logDebug(`Downloading OS image...`);
|
logger.logDebug(`Downloading OS image...`);
|
||||||
const osVersion = options['os-version'] || 'default';
|
const osVersion = options['os-version'] || 'default';
|
||||||
await downloadOSImage(application.device_type, tmpPath, osVersion);
|
const deviceType = application.is_for__device_type[0].slug;
|
||||||
|
await downloadOSImage(deviceType, tmpPath, osVersion);
|
||||||
|
|
||||||
logger.logDebug(`Configuring OS image...`);
|
logger.logDebug(`Configuring OS image...`);
|
||||||
await this.configureOsImage(tmpPath, device.uuid, options);
|
await this.configureOsImage(tmpPath, device.uuid, options);
|
||||||
|
|
||||||
logger.logDebug(`Writing OS image...`);
|
logger.logDebug(`Writing OS image...`);
|
||||||
await this.writeOsImage(tmpPath, application.device_type, options);
|
await this.writeOsImage(tmpPath, deviceType, options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Remove device in failed cases
|
// Remove device in failed cases
|
||||||
try {
|
try {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { flags } from '@oclif/command';
|
import { flags } from '@oclif/command';
|
||||||
import type { IArg } from '@oclif/parser/lib/args';
|
import type { IArg } from '@oclif/parser/lib/args';
|
||||||
import type { Application, Device } from 'balena-sdk';
|
import type { Application } from 'balena-sdk';
|
||||||
import Command from '../../command';
|
import Command from '../../command';
|
||||||
import * as cf from '../../utils/common-flags';
|
import * as cf from '../../utils/common-flags';
|
||||||
import { expandForAppName } from '../../utils/helpers';
|
import { expandForAppName } from '../../utils/helpers';
|
||||||
@ -25,7 +25,7 @@ import { getBalenaSdk, stripIndent } from '../../utils/lazy';
|
|||||||
import { tryAsInteger } from '../../utils/validation';
|
import { tryAsInteger } from '../../utils/validation';
|
||||||
import { ExpectedError } from '../../errors';
|
import { ExpectedError } from '../../errors';
|
||||||
|
|
||||||
interface ExtendedDevice extends Device {
|
interface ExtendedDevice extends DeviceWithDeviceType {
|
||||||
application_name?: string;
|
application_name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +85,15 @@ export default class DeviceMoveCmd extends Command {
|
|||||||
options.application = options.application || options.app;
|
options.application = options.application || options.app;
|
||||||
delete options.app;
|
delete options.app;
|
||||||
|
|
||||||
const devices: ExtendedDevice[] = await Promise.all(
|
const devices = await Promise.all(
|
||||||
params.uuid
|
params.uuid
|
||||||
.split(',')
|
.split(',')
|
||||||
.map((uuid) => balena.models.device.get(uuid, expandForAppName)),
|
.map(
|
||||||
|
(uuid) =>
|
||||||
|
balena.models.device.get(uuid, expandForAppName) as Promise<
|
||||||
|
ExtendedDevice
|
||||||
|
>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const device of devices) {
|
for (const device of devices) {
|
||||||
@ -106,7 +111,9 @@ export default class DeviceMoveCmd extends Command {
|
|||||||
const [deviceDeviceTypes, deviceTypes] = await Promise.all([
|
const [deviceDeviceTypes, deviceTypes] = await Promise.all([
|
||||||
Promise.all(
|
Promise.all(
|
||||||
devices.map((device) =>
|
devices.map((device) =>
|
||||||
balena.models.device.getManifestBySlug(device.device_type),
|
balena.models.device.getManifestBySlug(
|
||||||
|
device.is_of__device_type[0].slug,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
balena.models.config.getDeviceTypes(),
|
balena.models.config.getDeviceTypes(),
|
||||||
@ -127,8 +134,10 @@ export default class DeviceMoveCmd extends Command {
|
|||||||
const patterns = await import('../../utils/patterns');
|
const patterns = await import('../../utils/patterns');
|
||||||
try {
|
try {
|
||||||
application = await patterns.selectApplication(
|
application = await patterns.selectApplication(
|
||||||
(app: Application) =>
|
(app) =>
|
||||||
compatibleDeviceTypes.some((dt) => dt.slug === app.device_type) &&
|
compatibleDeviceTypes.some(
|
||||||
|
(dt) => dt.slug === app.is_for__device_type[0].slug,
|
||||||
|
) &&
|
||||||
// @ts-ignore using the extended device object prop
|
// @ts-ignore using the extended device object prop
|
||||||
devices.some((device) => device.application_name !== app.app_name),
|
devices.some((device) => device.application_name !== app.app_name),
|
||||||
true,
|
true,
|
||||||
|
@ -81,12 +81,17 @@ export default class DeviceOsUpdateCmd extends Command {
|
|||||||
// Get device info
|
// Get device info
|
||||||
const {
|
const {
|
||||||
uuid,
|
uuid,
|
||||||
device_type,
|
is_of__device_type,
|
||||||
os_version,
|
os_version,
|
||||||
os_variant,
|
os_variant,
|
||||||
} = await sdk.models.device.get(params.uuid, {
|
} = (await sdk.models.device.get(params.uuid, {
|
||||||
$select: ['uuid', 'device_type', 'os_version', 'os_variant'],
|
$select: ['uuid', 'os_version', 'os_variant'],
|
||||||
});
|
$expand: {
|
||||||
|
is_of__device_type: {
|
||||||
|
$select: 'slug',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})) as DeviceWithDeviceType;
|
||||||
|
|
||||||
// Get current device OS version
|
// Get current device OS version
|
||||||
const currentOsVersion = sdk.models.device.getOsVersion({
|
const currentOsVersion = sdk.models.device.getOsVersion({
|
||||||
@ -101,7 +106,7 @@ export default class DeviceOsUpdateCmd extends Command {
|
|||||||
|
|
||||||
// Get supported OS update versions
|
// Get supported OS update versions
|
||||||
const hupVersionInfo = await sdk.models.os.getSupportedOsUpdateVersions(
|
const hupVersionInfo = await sdk.models.os.getSupportedOsUpdateVersions(
|
||||||
device_type,
|
is_of__device_type[0].slug,
|
||||||
currentOsVersion,
|
currentOsVersion,
|
||||||
);
|
);
|
||||||
if (hupVersionInfo.versions.length === 0) {
|
if (hupVersionInfo.versions.length === 0) {
|
||||||
|
@ -21,9 +21,9 @@ import * as cf from '../../utils/common-flags';
|
|||||||
import { expandForAppName } from '../../utils/helpers';
|
import { expandForAppName } from '../../utils/helpers';
|
||||||
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
|
||||||
import { tryAsInteger } from '../../utils/validation';
|
import { tryAsInteger } from '../../utils/validation';
|
||||||
import type { Device, Application } from 'balena-sdk';
|
import type { Application } from 'balena-sdk';
|
||||||
|
|
||||||
interface ExtendedDevice extends Device {
|
interface ExtendedDevice extends DeviceWithDeviceType {
|
||||||
dashboard_url?: string;
|
dashboard_url?: string;
|
||||||
application_name?: string;
|
application_name?: string;
|
||||||
}
|
}
|
||||||
@ -80,15 +80,17 @@ export default class DevicesCmd extends Command {
|
|||||||
options.application = options.application || options.app;
|
options.application = options.application || options.app;
|
||||||
delete options.app;
|
delete options.app;
|
||||||
|
|
||||||
let devices: ExtendedDevice[];
|
let devices;
|
||||||
|
|
||||||
if (options.application != null) {
|
if (options.application != null) {
|
||||||
devices = await balena.models.device.getAllByApplication(
|
devices = (await balena.models.device.getAllByApplication(
|
||||||
tryAsInteger(options.application),
|
tryAsInteger(options.application),
|
||||||
expandForAppName,
|
expandForAppName,
|
||||||
);
|
)) as ExtendedDevice[];
|
||||||
} else {
|
} else {
|
||||||
devices = await balena.models.device.getAll(expandForAppName);
|
devices = (await balena.models.device.getAll(
|
||||||
|
expandForAppName,
|
||||||
|
)) as ExtendedDevice[];
|
||||||
}
|
}
|
||||||
|
|
||||||
devices = devices.map(function (device) {
|
devices = devices.map(function (device) {
|
||||||
@ -100,6 +102,9 @@ export default class DevicesCmd extends Command {
|
|||||||
: 'N/a';
|
: 'N/a';
|
||||||
|
|
||||||
device.uuid = device.uuid.slice(0, 7);
|
device.uuid = device.uuid.slice(0, 7);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
device.device_type = device.is_of__device_type[0].slug;
|
||||||
return device;
|
return device;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -76,7 +76,9 @@ export default class DevicesSupportedCmd extends Command {
|
|||||||
|
|
||||||
public async run() {
|
public async run() {
|
||||||
const { flags: options } = this.parse<FlagsDef, {}>(DevicesSupportedCmd);
|
const { flags: options } = this.parse<FlagsDef, {}>(DevicesSupportedCmd);
|
||||||
let deviceTypes: Array<Partial<SDK.DeviceType>> = await getBalenaSdk()
|
let deviceTypes: Array<Partial<
|
||||||
|
SDK.DeviceTypeJson.DeviceType
|
||||||
|
>> = await getBalenaSdk()
|
||||||
.models.config.getDeviceTypes()
|
.models.config.getDeviceTypes()
|
||||||
.map((d) => {
|
.map((d) => {
|
||||||
if (d.aliases && d.aliases.length) {
|
if (d.aliases && d.aliases.length) {
|
||||||
@ -100,7 +102,7 @@ export default class DevicesSupportedCmd extends Command {
|
|||||||
: ['slug', 'aliases', 'arch', 'name'];
|
: ['slug', 'aliases', 'arch', 'name'];
|
||||||
deviceTypes = _.sortBy(
|
deviceTypes = _.sortBy(
|
||||||
deviceTypes.map((d) => {
|
deviceTypes.map((d) => {
|
||||||
const picked = _.pick<Partial<SDK.DeviceType>>(d, fields);
|
const picked = _.pick(d, fields);
|
||||||
// 'BETA' renamed to 'NEW'
|
// 'BETA' renamed to 'NEW'
|
||||||
picked.state = picked.state === 'BETA' ? 'NEW' : picked.state;
|
picked.state = picked.state === 'BETA' ? 'NEW' : picked.state;
|
||||||
return picked;
|
return picked;
|
||||||
|
@ -317,7 +317,7 @@ async function getAppVars(
|
|||||||
appVars.push(...vars);
|
appVars.push(...vars);
|
||||||
}
|
}
|
||||||
if (!options.config && (options.service || options.all)) {
|
if (!options.config && (options.service || options.all)) {
|
||||||
const pineOpts: SDK.PineOptionsFor<SDK.ServiceEnvironmentVariable> = {
|
const pineOpts: SDK.PineOptions<SDK.ServiceEnvironmentVariable> = {
|
||||||
$expand: {
|
$expand: {
|
||||||
service: {},
|
service: {},
|
||||||
},
|
},
|
||||||
@ -359,7 +359,7 @@ async function getDeviceVars(
|
|||||||
deviceVars.push(...deviceConfigVars);
|
deviceVars.push(...deviceConfigVars);
|
||||||
} else {
|
} else {
|
||||||
if (options.service || options.all) {
|
if (options.service || options.all) {
|
||||||
const pineOpts: SDK.PineOptionsFor<SDK.DeviceServiceEnvironmentVariable> = {
|
const pineOpts: SDK.PineOptions<SDK.DeviceServiceEnvironmentVariable> = {
|
||||||
$expand: {
|
$expand: {
|
||||||
service_install: {
|
service_install: {
|
||||||
$expand: 'installs__service',
|
$expand: 'installs__service',
|
||||||
|
@ -20,7 +20,7 @@ import Command from '../../command';
|
|||||||
import * as cf from '../../utils/common-flags';
|
import * as cf from '../../utils/common-flags';
|
||||||
import { getCliForm, stripIndent } from '../../utils/lazy';
|
import { getCliForm, stripIndent } from '../../utils/lazy';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import type { DeviceType } from 'balena-sdk';
|
import type { DeviceTypeJson } from 'balena-sdk';
|
||||||
|
|
||||||
interface FlagsDef {
|
interface FlagsDef {
|
||||||
advanced: boolean;
|
advanced: boolean;
|
||||||
@ -104,7 +104,7 @@ export default class OsBuildConfigCmd extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async buildConfigForDeviceType(
|
async buildConfigForDeviceType(
|
||||||
deviceTypeManifest: DeviceType,
|
deviceTypeManifest: DeviceTypeJson.DeviceType,
|
||||||
advanced: boolean,
|
advanced: boolean,
|
||||||
) {
|
) {
|
||||||
if (advanced == null) {
|
if (advanced == null) {
|
||||||
|
@ -51,10 +51,6 @@ interface ArgsDef {
|
|||||||
image: string;
|
image: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeferredDevice extends BalenaSdk.Device {
|
|
||||||
belongs_to__application: BalenaSdk.PineDeferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Answers {
|
interface Answers {
|
||||||
appUpdatePollInterval: number; // in minutes
|
appUpdatePollInterval: number; // in minutes
|
||||||
deviceType: string; // e.g. "raspberrypi3"
|
deviceType: string; // e.g. "raspberrypi3"
|
||||||
@ -192,18 +188,29 @@ export default class OsConfigureCmd extends Command {
|
|||||||
'../../utils/config'
|
'../../utils/config'
|
||||||
);
|
);
|
||||||
const helpers = await import('../../utils/helpers');
|
const helpers = await import('../../utils/helpers');
|
||||||
let app: BalenaSdk.Application | undefined;
|
let app: ApplicationWithDeviceType | undefined;
|
||||||
let device: BalenaSdk.Device | undefined;
|
let device;
|
||||||
let deviceTypeSlug: string;
|
let deviceTypeSlug: string;
|
||||||
|
|
||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
if (options.device) {
|
if (options.device) {
|
||||||
device = await balena.models['device'].get(options.device);
|
device = (await balena.models.device.get(options.device, {
|
||||||
deviceTypeSlug = device.device_type;
|
$expand: {
|
||||||
|
is_of__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
})) as DeviceWithDeviceType & {
|
||||||
|
belongs_to__application: BalenaSdk.PineDeferred;
|
||||||
|
};
|
||||||
|
deviceTypeSlug = device.is_of__device_type[0].slug;
|
||||||
} else {
|
} else {
|
||||||
app = await balena.models['application'].get(options.application!);
|
app = (await balena.models.application.get(options.application!, {
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
})) as ApplicationWithDeviceType;
|
||||||
await checkDeviceTypeCompatibility(balena, options, app);
|
await checkDeviceTypeCompatibility(balena, options, app);
|
||||||
deviceTypeSlug = options['device-type'] || app.device_type;
|
deviceTypeSlug =
|
||||||
|
options['device-type'] || app.is_for__device_type[0].slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
const deviceTypeManifest = await helpers.getManifest(
|
const deviceTypeManifest = await helpers.getManifest(
|
||||||
@ -232,7 +239,7 @@ export default class OsConfigureCmd extends Command {
|
|||||||
if (_.isEmpty(configJson)) {
|
if (_.isEmpty(configJson)) {
|
||||||
if (device) {
|
if (device) {
|
||||||
configJson = await generateDeviceConfig(
|
configJson = await generateDeviceConfig(
|
||||||
device as DeferredDevice,
|
device,
|
||||||
options['device-api-key'],
|
options['device-api-key'],
|
||||||
answers,
|
answers,
|
||||||
);
|
);
|
||||||
@ -335,7 +342,7 @@ async function validateOptions(options: FlagsDef) {
|
|||||||
*/
|
*/
|
||||||
async function getOsVersionFromImage(
|
async function getOsVersionFromImage(
|
||||||
imagePath: string,
|
imagePath: string,
|
||||||
deviceTypeManifest: BalenaSdk.DeviceType,
|
deviceTypeManifest: BalenaSdk.DeviceTypeJson.DeviceType,
|
||||||
devInit: typeof import('balena-device-init'),
|
devInit: typeof import('balena-device-init'),
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const osVersion = await devInit.getImageOsVersion(
|
const osVersion = await devInit.getImageOsVersion(
|
||||||
@ -361,11 +368,11 @@ async function getOsVersionFromImage(
|
|||||||
async function checkDeviceTypeCompatibility(
|
async function checkDeviceTypeCompatibility(
|
||||||
sdk: BalenaSdk.BalenaSDK,
|
sdk: BalenaSdk.BalenaSDK,
|
||||||
options: FlagsDef,
|
options: FlagsDef,
|
||||||
app: BalenaSdk.Application,
|
app: ApplicationWithDeviceType,
|
||||||
) {
|
) {
|
||||||
if (options['device-type']) {
|
if (options['device-type']) {
|
||||||
const [appDeviceType, optionDeviceType] = await Promise.all([
|
const [appDeviceType, optionDeviceType] = await Promise.all([
|
||||||
sdk.models.device.getManifestBySlug(app.device_type),
|
sdk.models.device.getManifestBySlug(app.is_for__device_type[0].slug),
|
||||||
sdk.models.device.getManifestBySlug(options['device-type']),
|
sdk.models.device.getManifestBySlug(options['device-type']),
|
||||||
]);
|
]);
|
||||||
const helpers = await import('../../utils/helpers');
|
const helpers = await import('../../utils/helpers');
|
||||||
@ -392,7 +399,7 @@ async function checkDeviceTypeCompatibility(
|
|||||||
* The questions are extracted from the given deviceType "manifest".
|
* The questions are extracted from the given deviceType "manifest".
|
||||||
*/
|
*/
|
||||||
async function askQuestionsForDeviceType(
|
async function askQuestionsForDeviceType(
|
||||||
deviceType: BalenaSdk.DeviceType,
|
deviceType: BalenaSdk.DeviceTypeJson.DeviceType,
|
||||||
options: FlagsDef,
|
options: FlagsDef,
|
||||||
configJson?: import('../../utils/config').ImgConfig,
|
configJson?: import('../../utils/config').ImgConfig,
|
||||||
): Promise<Answers> {
|
): Promise<Answers> {
|
||||||
@ -460,14 +467,17 @@ async function askQuestionsForDeviceType(
|
|||||||
* [ 'network', 'wifiSsid', 'wifiKey', 'appUpdatePollInterval' ]
|
* [ 'network', 'wifiSsid', 'wifiKey', 'appUpdatePollInterval' ]
|
||||||
*/
|
*/
|
||||||
function getQuestionNames(
|
function getQuestionNames(
|
||||||
deviceType: BalenaSdk.DeviceType,
|
deviceType: BalenaSdk.DeviceTypeJson.DeviceType,
|
||||||
): Array<keyof Answers> {
|
): Array<keyof Answers> {
|
||||||
const questionNames: string[] = _.chain(deviceType.options)
|
const questionNames: string[] = _.chain(deviceType.options)
|
||||||
.flatMap(
|
.flatMap(
|
||||||
(group: BalenaSdk.DeviceTypeOptions) =>
|
(group: BalenaSdk.DeviceTypeJson.DeviceTypeOptions) =>
|
||||||
(group.isGroup && group.options) || [],
|
(group.isGroup && group.options) || [],
|
||||||
)
|
)
|
||||||
.map((groupOption: BalenaSdk.DeviceTypeOptionsGroup) => groupOption.name)
|
.map(
|
||||||
|
(groupOption: BalenaSdk.DeviceTypeJson.DeviceTypeOptionsGroup) =>
|
||||||
|
groupOption.name,
|
||||||
|
)
|
||||||
.filter()
|
.filter()
|
||||||
.value();
|
.value();
|
||||||
return questionNames as Array<keyof Answers>;
|
return questionNames as Array<keyof Answers>;
|
||||||
|
@ -20,7 +20,7 @@ import Command from '../command';
|
|||||||
import * as cf from '../utils/common-flags';
|
import * as cf from '../utils/common-flags';
|
||||||
import { getBalenaSdk, stripIndent } from '../utils/lazy';
|
import { getBalenaSdk, stripIndent } from '../utils/lazy';
|
||||||
import { dockerignoreHelp, registrySecretsHelp } from '../utils/messages';
|
import { dockerignoreHelp, registrySecretsHelp } from '../utils/messages';
|
||||||
import type { BalenaSDK } from 'balena-sdk';
|
import type { BalenaSDK, Application, Organization } from 'balena-sdk';
|
||||||
import { ExpectedError, instanceOf } from '../errors';
|
import { ExpectedError, instanceOf } from '../errors';
|
||||||
|
|
||||||
enum BuildTarget {
|
enum BuildTarget {
|
||||||
@ -362,17 +362,21 @@ export default class PushCmd extends Command {
|
|||||||
async getAppOwner(sdk: BalenaSDK, appName: string) {
|
async getAppOwner(sdk: BalenaSDK, appName: string) {
|
||||||
const _ = await import('lodash');
|
const _ = await import('lodash');
|
||||||
|
|
||||||
const applications = await sdk.models.application.getAll({
|
const applications = (await sdk.models.application.getAll({
|
||||||
$expand: {
|
$expand: {
|
||||||
user: {
|
organization: {
|
||||||
$select: ['username'],
|
$select: ['handle'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
$filter: {
|
$filter: {
|
||||||
$eq: [{ $tolower: { $: 'app_name' } }, appName.toLowerCase()],
|
$eq: [{ $tolower: { $: 'app_name' } }, appName.toLowerCase()],
|
||||||
},
|
},
|
||||||
$select: ['id'],
|
$select: ['id'],
|
||||||
});
|
})) as Array<
|
||||||
|
Application & {
|
||||||
|
organization: [Organization];
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
if (applications == null || applications.length === 0) {
|
if (applications == null || applications.length === 0) {
|
||||||
throw new ExpectedError(
|
throw new ExpectedError(
|
||||||
@ -385,7 +389,7 @@ export default class PushCmd extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (applications.length === 1) {
|
if (applications.length === 1) {
|
||||||
return _.get(applications, '[0].user[0].username');
|
return applications[0].organization[0].handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got more than one application with the same name it means that the
|
// If we got more than one application with the same name it means that the
|
||||||
@ -393,7 +397,7 @@ export default class PushCmd extends Command {
|
|||||||
// present a list to the user which shows the fully qualified application
|
// present a list to the user which shows the fully qualified application
|
||||||
// name (user/appname) and allows them to select
|
// name (user/appname) and allows them to select
|
||||||
const entries = _.map(applications, (app) => {
|
const entries = _.map(applications, (app) => {
|
||||||
const username = _.get(app, 'user[0].username');
|
const username = app.organization[0].handle;
|
||||||
return {
|
return {
|
||||||
name: `${username}/${appName}`,
|
name: `${username}/${appName}`,
|
||||||
extra: username,
|
extra: username,
|
||||||
|
@ -94,7 +94,7 @@ const deployProject = function (docker, logger, composeOpts, opts) {
|
|||||||
project.name,
|
project.name,
|
||||||
compositionToBuild,
|
compositionToBuild,
|
||||||
opts.app.arch,
|
opts.app.arch,
|
||||||
opts.app.device_type,
|
opts.app.is_for__device_type[0].slug,
|
||||||
opts.buildEmulated,
|
opts.buildEmulated,
|
||||||
opts.buildOpts,
|
opts.buildOpts,
|
||||||
composeOpts.inlineLogs,
|
composeOpts.inlineLogs,
|
||||||
|
@ -39,6 +39,9 @@ const applicationExpandOptions = {
|
|||||||
status: 'success',
|
status: 'success',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
should_be_running__release: {
|
||||||
|
$select: 'commit',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let allDeviceTypes;
|
let allDeviceTypes;
|
||||||
@ -69,11 +72,18 @@ const getApplicationsWithSuccessfulBuilds = function (deviceType) {
|
|||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
|
|
||||||
return getDeviceTypesWithSameArch(deviceType).then((deviceTypes) => {
|
return getDeviceTypesWithSameArch(deviceType).then((deviceTypes) => {
|
||||||
/** @type {import('balena-sdk').PineOptionsFor<import('balena-sdk').Application>} */
|
/** @type {import('balena-sdk').PineOptions<ApplicationWithDeviceType & { should_be_running__release: [import('balena-sdk').Release?] }>} */
|
||||||
const options = {
|
const options = {
|
||||||
$filter: {
|
$filter: {
|
||||||
device_type: {
|
is_for__device_type: {
|
||||||
$in: deviceTypes,
|
$any: {
|
||||||
|
$alias: 'dt',
|
||||||
|
$expr: {
|
||||||
|
dt: {
|
||||||
|
slug: { $in: deviceTypes },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
owns__release: {
|
owns__release: {
|
||||||
$any: {
|
$any: {
|
||||||
@ -87,13 +97,7 @@ const getApplicationsWithSuccessfulBuilds = function (deviceType) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
$expand: applicationExpandOptions,
|
$expand: applicationExpandOptions,
|
||||||
$select: [
|
$select: ['id', 'app_name', 'should_track_latest_release'],
|
||||||
'id',
|
|
||||||
'app_name',
|
|
||||||
'device_type',
|
|
||||||
'commit',
|
|
||||||
'should_track_latest_release',
|
|
||||||
],
|
|
||||||
$orderby: 'app_name asc',
|
$orderby: 'app_name asc',
|
||||||
};
|
};
|
||||||
return balena.pine.get({
|
return balena.pine.get({
|
||||||
@ -209,9 +213,10 @@ Would you like to disable automatic updates for this application now?\
|
|||||||
/**
|
/**
|
||||||
* @param {import('balena-sdk').BalenaSDK} balenaSdk
|
* @param {import('balena-sdk').BalenaSDK} balenaSdk
|
||||||
* @param {string | number} appId
|
* @param {string | number} appId
|
||||||
* @returns {Promise<import('balena-sdk').Application>}
|
* @returns {Promise<import('balena-sdk').Application & { should_be_running__release: [import('balena-sdk').Release?] }>}
|
||||||
*/
|
*/
|
||||||
async function getAppWithReleases(balenaSdk, appId) {
|
async function getAppWithReleases(balenaSdk, appId) {
|
||||||
|
// @ts-ignore
|
||||||
return balenaSdk.models.application.get(appId, {
|
return balenaSdk.models.application.get(appId, {
|
||||||
$expand: applicationExpandOptions,
|
$expand: applicationExpandOptions,
|
||||||
});
|
});
|
||||||
@ -229,10 +234,12 @@ async function prepareAndPreload(preloader, balenaSdk, options) {
|
|||||||
/** @type {string} commit hash or the strings 'latest' or 'current' */
|
/** @type {string} commit hash or the strings 'latest' or 'current' */
|
||||||
let commit;
|
let commit;
|
||||||
|
|
||||||
|
const appCommit = application.should_be_running__release[0]?.commit;
|
||||||
|
|
||||||
// Use the commit given as --commit or show an interactive commit selection menu
|
// Use the commit given as --commit or show an interactive commit selection menu
|
||||||
if (options.commit) {
|
if (options.commit) {
|
||||||
if (isCurrent(options.commit)) {
|
if (isCurrent(options.commit)) {
|
||||||
if (!application.commit) {
|
if (!appCommit) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unexpected empty commit hash for app ID "${application.id}"`,
|
`Unexpected empty commit hash for app ID "${application.id}"`,
|
||||||
);
|
);
|
||||||
@ -257,7 +264,7 @@ async function prepareAndPreload(preloader, balenaSdk, options) {
|
|||||||
|
|
||||||
await preloader.setAppIdAndCommit(
|
await preloader.setAppIdAndCommit(
|
||||||
application.id,
|
application.id,
|
||||||
isCurrent(commit) ? application.commit : commit,
|
isCurrent(commit) ? appCommit : commit,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Propose to disable automatic app updates if the commit is not the current release
|
// Propose to disable automatic app updates if the commit is not the current release
|
||||||
|
@ -92,7 +92,7 @@ export const getDeviceAndMaybeAppFromUUID = _.memoize(
|
|||||||
$expand: selectAppFields
|
$expand: selectAppFields
|
||||||
? { belongs_to__application: { $select: selectAppFields } }
|
? { belongs_to__application: { $select: selectAppFields } }
|
||||||
: 'belongs_to__application',
|
: 'belongs_to__application',
|
||||||
} as SDK.PineOptionsFor<SDK.Device>;
|
} as SDK.PineOptions<SDK.Device>;
|
||||||
if (selectDeviceFields) {
|
if (selectDeviceFields) {
|
||||||
pineOpts.$select = selectDeviceFields as any;
|
pineOpts.$select = selectDeviceFields as any;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ export async function generateApplicationConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function generateDeviceConfig(
|
export function generateDeviceConfig(
|
||||||
device: BalenaSdk.Device & {
|
device: DeviceWithDeviceType & {
|
||||||
belongs_to__application: BalenaSdk.PineDeferred;
|
belongs_to__application: BalenaSdk.PineDeferred;
|
||||||
},
|
},
|
||||||
deviceApiKey: string | true | undefined,
|
deviceApiKey: string | true | undefined,
|
||||||
@ -113,7 +113,7 @@ export function generateDeviceConfig(
|
|||||||
.then(async (application) => {
|
.then(async (application) => {
|
||||||
const baseConfigOpts = {
|
const baseConfigOpts = {
|
||||||
...options,
|
...options,
|
||||||
deviceType: device.device_type,
|
deviceType: device.is_of__device_type[0].slug,
|
||||||
};
|
};
|
||||||
const config = await generateBaseConfig(application, baseConfigOpts);
|
const config = await generateBaseConfig(application, baseConfigOpts);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import * as _ from 'lodash';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import type * as ShellEscape from 'shell-escape';
|
import type * as ShellEscape from 'shell-escape';
|
||||||
|
|
||||||
import type { Device, PineOptionsFor } from 'balena-sdk';
|
import type { Device, PineOptions } from 'balena-sdk';
|
||||||
import { ExpectedError } from '../errors';
|
import { ExpectedError } from '../errors';
|
||||||
import { getBalenaSdk, getChalk, getVisuals } from './lazy';
|
import { getBalenaSdk, getChalk, getVisuals } from './lazy';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
@ -121,7 +121,7 @@ export function runCommand<T>(commandArgs: string[]): Promise<T> {
|
|||||||
export async function getManifest(
|
export async function getManifest(
|
||||||
image: string,
|
image: string,
|
||||||
deviceType: string,
|
deviceType: string,
|
||||||
): Promise<BalenaSdk.DeviceType> {
|
): Promise<BalenaSdk.DeviceTypeJson.DeviceType> {
|
||||||
const init = await import('balena-device-init');
|
const init = await import('balena-device-init');
|
||||||
const manifest = await init.getImageManifest(image);
|
const manifest = await init.getImageManifest(image);
|
||||||
if (manifest != null) {
|
if (manifest != null) {
|
||||||
@ -131,8 +131,8 @@ export async function getManifest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const areDeviceTypesCompatible = (
|
export const areDeviceTypesCompatible = (
|
||||||
appDeviceType: BalenaSdk.DeviceType,
|
appDeviceType: BalenaSdk.DeviceTypeJson.DeviceType,
|
||||||
osDeviceType: BalenaSdk.DeviceType,
|
osDeviceType: BalenaSdk.DeviceTypeJson.DeviceType,
|
||||||
) =>
|
) =>
|
||||||
getBalenaSdk().models.os.isArchitectureCompatibleWith(
|
getBalenaSdk().models.os.isArchitectureCompatibleWith(
|
||||||
osDeviceType.arch,
|
osDeviceType.arch,
|
||||||
@ -166,13 +166,13 @@ export async function osProgressHandler(step: InitializeEmitter) {
|
|||||||
|
|
||||||
export function getAppWithArch(
|
export function getAppWithArch(
|
||||||
applicationName: string,
|
applicationName: string,
|
||||||
): Promise<BalenaSdk.Application & { arch: string }> {
|
): Promise<ApplicationWithDeviceType & { arch: string }> {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
getApplication(applicationName),
|
getApplication(applicationName),
|
||||||
getBalenaSdk().models.config.getDeviceTypes(),
|
getBalenaSdk().models.config.getDeviceTypes(),
|
||||||
]).then(function ([app, deviceTypes]) {
|
]).then(function ([app, deviceTypes]) {
|
||||||
const config = _.find<BalenaSdk.DeviceType>(deviceTypes, {
|
const config = _.find<BalenaSdk.DeviceTypeJson.DeviceType>(deviceTypes, {
|
||||||
slug: app.device_type,
|
slug: app.is_for__device_type[0].slug,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
@ -183,16 +183,21 @@ export function getAppWithArch(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getApplication(applicationName: string) {
|
function getApplication(
|
||||||
|
applicationName: string,
|
||||||
|
): Promise<ApplicationWithDeviceType> {
|
||||||
// Check for an app of the form `user/application`, and send
|
// Check for an app of the form `user/application`, and send
|
||||||
// that off to a special handler (before importing any modules)
|
// that off to a special handler (before importing any modules)
|
||||||
const match = applicationName.split('/');
|
const match = applicationName.split('/');
|
||||||
|
|
||||||
const extraOptions: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {
|
const extraOptions: BalenaSdk.PineOptions<BalenaSdk.Application> = {
|
||||||
$expand: {
|
$expand: {
|
||||||
application_type: {
|
application_type: {
|
||||||
$select: ['name', 'slug', 'supports_multicontainer', 'is_legacy'],
|
$select: ['name', 'slug', 'supports_multicontainer', 'is_legacy'],
|
||||||
},
|
},
|
||||||
|
is_for__device_type: {
|
||||||
|
$select: 'slug',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -487,6 +492,10 @@ export function getProxyConfig(): ProxyConfig | undefined {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const expandForAppName: PineOptionsFor<Device> = {
|
export const expandForAppName: PineOptions<Device> = {
|
||||||
$expand: { belongs_to__application: { $select: 'app_name' } },
|
$expand: {
|
||||||
|
belongs_to__application: { $select: 'app_name' },
|
||||||
|
is_of__device_type: { $select: 'slug' },
|
||||||
|
is_running__release: { $select: 'commit' },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -168,7 +168,7 @@ export async function confirm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function selectApplication(
|
export function selectApplication(
|
||||||
filter?: (app: BalenaSdk.Application) => boolean,
|
filter?: (app: ApplicationWithDeviceType) => boolean,
|
||||||
errorOnEmptySelection = false,
|
errorOnEmptySelection = false,
|
||||||
) {
|
) {
|
||||||
const balena = getBalenaSdk();
|
const balena = getBalenaSdk();
|
||||||
@ -179,7 +179,7 @@ export function selectApplication(
|
|||||||
throw new ExpectedError("You don't have any applications");
|
throw new ExpectedError("You don't have any applications");
|
||||||
}
|
}
|
||||||
|
|
||||||
return balena.models.application.getAll();
|
return balena.models.application.getAll() as Promise<ApplicationWithDeviceType[]>;
|
||||||
})
|
})
|
||||||
.filter(filter || _.constant(true))
|
.filter(filter || _.constant(true))
|
||||||
.then((applications) => {
|
.then((applications) => {
|
||||||
@ -190,7 +190,7 @@ export function selectApplication(
|
|||||||
message: 'Select an application',
|
message: 'Select an application',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
choices: _.map(applications, (application) => ({
|
choices: _.map(applications, (application) => ({
|
||||||
name: `${application.app_name} (${application.device_type})`,
|
name: `${application.app_name} (${application.is_for__device_type[0].slug})`,
|
||||||
value: application.app_name,
|
value: application.app_name,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
@ -207,14 +207,20 @@ export function selectOrCreateApplication() {
|
|||||||
return Promise.resolve(undefined);
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
return balena.models.application.getAll().then((applications) => {
|
return (balena.models.application.getAll({
|
||||||
const appOptions = _.map<
|
$expand: {
|
||||||
BalenaSdk.Application,
|
is_for__device_type: {
|
||||||
{ name: string; value: string | null }
|
$select: 'slug',
|
||||||
>(applications, (application) => ({
|
},
|
||||||
name: `${application.app_name} (${application.device_type})`,
|
},
|
||||||
|
}) as Promise<ApplicationWithDeviceType[]>).then((applications) => {
|
||||||
|
const appOptions: Array<{ name: string; value: string | null }> = _.map(
|
||||||
|
applications,
|
||||||
|
(application) => ({
|
||||||
|
name: `${application.app_name} (${application.is_for__device_type[0].slug})`,
|
||||||
value: application.app_name,
|
value: application.app_name,
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
appOptions.unshift({
|
appOptions.unshift({
|
||||||
name: 'Create a new application',
|
name: 'Create a new application',
|
||||||
|
@ -40,10 +40,12 @@ export async function join(
|
|||||||
|
|
||||||
logger.logDebug('Determining application...');
|
logger.logDebug('Determining application...');
|
||||||
const app = await getOrSelectApplication(sdk, deviceType, appName);
|
const app = await getOrSelectApplication(sdk, deviceType, appName);
|
||||||
logger.logDebug(`Using application: ${app.app_name} (${app.device_type})`);
|
logger.logDebug(
|
||||||
if (app.device_type !== deviceType) {
|
`Using application: ${app.app_name} (${app.is_for__device_type[0].slug})`,
|
||||||
|
);
|
||||||
|
if (app.is_for__device_type[0].slug !== deviceType) {
|
||||||
logger.logDebug(`Forcing device type to: ${deviceType}`);
|
logger.logDebug(`Forcing device type to: ${deviceType}`);
|
||||||
app.device_type = deviceType;
|
app.is_for__device_type[0].slug = deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.logDebug('Determining device OS version...');
|
logger.logDebug('Determining device OS version...');
|
||||||
@ -186,7 +188,9 @@ async function getOrSelectLocalDevice(deviceIp?: string): Promise<string> {
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectAppFromList(applications: BalenaSdk.Application[]) {
|
async function selectAppFromList(
|
||||||
|
applications: ApplicationWithDeviceType[],
|
||||||
|
): Promise<ApplicationWithDeviceType> {
|
||||||
const _ = await import('lodash');
|
const _ = await import('lodash');
|
||||||
const { selectFromList } = await import('../utils/patterns');
|
const { selectFromList } = await import('../utils/patterns');
|
||||||
|
|
||||||
@ -204,7 +208,7 @@ async function getOrSelectApplication(
|
|||||||
sdk: BalenaSdk.BalenaSDK,
|
sdk: BalenaSdk.BalenaSDK,
|
||||||
deviceType: string,
|
deviceType: string,
|
||||||
appName?: string,
|
appName?: string,
|
||||||
): Promise<BalenaSdk.Application> {
|
): Promise<ApplicationWithDeviceType> {
|
||||||
const _ = await import('lodash');
|
const _ = await import('lodash');
|
||||||
|
|
||||||
const allDeviceTypes = await sdk.models.config.getDeviceTypes();
|
const allDeviceTypes = await sdk.models.config.getDeviceTypes();
|
||||||
@ -229,7 +233,11 @@ async function getOrSelectApplication(
|
|||||||
return createOrSelectAppOrExit(sdk, compatibleDeviceTypes, deviceType);
|
return createOrSelectAppOrExit(sdk, compatibleDeviceTypes, deviceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: BalenaSdk.PineOptionsFor<BalenaSdk.Application> = {};
|
const options: BalenaSdk.PineOptions<BalenaSdk.Application> = {
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Check for an app of the form `user/application` and update the API query.
|
// Check for an app of the form `user/application` and update the API query.
|
||||||
let name: string;
|
let name: string;
|
||||||
@ -245,7 +253,9 @@ async function getOrSelectApplication(
|
|||||||
name = appName;
|
name = appName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const applications = await sdk.models.application.getAll(options);
|
const applications = (await sdk.models.application.getAll(
|
||||||
|
options,
|
||||||
|
)) as ApplicationWithDeviceType[];
|
||||||
|
|
||||||
if (applications.length === 0) {
|
if (applications.length === 0) {
|
||||||
const shouldCreateApp = await getCliForm().ask({
|
const shouldCreateApp = await getCliForm().ask({
|
||||||
@ -264,7 +274,7 @@ async function getOrSelectApplication(
|
|||||||
// We've found at least one app with the given name.
|
// We've found at least one app with the given name.
|
||||||
// Filter out apps for non-matching device types and see what we're left with.
|
// Filter out apps for non-matching device types and see what we're left with.
|
||||||
const validApplications = applications.filter((app) =>
|
const validApplications = applications.filter((app) =>
|
||||||
_.includes(compatibleDeviceTypes, app.device_type),
|
_.includes(compatibleDeviceTypes, app.is_for__device_type[0].slug),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (validApplications.length === 0) {
|
if (validApplications.length === 0) {
|
||||||
@ -285,13 +295,19 @@ async function createOrSelectAppOrExit(
|
|||||||
sdk: BalenaSdk.BalenaSDK,
|
sdk: BalenaSdk.BalenaSDK,
|
||||||
compatibleDeviceTypes: string[],
|
compatibleDeviceTypes: string[],
|
||||||
deviceType: string,
|
deviceType: string,
|
||||||
) {
|
): Promise<ApplicationWithDeviceType> {
|
||||||
const options = {
|
|
||||||
$filter: { device_type: { $in: compatibleDeviceTypes } },
|
|
||||||
};
|
|
||||||
|
|
||||||
// No application specified, show a list to select one.
|
// No application specified, show a list to select one.
|
||||||
const applications = await sdk.models.application.getAll(options);
|
const applications = (await sdk.models.application.getAll({
|
||||||
|
$expand: { is_for__device_type: { $select: 'slug' } },
|
||||||
|
$filter: {
|
||||||
|
is_for__device_type: {
|
||||||
|
$any: {
|
||||||
|
$alias: 'dt',
|
||||||
|
$expr: { dt: { slug: { $in: compatibleDeviceTypes } } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})) as ApplicationWithDeviceType[];
|
||||||
|
|
||||||
if (applications.length === 0) {
|
if (applications.length === 0) {
|
||||||
const shouldCreateApp = await getCliForm().ask({
|
const shouldCreateApp = await getCliForm().ask({
|
||||||
@ -314,14 +330,13 @@ async function createApplication(
|
|||||||
sdk: BalenaSdk.BalenaSDK,
|
sdk: BalenaSdk.BalenaSDK,
|
||||||
deviceType: string,
|
deviceType: string,
|
||||||
name?: string,
|
name?: string,
|
||||||
): Promise<BalenaSdk.Application> {
|
): Promise<ApplicationWithDeviceType> {
|
||||||
const validation = await import('./validation');
|
const validation = await import('./validation');
|
||||||
|
|
||||||
let username = await sdk.auth.whoami();
|
const username = await sdk.auth.whoami();
|
||||||
if (!username) {
|
if (!username) {
|
||||||
throw new sdk.errors.BalenaNotLoggedIn();
|
throw new sdk.errors.BalenaNotLoggedIn();
|
||||||
}
|
}
|
||||||
username = username.toLowerCase();
|
|
||||||
|
|
||||||
const applicationName = await new Promise<string>(async (resolve, reject) => {
|
const applicationName = await new Promise<string>(async (resolve, reject) => {
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -337,7 +352,7 @@ async function createApplication(
|
|||||||
await sdk.models.application.get(appName, {
|
await sdk.models.application.get(appName, {
|
||||||
$filter: {
|
$filter: {
|
||||||
$or: [
|
$or: [
|
||||||
{ slug: { $startswith: `${username}/` } },
|
{ slug: { $startswith: `${username!.toLowerCase()}/` } },
|
||||||
{ $not: { slug: { $contains: '/' } } },
|
{ $not: { slug: { $contains: '/' } } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -357,20 +372,28 @@ async function createApplication(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return sdk.models.application.create({
|
const app = await sdk.models.application.create({
|
||||||
name: applicationName,
|
name: applicationName,
|
||||||
deviceType,
|
deviceType,
|
||||||
|
organization: username,
|
||||||
});
|
});
|
||||||
|
return (await sdk.models.application.get(app.id, {
|
||||||
|
$expand: {
|
||||||
|
is_for__device_type: { $select: 'slug' },
|
||||||
|
},
|
||||||
|
})) as ApplicationWithDeviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateApplicationConfig(
|
async function generateApplicationConfig(
|
||||||
sdk: BalenaSdk.BalenaSDK,
|
sdk: BalenaSdk.BalenaSDK,
|
||||||
app: BalenaSdk.Application,
|
app: ApplicationWithDeviceType,
|
||||||
options: { version: string },
|
options: { version: string },
|
||||||
) {
|
) {
|
||||||
const { generateApplicationConfig: configGen } = await import('./config');
|
const { generateApplicationConfig: configGen } = await import('./config');
|
||||||
|
|
||||||
const manifest = await sdk.models.device.getManifestBySlug(app.device_type);
|
const manifest = await sdk.models.device.getManifestBySlug(
|
||||||
|
app.is_for__device_type[0].slug,
|
||||||
|
);
|
||||||
const opts =
|
const opts =
|
||||||
manifest.options &&
|
manifest.options &&
|
||||||
manifest.options.filter((opt) => opt.name !== 'network');
|
manifest.options.filter((opt) => opt.name !== 'network');
|
||||||
|
165
npm-shrinkwrap.json
generated
165
npm-shrinkwrap.json
generated
@ -2243,44 +2243,6 @@
|
|||||||
"resin-image-fs": "^5.0.9"
|
"resin-image-fs": "^5.0.9"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balena-sdk": {
|
|
||||||
"version": "14.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-14.1.0.tgz",
|
|
||||||
"integrity": "sha512-J/T1F3zQI6GChK0zZp5YKdNhBSynx3VaXk7tGcGykNnLuN4ZVeApHPZ7vVLUuyN/hvckax55iKSPO5JSEYA0sg==",
|
|
||||||
"requires": {
|
|
||||||
"@balena/es-version": "^1.0.0",
|
|
||||||
"@types/bluebird": "^3.5.30",
|
|
||||||
"@types/lodash": "^4.14.150",
|
|
||||||
"@types/memoizee": "^0.4.3",
|
|
||||||
"@types/node": "^10.17.20",
|
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
|
||||||
"balena-auth": "^3.1.0",
|
|
||||||
"balena-errors": "^4.4.0",
|
|
||||||
"balena-hup-action-utils": "~4.0.1",
|
|
||||||
"balena-pine": "^11.2.0",
|
|
||||||
"balena-register-device": "^6.1.1",
|
|
||||||
"balena-request": "^10.0.9",
|
|
||||||
"balena-semver": "^2.3.0",
|
|
||||||
"balena-settings-client": "^4.0.4",
|
|
||||||
"bluebird": "^3.7.2",
|
|
||||||
"lodash": "^4.17.15",
|
|
||||||
"memoizee": "^0.4.14",
|
|
||||||
"moment": "~2.24.0 || ^2.25.1",
|
|
||||||
"ndjson": "^1.5.0",
|
|
||||||
"semver": "^7.3.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"balena-errors": {
|
|
||||||
"version": "4.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-errors/-/balena-errors-4.4.0.tgz",
|
|
||||||
"integrity": "sha512-w5Zje97Gl0veNKpAhH4OQ3R7ACt0MYNUBfb37o1/Yq7EeeB7HsVFsvXNhZwBn8DIBvJamxZWSIbqjw53GKjUzQ==",
|
|
||||||
"requires": {
|
|
||||||
"tslib": "^1.11.1",
|
|
||||||
"typed-error": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balena-semver": {
|
"balena-semver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
||||||
@ -2354,44 +2316,6 @@
|
|||||||
"rimraf": "^3.0.2"
|
"rimraf": "^3.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balena-sdk": {
|
|
||||||
"version": "14.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-14.1.0.tgz",
|
|
||||||
"integrity": "sha512-J/T1F3zQI6GChK0zZp5YKdNhBSynx3VaXk7tGcGykNnLuN4ZVeApHPZ7vVLUuyN/hvckax55iKSPO5JSEYA0sg==",
|
|
||||||
"requires": {
|
|
||||||
"@balena/es-version": "^1.0.0",
|
|
||||||
"@types/bluebird": "^3.5.30",
|
|
||||||
"@types/lodash": "^4.14.150",
|
|
||||||
"@types/memoizee": "^0.4.3",
|
|
||||||
"@types/node": "^10.17.20",
|
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
|
||||||
"balena-auth": "^3.1.0",
|
|
||||||
"balena-errors": "^4.4.0",
|
|
||||||
"balena-hup-action-utils": "~4.0.1",
|
|
||||||
"balena-pine": "^11.2.0",
|
|
||||||
"balena-register-device": "^6.1.1",
|
|
||||||
"balena-request": "^10.0.9",
|
|
||||||
"balena-semver": "^2.3.0",
|
|
||||||
"balena-settings-client": "^4.0.4",
|
|
||||||
"bluebird": "^3.7.2",
|
|
||||||
"lodash": "^4.17.15",
|
|
||||||
"memoizee": "^0.4.14",
|
|
||||||
"moment": "~2.24.0 || ^2.25.1",
|
|
||||||
"ndjson": "^1.5.0",
|
|
||||||
"semver": "^7.3.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"balena-errors": {
|
|
||||||
"version": "4.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-errors/-/balena-errors-4.4.0.tgz",
|
|
||||||
"integrity": "sha512-w5Zje97Gl0veNKpAhH4OQ3R7ACt0MYNUBfb37o1/Yq7EeeB7HsVFsvXNhZwBn8DIBvJamxZWSIbqjw53GKjUzQ==",
|
|
||||||
"requires": {
|
|
||||||
"tslib": "^1.11.1",
|
|
||||||
"typed-error": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balena-semver": {
|
"balena-semver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
||||||
@ -2474,34 +2398,6 @@
|
|||||||
"typed-error": "^3.0.0"
|
"typed-error": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-sdk": {
|
|
||||||
"version": "14.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-14.8.0.tgz",
|
|
||||||
"integrity": "sha512-GptB/Ju8BtE1E9NODHioScdF4HW8svcDhfdMHPrDjMFWbs38KOoTgiKogDjLlvEjoAg5FIvz8DaUeH27EtZ1Rg==",
|
|
||||||
"requires": {
|
|
||||||
"@balena/es-version": "^1.0.0",
|
|
||||||
"@types/bluebird": "^3.5.30",
|
|
||||||
"@types/lodash": "^4.14.150",
|
|
||||||
"@types/memoizee": "^0.4.3",
|
|
||||||
"@types/node": "^10.17.20",
|
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
|
||||||
"balena-auth": "^3.1.0",
|
|
||||||
"balena-errors": "^4.4.0",
|
|
||||||
"balena-hup-action-utils": "~4.0.1",
|
|
||||||
"balena-pine": "^11.2.0",
|
|
||||||
"balena-register-device": "^6.1.1",
|
|
||||||
"balena-request": "^10.0.9",
|
|
||||||
"balena-semver": "^2.3.0",
|
|
||||||
"balena-settings-client": "^4.0.4",
|
|
||||||
"bluebird": "^3.7.2",
|
|
||||||
"lodash": "^4.17.15",
|
|
||||||
"memoizee": "^0.4.14",
|
|
||||||
"moment": "~2.24.0 || ^2.25.1",
|
|
||||||
"ndjson": "^1.5.0",
|
|
||||||
"semver": "^7.3.2",
|
|
||||||
"tslib": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balena-semver": {
|
"balena-semver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
||||||
@ -2638,19 +2534,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-sdk": {
|
"balena-sdk": {
|
||||||
"version": "13.8.0",
|
"version": "14.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-13.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-14.8.0.tgz",
|
||||||
"integrity": "sha512-EhaXZq7kNCewhp0oSMeeTslvRIhvaV0QxlS7u3SWmdMoDjH1gdg01sG2I3b20DkN8oDAIoNkaD14eo2eTf0C8w==",
|
"integrity": "sha512-GptB/Ju8BtE1E9NODHioScdF4HW8svcDhfdMHPrDjMFWbs38KOoTgiKogDjLlvEjoAg5FIvz8DaUeH27EtZ1Rg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@balena/es-version": "^1.0.0",
|
||||||
"@types/bluebird": "^3.5.30",
|
"@types/bluebird": "^3.5.30",
|
||||||
"@types/lodash": "^4.14.150",
|
"@types/lodash": "^4.14.150",
|
||||||
"@types/memoizee": "^0.4.3",
|
"@types/memoizee": "^0.4.3",
|
||||||
"@types/node": "^10.17.20",
|
"@types/node": "^10.17.20",
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
"abortcontroller-polyfill": "^1.4.0",
|
||||||
"balena-auth": "^3.0.1",
|
"balena-auth": "^3.1.0",
|
||||||
"balena-errors": "^4.4.0",
|
"balena-errors": "^4.4.0",
|
||||||
"balena-hup-action-utils": "~4.0.1",
|
"balena-hup-action-utils": "~4.0.1",
|
||||||
"balena-pine": "^11.0.1",
|
"balena-pine": "^11.2.0",
|
||||||
"balena-register-device": "^6.1.1",
|
"balena-register-device": "^6.1.1",
|
||||||
"balena-request": "^10.0.9",
|
"balena-request": "^10.0.9",
|
||||||
"balena-semver": "^2.3.0",
|
"balena-semver": "^2.3.0",
|
||||||
@ -2660,15 +2557,16 @@
|
|||||||
"memoizee": "^0.4.14",
|
"memoizee": "^0.4.14",
|
||||||
"moment": "~2.24.0 || ^2.25.1",
|
"moment": "~2.24.0 || ^2.25.1",
|
||||||
"ndjson": "^1.5.0",
|
"ndjson": "^1.5.0",
|
||||||
"semver": "^7.3.2"
|
"semver": "^7.3.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balena-errors": {
|
"balena-errors": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/balena-errors/-/balena-errors-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-errors/-/balena-errors-4.4.1.tgz",
|
||||||
"integrity": "sha512-w5Zje97Gl0veNKpAhH4OQ3R7ACt0MYNUBfb37o1/Yq7EeeB7HsVFsvXNhZwBn8DIBvJamxZWSIbqjw53GKjUzQ==",
|
"integrity": "sha512-912lPp1LyBjkpxRg6m/EpOCssqMhgkzyYbrKwtT2uRvixm89WOlJrj5sPkxnbPnp5IoMNaoRONxFt1jtiQf50Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^1.11.1",
|
"tslib": "^2.0.0",
|
||||||
"typed-error": "^3.0.0"
|
"typed-error": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2689,9 +2587,9 @@
|
|||||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
|
||||||
},
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.13.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
|
||||||
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q=="
|
"integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2794,33 +2692,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-sdk": {
|
|
||||||
"version": "14.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-14.1.0.tgz",
|
|
||||||
"integrity": "sha512-J/T1F3zQI6GChK0zZp5YKdNhBSynx3VaXk7tGcGykNnLuN4ZVeApHPZ7vVLUuyN/hvckax55iKSPO5JSEYA0sg==",
|
|
||||||
"requires": {
|
|
||||||
"@balena/es-version": "^1.0.0",
|
|
||||||
"@types/bluebird": "^3.5.30",
|
|
||||||
"@types/lodash": "^4.14.150",
|
|
||||||
"@types/memoizee": "^0.4.3",
|
|
||||||
"@types/node": "^10.17.20",
|
|
||||||
"abortcontroller-polyfill": "^1.4.0",
|
|
||||||
"balena-auth": "^3.1.0",
|
|
||||||
"balena-errors": "^4.4.0",
|
|
||||||
"balena-hup-action-utils": "~4.0.1",
|
|
||||||
"balena-pine": "^11.2.0",
|
|
||||||
"balena-register-device": "^6.1.1",
|
|
||||||
"balena-request": "^10.0.9",
|
|
||||||
"balena-semver": "^2.3.0",
|
|
||||||
"balena-settings-client": "^4.0.4",
|
|
||||||
"bluebird": "^3.7.2",
|
|
||||||
"lodash": "^4.17.15",
|
|
||||||
"memoizee": "^0.4.14",
|
|
||||||
"moment": "~2.24.0 || ^2.25.1",
|
|
||||||
"ndjson": "^1.5.0",
|
|
||||||
"semver": "^7.3.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balena-semver": {
|
"balena-semver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/balena-semver/-/balena-semver-2.3.0.tgz",
|
||||||
@ -12604,9 +12475,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ref-napi": {
|
"ref-napi": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-2.0.4.tgz",
|
||||||
"integrity": "sha512-zsAhPhh9gUlk0pP5iR9nhvwFeC/E9G1X0cdH/qQRTwx3VDgVi40Aflq/EdbobcVg++RNaMxZsbaQV+/E2u57LQ==",
|
"integrity": "sha512-Ees+O+abgS4skRDU/RyICk9gbSaVjYCN1FXivAlcxdj/yW9N+GFKbB9fYACa+lgBjjqjSGHw5SkoP5GU0anwwQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"pkg": {
|
"pkg": {
|
||||||
"scripts": [
|
"scripts": [
|
||||||
"build/**/*.js",
|
"build/**/*.js",
|
||||||
|
"node_modules/balena-sdk/es2018/index.js",
|
||||||
"node_modules/balena-sync/build/capitano/*.js",
|
"node_modules/balena-sync/build/capitano/*.js",
|
||||||
"node_modules/balena-sync/build/sync/*.js",
|
"node_modules/balena-sync/build/sync/*.js",
|
||||||
"node_modules/pinejs-client-request/node_modules/pinejs-client-core/es2018/index.js",
|
"node_modules/pinejs-client-request/node_modules/pinejs-client-core/es2018/index.js",
|
||||||
@ -192,7 +193,7 @@
|
|||||||
"balena-image-manager": "^7.0.1",
|
"balena-image-manager": "^7.0.1",
|
||||||
"balena-preload": "^10.2.0",
|
"balena-preload": "^10.2.0",
|
||||||
"balena-release": "^3.0.0",
|
"balena-release": "^3.0.0",
|
||||||
"balena-sdk": "^13.6.0",
|
"balena-sdk": "^14.8.0",
|
||||||
"balena-semver": "^2.2.0",
|
"balena-semver": "^2.2.0",
|
||||||
"balena-settings-client": "^4.0.5",
|
"balena-settings-client": "^4.0.5",
|
||||||
"balena-settings-storage": "^6.0.0",
|
"balena-settings-storage": "^6.0.0",
|
||||||
|
@ -35,26 +35,6 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
notFound = false,
|
notFound = false,
|
||||||
optional = false,
|
optional = false,
|
||||||
persist = false,
|
persist = false,
|
||||||
} = {}) {
|
|
||||||
const interceptor = this.optGet(/^\/v5\/application($|[(?])/, {
|
|
||||||
optional,
|
|
||||||
persist,
|
|
||||||
});
|
|
||||||
if (notFound) {
|
|
||||||
interceptor.reply(200, { d: [] });
|
|
||||||
} else {
|
|
||||||
interceptor.replyWithFile(
|
|
||||||
200,
|
|
||||||
path.join(apiResponsePath, 'application-GET-v5-expanded-app-type.json'),
|
|
||||||
jHeader,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public expectGetApplicationV6({
|
|
||||||
notFound = false,
|
|
||||||
optional = false,
|
|
||||||
persist = false,
|
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const interceptor = this.optGet(/^\/v6\/application($|[(?])/, {
|
const interceptor = this.optGet(/^\/v6\/application($|[(?])/, {
|
||||||
optional,
|
optional,
|
||||||
@ -99,10 +79,10 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public expectGetMyApplication(opts: ScopeOpts = {}) {
|
public expectGetMyApplication(opts: ScopeOpts = {}) {
|
||||||
this.optGet(/^\/v5\/my_application($|[(?])/, opts).reply(
|
this.optGet(/^\/v6\/my_application($|[(?])/, opts).reply(
|
||||||
200,
|
200,
|
||||||
JSON.parse(`{"d": [{
|
JSON.parse(`{"d": [{
|
||||||
"user": [{ "username": "bob", "__metadata": {} }],
|
"organization": [{ "handle": "bob", "__metadata": {} }],
|
||||||
"id": 1301645,
|
"id": 1301645,
|
||||||
"__metadata": { "uri": "/resin/my_application(@id)?@id=1301645" }}]}
|
"__metadata": { "uri": "/resin/my_application(@id)?@id=1301645" }}]}
|
||||||
`),
|
`),
|
||||||
@ -116,13 +96,16 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public expectGetRelease(opts: ScopeOpts = {}) {
|
public expectGetRelease(opts: ScopeOpts = {}) {
|
||||||
this.optGet(/^\/v5\/release($|[(?])/, opts).replyWithFile(
|
this.optGet(/^\/v6\/release($|[(?])/, opts).replyWithFile(
|
||||||
200,
|
200,
|
||||||
path.join(apiResponsePath, 'release-GET-v5.json'),
|
path.join(apiResponsePath, 'release-GET-v6.json'),
|
||||||
jHeader,
|
jHeader,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPatchRelease({
|
public expectPatchRelease({
|
||||||
replyBody = 'OK',
|
replyBody = 'OK',
|
||||||
statusCode = 200,
|
statusCode = 200,
|
||||||
@ -136,6 +119,9 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPostRelease(opts: ScopeOpts = {}) {
|
public expectPostRelease(opts: ScopeOpts = {}) {
|
||||||
this.optPost(/^\/v6\/release($|[(?])/, opts).replyWithFile(
|
this.optPost(/^\/v6\/release($|[(?])/, opts).replyWithFile(
|
||||||
200,
|
200,
|
||||||
@ -144,6 +130,9 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPatchImage({
|
public expectPatchImage({
|
||||||
replyBody = 'OK',
|
replyBody = 'OK',
|
||||||
statusCode = 200,
|
statusCode = 200,
|
||||||
@ -157,6 +146,9 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPostImage(opts: ScopeOpts = {}) {
|
public expectPostImage(opts: ScopeOpts = {}) {
|
||||||
this.optPost(/^\/v6\/image($|[(?])/, opts).replyWithFile(
|
this.optPost(/^\/v6\/image($|[(?])/, opts).replyWithFile(
|
||||||
201,
|
201,
|
||||||
@ -165,6 +157,9 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPostImageLabel(opts: ScopeOpts = {}) {
|
public expectPostImageLabel(opts: ScopeOpts = {}) {
|
||||||
this.optPost(/^\/v6\/image_label($|[(?])/, opts).replyWithFile(
|
this.optPost(/^\/v6\/image_label($|[(?])/, opts).replyWithFile(
|
||||||
201,
|
201,
|
||||||
@ -173,6 +168,9 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectPostImageIsPartOfRelease(opts: ScopeOpts = {}) {
|
public expectPostImageIsPartOfRelease(opts: ScopeOpts = {}) {
|
||||||
this.optPost(
|
this.optPost(
|
||||||
/^\/v6\/image__is_part_of__release($|[(?])/,
|
/^\/v6\/image__is_part_of__release($|[(?])/,
|
||||||
@ -350,23 +348,10 @@ export class BalenaAPIMock extends NockMock {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks balena-release call
|
||||||
|
*/
|
||||||
public expectGetUser(opts: ScopeOpts = {}) {
|
public expectGetUser(opts: ScopeOpts = {}) {
|
||||||
this.optGet(/^\/v5\/user/, opts).reply(200, {
|
|
||||||
d: [
|
|
||||||
{
|
|
||||||
id: 99999,
|
|
||||||
actor: 1234567,
|
|
||||||
username: 'gh_user',
|
|
||||||
created_at: '2018-08-19T13:55:04.485Z',
|
|
||||||
__metadata: {
|
|
||||||
uri: '/resin/user(@id)?@id=43699',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public expectGetUserV6(opts: ScopeOpts = {}) {
|
|
||||||
this.optGet(/^\/v6\/user/, opts).reply(200, {
|
this.optGet(/^\/v6\/user/, opts).reply(200, {
|
||||||
d: [
|
d: [
|
||||||
{
|
{
|
||||||
|
@ -80,10 +80,9 @@ describe('balena deploy', function () {
|
|||||||
api.expectGetMixpanel({ optional: true });
|
api.expectGetMixpanel({ optional: true });
|
||||||
api.expectGetDeviceTypes();
|
api.expectGetDeviceTypes();
|
||||||
api.expectGetApplication();
|
api.expectGetApplication();
|
||||||
api.expectGetApplicationV6();
|
|
||||||
api.expectPostRelease();
|
api.expectPostRelease();
|
||||||
api.expectGetRelease();
|
api.expectGetRelease();
|
||||||
api.expectGetUserV6();
|
api.expectGetUser();
|
||||||
api.expectGetService({ serviceName: 'main' });
|
api.expectGetService({ serviceName: 'main' });
|
||||||
api.expectPostService409();
|
api.expectPostService409();
|
||||||
api.expectGetAuth();
|
api.expectGetAuth();
|
||||||
|
@ -74,7 +74,7 @@ describe('balena device', function () {
|
|||||||
it('should list device details for provided uuid', async () => {
|
it('should list device details for provided uuid', async () => {
|
||||||
api.scope
|
api.scope
|
||||||
.get(
|
.get(
|
||||||
/^\/v5\/device\?.+&\$expand=belongs_to__application\(\$select=app_name\)/,
|
/^\/v6\/device\?.+&\$expand=belongs_to__application\(\$select=app_name\)/,
|
||||||
)
|
)
|
||||||
.replyWithFile(200, path.join(apiResponsePath, 'device.json'), {
|
.replyWithFile(200, path.join(apiResponsePath, 'device.json'), {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -96,7 +96,7 @@ describe('balena device', function () {
|
|||||||
// e.g. When user has a device associated with app that user is no longer a collaborator of.
|
// e.g. When user has a device associated with app that user is no longer a collaborator of.
|
||||||
api.scope
|
api.scope
|
||||||
.get(
|
.get(
|
||||||
/^\/v5\/device\?.+&\$expand=belongs_to__application\(\$select=app_name\)/,
|
/^\/v6\/device\?.+&\$expand=belongs_to__application\(\$select=app_name\)/,
|
||||||
)
|
)
|
||||||
.replyWithFile(
|
.replyWithFile(
|
||||||
200,
|
200,
|
||||||
|
@ -75,7 +75,7 @@ describe('balena devices', function () {
|
|||||||
it('should list devices from own and collaborator apps', async () => {
|
it('should list devices from own and collaborator apps', async () => {
|
||||||
api.scope
|
api.scope
|
||||||
.get(
|
.get(
|
||||||
'/v5/device?$orderby=device_name%20asc&$expand=belongs_to__application($select=app_name)',
|
'/v6/device?$orderby=device_name%20asc&$expand=belongs_to__application($select=app_name),is_of__device_type($select=slug),is_running__release($select=commit)',
|
||||||
)
|
)
|
||||||
.replyWithFile(200, path.join(apiResponsePath, 'devices.json'), {
|
.replyWithFile(200, path.join(apiResponsePath, 'devices.json'), {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"d": [
|
|
||||||
{
|
|
||||||
"application_type": [
|
|
||||||
{
|
|
||||||
"name": "Starter",
|
|
||||||
"slug": "microservices-starter",
|
|
||||||
"supports_multicontainer": true,
|
|
||||||
"is_legacy": false,
|
|
||||||
"__metadata": {}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": 1301645,
|
|
||||||
"user": {
|
|
||||||
"__deferred": {
|
|
||||||
"uri": "/resin/user(43699)"
|
|
||||||
},
|
|
||||||
"__id": 43699
|
|
||||||
},
|
|
||||||
"depends_on__application": null,
|
|
||||||
"actor": 3423895,
|
|
||||||
"app_name": "testApp",
|
|
||||||
"slug": "gh_user/testApp",
|
|
||||||
"commit": "96eec431d57e6976d3a756df33fde7e2",
|
|
||||||
"device_type": "raspberrypi3",
|
|
||||||
"should_track_latest_release": true,
|
|
||||||
"is_accessible_by_support_until__date": null,
|
|
||||||
"is_public": false,
|
|
||||||
"is_host": false,
|
|
||||||
"__metadata": {
|
|
||||||
"uri": "/resin/application(@id)?@id=1301645"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -21,8 +21,16 @@
|
|||||||
"actor": 3423895,
|
"actor": 3423895,
|
||||||
"app_name": "testApp",
|
"app_name": "testApp",
|
||||||
"slug": "gh_user/testApp",
|
"slug": "gh_user/testApp",
|
||||||
"commit": "96eec431d57e6976d3a756df33fde7e2",
|
"should_be__running_release": [
|
||||||
"device_type": "raspberrypi3",
|
{
|
||||||
|
"commit": "96eec431d57e6976d3a756df33fde7e2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_for__device_type": [
|
||||||
|
{
|
||||||
|
"slug": "raspberrypi3"
|
||||||
|
}
|
||||||
|
],
|
||||||
"should_track_latest_release": true,
|
"should_track_latest_release": true,
|
||||||
"is_accessible_by_support_until__date": null,
|
"is_accessible_by_support_until__date": null,
|
||||||
"is_public": false,
|
"is_public": false,
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
"d": [
|
"d": [
|
||||||
{
|
{
|
||||||
"belongs_to__application": [
|
"belongs_to__application": [],
|
||||||
],
|
|
||||||
"id": 1747415,
|
"id": 1747415,
|
||||||
"is_managed_by__device": null,
|
"is_managed_by__device": null,
|
||||||
"device_name": "sparkling-wood",
|
"device_name": "sparkling-wood",
|
||||||
"device_type": "raspberrypi4-64",
|
"is_of__device_type": [{ "slug": "raspberrypi4-64" }],
|
||||||
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
||||||
"is_on__commit": "18756d3386c25a044db66b89e0409804",
|
"is_running__release": [{ "commit": "18756d3386c25a044db66b89e0409804" }],
|
||||||
"note": null,
|
"note": null,
|
||||||
"is_online": false,
|
"is_online": false,
|
||||||
"last_connectivity_event": "2019-11-23T00:26:35.074Z",
|
"last_connectivity_event": "2019-11-23T00:26:35.074Z",
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
"id": 1747415,
|
"id": 1747415,
|
||||||
"is_managed_by__device": null,
|
"is_managed_by__device": null,
|
||||||
"device_name": "sparkling-wood",
|
"device_name": "sparkling-wood",
|
||||||
"device_type": "raspberrypi4-64",
|
"is_of__device_type": [{ "slug": "raspberrypi4-64" }],
|
||||||
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
||||||
"is_on__commit": "18756d3386c25a044db66b89e0409804",
|
"is_running__release": [{ "commit": "18756d3386c25a044db66b89e0409804" }],
|
||||||
"note": null,
|
"note": null,
|
||||||
"is_online": false,
|
"is_online": false,
|
||||||
"last_connectivity_event": "2019-11-23T00:26:35.074Z",
|
"last_connectivity_event": "2019-11-23T00:26:35.074Z",
|
||||||
|
@ -16,11 +16,14 @@
|
|||||||
},
|
},
|
||||||
"is_managed_by__device": null,
|
"is_managed_by__device": null,
|
||||||
"actor": 4180757,
|
"actor": 4180757,
|
||||||
"should_be_running__release": null,
|
|
||||||
"device_name": "sparkling-wood",
|
"device_name": "sparkling-wood",
|
||||||
"device_type": "raspberrypi4-64",
|
"is_of__device_type": [{ "slug": "raspberrypi4-64" }],
|
||||||
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
"uuid": "fda508c8583011b8466c26abdd5159f2",
|
||||||
"is_on__commit": "18756d3386c25a044db66b89e0409804",
|
"is_running__release": [
|
||||||
|
{
|
||||||
|
"commit": "18756d3386c25a044db66b89e0409804"
|
||||||
|
}
|
||||||
|
],
|
||||||
"note": null,
|
"note": null,
|
||||||
"local_id": null,
|
"local_id": null,
|
||||||
"status": "Idle",
|
"status": "Idle",
|
||||||
@ -61,8 +64,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"belongs_to__application": [
|
"belongs_to__application": [],
|
||||||
],
|
|
||||||
"id": 1747416,
|
"id": 1747416,
|
||||||
"belongs_to__user": {
|
"belongs_to__user": {
|
||||||
"__deferred": {
|
"__deferred": {
|
||||||
@ -72,11 +74,14 @@
|
|||||||
},
|
},
|
||||||
"is_managed_by__device": null,
|
"is_managed_by__device": null,
|
||||||
"actor": 4180757,
|
"actor": 4180757,
|
||||||
"should_be_running__release": null,
|
|
||||||
"device_name": "dashing-spruce",
|
"device_name": "dashing-spruce",
|
||||||
"device_type": "raspberrypi4-64",
|
"is_of__device_type": [{ "slug": "raspberrypi4-64" }],
|
||||||
"uuid": "fda508c8583011b8466c26abdd5159f3",
|
"uuid": "fda508c8583011b8466c26abdd5159f3",
|
||||||
"is_on__commit": "18756d3386c25a044db66b89e0409804",
|
"is_running__release": [
|
||||||
|
{
|
||||||
|
"commit": "18756d3386c25a044db66b89e0409804"
|
||||||
|
}
|
||||||
|
],
|
||||||
"note": null,
|
"note": null,
|
||||||
"local_id": null,
|
"local_id": null,
|
||||||
"status": "Idle",
|
"status": "Idle",
|
||||||
|
12
typings/balena-device-init/index.d.ts
vendored
12
typings/balena-device-init/index.d.ts
vendored
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
declare module 'balena-device-init' {
|
declare module 'balena-device-init' {
|
||||||
import { DeviceType } from 'balena-sdk';
|
import { DeviceTypeJson } from 'balena-sdk';
|
||||||
import * as Bluebird from 'bluebird';
|
import * as Bluebird from 'bluebird';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
@ -81,21 +81,23 @@ declare module 'balena-device-init' {
|
|||||||
|
|
||||||
export function configure(
|
export function configure(
|
||||||
image: string,
|
image: string,
|
||||||
manifest: DeviceType,
|
manifest: BalenaSdk.DeviceTypeJson.DeviceType.DeviceType,
|
||||||
config: {},
|
config: {},
|
||||||
options?: {},
|
options?: {},
|
||||||
): Bluebird<InitializeEmitter>;
|
): Bluebird<InitializeEmitter>;
|
||||||
|
|
||||||
export function initialize(
|
export function initialize(
|
||||||
image: string,
|
image: string,
|
||||||
manifest: DeviceType,
|
manifest: BalenaSdk.DeviceTypeJson.DeviceType.DeviceType,
|
||||||
config: {},
|
config: {},
|
||||||
): Bluebird<InitializeEmitter>;
|
): Bluebird<InitializeEmitter>;
|
||||||
|
|
||||||
export function getImageOsVersion(
|
export function getImageOsVersion(
|
||||||
image: string,
|
image: string,
|
||||||
manifest: DeviceType,
|
manifest: BalenaSdk.DeviceTypeJson.DeviceType.DeviceType,
|
||||||
): Bluebird<string | null>;
|
): Bluebird<string | null>;
|
||||||
|
|
||||||
export function getImageManifest(image: string): Bluebird<DeviceType | null>;
|
export function getImageManifest(
|
||||||
|
image: string,
|
||||||
|
): Bluebird<BalenaSdk.DeviceTypeJson.DeviceType.DeviceType | null>;
|
||||||
}
|
}
|
||||||
|
10
typings/global.d.ts
vendored
Normal file
10
typings/global.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Application, DeviceType, Device } from 'balena-sdk';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
type ApplicationWithDeviceType = Application & {
|
||||||
|
is_for__device_type: [DeviceType];
|
||||||
|
};
|
||||||
|
type DeviceWithDeviceType = Device & {
|
||||||
|
is_of__device_type: [DeviceType];
|
||||||
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user