mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-28 04:12:41 +00:00
Add support for init field from compose
Init supports boolean values, and is not included in the config when not defined. Change-type: patch Signed-off-by: Christina Ying Wang <christina@balena.io>
This commit is contained in:
parent
e01aaaaafb
commit
ed1c18e369
@ -337,6 +337,13 @@ class ServiceImpl implements Service {
|
||||
config.tty = Boolean(config.tty);
|
||||
}
|
||||
|
||||
// Only keep init field if it's a boolean
|
||||
if (config.init != null) {
|
||||
config.init = Boolean(config.init);
|
||||
} else {
|
||||
delete config.init;
|
||||
}
|
||||
|
||||
if (Array.isArray(config.sysctls)) {
|
||||
config.sysctls = _.fromPairs(
|
||||
_.map(config.sysctls, (v) => _.split(v, '=')),
|
||||
@ -598,6 +605,11 @@ class ServiceImpl implements Service {
|
||||
tty: container.Config.Tty || false,
|
||||
};
|
||||
|
||||
// Only add `init` if true or false, otherwise leave blank
|
||||
if (typeof container.HostConfig.Init === 'boolean') {
|
||||
svc.config.init = container.HostConfig.Init;
|
||||
}
|
||||
|
||||
const appId = checkInt(svc.config.labels['io.balena.app-id']);
|
||||
if (appId == null) {
|
||||
throw new InternalInconsistencyError(
|
||||
@ -739,6 +751,7 @@ class ServiceImpl implements Service {
|
||||
UsernsMode: this.config.usernsMode,
|
||||
NanoCpus: this.config.cpus,
|
||||
IpcMode: this.config.ipc,
|
||||
Init: this.config.init,
|
||||
} as Dockerode.ContainerCreateOptions['HostConfig'],
|
||||
Healthcheck: ComposeUtils.serviceHealthcheckToDockerHealthcheck(
|
||||
this.config.healthcheck,
|
||||
|
@ -183,7 +183,7 @@ export interface ServiceComposeConfig {
|
||||
groupAdd?: string[];
|
||||
healthcheck?: ComposeHealthcheck;
|
||||
image: string;
|
||||
init?: string | boolean;
|
||||
init?: boolean;
|
||||
labels?: { [labelName: string]: string };
|
||||
running?: boolean;
|
||||
networkMode?: string;
|
||||
@ -272,6 +272,7 @@ export interface ServiceConfig {
|
||||
domainname: string;
|
||||
hostname: string;
|
||||
ipc: string;
|
||||
init?: boolean;
|
||||
macAddress: string;
|
||||
memLimit: number;
|
||||
memReservation: number;
|
||||
|
@ -105,8 +105,7 @@
|
||||
"CpuCount": 0,
|
||||
"CpuPercent": 0,
|
||||
"IOMaximumIOps": 0,
|
||||
"IOMaximumBandwidth": 0,
|
||||
"Init": false
|
||||
"IOMaximumBandwidth": 0
|
||||
},
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
|
17
test/data/docker-states/init/compose.json
Normal file
17
test/data/docker-states/init/compose.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"imageId": 478890,
|
||||
"serviceName": "main",
|
||||
"image": "sha256:7f54fa690ce19a1f625b04479ae1f12f44d36112a74be7edfefa777ecfdb194b",
|
||||
"running": true,
|
||||
"environment": {},
|
||||
"labels": {},
|
||||
"appId": 1011165,
|
||||
"appUuid": "aaaaaaaa",
|
||||
"releaseId": 597007,
|
||||
"serviceId": 43697,
|
||||
"commit": "ff300a701054ac15281de1f9c0e84b8c",
|
||||
"imageName": "registry2.resin.io/v2/bf9c649a5ac2fe147bbe350875042388@sha256:3a5c17b715b4f8265539c1a006dd1abdd2ff3b758aa23df99f77c792f40c3d43",
|
||||
"composition": {
|
||||
"init": true
|
||||
}
|
||||
}
|
103
test/data/docker-states/init/imageInfo.json
Normal file
103
test/data/docker-states/init/imageInfo.json
Normal file
@ -0,0 +1,103 @@
|
||||
{
|
||||
"serviceName": "main",
|
||||
"imageInfo": {
|
||||
"Id": "sha256:7f54fa690ce19a1f625b04479ae1f12f44d36112a74be7edfefa777ecfdb194b",
|
||||
"RepoTags": [],
|
||||
"RepoDigests": [
|
||||
"registry2.resin.io/v2/90e3bf4c3dc1e59221b7b3e659a327f6@sha256:3a5c17b715b4f8265539c1a006dd1abdd2ff3b758aa23df99f77c792f40c3d43"
|
||||
],
|
||||
"Parent": "",
|
||||
"Comment": "",
|
||||
"Created": "2018-09-12T13:00:43.974720835Z",
|
||||
"Container": "07cb0400e218ae235e67cf1fd283dc09559f57fbe2a36f5cc89302388371781c",
|
||||
"ContainerConfig": {
|
||||
"Hostname": "137f767087a2",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"AttachStderr": false,
|
||||
"Tty": false,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"#(nop) ",
|
||||
"CMD [\"/bin/sh\" \"-c\" \"while true; do echo 'hello'; sleep 5; done;\"]"
|
||||
],
|
||||
"ArgsEscaped": true,
|
||||
"Image": "sha256:8d68949dbddcb3ab1a61caeffa0aa1a6e27425ecc4f7665d04d8d0e5bfa03298",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": null,
|
||||
"OnBuild": [],
|
||||
"Labels": {}
|
||||
},
|
||||
"DockerVersion": "17.05.0-ce",
|
||||
"Author": "",
|
||||
"Config": {
|
||||
"Hostname": "137f767087a2",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"AttachStderr": false,
|
||||
"Tty": false,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"while true; do echo 'hello'; sleep 5; done;"
|
||||
],
|
||||
"ArgsEscaped": true,
|
||||
"Image": "sha256:8d68949dbddcb3ab1a61caeffa0aa1a6e27425ecc4f7665d04d8d0e5bfa03298",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": null,
|
||||
"OnBuild": [],
|
||||
"Labels": {}
|
||||
},
|
||||
"Architecture": "arm64",
|
||||
"Os": "linux",
|
||||
"Size": 104966431,
|
||||
"VirtualSize": 104966431,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": "aufs"
|
||||
},
|
||||
"RootFS": {
|
||||
"Type": "layers",
|
||||
"Layers": [
|
||||
"sha256:a3075e9def48840598abcfe08c1ee564c989d1014d847082d950dca2c94098ec",
|
||||
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
|
||||
]
|
||||
},
|
||||
"Metadata": {
|
||||
"LastTagTime": "0001-01-01T00:00:00Z"
|
||||
}
|
||||
},
|
||||
"appName": "supervisortest",
|
||||
"supervisorApiHost": "172.17.0.1",
|
||||
"hostPathExists": {
|
||||
"firmware": true,
|
||||
"modules": true
|
||||
},
|
||||
"hostname": "7dadabd",
|
||||
"uuid": "a7feb967fac7f559ccf2a006a36bcf5d",
|
||||
"listenPort": "48484",
|
||||
"name": "Office",
|
||||
"apiSecret": "d4bf8369519c32adaa5dd1f84367aa817403f2a3ce976be9c9bacd4d344fdd",
|
||||
"deviceApiKey": "ff89e1d8db58a7ca52a435f2adea319a",
|
||||
"version": "7.18.0",
|
||||
"deviceArch": "amd64",
|
||||
"deviceType": "raspberrypi3",
|
||||
"osVersion": "Resin OS 2.13.6+rev1"
|
||||
}
|
232
test/data/docker-states/init/inspect.json
Normal file
232
test/data/docker-states/init/inspect.json
Normal file
@ -0,0 +1,232 @@
|
||||
{
|
||||
"Id": "52cfd7a64d50236376741dd2578c4fbb0178d90e2e4fae55f3e14cd905e9ac9e",
|
||||
"Created": "2018-09-12T14:38:42.696028995Z",
|
||||
"Path": "/bin/sh",
|
||||
"Args": [
|
||||
"-c",
|
||||
"while true; do echo 'hello'; sleep 5; done;"
|
||||
],
|
||||
"State": {
|
||||
"Status": "exited",
|
||||
"Running": false,
|
||||
"Paused": false,
|
||||
"Restarting": false,
|
||||
"OOMKilled": false,
|
||||
"Dead": false,
|
||||
"Pid": 0,
|
||||
"ExitCode": 137,
|
||||
"Error": "",
|
||||
"StartedAt": "2018-09-12T14:38:45.408574694Z",
|
||||
"FinishedAt": "2018-09-12T14:38:46.462783621Z"
|
||||
},
|
||||
"Image": "sha256:7f54fa690ce19a1f625b04479ae1f12f44d36112a74be7edfefa777ecfdb194b",
|
||||
"ResolvConfPath": "/var/lib/docker/containers/52cfd7a64d50236376741dd2578c4fbb0178d90e2e4fae55f3e14cd905e9ac9e/resolv.conf",
|
||||
"HostnamePath": "/var/lib/docker/containers/52cfd7a64d50236376741dd2578c4fbb0178d90e2e4fae55f3e14cd905e9ac9e/hostname",
|
||||
"HostsPath": "/var/lib/docker/containers/52cfd7a64d50236376741dd2578c4fbb0178d90e2e4fae55f3e14cd905e9ac9e/hosts",
|
||||
"LogPath": "",
|
||||
"Name": "main_1_1",
|
||||
"RestartCount": 0,
|
||||
"Driver": "aufs",
|
||||
"Platform": "linux",
|
||||
"MountLabel": "",
|
||||
"ProcessLabel": "",
|
||||
"AppArmorProfile": "",
|
||||
"ExecIDs": null,
|
||||
"HostConfig": {
|
||||
"Binds": [
|
||||
"/tmp/balena-supervisor/services/1011165/main:/tmp/resin",
|
||||
"/tmp/balena-supervisor/services/1011165/main:/tmp/balena"
|
||||
],
|
||||
"ContainerIDFile": "",
|
||||
"LogConfig": {
|
||||
"Type": "journald",
|
||||
"Config": {}
|
||||
},
|
||||
"NetworkMode": "aaaaaaaa_default",
|
||||
"PortBindings": {},
|
||||
"RestartPolicy": {
|
||||
"Name": "always",
|
||||
"MaximumRetryCount": 0
|
||||
},
|
||||
"AutoRemove": false,
|
||||
"VolumeDriver": "",
|
||||
"VolumesFrom": null,
|
||||
"CapAdd": [],
|
||||
"CapDrop": [],
|
||||
"Dns": [],
|
||||
"DnsOptions": [],
|
||||
"DnsSearch": [],
|
||||
"ExtraHosts": [],
|
||||
"GroupAdd": [],
|
||||
"IpcMode": "shareable",
|
||||
"Cgroup": "",
|
||||
"Links": null,
|
||||
"OomScoreAdj": 0,
|
||||
"PidMode": "",
|
||||
"Privileged": false,
|
||||
"PublishAllPorts": false,
|
||||
"ReadonlyRootfs": false,
|
||||
"SecurityOpt": [],
|
||||
"UTSMode": "",
|
||||
"UsernsMode": "",
|
||||
"ShmSize": 67108864,
|
||||
"Runtime": "runc",
|
||||
"ConsoleSize": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"Isolation": "",
|
||||
"CpuShares": 0,
|
||||
"Memory": 0,
|
||||
"NanoCpus": 0,
|
||||
"CgroupParent": "",
|
||||
"BlkioWeight": 0,
|
||||
"BlkioWeightDevice": null,
|
||||
"BlkioDeviceReadBps": null,
|
||||
"BlkioDeviceWriteBps": null,
|
||||
"BlkioDeviceReadIOps": null,
|
||||
"BlkioDeviceWriteIOps": null,
|
||||
"CpuPeriod": 0,
|
||||
"CpuQuota": 0,
|
||||
"CpuRealtimePeriod": 0,
|
||||
"CpuRealtimeRuntime": 0,
|
||||
"CpusetCpus": "",
|
||||
"CpusetMems": "",
|
||||
"Devices": [],
|
||||
"DeviceCgroupRules": null,
|
||||
"DiskQuota": 0,
|
||||
"KernelMemory": 0,
|
||||
"MemoryReservation": 0,
|
||||
"MemorySwap": 0,
|
||||
"MemorySwappiness": -1,
|
||||
"OomKillDisable": false,
|
||||
"PidsLimit": 0,
|
||||
"Ulimits": [],
|
||||
"CpuCount": 0,
|
||||
"CpuPercent": 0,
|
||||
"IOMaximumIOps": 0,
|
||||
"IOMaximumBandwidth": 0,
|
||||
"Init": true
|
||||
},
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": "aufs"
|
||||
},
|
||||
"Mounts": [
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/tmp/balena-supervisor/services/1011165/main",
|
||||
"Destination": "/tmp/resin",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
},
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/tmp/balena-supervisor/services/1011165/main",
|
||||
"Destination": "/tmp/balena",
|
||||
"Mode": "",
|
||||
"RW": true,
|
||||
"Propagation": "rprivate"
|
||||
}
|
||||
],
|
||||
"Config": {
|
||||
"Hostname": "52cfd7a64d50",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"AttachStderr": false,
|
||||
"Tty": true,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Env": [
|
||||
"RESIN_APP_ID=1011165",
|
||||
"RESIN_APP_UUID=aaaaaaaa",
|
||||
"RESIN_APP_NAME=supervisortest",
|
||||
"RESIN_SERVICE_NAME=main",
|
||||
"RESIN_DEVICE_UUID=a7feb967fac7f559ccf2a006a36bcf5d",
|
||||
"RESIN_DEVICE_ARCH=amd64",
|
||||
"RESIN_DEVICE_TYPE=raspberrypi3",
|
||||
"RESIN_HOST_OS_VERSION=Resin OS 2.13.6+rev1",
|
||||
"RESIN_APP_LOCK_PATH=/tmp/balena/updates.lock",
|
||||
"RESIN_SERVICE_KILL_ME_PATH=/tmp/balena/handover-complete",
|
||||
"RESIN=1",
|
||||
"BALENA_APP_ID=1011165",
|
||||
"BALENA_APP_UUID=aaaaaaaa",
|
||||
"BALENA_APP_NAME=supervisortest",
|
||||
"BALENA_SERVICE_NAME=main",
|
||||
"BALENA_DEVICE_UUID=a7feb967fac7f559ccf2a006a36bcf5d",
|
||||
"BALENA_DEVICE_ARCH=amd64",
|
||||
"BALENA_DEVICE_TYPE=raspberrypi3",
|
||||
"BALENA_HOST_OS_VERSION=Resin OS 2.13.6+rev1",
|
||||
"BALENA_APP_LOCK_PATH=/tmp/balena/updates.lock",
|
||||
"BALENA_SERVICE_HANDOVER_COMPLETE_PATH=/tmp/balena/handover-complete",
|
||||
"BALENA=1",
|
||||
"USER=root",
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
],
|
||||
"Cmd": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
"while true; do echo 'hello'; sleep 5; done;"
|
||||
],
|
||||
"Healthcheck": {
|
||||
"Test": [
|
||||
"NONE"
|
||||
]
|
||||
},
|
||||
"Image": "sha256:7f54fa690ce19a1f625b04479ae1f12f44d36112a74be7edfefa777ecfdb194b",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": null,
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"io.resin.app-id": "1011165",
|
||||
"io.balena.app-uuid": "aaaaaaaa",
|
||||
"io.resin.service-id": "43697",
|
||||
"io.resin.service-name": "main",
|
||||
"io.resin.supervised": "true"
|
||||
},
|
||||
"StopTimeout": 0
|
||||
},
|
||||
"NetworkSettings": {
|
||||
"Bridge": "",
|
||||
"SandboxID": "bf4952b7f6695a8f05da1807946723b37e1041b8f41588678d6dece310270990",
|
||||
"HairpinMode": false,
|
||||
"LinkLocalIPv6Address": "",
|
||||
"LinkLocalIPv6PrefixLen": 0,
|
||||
"Ports": {},
|
||||
"SandboxKey": "/var/run/balena/netns/bf4952b7f669",
|
||||
"SecondaryIPAddresses": null,
|
||||
"SecondaryIPv6Addresses": null,
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"MacAddress": "",
|
||||
"Networks": {
|
||||
"aaaaaaaa_default": {
|
||||
"IPAMConfig": {},
|
||||
"Links": null,
|
||||
"Aliases": [
|
||||
"main",
|
||||
"52cfd7a64d50"
|
||||
],
|
||||
"NetworkID": "f88716ed3d340f1b9aa61df22d92ce6ad8aa752d8bf8e4aa6e74142dea677465",
|
||||
"EndpointID": "",
|
||||
"Gateway": "",
|
||||
"IPAddress": "",
|
||||
"IPPrefixLen": 0,
|
||||
"IPv6Gateway": "",
|
||||
"GlobalIPv6Address": "",
|
||||
"GlobalIPv6PrefixLen": 0,
|
||||
"MacAddress": "",
|
||||
"DriverOpts": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,11 @@ const configs = {
|
||||
imageInfo: require('~/test-data/docker-states/network-mode-service/imageInfo.json'),
|
||||
inspect: require('~/test-data/docker-states/network-mode-service/inspect.json'),
|
||||
},
|
||||
init: {
|
||||
compose: require('~/test-data/docker-states/init/compose.json'),
|
||||
imageInfo: require('~/test-data/docker-states/init/imageInfo.json'),
|
||||
inspect: require('~/test-data/docker-states/init/inspect.json'),
|
||||
},
|
||||
};
|
||||
|
||||
describe('compose/service: unit tests', () => {
|
||||
@ -263,6 +268,31 @@ describe('compose/service: unit tests', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should support init property', async () => {
|
||||
const appConfigWithInit = (init?: boolean) => ({
|
||||
appId: 123,
|
||||
serviceId: 123,
|
||||
serviceName: 'test',
|
||||
composition: {
|
||||
init,
|
||||
},
|
||||
});
|
||||
const svc = await Service.fromComposeObject(appConfigWithInit(true), {
|
||||
appName: 'test',
|
||||
} as any);
|
||||
expect(svc.config).to.have.property('init').that.equals(true);
|
||||
|
||||
const svc2 = await Service.fromComposeObject(appConfigWithInit(false), {
|
||||
appName: 'test',
|
||||
} as any);
|
||||
expect(svc2.config).to.have.property('init').that.equals(false);
|
||||
|
||||
const svc3 = await Service.fromComposeObject(appConfigWithInit(), {
|
||||
appName: 'test',
|
||||
} as any);
|
||||
expect(svc3.config).to.not.have.property('init');
|
||||
});
|
||||
|
||||
describe('Parsing memory strings from compose configuration', () => {
|
||||
const makeComposeServiceWithLimit = async (memLimit?: string | number) =>
|
||||
await Service.fromComposeObject(
|
||||
@ -898,6 +928,20 @@ describe('compose/service: unit tests', () => {
|
||||
expect(dockerSvc.isEqualConfig(composeSvc, {})).to.equals(true);
|
||||
});
|
||||
|
||||
it('should correctly handle the init config', async () => {
|
||||
const composeSvc = await Service.fromComposeObject(
|
||||
configs.init.compose,
|
||||
configs.init.imageInfo,
|
||||
);
|
||||
const dockerSvc = Service.fromDockerContainer(configs.init.inspect);
|
||||
|
||||
const composeConfig = omitConfigForComparison(composeSvc.config);
|
||||
const dockerConfig = omitConfigForComparison(dockerSvc.config);
|
||||
expect(composeConfig).to.deep.equal(dockerConfig);
|
||||
|
||||
expect(dockerSvc.isEqualConfig(composeSvc, {})).to.equals(true);
|
||||
});
|
||||
|
||||
describe('Networks', () => {
|
||||
it('should correctly convert Docker format to service format', () => {
|
||||
const { inspectInfo } = createContainer({
|
||||
|
Loading…
x
Reference in New Issue
Block a user