diff --git a/src/compose/ports.ts b/src/compose/ports.ts index 8ed9c318..1d80cb29 100644 --- a/src/compose/ports.ts +++ b/src/compose/ports.ts @@ -30,7 +30,7 @@ interface PortRange { export class PortMap { private ports: PortRange; - public constructor(portStrOrObj: string | PortRange) { + private constructor(portStrOrObj: string | PortRange) { if (_.isString(portStrOrObj)) { this.parsePortString(portStrOrObj); } else { @@ -139,6 +139,13 @@ export class PortMap { }, []); } + public static fromComposePorts(ports: string[]): PortMap[] { + return _(ports) + .map(p => new PortMap(p)) + .sortBy(p => p.ports.internalStart) + .value(); + } + private parsePortString(portStr: string): void { const match = portStr.match(PORTS_REGEX); if (match == null) { diff --git a/src/compose/service.ts b/src/compose/service.ts index 44c856bb..c4882a71 100644 --- a/src/compose/service.ts +++ b/src/compose/service.ts @@ -253,7 +253,7 @@ export class Service { let portMaps: PortMap[] = []; if (config.ports != null) { - portMaps = _.map(config.ports, p => new PortMap(p)); + portMaps = PortMap.fromComposePorts(config.ports); } delete config.ports; diff --git a/test/16-ports.spec.coffee b/test/16-ports.spec.coffee index 1747a283..80e83740 100644 --- a/test/16-ports.spec.coffee +++ b/test/16-ports.spec.coffee @@ -243,6 +243,16 @@ describe 'Ports', -> }) ]) + describe 'Running container comparison', -> + it 'should not consider order when comparing current and target state', -> + portBindings = require('./data/ports/not-ascending/port-bindings.json') + compose = require('./data/ports/not-ascending/compose.json') + portMapsCurrent = PortMap.fromDockerOpts(portBindings) + portMapsTarget = PortMap.fromComposePorts(compose.ports) + + expect(portMapsTarget).to.deep.equal(portMapsCurrent) + + describe 'normalisePortMaps', -> it 'should correctly normalise PortMap lists', -> diff --git a/test/data/ports/not-ascending/compose.json b/test/data/ports/not-ascending/compose.json new file mode 100644 index 00000000..b90661e5 --- /dev/null +++ b/test/data/ports/not-ascending/compose.json @@ -0,0 +1,14 @@ +{ + "imageId": 730944, + "serviceName": "port-service", + "image": "sha256:6d101a6659bf5c10616bacd696feb80c927d56c0f14baadf8cf1f8956c492905", + "running": true, + "environment": {}, + "labels": {}, + "ports": ["80-90", "10:1000", "300/udp", "20/udp"], + "appId": 1032480, + "releaseId": 720081, + "serviceId": 155981, + "commit": "a41cede6b2dde6553476d02feba34a5e", + "imageName": "registry2.balena-cloud.com/v2/fa91ca88f7df77517ead234e4ea7e381@sha256:08a9abf8dbc21540a5db17caea829ac236bfa8c387c83fa56c8ec1c7975a0952" +} diff --git a/test/data/ports/not-ascending/port-bindings.json b/test/data/ports/not-ascending/port-bindings.json new file mode 100644 index 00000000..0b4e0fdd --- /dev/null +++ b/test/data/ports/not-ascending/port-bindings.json @@ -0,0 +1,16 @@ +{ + "1000/tcp": [{ "HostIp": "", "HostPort": "10" }], + "20/udp": [{ "HostIp": "", "HostPort": "20" }], + "300/udp": [{ "HostIp": "", "HostPort": "300" }], + "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" }], + "86/tcp": [{ "HostIp": "", "HostPort": "86" }], + "87/tcp": [{ "HostIp": "", "HostPort": "87" }], + "88/tcp": [{ "HostIp": "", "HostPort": "88" }], + "89/tcp": [{ "HostIp": "", "HostPort": "89" }], + "90/tcp": [{ "HostIp": "", "HostPort": "90" }] +}