mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-19 05:37:53 +00:00
Use compose long syntax for /lib/firmware and /lib/modules
As /lib/firmware and /lib/modules are always expected to be in the host filesystem, using long syntax ensures that the Supervisor container cannot start on an invalid host. (Long syntax volumes error when the host path does not exist, whereas short syntax volumes create the host path.) Change-type: major Closes: #1965 Signed-off-by: Christina Wang <christina@balena.io>
This commit is contained in:
parent
51c5456af9
commit
7531685b4f
@ -14,3 +14,4 @@ services:
|
|||||||
io.balena.features.balena-api: '1'
|
io.balena.features.balena-api: '1'
|
||||||
io.balena.features.dbus: '1'
|
io.balena.features.dbus: '1'
|
||||||
io.balena.features.balena-socket: '1'
|
io.balena.features.balena-socket: '1'
|
||||||
|
io.balena.features.kernel-modules: '1'
|
||||||
|
3
entry.sh
3
entry.sh
@ -42,6 +42,9 @@ if [ -n "${BALENA_ROOT_CA}" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# TODO: Remove this symlink and modprobe call when the Supervisor
|
||||||
|
# can update itself. At that point, we should run modprobe through
|
||||||
|
# the bind mount as we have the kernel-modules docker-compose label.
|
||||||
# Mount the host kernel module path onto the expected location
|
# Mount the host kernel module path onto the expected location
|
||||||
# We need to do this as busybox doesn't support using a custom location
|
# We need to do this as busybox doesn't support using a custom location
|
||||||
if [ ! -d /lib/modules ]; then
|
if [ ! -d /lib/modules ]; then
|
||||||
|
@ -24,7 +24,6 @@ import * as config from '../config';
|
|||||||
import { checkTruthy, checkString } from '../lib/validation';
|
import { checkTruthy, checkString } from '../lib/validation';
|
||||||
import { ServiceComposeConfig, DeviceMetadata } from './types/service';
|
import { ServiceComposeConfig, DeviceMetadata } from './types/service';
|
||||||
import { ImageInspectInfo } from 'dockerode';
|
import { ImageInspectInfo } from 'dockerode';
|
||||||
import { pathExistsOnHost } from '../lib/fs-utils';
|
|
||||||
import { getSupervisorMetadata } from '../lib/supervisor-metadata';
|
import { getSupervisorMetadata } from '../lib/supervisor-metadata';
|
||||||
|
|
||||||
export interface AppConstructOpts {
|
export interface AppConstructOpts {
|
||||||
@ -738,20 +737,11 @@ export class App {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [
|
const [opts, supervisorApiHost, hostnameOnHost] = await Promise.all([
|
||||||
opts,
|
|
||||||
supervisorApiHost,
|
|
||||||
hostPathExists,
|
|
||||||
hostnameOnHost,
|
|
||||||
] = await Promise.all([
|
|
||||||
config.get('extendedEnvOptions'),
|
config.get('extendedEnvOptions'),
|
||||||
dockerUtils
|
dockerUtils
|
||||||
.getNetworkGateway(constants.supervisorNetworkInterface)
|
.getNetworkGateway(constants.supervisorNetworkInterface)
|
||||||
.catch(() => '127.0.0.1'),
|
.catch(() => '127.0.0.1'),
|
||||||
(async () => ({
|
|
||||||
firmware: await pathExistsOnHost('/lib/firmware'),
|
|
||||||
modules: await pathExistsOnHost('/lib/modules'),
|
|
||||||
}))(),
|
|
||||||
(async () =>
|
(async () =>
|
||||||
_.trim(
|
_.trim(
|
||||||
await fs.readFile(
|
await fs.readFile(
|
||||||
@ -764,7 +754,6 @@ export class App {
|
|||||||
const svcOpts = {
|
const svcOpts = {
|
||||||
appName: app.name,
|
appName: app.name,
|
||||||
supervisorApiHost,
|
supervisorApiHost,
|
||||||
hostPathExists,
|
|
||||||
hostnameOnHost,
|
hostnameOnHost,
|
||||||
...opts,
|
...opts,
|
||||||
};
|
};
|
||||||
|
@ -328,10 +328,6 @@ export interface DeviceMetadata {
|
|||||||
supervisorApiHost: string;
|
supervisorApiHost: string;
|
||||||
osVersion: string;
|
osVersion: string;
|
||||||
hostnameOnHost: string;
|
hostnameOnHost: string;
|
||||||
hostPathExists: {
|
|
||||||
modules: boolean;
|
|
||||||
firmware: boolean;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DockerDevice {
|
export interface DockerDevice {
|
||||||
|
@ -338,13 +338,17 @@ export async function addFeaturesFromLabels(
|
|||||||
'io.balena.features.dbus': () =>
|
'io.balena.features.dbus': () =>
|
||||||
service.config.volumes.push('/run/dbus:/host/run/dbus'),
|
service.config.volumes.push('/run/dbus:/host/run/dbus'),
|
||||||
'io.balena.features.kernel-modules': () =>
|
'io.balena.features.kernel-modules': () =>
|
||||||
options.hostPathExists.modules
|
service.config.volumes.push({
|
||||||
? service.config.volumes.push('/lib/modules:/lib/modules')
|
type: 'bind',
|
||||||
: null,
|
source: '/lib/modules',
|
||||||
|
target: '/lib/modules',
|
||||||
|
} as LongBind),
|
||||||
'io.balena.features.firmware': () =>
|
'io.balena.features.firmware': () =>
|
||||||
options.hostPathExists.firmware
|
service.config.volumes.push({
|
||||||
? service.config.volumes.push('/lib/firmware:/lib/firmware')
|
type: 'bind',
|
||||||
: null,
|
source: '/lib/firmware',
|
||||||
|
target: '/lib/firmware',
|
||||||
|
} as LongBind),
|
||||||
'io.balena.features.balena-socket': () => {
|
'io.balena.features.balena-socket': () => {
|
||||||
service.config.volumes.push({
|
service.config.volumes.push({
|
||||||
type: 'bind',
|
type: 'bind',
|
||||||
|
@ -86,10 +86,6 @@
|
|||||||
},
|
},
|
||||||
"appName": "supervisortest",
|
"appName": "supervisortest",
|
||||||
"supervisorApiHost": "172.17.0.1",
|
"supervisorApiHost": "172.17.0.1",
|
||||||
"hostPathExists": {
|
|
||||||
"firmware": true,
|
|
||||||
"modules": true
|
|
||||||
},
|
|
||||||
"hostnameOnHost": "7dadabd",
|
"hostnameOnHost": "7dadabd",
|
||||||
"uuid": "a7feb967fac7f559ccf2a006a36bcf5d",
|
"uuid": "a7feb967fac7f559ccf2a006a36bcf5d",
|
||||||
"listenPort": "48484",
|
"listenPort": "48484",
|
||||||
|
@ -112,10 +112,6 @@
|
|||||||
},
|
},
|
||||||
"appName": "supervisortest",
|
"appName": "supervisortest",
|
||||||
"supervisorApiHost": "172.17.0.1",
|
"supervisorApiHost": "172.17.0.1",
|
||||||
"hostPathExists": {
|
|
||||||
"firmware": true,
|
|
||||||
"modules": true
|
|
||||||
},
|
|
||||||
"hostnameOnHost": "7dadabd",
|
"hostnameOnHost": "7dadabd",
|
||||||
"uuid": "7dadabd4edec3067948d5952c2f2f26f",
|
"uuid": "7dadabd4edec3067948d5952c2f2f26f",
|
||||||
"listenPort": "48484",
|
"listenPort": "48484",
|
||||||
|
@ -112,10 +112,6 @@
|
|||||||
},
|
},
|
||||||
"appName": "supervisortest",
|
"appName": "supervisortest",
|
||||||
"supervisorApiHost": "172.17.0.1",
|
"supervisorApiHost": "172.17.0.1",
|
||||||
"hostPathExists": {
|
|
||||||
"firmware": true,
|
|
||||||
"modules": true
|
|
||||||
},
|
|
||||||
"hostnameOnHost": "7dadabd",
|
"hostnameOnHost": "7dadabd",
|
||||||
"uuid": "7dadabd4edec3067948d5952c2f2f26f",
|
"uuid": "7dadabd4edec3067948d5952c2f2f26f",
|
||||||
"listenPort": "48484",
|
"listenPort": "48484",
|
||||||
|
@ -682,7 +682,7 @@ describe('compose/service', () => {
|
|||||||
expect(service.config.volumes).to.include.members(['/proc:/proc']);
|
expect(service.config.volumes).to.include.members(['/proc:/proc']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add `/lib/modules` to the container bind mounts when io.balena.features.kernel-modules is used (if the host path exists)', async () => {
|
it('should add `/lib/modules` to the container bind mounts with long syntax when io.balena.features.kernel-modules is used', async () => {
|
||||||
const service = await Service.fromComposeObject(
|
const service = await Service.fromComposeObject(
|
||||||
{
|
{
|
||||||
appId: 123456,
|
appId: 123456,
|
||||||
@ -694,41 +694,19 @@ describe('compose/service', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
appName: 'test',
|
appName: 'test',
|
||||||
hostPathExists: {
|
|
||||||
modules: true,
|
|
||||||
},
|
|
||||||
} as any,
|
} as any,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(service.config.volumes).to.include.members([
|
expect(service.config.volumes).to.deep.include.members([
|
||||||
'/lib/modules:/lib/modules',
|
{
|
||||||
|
type: 'bind',
|
||||||
|
source: '/lib/modules',
|
||||||
|
target: '/lib/modules',
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT add `/lib/modules` to the container bind mounts when io.balena.features.kernel-modules is used (if the host path does NOT exist)', async () => {
|
it('should add `/lib/firmware` to the container bind mounts with long syntax when io.balena.features.firmware is used', async () => {
|
||||||
const service = await Service.fromComposeObject(
|
|
||||||
{
|
|
||||||
appId: 123456,
|
|
||||||
serviceId: 123456,
|
|
||||||
serviceName: 'foobar',
|
|
||||||
labels: {
|
|
||||||
'io.balena.features.kernel-modules': '1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
appName: 'test',
|
|
||||||
hostPathExists: {
|
|
||||||
modules: false,
|
|
||||||
},
|
|
||||||
} as any,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(service.config.volumes).to.not.include.members([
|
|
||||||
'/lib/modules:/lib/modules',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add `/lib/firmware` to the container bind mounts when io.balena.features.firmware is used (if the host path exists)', async () => {
|
|
||||||
const service = await Service.fromComposeObject(
|
const service = await Service.fromComposeObject(
|
||||||
{
|
{
|
||||||
appId: 123456,
|
appId: 123456,
|
||||||
@ -740,37 +718,15 @@ describe('compose/service', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
appName: 'test',
|
appName: 'test',
|
||||||
hostPathExists: {
|
|
||||||
firmware: true,
|
|
||||||
},
|
|
||||||
} as any,
|
} as any,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(service.config.volumes).to.include.members([
|
expect(service.config.volumes).to.deep.include.members([
|
||||||
'/lib/firmware:/lib/firmware',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should NOT add `/lib/firmware` to the container bind mounts when io.balena.features.firmware is used (if the host path does NOT exist)', async () => {
|
|
||||||
const service = await Service.fromComposeObject(
|
|
||||||
{
|
{
|
||||||
appId: 123456,
|
type: 'bind',
|
||||||
serviceId: 123456,
|
source: '/lib/firmware',
|
||||||
serviceName: 'foobar',
|
target: '/lib/firmware',
|
||||||
labels: {
|
|
||||||
'io.balena.features.firmware': '1',
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
appName: 'test',
|
|
||||||
hostPathExists: {
|
|
||||||
firmware: false,
|
|
||||||
},
|
|
||||||
} as any,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(service.config.volumes).to.not.include.members([
|
|
||||||
'/lib/firmware:/lib/firmware',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user