Skip to content

Commit 258c8bc

Browse files
committed
Fix specifies_host_port() to handle port binding with host IP but no host port
Signed-off-by: Viranch Mehta <viranch.mehta@gmail.com>
1 parent ae3c66b commit 258c8bc

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

compose/service.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -770,10 +770,28 @@ def custom_container_name(self):
770770
return self.options.get('container_name')
771771

772772
def specifies_host_port(self):
773-
for port in self.options.get('ports', []):
774-
if ':' in str(port):
773+
def has_host_port(binding):
774+
_, external_bindings = split_port(binding)
775+
776+
# there are no external bindings
777+
if external_bindings is None:
778+
return False
779+
780+
# we only need to check the first binding from the range
781+
external_binding = external_bindings[0]
782+
783+
# non-tuple binding means there is a host port specified
784+
if not isinstance(external_binding, tuple):
775785
return True
776-
return False
786+
787+
# extract actual host port from tuple of (host_ip, host_port)
788+
_, host_port = external_binding
789+
if host_port is not None:
790+
return True
791+
792+
return False
793+
794+
return any(has_host_port(binding) for binding in self.options.get('ports', []))
777795

778796
def pull(self, ignore_pull_failures=False):
779797
if 'image' not in self.options:

tests/unit/service_test.py

+62
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,68 @@ def test_config_dict_with_net_from_container(self):
444444
}
445445
self.assertEqual(config_dict, expected)
446446

447+
def test_specifies_host_port_with_no_ports(self):
448+
service = Service(
449+
'foo',
450+
image='foo')
451+
self.assertEqual(service.specifies_host_port(), False)
452+
453+
def test_specifies_host_port_with_container_port(self):
454+
service = Service(
455+
'foo',
456+
image='foo',
457+
ports=["2000"])
458+
self.assertEqual(service.specifies_host_port(), False)
459+
460+
def test_specifies_host_port_with_host_port(self):
461+
service = Service(
462+
'foo',
463+
image='foo',
464+
ports=["1000:2000"])
465+
self.assertEqual(service.specifies_host_port(), True)
466+
467+
def test_specifies_host_port_with_host_ip_no_port(self):
468+
service = Service(
469+
'foo',
470+
image='foo',
471+
ports=["127.0.0.1::2000"])
472+
self.assertEqual(service.specifies_host_port(), False)
473+
474+
def test_specifies_host_port_with_host_ip_and_port(self):
475+
service = Service(
476+
'foo',
477+
image='foo',
478+
ports=["127.0.0.1:1000:2000"])
479+
self.assertEqual(service.specifies_host_port(), True)
480+
481+
def test_specifies_host_port_with_container_port_range(self):
482+
service = Service(
483+
'foo',
484+
image='foo',
485+
ports=["2000-3000"])
486+
self.assertEqual(service.specifies_host_port(), False)
487+
488+
def test_specifies_host_port_with_host_port_range(self):
489+
service = Service(
490+
'foo',
491+
image='foo',
492+
ports=["1000-2000:2000-3000"])
493+
self.assertEqual(service.specifies_host_port(), True)
494+
495+
def test_specifies_host_port_with_host_ip_no_port_range(self):
496+
service = Service(
497+
'foo',
498+
image='foo',
499+
ports=["127.0.0.1::2000-3000"])
500+
self.assertEqual(service.specifies_host_port(), False)
501+
502+
def test_specifies_host_port_with_host_ip_and_port_range(self):
503+
service = Service(
504+
'foo',
505+
image='foo',
506+
ports=["127.0.0.1:1000-2000:2000-3000"])
507+
self.assertEqual(service.specifies_host_port(), True)
508+
447509

448510
class NetTestCase(unittest.TestCase):
449511

0 commit comments

Comments
 (0)