Merge pull request #969 from balena-io/968-multiple-ports

Handle multiple host ports pointing to a single container port
This commit is contained in:
CameronDiver 2019-04-25 16:11:35 +01:00 committed by GitHub
commit 84c03f89ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 15 deletions

View File

@ -90,17 +90,17 @@ export class PortMap {
public static fromDockerOpts(portBindings: PortBindings): PortMap[] {
// Create a list of portBindings, rather than the map (which we can't
// order)
const portMaps = _.map(portBindings, (hostObj, internalStr) => {
const portMaps = _.flatMap(portBindings, (hostObj, internalStr) => {
const match = internalStr.match(DOCKER_OPTS_PORTS_REGEX);
if (match == null) {
throw new Error(`Could not parse docker port output: ${internalStr}`);
}
const internal = parseInt(match[1], 10);
const external = parseInt(hostObj[0].HostPort, 10);
const host = hostObj[0].HostIp;
const proto = match[2] || 'tcp';
return _.map(hostObj, ({ HostIp, HostPort }) => {
const external = parseInt(HostPort, 10);
const host = HostIp;
return new PortMap({
internalStart: internal,
internalEnd: internal,
@ -110,6 +110,7 @@ export class PortMap {
host,
});
});
});
return PortMap.normalisePortMaps(portMaps);
}

View File

@ -775,7 +775,12 @@ export class Service {
_.each(this.config.portMaps, pmap => {
const { exposedPorts, portBindings } = pmap.toDockerOpts();
_.merge(exposed, exposedPorts);
_.merge(ports, portBindings);
_.mergeWith(ports, portBindings, (destVal, srcVal) => {
if (destVal == null) {
return srcVal;
}
return destVal.concat(srcVal);
});
});
// We also want to merge the compose and image exposedPorts

View File

@ -198,13 +198,16 @@ describe 'deviceState', ->
prepare()
@db = new DB()
@config = new Config({ @db })
@logger = {
clearOutOfDateDBLogs: ->
}
eventTracker = {
track: console.log
}
stub(Service, 'extendEnvVars').callsFake (env) ->
env['ADDITIONAL_ENV_VAR'] = 'foo'
return env
@deviceState = new DeviceState({ @db, @config, eventTracker })
@deviceState = new DeviceState({ @db, @config, eventTracker, @logger })
stub(@deviceState.applications.docker, 'getNetworkGateway').returns(Promise.resolve('172.17.0.1'))
stub(@deviceState.applications.images, 'inspectByName').callsFake ->
Promise.try ->

View File

@ -20,7 +20,10 @@ initModels = (filename) ->
track: stub().callsFake (ev, props) ->
console.log(ev, props)
}
@deviceState = new DeviceState({ @db, @config, @eventTracker })
@logger = {
clearOutOfDateDBLogs: ->
}
@deviceState = new DeviceState({ @db, @config, @eventTracker, @logger })
@apiBinder = new APIBinder({ @db, @config, @eventTracker, @deviceState })
@db.init()
.then =>

View File

@ -123,7 +123,10 @@ describe 'ApplicationManager', ->
eventTracker = {
track: console.log
}
@deviceState = new DeviceState({ @db, @config, eventTracker })
@logger = {
clearOutOfDateDBLogs: ->
}
@deviceState = new DeviceState({ @db, @config, eventTracker, @logger })
@applications = @deviceState.applications
stub(@applications.images, 'inspectByName').callsFake (imageName) ->
Promise.resolve({

View File

@ -243,6 +243,28 @@ describe 'Ports', ->
})
])
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 PortMap({
internalStart: 100,
internalEnd: 100,
externalStart: 200,
externalEnd: 200,
protocol: 'tcp',
host: '123'
})
new PortMap({
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', ->
portBindings = require('./data/ports/not-ascending/port-bindings.json')