mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-01-20 19:49:01 +00:00
Fix filtering of the supervisor app on the target state
Under some conditions, an aarch64 device may get a reference to a armv7hf supervisor on the target state. One of the ways this can happen is if an aarch64 device is added to an armv7hf fleet and the target supervisor is set before the device fully provisions. If that happens, the previous filtering for the supervisor app (which relied on the architecture in device-type.json) would fail and the user would end up with two supervisor containers, one running correctly and the other crash looping. This fixes the filtering and just checks if the supervisor uuid/service name belongs to a group of known uuids. Closes: #2006 Change-type: patch
This commit is contained in:
parent
39cf98243f
commit
5a57647450
@ -24,7 +24,7 @@ import { checkTruthy, checkString } from '../lib/validation';
|
||||
import { ServiceComposeConfig, DeviceMetadata } from './types/service';
|
||||
import { ImageInspectInfo } from 'dockerode';
|
||||
import { pathExistsOnHost } from '../lib/fs-utils';
|
||||
import { getSupervisorMetadata } from '../lib/supervisor-metadata';
|
||||
import { isSupervisor } from '../lib/supervisor-metadata';
|
||||
|
||||
export interface AppConstructOpts {
|
||||
appId: number;
|
||||
@ -778,8 +778,6 @@ export class App {
|
||||
...opts,
|
||||
};
|
||||
|
||||
const supervisorMeta = await getSupervisorMetadata();
|
||||
|
||||
const isService = (svc: ServiceComposeConfig) =>
|
||||
svc.labels?.['io.balena.image.class'] == null ||
|
||||
svc.labels['io.balena.image.class'] === 'service';
|
||||
@ -788,12 +786,6 @@ export class App {
|
||||
svc.labels?.['io.balena.image.store'] == null ||
|
||||
svc.labels['io.balena.image.store'] === 'data';
|
||||
|
||||
const isSupervisor = (svc: ServiceComposeConfig) =>
|
||||
app.uuid === supervisorMeta.uuid &&
|
||||
(svc.serviceName === supervisorMeta.serviceName ||
|
||||
// keep compatibility with older supervisor releases
|
||||
svc.serviceName === 'main');
|
||||
|
||||
// In the db, the services are an array, but here we switch them to an
|
||||
// object so that they are consistent
|
||||
const services: Service[] = await Promise.all(
|
||||
@ -808,7 +800,10 @@ export class App {
|
||||
)
|
||||
// Ignore the supervisor service itself from the target state for now
|
||||
// until the supervisor can update itself
|
||||
.filter((svc: ServiceComposeConfig) => !isSupervisor(svc))
|
||||
.filter(
|
||||
(svc: ServiceComposeConfig) =>
|
||||
!isSupervisor(app.uuid, svc.serviceName),
|
||||
)
|
||||
.map(async (svc: ServiceComposeConfig) => {
|
||||
// Try to fill the image id if the image is downloaded
|
||||
let imageInfo: ImageInspectInfo | undefined;
|
||||
|
@ -1,7 +1,3 @@
|
||||
import * as memoizee from 'memoizee';
|
||||
import * as config from '../config';
|
||||
import { InternalInconsistencyError } from './errors';
|
||||
|
||||
export type SupervisorMetadata = {
|
||||
uuid: string;
|
||||
serviceName: string;
|
||||
@ -41,24 +37,21 @@ const SUPERVISOR_APPS: { [arch: string]: SupervisorMetadata } = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the metadata from the supervisor container
|
||||
* Check if the supervisor in the target state belongs to the known
|
||||
* supervisors
|
||||
*
|
||||
* This is needed for the supervisor to identify itself on the target
|
||||
* state and on getStatus() in device-state.ts
|
||||
*
|
||||
* TODO: remove this once the supervisor knows how to update itself
|
||||
*/
|
||||
export const getSupervisorMetadata = memoizee(
|
||||
async () => {
|
||||
const deviceArch = await config.get('deviceArch');
|
||||
const meta: SupervisorMetadata = SUPERVISOR_APPS[deviceArch];
|
||||
if (meta == null) {
|
||||
throw new InternalInconsistencyError(
|
||||
`Unknown device architecture ${deviceArch}. Could not find matching supervisor metadata.`,
|
||||
);
|
||||
}
|
||||
|
||||
return meta;
|
||||
},
|
||||
{ promise: true },
|
||||
);
|
||||
export const isSupervisor = (appUuid: string, svcName: string) => {
|
||||
return (
|
||||
Object.values(SUPERVISOR_APPS).filter(
|
||||
({ uuid, serviceName }) =>
|
||||
// Compare with `main` as well for compatibility with older supervisors
|
||||
appUuid === uuid && (svcName === serviceName || svcName === 'main'),
|
||||
).length > 0
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user