Skip to content

Commit

Permalink
Stop silencing Not Found errors for devices, applications, and organi…
Browse files Browse the repository at this point in the history
…zations

Resolves: #577
Resolves: #649
Change-type: major
  • Loading branch information
myarmolinsky committed Dec 3, 2024
1 parent 24d38d2 commit fdaefec
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 218 deletions.
57 changes: 6 additions & 51 deletions src/models/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ import * as errors from 'balena-errors';

import {
isId,
isNoApplicationForKeyResponse,
isNotFoundResponse,
mergePineOptions,
treatAsMissingApplication,
withSupervisorLockedError,
} from '../util';

Expand Down Expand Up @@ -732,18 +729,11 @@ const getApplicationModel = function (
slugOrUuidOrIdOrIds: string | number | number[],
): Promise<void> => {
if (typeof slugOrUuidOrIdOrIds === 'string') {
try {
const applicationId = await getId(slugOrUuidOrIdOrIds);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrIdOrIds)).id;
await pine.delete({
resource: 'application',
id: applicationId,
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingApplication(slugOrUuidOrIdOrIds, err);
}
throw err;
}
return;
}
await batchApplicationOperation()({
Expand Down Expand Up @@ -783,21 +773,14 @@ const getApplicationModel = function (
slugOrUuidOrId: string | number,
newAppName: string,
): Promise<void> => {
try {
const applicationId = await getId(slugOrUuidOrId);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrId)).id;
await pine.patch({
resource: 'application',
id: applicationId,
body: {
app_name: newAppName,
},
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingApplication(slugOrUuidOrId, err);
}
throw err;
}
},

/**
Expand All @@ -818,20 +801,13 @@ const getApplicationModel = function (
*/
restart: (slugOrUuidOrId: string | number): Promise<void> =>
withSupervisorLockedError(async () => {
try {
const applicationId = await getId(slugOrUuidOrId);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrId)).id;

await request.send({
method: 'POST',
url: `/application/${applicationId}/restart`,
baseUrl: apiUrl,
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingApplication(slugOrUuidOrId, err);
}
throw err;
}
}),

/**
Expand Down Expand Up @@ -869,8 +845,7 @@ const getApplicationModel = function (
keyDescription?: string,
keyExpiryDate?: string,
): Promise<string> => {
try {
const applicationId = await getId(slugOrUuidOrId);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrId)).id;
const { body } = await request.send({
method: 'POST',
url: '/api-key/v1/',
Expand All @@ -885,12 +860,6 @@ const getApplicationModel = function (
},
});
return body;
} catch (err) {
if (isNoApplicationForKeyResponse(err)) {
treatAsMissingApplication(slugOrUuidOrId, err);
}
throw err;
}
},

/**
Expand Down Expand Up @@ -1318,19 +1287,12 @@ const getApplicationModel = function (
);
}

try {
const applicationId = await getId(slugOrUuidOrId);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrId)).id;
await pine.patch({
resource: 'application',
id: applicationId,
body: { is_accessible_by_support_until__date: expiryTimestamp },
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingApplication(slugOrUuidOrId, err);
}
throw err;
}
},

/**
Expand All @@ -1352,19 +1314,12 @@ const getApplicationModel = function (
revokeSupportAccess: async (
slugOrUuidOrId: string | number,
): Promise<void> => {
try {
const applicationId = await getId(slugOrUuidOrId);
const applicationId = (await sdkInstance.models.application.get(slugOrUuidOrId)).id;
await pine.patch({
resource: 'application',
id: applicationId,
body: { is_accessible_by_support_until__date: null },
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingApplication(slugOrUuidOrId, err);
}
throw err;
}
},

/**
Expand Down
89 changes: 34 additions & 55 deletions src/models/device.supervisor-api.partial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ import type {
} from '..';
import type { Device } from '../types/models';

import {
isNotFoundResponse,
treatAsMissingDevice,
withSupervisorLockedError,
} from '../util';
import { withSupervisorLockedError } from '../util';

import { ensureVersionCompatibility } from '../util/device-os-version';

Expand Down Expand Up @@ -68,9 +64,6 @@ export const getSupervisorApiHelper = function (
} = deps;
const { apiUrl } = opts;

const getId = (uuidOrId: string | number) =>
sdkInstance.models.device._getId(uuidOrId);

const exports = {
/**
* @summary Ping a device
Expand Down Expand Up @@ -166,37 +159,30 @@ export const getSupervisorApiHelper = function (
*/
restartApplication: (uuidOrId: string | number): Promise<void> =>
withSupervisorLockedError(async () => {
try {
const deviceOptions = {
$select: ['id', 'supervisor_version'],
$expand: { belongs_to__application: { $select: 'id' } },
} satisfies PineOptions<Device>;
const device = (await sdkInstance.models.device.get(
uuidOrId,
deviceOptions,
)) as PineTypedResult<Device, typeof deviceOptions>;
const deviceOptions = {
$select: ['id', 'supervisor_version'],
$expand: { belongs_to__application: { $select: 'id' } },
} satisfies PineOptions<Device>;
const device = (await sdkInstance.models.device.get(
uuidOrId,
deviceOptions,
)) as PineTypedResult<Device, typeof deviceOptions>;

const appId = device.belongs_to__application[0].id;
const { body } = await request.send({
method: 'POST',
url: `/supervisor/v1/restart`,
baseUrl: apiUrl,
body: {
deviceId: device.id,
const appId = device.belongs_to__application[0].id;
const { body } = await request.send({
method: 'POST',
url: `/supervisor/v1/restart`,
baseUrl: apiUrl,
body: {
deviceId: device.id,
appId,
data: {
appId,
data: {
appId,
},
},
timeout: CONTAINER_ACTION_ENDPOINT_TIMEOUT,
});
return body;
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingDevice(uuidOrId, err);
}
throw err;
}
},
timeout: CONTAINER_ACTION_ENDPOINT_TIMEOUT,
});
return body;
}),

