diff --git a/src/ContainerIntegration.jsx b/src/ContainerIntegration.jsx
index f2ed525f2..7f1b405ba 100644
--- a/src/ContainerIntegration.jsx
+++ b/src/ContainerIntegration.jsx
@@ -15,17 +15,58 @@ export const renderContainerPublishedPorts = ports => {
if (!ports)
return null;
+ const ranges = [];
const items = [];
+
+ // create port ranges
Object.entries(ports).forEach(([containerPort, hostBindings]) => {
- (hostBindings ?? []).forEach(binding => { // not-covered: null was observed in the wild, but unknown how to reproduce
- items.push(
-
- { binding.HostIp || "0.0.0.0" }:{ binding.HostPort } → { containerPort }
-
- );
+ const [port, proto] = containerPort.split('/');
+ const portNumber = Number(port);
+ // not-covered: null was observed in the wild, but unknown how to reproduce
+ (hostBindings ?? []).forEach(binding => {
+ const lastRange = ranges[ranges.length - 1];
+ const hostIP = binding.HostIp || "0.0.0.0";
+ const hostPort = Number(binding.HostPort);
+
+ let isPortConsecutive = false;
+ let isHostPortConsecutive = false;
+ let isSameHostIP = false;
+ let isSameProtocol = false;
+
+ if (lastRange) {
+ isPortConsecutive = portNumber === lastRange.endPort + 1;
+ isHostPortConsecutive = hostPort === lastRange.hostEndPort + 1;
+ isSameHostIP = hostIP === lastRange.hostIp;
+ isSameProtocol = proto === lastRange.protocol;
+ }
+
+ if (isPortConsecutive && isHostPortConsecutive && isSameHostIP && isSameProtocol) {
+ // ports are consecutive, so extend the range
+ lastRange.endPort = portNumber;
+ lastRange.hostEndPort = hostPort;
+ } else {
+ // ports are not consecutive, so start a new range
+ ranges.push({
+ startPort: portNumber,
+ endPort: portNumber,
+ protocol: proto,
+ hostIp: hostIP,
+ hostStartPort: hostPort,
+ hostEndPort: hostPort
+ });
+ }
});
});
+ // create list items based on the ranges
+ ranges.forEach(({ startPort, endPort, protocol, hostIp, hostStartPort, hostEndPort }) => {
+ items.push(
+
+ {hostIp}:{hostStartPort}{hostStartPort !== hostEndPort ? `-${hostEndPort}` : ''} → {startPort}{startPort !== endPort ? `-${endPort}` : ''}/{protocol}
+
+ );
+ });
+
return {items}
;
};
diff --git a/test/check-application b/test/check-application
index 1c4f012b4..70d81263b 100755
--- a/test/check-application
+++ b/test/check-application
@@ -1915,6 +1915,19 @@ class TestApplication(testlib.MachineCase):
b.click('.publish-port-form .btn-add')
b.set_input_text('#run-image-dialog-publish-4-ip-address', '127.0.0.2')
b.set_input_text('#run-image-dialog-publish-4-container-port', '9001')
+ # publish range of ports
+ b.click('.publish-port-form .btn-add')
+ b.set_input_text('#run-image-dialog-publish-5-container-port', '4000')
+ b.set_input_text('#run-image-dialog-publish-5-host-port', '4000')
+ b.click('.publish-port-form .btn-add')
+ b.set_input_text('#run-image-dialog-publish-6-container-port', '4001')
+ b.set_input_text('#run-image-dialog-publish-6-host-port', '4001')
+ b.click('.publish-port-form .btn-add')
+ b.set_input_text('#run-image-dialog-publish-7-container-port', '4002')
+ b.set_input_text('#run-image-dialog-publish-7-host-port', '4002')
+ b.click('.publish-port-form .btn-add')
+ b.set_input_text('#run-image-dialog-publish-8-container-port', '4003')
+ b.set_input_text('#run-image-dialog-publish-8-host-port', '4003')
# Configure env
b.click('.env-form .btn-add')
@@ -2033,11 +2046,14 @@ class TestApplication(testlib.MachineCase):
'127.0.0.2:')
b.wait_in_text(f'#containers-containers tr:contains("{IMG_BUSYBOX}") dt:contains("Ports") + dd',
' \u2192 8001/tcp')
+ b.wait_in_text(f'#containers-containers tr:contains("{IMG_BUSYBOX}") dt:contains("Ports") + dd',
+ '0.0.0.0:4000-4003 \u2192 4000-4003/tcp')
b.wait_not_in_text(f'#containers-containers tr:contains("{IMG_BUSYBOX}") dt:contains("Ports") + dd',
'7001/tcp')
ports = self.execute(auth, "podman inspect --format '{{.NetworkSettings.Ports}}' busybox-with-tty")
self.assertRegex(ports, r'5000/tcp:\[{(0.0.0.0)? 6000}\]')
+ self.assertRegex(ports, r'400[0-3]?/tcp:\[{(0.0.0.0)? 400[0-3]?}\]')
self.assertIn('5001/udp:[{127.0.0.1 6001}]', ports)
self.assertIn('8001/tcp:[{', ports)
self.assertIn('9001/tcp:[{127.0.0.2 ', ports)
diff --git a/test/reference b/test/reference
index 618b490bd..cf4bc98ca 160000
--- a/test/reference
+++ b/test/reference
@@ -1 +1 @@
-Subproject commit 618b490bd3db1fc4a106652d5fb708a8e4309207
+Subproject commit cf4bc98caa368b3907caa697d6ac0861ebc8a25a