mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-19 05:37:51 +00:00
device os-update: allow host OS upgrade with development balenaOS images
also: fix `device os-update` incorrectly showing 0% progress convert `device os-update` to use async/await Change-type: minor Resolves: #1725 Signed-off-by: Scott Lowe <scott@balena.io>
This commit is contained in:
parent
7f79451376
commit
320b4864d9
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2016-2017 Balena
|
Copyright 2016-2020 Balena Ltd.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,7 @@ limitations under the License.
|
|||||||
import { Device } from 'balena-sdk';
|
import { Device } from 'balena-sdk';
|
||||||
import { CommandDefinition } from 'capitano';
|
import { CommandDefinition } from 'capitano';
|
||||||
import { stripIndent } from 'common-tags';
|
import { stripIndent } from 'common-tags';
|
||||||
|
import { ExpectedError } from '../errors';
|
||||||
import { getBalenaSdk } from '../utils/lazy';
|
import { getBalenaSdk } from '../utils/lazy';
|
||||||
import { normalizeUuidProp } from '../utils/normalization';
|
import { normalizeUuidProp } from '../utils/normalization';
|
||||||
import * as commandOptions from './command-options';
|
import * as commandOptions from './command-options';
|
||||||
@ -55,42 +56,48 @@ export const osUpdate: CommandDefinition<OsUpdate.Args, OsUpdate.Options> = {
|
|||||||
const patterns = await import('../utils/patterns');
|
const patterns = await import('../utils/patterns');
|
||||||
const form = await import('resin-cli-form');
|
const form = await import('resin-cli-form');
|
||||||
|
|
||||||
return sdk.models.device
|
// Get device info
|
||||||
.get(params.uuid, {
|
const {
|
||||||
|
uuid,
|
||||||
|
device_type,
|
||||||
|
os_version,
|
||||||
|
os_variant,
|
||||||
|
} = await sdk.models.device.get(params.uuid, {
|
||||||
$select: ['uuid', 'device_type', 'os_version', 'os_variant'],
|
$select: ['uuid', 'device_type', 'os_version', 'os_variant'],
|
||||||
})
|
});
|
||||||
.then(async ({ uuid, device_type, os_version, os_variant }) => {
|
|
||||||
|
// Get current device OS version
|
||||||
const currentOsVersion = sdk.models.device.getOsVersion({
|
const currentOsVersion = sdk.models.device.getOsVersion({
|
||||||
os_version,
|
os_version,
|
||||||
os_variant,
|
os_variant,
|
||||||
} as Device);
|
} as Device);
|
||||||
if (!currentOsVersion) {
|
if (!currentOsVersion) {
|
||||||
patterns.exitWithExpectedError(
|
throw new ExpectedError(
|
||||||
'The current os version of the device is not available',
|
'The current os version of the device is not available',
|
||||||
);
|
);
|
||||||
// Just to make TS happy
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdk.models.os
|
// Get supported OS update versions
|
||||||
.getSupportedOsUpdateVersions(device_type, currentOsVersion)
|
const hupVersionInfo = await sdk.models.os.getSupportedOsUpdateVersions(
|
||||||
.then(hupVersionInfo => {
|
device_type,
|
||||||
|
currentOsVersion,
|
||||||
|
);
|
||||||
if (hupVersionInfo.versions.length === 0) {
|
if (hupVersionInfo.versions.length === 0) {
|
||||||
patterns.exitWithExpectedError(
|
throw new ExpectedError(
|
||||||
'There are no available Host OS update targets for this device',
|
'There are no available Host OS update targets for this device',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.version != null) {
|
// Get target OS version
|
||||||
if (!_.includes(hupVersionInfo.versions, options.version)) {
|
let targetOsVersion = options.version;
|
||||||
patterns.exitWithExpectedError(
|
if (targetOsVersion != null) {
|
||||||
'The provided version is not in the Host OS update targets for this device',
|
if (!_.includes(hupVersionInfo.versions, targetOsVersion)) {
|
||||||
|
throw new ExpectedError(
|
||||||
|
`The provided version ${targetOsVersion} is not in the Host OS update targets for this device`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return options.version;
|
} else {
|
||||||
}
|
targetOsVersion = await form.ask({
|
||||||
|
|
||||||
return form.ask({
|
|
||||||
message: 'Target OS version',
|
message: 'Target OS version',
|
||||||
type: 'list',
|
type: 'list',
|
||||||
choices: hupVersionInfo.versions.map(version => ({
|
choices: hupVersionInfo.versions.map(version => ({
|
||||||
@ -101,16 +108,15 @@ export const osUpdate: CommandDefinition<OsUpdate.Args, OsUpdate.Options> = {
|
|||||||
value: version,
|
value: version,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
.then(version =>
|
|
||||||
patterns
|
// Confirm and start update
|
||||||
.confirm(
|
await patterns.confirm(
|
||||||
options.yes || false,
|
options.yes || false,
|
||||||
'Host OS updates require a device restart when they complete. Are you sure you want to proceed?',
|
'Host OS updates require a device restart when they complete. Are you sure you want to proceed?',
|
||||||
)
|
|
||||||
.then(() => sdk.models.device.startOsUpdate(uuid, version))
|
|
||||||
.then(() => patterns.awaitDeviceOsUpdate(uuid, version)),
|
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
await sdk.models.device.startOsUpdate(uuid, targetOsVersion);
|
||||||
|
await patterns.awaitDeviceOsUpdate(uuid, targetOsVersion);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,7 @@ Examples:
|
|||||||
`,
|
`,
|
||||||
permission: 'user',
|
permission: 'user',
|
||||||
async action(params) {
|
async action(params) {
|
||||||
const key = await getBalenaSdk().models.key.get(params.id);
|
const key = await getBalenaSdk().models.key.get(parseInt(params.id, 10));
|
||||||
|
|
||||||
console.log(getVisuals().table.vertical(key, ['id', 'title']));
|
console.log(getVisuals().table.vertical(key, ['id', 'title']));
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ Examples:
|
|||||||
'Are you sure you want to delete the key?',
|
'Are you sure you want to delete the key?',
|
||||||
);
|
);
|
||||||
|
|
||||||
await getBalenaSdk().models.key.remove(params.id);
|
await getBalenaSdk().models.key.remove(parseInt(params.id, 10));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import { Device } from 'balena-sdk';
|
|||||||
|
|
||||||
export const getDeviceOsProgress = (device: Device) => {
|
export const getDeviceOsProgress = (device: Device) => {
|
||||||
if (!device.is_online) {
|
if (!device.is_online) {
|
||||||
return 0;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = BalenaDeviceStatus.getStatus(device).key;
|
const status = BalenaDeviceStatus.getStatus(device).key;
|
||||||
|
@ -293,10 +293,7 @@ export function awaitDeviceOsUpdate(uuid: string, targetOsVersion: string) {
|
|||||||
balena.models.device.getOsUpdateStatus(uuid),
|
balena.models.device.getOsUpdateStatus(uuid),
|
||||||
balena.models.device.get(uuid).then(getDeviceOsProgress),
|
balena.models.device.get(uuid).then(getDeviceOsProgress),
|
||||||
]).then(([osUpdateStatus, osUpdateProgress]) => {
|
]).then(([osUpdateStatus, osUpdateProgress]) => {
|
||||||
if (
|
if (osUpdateStatus.status === 'done') {
|
||||||
osUpdateStatus.status === 'update_done' ||
|
|
||||||
osUpdateStatus.status === 'done'
|
|
||||||
) {
|
|
||||||
console.info(
|
console.info(
|
||||||
`The device ${deviceName} has been updated to v${targetOsVersion} and will restart shortly!`,
|
`The device ${deviceName} has been updated to v${targetOsVersion} and will restart shortly!`,
|
||||||
);
|
);
|
||||||
@ -311,7 +308,10 @@ export function awaitDeviceOsUpdate(uuid: string, targetOsVersion: string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (osUpdateProgress !== null) {
|
||||||
|
// Avoid resetting to 0% at end of process when device goes offline.
|
||||||
progressBar.update({ percentage: osUpdateProgress });
|
progressBar.update({ percentage: osUpdateProgress });
|
||||||
|
}
|
||||||
|
|
||||||
return Bluebird.delay(3000).then(poll);
|
return Bluebird.delay(3000).then(poll);
|
||||||
});
|
});
|
||||||
@ -451,6 +451,8 @@ export function printErrorMessage(message: string) {
|
|||||||
* "expected" errors (say, a JSON parsing error in a file provided by the user)
|
* "expected" errors (say, a JSON parsing error in a file provided by the user)
|
||||||
* don't warrant reporting through Sentry.io. For such mundane errors, catch
|
* don't warrant reporting through Sentry.io. For such mundane errors, catch
|
||||||
* them and call this function.
|
* them and call this function.
|
||||||
|
*
|
||||||
|
* DEPRECATED: Use `throw new ExpectedError(<message>)` instead.
|
||||||
*/
|
*/
|
||||||
export function exitWithExpectedError(message: string | Error): never {
|
export function exitWithExpectedError(message: string | Error): never {
|
||||||
if (message instanceof Error) {
|
if (message instanceof Error) {
|
||||||
|
54
npm-shrinkwrap.json
generated
54
npm-shrinkwrap.json
generated
@ -2089,9 +2089,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-hup-action-utils": {
|
"balena-hup-action-utils": {
|
||||||
"version": "3.0.2",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-hup-action-utils/-/balena-hup-action-utils-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balena-hup-action-utils/-/balena-hup-action-utils-4.0.0.tgz",
|
||||||
"integrity": "sha512-AwTAFQN4mtjsRLhkzspMKGBykWKvjVlZnzhAu6uyPBn8PGocyB3D30bR2jWgapd6uSdPJf38fcspRDbcpx3CHA==",
|
"integrity": "sha512-Qwk4h6QRqBiJNONRyoHPKtxgoRucdCK5VTG0A6LSCAo0qQrBRi4Alhdq76ksHQgZ2t/Gewfa7cuVAgiH78YMfw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"balena-semver": "^2.0.0",
|
"balena-semver": "^2.0.0",
|
||||||
"lodash": "^4.17.11"
|
"lodash": "^4.17.11"
|
||||||
@ -2124,9 +2124,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-pine": {
|
"balena-pine": {
|
||||||
"version": "10.1.1",
|
"version": "10.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/balena-pine/-/balena-pine-10.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/balena-pine/-/balena-pine-10.1.3.tgz",
|
||||||
"integrity": "sha512-Py0Id0w1QwwM20/gmZ4hRgTOf0sbCwmjGwkE0G/AO6fqnlFDe5ehaebzXk3AtWmW3K7WGDPUxcNAHohHG8aRJA==",
|
"integrity": "sha512-dOjftYx7vf9e3C9ENJyYyD8DNtQl6CxXuWgvNImfvK3Rw+zSRBPYfLw6S4MqbCWkcsQGjaS/zun/VJ9UNjJYhQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"balena-errors": "^4.2.1",
|
"balena-errors": "^4.2.1",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
@ -2235,16 +2235,16 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.9.1",
|
"version": "6.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
|
||||||
"integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA=="
|
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"balena-sdk": {
|
"balena-sdk": {
|
||||||
"version": "12.29.1",
|
"version": "12.33.0",
|
||||||
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-12.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/balena-sdk/-/balena-sdk-12.33.0.tgz",
|
||||||
"integrity": "sha512-e6nIuP16AaDpGQnOCDPR7kptCM7/iWHPp6bdmUeBsw9e5IX4zwI0FwFHi4L9EoRxByLKI5oRZYeYGeU++Sd1Nw==",
|
"integrity": "sha512-riqcJeA8SYMf20bgt1lhgw/eWiWXVwivGHgBer54/dxDIo48RIwys98LvkisIO2sTco1AmTL4Q0rePsMGjEYwQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/bluebird": "^3.5.30",
|
"@types/bluebird": "^3.5.30",
|
||||||
"@types/lodash": "^4.14.149",
|
"@types/lodash": "^4.14.149",
|
||||||
@ -2253,8 +2253,8 @@
|
|||||||
"abortcontroller-polyfill": "^1.4.0",
|
"abortcontroller-polyfill": "^1.4.0",
|
||||||
"balena-auth": "^3.0.1",
|
"balena-auth": "^3.0.1",
|
||||||
"balena-device-status": "^3.2.1",
|
"balena-device-status": "^3.2.1",
|
||||||
"balena-errors": "^4.2.1",
|
"balena-errors": "^4.3.0",
|
||||||
"balena-hup-action-utils": "~3.0.0",
|
"balena-hup-action-utils": "~4.0.0",
|
||||||
"balena-pine": "^10.1.1",
|
"balena-pine": "^10.1.1",
|
||||||
"balena-register-device": "^6.0.1",
|
"balena-register-device": "^6.0.1",
|
||||||
"balena-request": "^10.0.8",
|
"balena-request": "^10.0.8",
|
||||||
@ -2269,9 +2269,23 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "8.10.59",
|
"version": "8.10.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.60.tgz",
|
||||||
"integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ=="
|
"integrity": "sha512-YjPbypHFuiOV0bTgeF07HpEEqhmHaZqYNSdCKeBJa+yFoQ/7BC+FpJcwmi34xUIIRVFktnUyP1dPU8U0612GOg=="
|
||||||
|
},
|
||||||
|
"balena-errors": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balena-errors/-/balena-errors-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-daa+3jHqvoha8zIIIX4jvxdus1LWhH+2Y5IJOzOuIzxmfLEq51EXeszMbcHrbSLlGlJpfaJDG7dfBmFXtabL6Q==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.11.1",
|
||||||
|
"typed-error": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
|
||||||
|
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2314,9 +2328,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "8.10.59",
|
"version": "8.10.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.60.tgz",
|
||||||
"integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ=="
|
"integrity": "sha512-YjPbypHFuiOV0bTgeF07HpEEqhmHaZqYNSdCKeBJa+yFoQ/7BC+FpJcwmi34xUIIRVFktnUyP1dPU8U0612GOg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -173,7 +173,7 @@
|
|||||||
"balena-errors": "^4.2.1",
|
"balena-errors": "^4.2.1",
|
||||||
"balena-image-manager": "^6.1.2",
|
"balena-image-manager": "^6.1.2",
|
||||||
"balena-preload": "^8.4.0",
|
"balena-preload": "^8.4.0",
|
||||||
"balena-sdk": "^12.29.1",
|
"balena-sdk": "^12.33.0",
|
||||||
"balena-semver": "^2.2.0",
|
"balena-semver": "^2.2.0",
|
||||||
"balena-settings-client": "^4.0.4",
|
"balena-settings-client": "^4.0.4",
|
||||||
"balena-sync": "^10.2.0",
|
"balena-sync": "^10.2.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user