mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-25 16:31:05 +00:00
9bd216327f
PR #2217 removed the expose configuration but also caused a regresion where ports set via the `ports` configuration would no longer get exposed to the host, despite portmappings being set. This fixes that issue by exposing only those ports comming from port mappings. Change-type: patch
399 lines
10 KiB
TypeScript
399 lines
10 KiB
TypeScript
import { PortMap, PortRange } from '~/src/compose/ports';
|
|
import { expect } from 'chai';
|
|
|
|
// Force cast `PortMap` as a public version so we can test it
|
|
const PortMapPublic = PortMap as any as new (
|
|
portStrOrObj: string | PortRange,
|
|
) => PortMap;
|
|
|
|
describe('compose/ports', function () {
|
|
describe('Port string parsing', function () {
|
|
it('should correctly parse a port string without a range', function () {
|
|
expect(new PortMapPublic('80')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 80,
|
|
internalEnd: 80,
|
|
externalStart: 80,
|
|
externalEnd: 80,
|
|
protocol: 'tcp',
|
|
host: '',
|
|
}),
|
|
);
|
|
|
|
expect(new PortMapPublic('80:80')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 80,
|
|
internalEnd: 80,
|
|
externalStart: 80,
|
|
externalEnd: 80,
|
|
protocol: 'tcp',
|
|
host: '',
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('should correctly parse a port string without an external range', () =>
|
|
expect(new PortMapPublic('80-90')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 80,
|
|
internalEnd: 90,
|
|
externalStart: 80,
|
|
externalEnd: 90,
|
|
protocol: 'tcp',
|
|
host: '',
|
|
}),
|
|
));
|
|
|
|
it('should correctly parse a port string with a range', () =>
|
|
expect(new PortMapPublic('80-100:100-120')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 120,
|
|
externalStart: 80,
|
|
externalEnd: 100,
|
|
protocol: 'tcp',
|
|
host: '',
|
|
}),
|
|
));
|
|
|
|
it('should correctly parse a protocol', function () {
|
|
expect(new PortMapPublic('80/udp')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 80,
|
|
internalEnd: 80,
|
|
externalStart: 80,
|
|
externalEnd: 80,
|
|
protocol: 'udp',
|
|
host: '',
|
|
}),
|
|
);
|
|
|
|
expect(new PortMapPublic('80:80/udp')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 80,
|
|
internalEnd: 80,
|
|
externalStart: 80,
|
|
externalEnd: 80,
|
|
protocol: 'udp',
|
|
host: '',
|
|
}),
|
|
);
|
|
|
|
expect(new PortMapPublic('80-90:100-110/udp')).to.deep.equal(
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 110,
|
|
externalStart: 80,
|
|
externalEnd: 90,
|
|
protocol: 'udp',
|
|
host: '',
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('should throw when the port string is incorrect', () =>
|
|
expect(() => new PortMapPublic('80-90:80-85')).to.throw);
|
|
});
|
|
|
|
describe('toDockerOpts', function () {
|
|
it('should correctly generate docker options', () =>
|
|
expect(new PortMapPublic('80').toDockerOpts()).to.deep.equal({
|
|
exposedPorts: {
|
|
'80/tcp': {},
|
|
},
|
|
portBindings: {
|
|
'80/tcp': [{ HostIp: '', HostPort: '80' }],
|
|
},
|
|
}));
|
|
|
|
it('should correctly generate docker options for a port range', () =>
|
|
expect(new PortMapPublic('80-85').toDockerOpts()).to.deep.equal({
|
|
exposedPorts: {
|
|
'80/tcp': {},
|
|
'81/tcp': {},
|
|
'82/tcp': {},
|
|
'83/tcp': {},
|
|
'84/tcp': {},
|
|
'85/tcp': {},
|
|
},
|
|
portBindings: {
|
|
'80/tcp': [{ HostIp: '', HostPort: '80' }],
|
|
'81/tcp': [{ HostIp: '', HostPort: '81' }],
|
|
'82/tcp': [{ HostIp: '', HostPort: '82' }],
|
|
'83/tcp': [{ HostIp: '', HostPort: '83' }],
|
|
'84/tcp': [{ HostIp: '', HostPort: '84' }],
|
|
'85/tcp': [{ HostIp: '', HostPort: '85' }],
|
|
},
|
|
}));
|
|
});
|
|
|
|
describe('fromDockerOpts', function () {
|
|
it('should correctly detect a port range', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [{ HostIp: '123', HostPort: '200' }],
|
|
'101/tcp': [{ HostIp: '123', HostPort: '201' }],
|
|
'102/tcp': [{ HostIp: '123', HostPort: '202' }],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 102,
|
|
externalStart: 200,
|
|
externalEnd: 202,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
]));
|
|
|
|
it('should correctly split ports into ranges', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [{ HostIp: '123', HostPort: '200' }],
|
|
'101/tcp': [{ HostIp: '123', HostPort: '201' }],
|
|
'105/tcp': [{ HostIp: '123', HostPort: '205' }],
|
|
'106/tcp': [{ HostIp: '123', HostPort: '206' }],
|
|
'110/tcp': [{ HostIp: '123', HostPort: '210' }],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 101,
|
|
externalStart: 200,
|
|
externalEnd: 201,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 105,
|
|
internalEnd: 106,
|
|
externalStart: 205,
|
|
externalEnd: 206,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 110,
|
|
internalEnd: 110,
|
|
externalStart: 210,
|
|
externalEnd: 210,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
]));
|
|
|
|
it('should correctly consider internal and external ports', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [{ HostIp: '123', HostPort: '200' }],
|
|
'101/tcp': [{ HostIp: '123', HostPort: '101' }],
|
|
'102/tcp': [{ HostIp: '123', HostPort: '202' }],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 100,
|
|
externalStart: 200,
|
|
externalEnd: 200,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 101,
|
|
internalEnd: 101,
|
|
externalStart: 101,
|
|
externalEnd: 101,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 102,
|
|
internalEnd: 102,
|
|
externalStart: 202,
|
|
externalEnd: 202,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
]));
|
|
|
|
it('should consider the host when generating ranges', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [{ HostIp: '123', HostPort: '200' }],
|
|
'101/tcp': [{ HostIp: '456', HostPort: '201' }],
|
|
'102/tcp': [{ HostIp: '456', HostPort: '202' }],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 100,
|
|
externalStart: 200,
|
|
externalEnd: 200,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 101,
|
|
internalEnd: 102,
|
|
externalStart: 201,
|
|
externalEnd: 202,
|
|
protocol: 'tcp',
|
|
host: '456',
|
|
}),
|
|
]));
|
|
|
|
it('should consider the protocol when generating ranges', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [{ HostIp: '123', HostPort: '200' }],
|
|
'101/udp': [{ HostIp: '123', HostPort: '201' }],
|
|
'102/udp': [{ HostIp: '123', HostPort: '202' }],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 100,
|
|
externalStart: 200,
|
|
externalEnd: 200,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 101,
|
|
internalEnd: 102,
|
|
externalStart: 201,
|
|
externalEnd: 202,
|
|
protocol: 'udp',
|
|
host: '123',
|
|
}),
|
|
]));
|
|
|
|
it('should correctly detect multiple hosts ports on an internal port', () =>
|
|
expect(
|
|
PortMap.fromDockerOpts({
|
|
'100/tcp': [
|
|
{ HostIp: '123', HostPort: '200' },
|
|
{ HostIp: '123', HostPort: '201' },
|
|
],
|
|
}),
|
|
).to.deep.equal([
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 100,
|
|
externalStart: 200,
|
|
externalEnd: 200,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
new PortMapPublic({
|
|
internalStart: 100,
|
|
internalEnd: 100,
|
|
externalStart: 201,
|
|
externalEnd: 201,
|
|
protocol: 'tcp',
|
|
host: '123',
|
|
}),
|
|
]));
|
|
});
|
|
|
|
describe('Running container comparison', () =>
|
|
it('should not consider order when comparing current and target state', function () {
|
|
const portBindings = require('~/test-data/ports/not-ascending/port-bindings.json');
|
|
const compose = require('~/test-data/ports/not-ascending/compose.json');
|
|
const portMapsCurrent = PortMap.fromDockerOpts(portBindings);
|
|
const portMapsTarget = PortMap.fromComposePorts(compose.ports);
|
|
|
|
expect(portMapsTarget).to.deep.equal(portMapsCurrent);
|
|
}));
|
|
|
|
describe('fromComposePorts', () =>
|
|
it('should normalise compose ports', () =>
|
|
expect(
|
|
PortMap.fromComposePorts(['80:80', '81:81', '82:82']),
|
|
).to.deep.equal([new PortMapPublic('80-82')])));
|
|
|
|
describe('normalisePortMaps', function () {
|
|
it('should correctly normalise PortMap lists', function () {
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('81:91'),
|
|
]),
|
|
).to.deep.equal([new PortMapPublic('80-81:90-91')]);
|
|
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('81:91'),
|
|
new PortMapPublic('82:92'),
|
|
new PortMapPublic('83:93'),
|
|
new PortMapPublic('84:94'),
|
|
new PortMapPublic('85:95'),
|
|
new PortMapPublic('86:96'),
|
|
new PortMapPublic('87:97'),
|
|
new PortMapPublic('88:98'),
|
|
new PortMapPublic('89:99'),
|
|
new PortMapPublic('90:100'),
|
|
]),
|
|
).to.deep.equal([new PortMapPublic('80-90:90-100')]);
|
|
|
|
expect(PortMap.normalisePortMaps([])).to.deep.equal([]);
|
|
});
|
|
|
|
it('should correctly consider protocols', function () {
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('81:91/udp'),
|
|
]),
|
|
).to.deep.equal([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('81:91/udp'),
|
|
]);
|
|
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('100:110/udp'),
|
|
new PortMapPublic('81:91'),
|
|
]),
|
|
).to.deep.equal([
|
|
new PortMapPublic('80-81:90-91'),
|
|
new PortMapPublic('100:110/udp'),
|
|
]);
|
|
|
|
// This shouldn't ever be provided, but it shows the algorithm
|
|
// working properly
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('80:90'),
|
|
new PortMapPublic('81:91/udp'),
|
|
new PortMapPublic('81:91'),
|
|
]),
|
|
).to.deep.equal([
|
|
new PortMapPublic('80-81:90-91'),
|
|
new PortMapPublic('81:91/udp'),
|
|
]);
|
|
});
|
|
|
|
it('should correctly consider hosts', function () {
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('127.0.0.1:80:80'),
|
|
new PortMapPublic('81:81'),
|
|
]),
|
|
).to.deep.equal([
|
|
new PortMapPublic('127.0.0.1:80:80'),
|
|
new PortMapPublic('81:81'),
|
|
]);
|
|
|
|
expect(
|
|
PortMap.normalisePortMaps([
|
|
new PortMapPublic('127.0.0.1:80:80'),
|
|
new PortMapPublic('127.0.0.1:81:81'),
|
|
]),
|
|
).to.deep.equal([new PortMapPublic('127.0.0.1:80-81:80-81')]);
|
|
});
|
|
});
|
|
});
|