mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-04-19 08:36:14 +00:00
Merge pull request #2040 from balena-os/docker-utils
Migrate some more legacy tests to integration
This commit is contained in:
commit
156aac4b02
38
package-lock.json
generated
38
package-lock.json
generated
@ -96,7 +96,7 @@
|
||||
"rimraf": "^2.7.1",
|
||||
"rwlock": "^5.0.0",
|
||||
"shell-quote": "^1.7.2",
|
||||
"sinon": "^11.1.2",
|
||||
"sinon": "^14.0.1",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"strict-event-emitter-types": "^2.0.0",
|
||||
"supertest": "^6.1.3",
|
||||
@ -1128,9 +1128,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/fake-timers": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz",
|
||||
"integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==",
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
|
||||
"integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
@ -10770,16 +10770,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sinon": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz",
|
||||
"integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==",
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.1.tgz",
|
||||
"integrity": "sha512-JhJ0jCiyBWVAHDS+YSjgEbDn7Wgz9iIjA1/RK+eseJN0vAAWIWiXBdrnb92ELPyjsfreCYntD1ORtLSfIrlvSQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sinonjs/commons": "^1.8.3",
|
||||
"@sinonjs/fake-timers": "^7.1.2",
|
||||
"@sinonjs/samsam": "^6.0.2",
|
||||
"@sinonjs/fake-timers": "^9.1.2",
|
||||
"@sinonjs/samsam": "^6.1.1",
|
||||
"diff": "^5.0.0",
|
||||
"nise": "^5.1.0",
|
||||
"nise": "^5.1.1",
|
||||
"supports-color": "^7.2.0"
|
||||
},
|
||||
"funding": {
|
||||
@ -14170,9 +14170,9 @@
|
||||
}
|
||||
},
|
||||
"@sinonjs/fake-timers": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz",
|
||||
"integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==",
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
|
||||
"integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1.7.0"
|
||||
@ -21907,16 +21907,16 @@
|
||||
}
|
||||
},
|
||||
"sinon": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz",
|
||||
"integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==",
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.1.tgz",
|
||||
"integrity": "sha512-JhJ0jCiyBWVAHDS+YSjgEbDn7Wgz9iIjA1/RK+eseJN0vAAWIWiXBdrnb92ELPyjsfreCYntD1ORtLSfIrlvSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1.8.3",
|
||||
"@sinonjs/fake-timers": "^7.1.2",
|
||||
"@sinonjs/samsam": "^6.0.2",
|
||||
"@sinonjs/fake-timers": "^9.1.2",
|
||||
"@sinonjs/samsam": "^6.1.1",
|
||||
"diff": "^5.0.0",
|
||||
"nise": "^5.1.0",
|
||||
"nise": "^5.1.1",
|
||||
"supports-color": "^7.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -122,7 +122,7 @@
|
||||
"rimraf": "^2.7.1",
|
||||
"rwlock": "^5.0.0",
|
||||
"shell-quote": "^1.7.2",
|
||||
"sinon": "^11.1.2",
|
||||
"sinon": "^14.0.1",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"strict-event-emitter-types": "^2.0.0",
|
||||
"supertest": "^6.1.3",
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { expect } from 'chai';
|
||||
import { isRight } from 'fp-ts/lib/Either';
|
||||
import * as sinon from 'sinon';
|
||||
import App from '~/src/compose/app';
|
||||
import Network from '~/src/compose/network';
|
||||
import * as config from '~/src/config';
|
||||
import * as testDb from '~/src/db';
|
||||
import * as dbFormat from '~/src/device-state/db-format';
|
||||
import log from '~/lib/supervisor-console';
|
||||
import { TargetApps } from '~/src/types/state';
|
||||
import * as dbHelper from '~/test-lib/db-helper';
|
||||
|
||||
function getDefaultNetwork(appId: number) {
|
||||
return {
|
||||
@ -15,15 +13,10 @@ function getDefaultNetwork(appId: number) {
|
||||
};
|
||||
}
|
||||
|
||||
describe('db-format', () => {
|
||||
let testDb: dbHelper.TestDatabase;
|
||||
describe('device-state/db-format', () => {
|
||||
let apiEndpoint: string;
|
||||
before(async () => {
|
||||
testDb = await dbHelper.createDB();
|
||||
|
||||
await config.initialized();
|
||||
// Prevent side effects from changes in config
|
||||
sinon.stub(config, 'on');
|
||||
|
||||
// TargetStateCache checks the API endpoint to
|
||||
// store and invalidate the cache
|
||||
@ -31,26 +24,14 @@ describe('db-format', () => {
|
||||
// should not be part of the test suite. We need to change
|
||||
// the target state architecture for this
|
||||
apiEndpoint = await config.get('apiEndpoint');
|
||||
|
||||
// disable log output during testing
|
||||
sinon.stub(log, 'debug');
|
||||
sinon.stub(log, 'warn');
|
||||
sinon.stub(log, 'info');
|
||||
sinon.stub(log, 'event');
|
||||
sinon.stub(log, 'success');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
try {
|
||||
await testDb.destroy();
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await testDb.reset();
|
||||
// Delete all apps between calls to prevent leaking tests
|
||||
await testDb.models('app').del();
|
||||
|
||||
// Disable local mode by default
|
||||
await config.set({ localMode: false });
|
||||
});
|
||||
|
||||
it('converts target apps into the database format', async () => {
|
173
test/integration/lib/docker-utils.spec.ts
Normal file
173
test/integration/lib/docker-utils.spec.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import { expect } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
|
||||
import * as dockerUtils from '~/lib/docker-utils';
|
||||
import { createDockerImage } from '~/test-lib/docker-helper';
|
||||
import * as Docker from 'dockerode';
|
||||
|
||||
describe('lib/docker-utils', () => {
|
||||
const docker = new Docker();
|
||||
|
||||
describe('getNetworkGateway', async () => {
|
||||
before(async () => {
|
||||
await docker.createNetwork({
|
||||
Name: 'supervisor0',
|
||||
Options: {
|
||||
'com.docker.network.bridge.name': 'supervisor0',
|
||||
},
|
||||
IPAM: {
|
||||
Driver: 'default',
|
||||
Config: [
|
||||
{
|
||||
Gateway: '10.0.105.1',
|
||||
Subnet: '10.0.105.0/16',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
const allNetworks = await docker.listNetworks();
|
||||
|
||||
// Delete any remaining networks
|
||||
await Promise.all(
|
||||
allNetworks
|
||||
.filter(({ Name }) => !['bridge', 'host', 'none'].includes(Name)) // exclude docker default network from the cleanup
|
||||
.map(({ Name }) => docker.getNetwork(Name).remove()),
|
||||
);
|
||||
});
|
||||
|
||||
// test using existing data...
|
||||
it('should return the correct gateway address for supervisor0', async () => {
|
||||
const gateway = await dockerUtils.getNetworkGateway('supervisor0');
|
||||
expect(gateway).to.equal('10.0.105.1');
|
||||
});
|
||||
|
||||
it('should return the correct gateway address for host', async () => {
|
||||
const gateway = await dockerUtils.getNetworkGateway('host');
|
||||
expect(gateway).to.equal('127.0.0.1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getImageEnv', () => {
|
||||
before(async () => {
|
||||
await createDockerImage('test-image', ['io.balena.testing=1'], docker, [
|
||||
'ENV TEST_VAR_1=1234',
|
||||
'ENV TEST_VAR_2=5678',
|
||||
]);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await docker.pruneImages({ filters: { dangling: { false: true } } });
|
||||
});
|
||||
|
||||
// test using existing data...
|
||||
it('should return the correct image environment', async () => {
|
||||
const obj = await dockerUtils.getImageEnv('test-image');
|
||||
expect(obj).to.have.property('TEST_VAR_1').equal('1234');
|
||||
expect(obj).to.have.property('TEST_VAR_2').equal('5678');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isV2DeltaImage', () => {
|
||||
it('should correctly detect a V2 delta', async () => {
|
||||
// INFO: we still use the stub here. V2 deltas should eventually go away and there is no
|
||||
// really easy way to create a real image that simulates a v2 delta.
|
||||
const imageStub = stub(dockerUtils.docker, 'getImage').returns({
|
||||
inspect: () => {
|
||||
return Promise.resolve({
|
||||
Id: 'sha256:34ec91fe6e08cb0f867bbc069c5f499d39297eb8e874bb8ce9707537d983bcbc',
|
||||
RepoTags: [],
|
||||
RepoDigests: [],
|
||||
Parent: '',
|
||||
Comment: '',
|
||||
Created: '2019-12-05T10:20:51.516Z',
|
||||
Container: '',
|
||||
ContainerConfig: {
|
||||
Hostname: '',
|
||||
Domainname: '',
|
||||
User: '',
|
||||
AttachStdin: false,
|
||||
AttachStdout: false,
|
||||
AttachStderr: false,
|
||||
Tty: false,
|
||||
OpenStdin: false,
|
||||
StdinOnce: false,
|
||||
Env: null,
|
||||
Cmd: null,
|
||||
Image: '',
|
||||
Volumes: null,
|
||||
WorkingDir: '',
|
||||
Entrypoint: null,
|
||||
OnBuild: null,
|
||||
Labels: null,
|
||||
},
|
||||
DockerVersion: '',
|
||||
Author: '',
|
||||
Config: {
|
||||
Hostname: '7675a23f4fdc',
|
||||
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',
|
||||
'TINI_VERSION=0.14.0',
|
||||
'LC_ALL=C.UTF-8',
|
||||
'DEBIAN_FRONTEND=noninteractive',
|
||||
'UDEV=on',
|
||||
'container=docker',
|
||||
'test=123',
|
||||
],
|
||||
Cmd: [
|
||||
'/bin/sh',
|
||||
'-c',
|
||||
"while true; do echo 'hello'; sleep 10; done;",
|
||||
],
|
||||
ArgsEscaped: true,
|
||||
Image:
|
||||
'sha256:b24946093df7157727b20934d11a7287359d8de42d8a80030f51f46a73d645ec',
|
||||
Volumes: {
|
||||
'/sys/fs/cgroup': {},
|
||||
},
|
||||
WorkingDir: '',
|
||||
Entrypoint: ['/usr/bin/entry.sh'],
|
||||
OnBuild: [],
|
||||
Labels: {
|
||||
'io.resin.architecture': 'amd64',
|
||||
'io.resin.device-type': 'intel-nuc',
|
||||
},
|
||||
StopSignal: '37',
|
||||
},
|
||||
Architecture: '',
|
||||
Os: 'linux',
|
||||
Size: 17,
|
||||
VirtualSize: 17,
|
||||
GraphDriver: {
|
||||
Data: null,
|
||||
Name: 'aufs',
|
||||
},
|
||||
RootFS: {
|
||||
Type: 'layers',
|
||||
Layers: [
|
||||
'sha256:c6e6cd4f95ef00e62f5c9df5798393470c991ca0148cb1e434b28101ed4219d3',
|
||||
],
|
||||
},
|
||||
Metadata: {
|
||||
LastTagTime: '0001-01-01T00:00:00Z',
|
||||
},
|
||||
});
|
||||
},
|
||||
} as any);
|
||||
|
||||
expect(await dockerUtils.isV2DeltaImage('test')).to.be.true;
|
||||
expect(imageStub.callCount).to.equal(1);
|
||||
imageStub.restore();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,46 +1,32 @@
|
||||
import _ = require('lodash');
|
||||
import { expect } from 'chai';
|
||||
|
||||
import * as Docker from 'dockerode';
|
||||
import { docker } from '~/lib/docker-utils';
|
||||
import * as sinon from 'sinon';
|
||||
|
||||
import * as config from '~/src/config';
|
||||
import * as firewall from '~/lib/firewall';
|
||||
import * as logger from '~/src/logger';
|
||||
import * as iptablesMock from '~/test-lib/mocked-iptables';
|
||||
import * as targetStateCache from '~/src/device-state/target-state-cache';
|
||||
import * as dbFormat from '~/src/device-state/db-format';
|
||||
|
||||
import constants = require('~/lib/constants');
|
||||
import { RuleAction, Rule } from '~/lib/iptables';
|
||||
import { log } from '~/lib/supervisor-console';
|
||||
|
||||
describe('Host Firewall', function () {
|
||||
const dockerStubs: Dictionary<sinon.SinonStub> = {};
|
||||
describe('lib/firewall', function () {
|
||||
let loggerSpy: sinon.SinonSpy;
|
||||
let logSpy: sinon.SinonSpy;
|
||||
let logSpy: sinon.SinonStub;
|
||||
|
||||
let apiEndpoint: string;
|
||||
let listenPort: number;
|
||||
|
||||
before(async () => {
|
||||
await config.initialized();
|
||||
|
||||
// spy the logs...
|
||||
loggerSpy = sinon.spy(logger, 'logSystemMessage');
|
||||
logSpy = sinon.spy(log, 'error');
|
||||
logSpy = log.error as sinon.SinonStub;
|
||||
|
||||
// stub the docker calls...
|
||||
dockerStubs.listContainers = sinon
|
||||
.stub(docker, 'listContainers')
|
||||
.resolves([]);
|
||||
dockerStubs.listImages = sinon.stub(docker, 'listImages').resolves([]);
|
||||
dockerStubs.getImage = sinon.stub(docker, 'getImage').returns({
|
||||
id: 'abcde',
|
||||
inspect: async () => {
|
||||
return {};
|
||||
},
|
||||
} as Docker.Image);
|
||||
|
||||
await targetStateCache.initialized();
|
||||
await firewall.initialised();
|
||||
|
||||
apiEndpoint = await config.get('apiEndpoint');
|
||||
@ -48,11 +34,7 @@ describe('Host Firewall', function () {
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
for (const stub of _.values(dockerStubs)) {
|
||||
stub.restore();
|
||||
}
|
||||
loggerSpy.restore();
|
||||
logSpy.restore();
|
||||
});
|
||||
|
||||
describe('Basic On/Off operation', () => {
|
||||
@ -158,35 +140,38 @@ describe('Host Firewall', function () {
|
||||
it('should respect the HOST_FIREWALL_MODE configuration value: auto (no services in host-network)', async function () {
|
||||
await iptablesMock.whilstMocked(
|
||||
async ({ hasAppliedRules, expectRule }) => {
|
||||
await targetStateCache.setTargetApps([
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
appId: 2,
|
||||
uuid: 'myapp',
|
||||
commit: 'abcdef2',
|
||||
name: 'test-app2',
|
||||
class: 'fleet',
|
||||
source: apiEndpoint,
|
||||
releaseId: 1232,
|
||||
isHost: false,
|
||||
services: JSON.stringify([
|
||||
{
|
||||
serviceName: 'test-service',
|
||||
image: 'test-image',
|
||||
imageId: 5,
|
||||
environment: {
|
||||
TEST_VAR: 'test-string',
|
||||
myapp: {
|
||||
id: 2,
|
||||
name: 'test-app2',
|
||||
class: 'fleet',
|
||||
is_host: false,
|
||||
releases: {
|
||||
abcdef2: {
|
||||
id: 1232,
|
||||
services: {
|
||||
'test-service': {
|
||||
id: 567,
|
||||
image: 'test-image',
|
||||
image_id: 5,
|
||||
environment: {
|
||||
TEST_VAR: 'test-string',
|
||||
},
|
||||
labels: {},
|
||||
composition: {
|
||||
tty: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
networks: {},
|
||||
volumes: {},
|
||||
},
|
||||
tty: true,
|
||||
appId: 2,
|
||||
releaseId: 1232,
|
||||
serviceId: 567,
|
||||
commit: 'abcdef2',
|
||||
},
|
||||
]),
|
||||
networks: '[]',
|
||||
volumes: '[]',
|
||||
},
|
||||
},
|
||||
]);
|
||||
apiEndpoint,
|
||||
);
|
||||
|
||||
// set the firewall to be in auto mode...
|
||||
await config.set({ firewallMode: 'auto' });
|
||||
@ -213,38 +198,39 @@ describe('Host Firewall', function () {
|
||||
it('should respect the HOST_FIREWALL_MODE configuration value: auto (service in host-network)', async function () {
|
||||
await iptablesMock.whilstMocked(
|
||||
async ({ hasAppliedRules, expectRule, expectNoRule }) => {
|
||||
await targetStateCache.setTargetApps([
|
||||
await dbFormat.setApps(
|
||||
{
|
||||
appId: 2,
|
||||
uuid: 'myapp',
|
||||
commit: 'abcdef2',
|
||||
name: 'test-app2',
|
||||
source: apiEndpoint,
|
||||
class: 'fleet',
|
||||
releaseId: 1232,
|
||||
isHost: false,
|
||||
services: JSON.stringify([
|
||||
{
|
||||
serviceName: 'test-service',
|
||||
image: 'test-image',
|
||||
imageId: 5,
|
||||
environment: {
|
||||
TEST_VAR: 'test-string',
|
||||
},
|
||||
appId: 2,
|
||||
releaseId: 1232,
|
||||
serviceId: 567,
|
||||
commit: 'abcdef2',
|
||||
composition: {
|
||||
tty: true,
|
||||
network_mode: 'host',
|
||||
myapp: {
|
||||
id: 2,
|
||||
name: 'test-app2',
|
||||
class: 'fleet',
|
||||
is_host: false,
|
||||
releases: {
|
||||
abcdef2: {
|
||||
id: 1232,
|
||||
services: {
|
||||
'test-service': {
|
||||
id: 567,
|
||||
image: 'test-image',
|
||||
image_id: 5,
|
||||
environment: {
|
||||
TEST_VAR: 'test-string',
|
||||
},
|
||||
labels: {},
|
||||
composition: {
|
||||
tty: true,
|
||||
network_mode: 'host',
|
||||
},
|
||||
},
|
||||
},
|
||||
networks: {},
|
||||
volumes: {},
|
||||
},
|
||||
},
|
||||
]),
|
||||
networks: '[]',
|
||||
volumes: '[]',
|
||||
},
|
||||
},
|
||||
]);
|
||||
apiEndpoint,
|
||||
);
|
||||
|
||||
// set the firewall to be in auto mode...
|
||||
await config.set({ firewallMode: 'auto' });
|
@ -1,103 +0,0 @@
|
||||
import { expect } from 'chai';
|
||||
import { stub } from 'sinon';
|
||||
|
||||
import * as dockerUtils from '~/lib/docker-utils';
|
||||
|
||||
describe('Deltas', () => {
|
||||
it('should correctly detect a V2 delta', async () => {
|
||||
const imageStub = stub(dockerUtils.docker, 'getImage').returns({
|
||||
inspect: () => {
|
||||
return Promise.resolve({
|
||||
Id: 'sha256:34ec91fe6e08cb0f867bbc069c5f499d39297eb8e874bb8ce9707537d983bcbc',
|
||||
RepoTags: [],
|
||||
RepoDigests: [],
|
||||
Parent: '',
|
||||
Comment: '',
|
||||
Created: '2019-12-05T10:20:51.516Z',
|
||||
Container: '',
|
||||
ContainerConfig: {
|
||||
Hostname: '',
|
||||
Domainname: '',
|
||||
User: '',
|
||||
AttachStdin: false,
|
||||
AttachStdout: false,
|
||||
AttachStderr: false,
|
||||
Tty: false,
|
||||
OpenStdin: false,
|
||||
StdinOnce: false,
|
||||
Env: null,
|
||||
Cmd: null,
|
||||
Image: '',
|
||||
Volumes: null,
|
||||
WorkingDir: '',
|
||||
Entrypoint: null,
|
||||
OnBuild: null,
|
||||
Labels: null,
|
||||
},
|
||||
DockerVersion: '',
|
||||
Author: '',
|
||||
Config: {
|
||||
Hostname: '7675a23f4fdc',
|
||||
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',
|
||||
'TINI_VERSION=0.14.0',
|
||||
'LC_ALL=C.UTF-8',
|
||||
'DEBIAN_FRONTEND=noninteractive',
|
||||
'UDEV=on',
|
||||
'container=docker',
|
||||
'test=123',
|
||||
],
|
||||
Cmd: [
|
||||
'/bin/sh',
|
||||
'-c',
|
||||
"while true; do echo 'hello'; sleep 10; done;",
|
||||
],
|
||||
ArgsEscaped: true,
|
||||
Image:
|
||||
'sha256:b24946093df7157727b20934d11a7287359d8de42d8a80030f51f46a73d645ec',
|
||||
Volumes: {
|
||||
'/sys/fs/cgroup': {},
|
||||
},
|
||||
WorkingDir: '',
|
||||
Entrypoint: ['/usr/bin/entry.sh'],
|
||||
OnBuild: [],
|
||||
Labels: {
|
||||
'io.resin.architecture': 'amd64',
|
||||
'io.resin.device-type': 'intel-nuc',
|
||||
},
|
||||
StopSignal: '37',
|
||||
},
|
||||
Architecture: '',
|
||||
Os: 'linux',
|
||||
Size: 17,
|
||||
VirtualSize: 17,
|
||||
GraphDriver: {
|
||||
Data: null,
|
||||
Name: 'aufs',
|
||||
},
|
||||
RootFS: {
|
||||
Type: 'layers',
|
||||
Layers: [
|
||||
'sha256:c6e6cd4f95ef00e62f5c9df5798393470c991ca0148cb1e434b28101ed4219d3',
|
||||
],
|
||||
},
|
||||
Metadata: {
|
||||
LastTagTime: '0001-01-01T00:00:00Z',
|
||||
},
|
||||
});
|
||||
},
|
||||
} as any);
|
||||
|
||||
expect(await dockerUtils.isV2DeltaImage('test')).to.be.true;
|
||||
expect(imageStub.callCount).to.equal(1);
|
||||
imageStub.restore();
|
||||
});
|
||||
});
|
@ -1,56 +0,0 @@
|
||||
import { expect } from 'chai';
|
||||
import { testWithData } from '~/test-lib/mocked-dockerode';
|
||||
|
||||
import * as dockerUtils from '~/lib/docker-utils';
|
||||
|
||||
describe('Docker Utils', () => {
|
||||
describe('Supervisor Address', () => {
|
||||
// setup some fake data...
|
||||
const networks = {
|
||||
supervisor0: {
|
||||
IPAM: {
|
||||
Config: [
|
||||
{
|
||||
Gateway: '10.0.105.1',
|
||||
Subnet: '10.0.105.0/16',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// test using existing data...
|
||||
it('should return the correct gateway address for supervisor0', async () => {
|
||||
await testWithData({ networks }, async () => {
|
||||
const gateway = await dockerUtils.getNetworkGateway('supervisor0');
|
||||
expect(gateway).to.equal('10.0.105.1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the correct gateway address for host', async () => {
|
||||
await testWithData({ networks }, async () => {
|
||||
const gateway = await dockerUtils.getNetworkGateway('host');
|
||||
expect(gateway).to.equal('127.0.0.1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Image Environment', () => {
|
||||
const images = {
|
||||
['test-image']: {
|
||||
Config: {
|
||||
Env: ['TEST_VAR_1=1234', 'TEST_VAR_2=5678'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// test using existing data...
|
||||
it('should return the correct image environment', async () => {
|
||||
await testWithData({ images }, async () => {
|
||||
const obj = await dockerUtils.getImageEnv('test-image');
|
||||
expect(obj).to.have.property('TEST_VAR_1').equal('1234');
|
||||
expect(obj).to.have.property('TEST_VAR_2').equal('5678');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -8,11 +8,15 @@ export async function createDockerImage(
|
||||
name: string,
|
||||
labels: [string, ...string[]],
|
||||
docker = new Docker(),
|
||||
extra = [] as string[], // Additional instructions to add to the dockerfile
|
||||
): Promise<string> {
|
||||
const pack = tar.pack(); // pack is a streams2 stream
|
||||
pack.entry(
|
||||
{ name: 'Dockerfile' },
|
||||
['FROM scratch'].concat(labels.map((l) => `LABEL ${l}`)).join('\n'),
|
||||
['FROM scratch']
|
||||
.concat(labels.map((l) => `LABEL ${l}`))
|
||||
.concat(extra)
|
||||
.join('\n'),
|
||||
(err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
|
@ -136,11 +136,11 @@ export const whilstMocked = async (
|
||||
|
||||
const stdin = new Writable();
|
||||
stdin._write = (
|
||||
chunk: Buffer,
|
||||
_chunk: Buffer,
|
||||
_encoding: string,
|
||||
callback: (err?: Error) => void,
|
||||
) => {
|
||||
console.log(chunk.toString('utf8'));
|
||||
// console.log(chunk.toString('utf8'));
|
||||
callback();
|
||||
fakeProc.emit('close', 1);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ import { NetworkInspectInfo } from 'dockerode';
|
||||
|
||||
import { log } from '~/lib/supervisor-console';
|
||||
|
||||
describe('compose/network: unit tests', () => {
|
||||
describe('compose/network', () => {
|
||||
describe('creating a network from a compose object', () => {
|
||||
it('creates a default network configuration if no config is given', () => {
|
||||
const network = Network.fromComposeObject(
|
||||
|
Loading…
x
Reference in New Issue
Block a user