Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for detached HUP on startOsUpdate #1443

Merged
merged 1 commit into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ const sdk = fromSharedOptions();
* [.pinToRelease(uuidOrIdOrArray, fullReleaseHashOrId)](#balena.models.device.pinToRelease) ⇒ <code>Promise</code>
* [.trackApplicationRelease(uuidOrIdOrArray)](#balena.models.device.trackApplicationRelease) ⇒ <code>Promise</code>
* [.setSupervisorRelease(uuidOrIdOrArray, supervisorVersionOrId)](#balena.models.device.setSupervisorRelease) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion)](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* [.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion, [options])](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* ~~[.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>~~
* [.ping(uuidOrId)](#balena.models.device.ping) ⇒ <code>Promise</code>
* ~~[.getApplicationInfo(uuidOrId)](#balena.models.device.getApplicationInfo) ⇒ <code>Promise</code>~~
* [.identify(uuidOrId)](#balena.models.device.identify) ⇒ <code>Promise</code>
Expand Down Expand Up @@ -708,8 +708,8 @@ balena.models.device.get(123).catch(function (error) {
* [.pinToRelease(uuidOrIdOrArray, fullReleaseHashOrId)](#balena.models.device.pinToRelease) ⇒ <code>Promise</code>
* [.trackApplicationRelease(uuidOrIdOrArray)](#balena.models.device.trackApplicationRelease) ⇒ <code>Promise</code>
* [.setSupervisorRelease(uuidOrIdOrArray, supervisorVersionOrId)](#balena.models.device.setSupervisorRelease) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion)](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* [.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion, [options])](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* ~~[.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>~~
* [.ping(uuidOrId)](#balena.models.device.ping) ⇒ <code>Promise</code>
* ~~[.getApplicationInfo(uuidOrId)](#balena.models.device.getApplicationInfo) ⇒ <code>Promise</code>~~
* [.identify(uuidOrId)](#balena.models.device.identify) ⇒ <code>Promise</code>
Expand Down Expand Up @@ -2283,8 +2283,8 @@ balena.models.application.revokeSupportAccess(123);
* [.pinToRelease(uuidOrIdOrArray, fullReleaseHashOrId)](#balena.models.device.pinToRelease) ⇒ <code>Promise</code>
* [.trackApplicationRelease(uuidOrIdOrArray)](#balena.models.device.trackApplicationRelease) ⇒ <code>Promise</code>
* [.setSupervisorRelease(uuidOrIdOrArray, supervisorVersionOrId)](#balena.models.device.setSupervisorRelease) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion)](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* [.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>
* [.startOsUpdate(uuidOrUuids, targetOsVersion, [options])](#balena.models.device.startOsUpdate) ⇒ <code>Promise</code>
* ~~[.getOsUpdateStatus(uuid)](#balena.models.device.getOsUpdateStatus) ⇒ <code>Promise</code>~~
* [.ping(uuidOrId)](#balena.models.device.ping) ⇒ <code>Promise</code>
* ~~[.getApplicationInfo(uuidOrId)](#balena.models.device.getApplicationInfo) ⇒ <code>Promise</code>~~
* [.identify(uuidOrId)](#balena.models.device.identify) ⇒ <code>Promise</code>
Expand Down Expand Up @@ -4017,7 +4017,7 @@ balena.models.device.setSupervisorRelease(123, '11.4.14').then(function() {
```
<a name="balena.models.device.startOsUpdate"></a>

##### device.startOsUpdate(uuidOrUuids, targetOsVersion) ⇒ <code>Promise</code>
##### device.startOsUpdate(uuidOrUuids, targetOsVersion, [options]) ⇒ <code>Promise</code>
**Kind**: static method of [<code>device</code>](#balena.models.device)
**Summary**: Start an OS update on a device
**Access**: public
Expand All @@ -4027,6 +4027,8 @@ balena.models.device.setSupervisorRelease(123, '11.4.14').then(function() {
| --- | --- | --- |
| uuidOrUuids | <code>String</code> \| <code>Array.&lt;String&gt;</code> | full device uuid or array of full uuids |
| targetOsVersion | <code>String</code> | semver-compatible version for the target device Unsupported (unpublished) version will result in rejection. The version **must** be the exact version number, a "prod" variant and greater than the one running on the device. To resolve the semver-compatible range use `balena.model.os.getMaxSatisfyingVersion`. |
| [options] | <code>Object</code> | options |
| [options.runDetached] | <code>Boolean</code> | run the update in detached mode. Default behaviour is runDetached=false but is DEPRECATED and will be removed in a future release. Use runDetached=true for more reliable updates. |

**Example**
```js
Expand All @@ -4036,9 +4038,11 @@ balena.models.device.startOsUpdate('7cf02a687b74206f92cb455969cf8e98', '2.29.2+r
```
<a name="balena.models.device.getOsUpdateStatus"></a>

##### device.getOsUpdateStatus(uuid) ⇒ <code>Promise</code>
##### ~~device.getOsUpdateStatus(uuid) ⇒ <code>Promise</code>~~
***Deprecated***

**Kind**: static method of [<code>device</code>](#balena.models.device)
**Summary**: Get the OS update status of a device
**Summary**: Get the OS update status of a device. This will no longer return a useful status for runDetached=true updates.
**Access**: public
**Fulfil**: <code>Object</code> - action response

Expand Down
19 changes: 16 additions & 3 deletions src/models/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,9 @@ const getDeviceModel = function (

const getOsUpdateHelper = once(async () => {
const $deviceUrlsBase = await getDeviceUrlsBase();
const { getOsUpdateHelper: _getOsUpdateHelper } =
require('../util/device-actions/os-update') as typeof import('../util/device-actions/os-update');
const _getOsUpdateHelper = (
await import('../util/device-actions/os-update')
).getOsUpdateHelper;
return _getOsUpdateHelper($deviceUrlsBase, request);
});
/* eslint-enable @typescript-eslint/no-require-imports */
Expand Down Expand Up @@ -334,14 +335,17 @@ const getDeviceModel = function (
async function startOsUpdate(
uuidOrUuids: string,
targetOsVersion: string,
options?: { runDetached?: boolean },
): Promise<OsUpdateActionResult>;
async function startOsUpdate(
uuidOrUuids: string[],
targetOsVersion: string,
options?: { runDetached?: boolean },
): Promise<Dictionary<OsUpdateActionResult>>;
async function startOsUpdate(
jaomaloy marked this conversation as resolved.
Show resolved Hide resolved
uuidOrUuids: string | string[],
targetOsVersion: string,
options: { runDetached?: boolean } = { runDetached: false },
): Promise<OsUpdateActionResult | Dictionary<OsUpdateActionResult>> {
if (!targetOsVersion) {
throw new errors.BalenaInvalidParameterError(
Expand Down Expand Up @@ -369,6 +373,7 @@ const getDeviceModel = function (
);

const osUpdateHelper = await getOsUpdateHelper();

const results: Dictionary<
ResolvableReturnType<typeof osUpdateHelper.startOsUpdate>
> = {};
Expand Down Expand Up @@ -410,10 +415,13 @@ const getDeviceModel = function (
);
}
}

// use the v2 device actions api for detached updates
await limitedMap(devices, async (device) => {
results[device.uuid] = await osUpdateHelper.startOsUpdate(
device.uuid,
targetOsVersion,
options.runDetached === true ? 'v2' : 'v1',
);
});
},
Expand Down Expand Up @@ -2262,6 +2270,10 @@ const getDeviceModel = function (
* Unsupported (unpublished) version will result in rejection.
* The version **must** be the exact version number, a "prod" variant and greater than the one running on the device.
* To resolve the semver-compatible range use `balena.model.os.getMaxSatisfyingVersion`.
* @param {Object} [options] - options
* @param {Boolean} [options.runDetached] - run the update in detached mode.
* Default behaviour is runDetached=false but is DEPRECATED and will be removed in a future release. Use runDetached=true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice comment!

* for more reliable updates.
* @fulfil {Object} - action response
* @returns {Promise}
*
Expand All @@ -2273,7 +2285,8 @@ const getDeviceModel = function (
startOsUpdate,

/**
* @summary Get the OS update status of a device
* @deprecated
* @summary Get the OS update status of a device. This will no longer return a useful status for runDetached=true updates.
* @name getOsUpdateStatus
* @public
* @function
Expand Down
12 changes: 8 additions & 4 deletions src/util/device-actions/device-actions-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { BalenaRequest } from 'balena-request';
interface MakeActionRequestParams {
uuid: string;
actionNameOrId: string | number;
deviceActionsApiVersion: 'v1' | 'v2';
params?: any;
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
extraOptions: any;
Expand All @@ -11,6 +12,7 @@ interface MakeActionRequestParams {
interface StartActionParams {
uuid: string;
actionName: string;
deviceActionsApiVersion: 'v1' | 'v2';
params: any;
extraOptions?: any;
}
Expand All @@ -21,28 +23,28 @@ interface GetActionStatusParams {
extraOptions?: any;
}

const DEVICE_ACTIONS_API_VERSION = 'v1';

export class DeviceActionsService {
private actionsEndpoint: string;

constructor(
deviceUrlsBase: string,
private request: BalenaRequest,
) {
this.actionsEndpoint = `https://actions.${deviceUrlsBase}/${DEVICE_ACTIONS_API_VERSION}`;
this.actionsEndpoint = `https://actions.${deviceUrlsBase}`;
}

public startAction = <T>({
uuid,
actionName,
deviceActionsApiVersion,
params,
extraOptions,
}: StartActionParams) =>
this.makeActionRequest<T>({
method: 'POST',
uuid,
actionNameOrId: actionName,
deviceActionsApiVersion,
params,
extraOptions,
});
Expand All @@ -55,6 +57,7 @@ export class DeviceActionsService {
this.makeActionRequest<T>({
method: 'GET',
uuid,
deviceActionsApiVersion: 'v1',
actionNameOrId: actionId,
extraOptions,
});
Expand All @@ -63,14 +66,15 @@ export class DeviceActionsService {
method,
uuid,
actionNameOrId,
deviceActionsApiVersion,
params,
extraOptions,
}: MakeActionRequestParams): Promise<T> => {
const data = params ? { parameters: params } : null;

const { body } = await this.request.send<T>({
method,
url: `${this.actionsEndpoint}/${uuid}/${actionNameOrId}`,
url: `${this.actionsEndpoint}/${deviceActionsApiVersion}/${uuid}/${actionNameOrId}`,
body: data,
...extraOptions,
});
Expand Down
15 changes: 13 additions & 2 deletions src/util/device-actions/os-update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ const OS_UPDATE_ACTION_NAME = 'resinhup';

// See: https://github.com/balena-io/resin-proxy/issues/51#issuecomment-274251469
export interface OsUpdateActionResult {
status: 'idle' | 'in_progress' | 'done' | 'error' | 'configuring';
status:
| 'idle'
| 'in_progress'
| 'done'
| 'error'
| 'configuring'
| 'triggered';
parameters?: {
target_version: string;
};
Expand All @@ -22,10 +28,15 @@ export const getOsUpdateHelper = function (
request,
);

const startOsUpdate = (uuid: string, targetOsVersion: string) => {
const startOsUpdate = (
uuid: string,
targetOsVersion: string,
deviceActionsApiVersion: 'v1' | 'v2',
) => {
return deviceActionsService.startAction<OsUpdateActionResult>({
uuid,
actionName: OS_UPDATE_ACTION_NAME,
deviceActionsApiVersion,
params: {
target_version: targetOsVersion,
},
Expand Down
Loading