/**
Expand Down Expand Up @@ -226,26 +212,19 @@ export const getSupervisorApiHelper = function (
options = {};
}

try {
const deviceId = await getId(uuidOrId);
const { body } = await request.send({
method: 'POST',
url: '/supervisor/v1/reboot',
baseUrl: apiUrl,
body: {
deviceId,
data: {
force: Boolean(options?.force),
},
const deviceId = (await sdkInstance.models.device.get(uuidOrId)).id;
const { body } = await request.send({
method: 'POST',
url: '/supervisor/v1/reboot',
baseUrl: apiUrl,
body: {
deviceId,
data: {
force: Boolean(options?.force),
},
});
return body;
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingDevice(uuidOrId, err);
}
throw err;
}
},
});
return body;
}),

/**
Expand Down
45 changes: 12 additions & 33 deletions src/models/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ import memoizee from 'memoizee';

import {
isId,
isNoDeviceForKeyResponse,
isFullUuid,
mergePineOptions,
treatAsMissingDevice,
limitedMap,
groupByMap,
} from '../util';
Expand Down Expand Up @@ -222,17 +220,6 @@ const getDeviceModel = function (
return (await sdkInstance.models.config.getAll()).deviceUrlsBase;
});

// Internal method for uuid/id disambiguation
// Note that this throws an exception for missing uuids, but not missing ids
const getId = async (uuidOrId: string | number) => {
if (isId(uuidOrId)) {
return uuidOrId;
} else {
const { id } = await exports.get(uuidOrId, { $select: 'id' });
return id;
}
};

const getAppliedConfigVariableValue = async (
uuidOrId: string | number,
name: string,
Expand Down Expand Up @@ -433,7 +420,6 @@ const getDeviceModel = function (
}

const exports = {
_getId: getId,
OverallStatus,
/**
* @summary Get Dashboard URL for a specific device
Expand Down Expand Up @@ -1456,25 +1442,18 @@ const getDeviceModel = function (
keyDescription?: string,
keyExpiryDate?: string,
): Promise<string> => {
try {
const deviceId = await getId(uuidOrId);
const { body } = await request.send({
method: 'POST',
url: `/api-key/device/${deviceId}/device-key`,
baseUrl: apiUrl,
body: {
name: keyName,
description: keyDescription,
expiryDate: keyExpiryDate,
},
});
return body;
} catch (err) {
if (isNoDeviceForKeyResponse(err)) {
treatAsMissingDevice(uuidOrId, err);
}
throw err;
}
const deviceId = (await sdkInstance.models.device.get(uuidOrId)).id;
const { body } = await request.send({
method: 'POST',
url: `/api-key/device/${deviceId}/device-key`,
baseUrl: apiUrl,
body: {
name: keyName,
description: keyDescription,
expiryDate: keyExpiryDate,
},
});
return body;
},

/**
Expand Down
31 changes: 7 additions & 24 deletions src/models/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,13 @@ import * as errors from 'balena-errors';

import type * as BalenaSdk from '..';
import type { InjectedDependenciesParam, InjectedOptionsParam } from '..';
import {
isId,
isNotFoundResponse,
mergePineOptions,
treatAsMissingOrganization,
} from '../util';
import { isId, mergePineOptions } from '../util';

const getOrganizationModel = function (
deps: InjectedDependenciesParam,
opts: InjectedOptionsParam,
) {
const { pine } = deps;
const { pine, sdkInstance } = deps;

/* eslint-disable @typescript-eslint/no-require-imports */
const membershipModel = (
Expand All @@ -41,11 +36,6 @@ const getOrganizationModel = function (
).default(deps, opts, (...args: Parameters<typeof get>) => get(...args));
/* eslint-enable @typescript-eslint/no-require-imports */

const getId = async (handleOrId: string | number) => {
const { id } = await get(handleOrId, { $select: 'id' });
return id;
};

/**
* @summary Creates a new organization
* @name create
Expand Down Expand Up @@ -186,18 +176,11 @@ const getOrganizationModel = function (
* balena.models.organization.remove(123);
*/
const remove = async function (handleOrId: string | number): Promise<void> {
try {
const id = await getId(handleOrId);
await pine.delete<BalenaSdk.Organization>({
resource: 'organization',
id,
});
} catch (err) {
if (isNotFoundResponse(err)) {
treatAsMissingOrganization(handleOrId, err);
}
throw err;
}
const id = (await sdkInstance.models.organization.get(handleOrId)).id;
await pine.delete<BalenaSdk.Organization>({
resource: 'organization',
id,
});
};

return {
Expand Down
Loading

0 comments on commit fdaefec

Please sign in to comment.