@@ -68,24 +68,18 @@ def chdir(path):
6868 os .chdir (old_dir )
6969
7070
71- def validate_and_generate_port_mapping (port_mapping ):
71+ def validate_and_generate_port_mapping (port_mappings ):
7272 """
73- Validate the port mapping list and return a list of validated tuples.
74-
75- Each entry in the passed port mapping list will be converted to a
76- tuple with a containing a string with the format 'key:value' with the
77- `key` being the container's port and the
78- `value` being `None`, `host_port` or `['interface_ip','host_port']`
79-
73+ Validate a list of port mappings and return a dictionary of port mappings.
8074
8175 Args:
82- port_mapping (list): List of strings of format
76+ port_mappings (list): List of strings of format
8377 `'host_port:container_port'` with optional tcp udp values and host
8478 network interface
8579
8680 Returns:
87- List of validated tuples of form ('host_port:container_port') with
88- optional tcp udp values and host network interface
81+ Dictionary of port mappings in the format accepted by docker-py's
82+ `containers.run()` method (https://docker-py.readthedocs.io/en/stable/containers.html)
8983
9084 Raises:
9185 Exception on invalid port mapping
@@ -94,55 +88,50 @@ def validate_and_generate_port_mapping(port_mapping):
9488 One limitation of repo2docker is it cannot bind a
9589 single container_port to multiple host_ports
9690 (docker-py supports this but repo2docker does not)
97-
98- Examples:
99- Valid port mappings are:
100- - `127.0.0.1:90:900`
101- - `:999` (match to any host port)
102- - `999:999/tcp` (bind 999 host port to 999 tcp container port)
103-
104- Invalid port mapping:
105- - `127.0.0.1::999` (even though docker accepts it)
106- - other invalid ip address combinations
10791 """
108- reg_regex = re .compile (r"""
109- ^(
110- ( # or capturing group
111- (?: # start capturing ip address of network interface
112- (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3} # first three parts
113- (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) # last part of the ip address
114- :(?:6553[0-5]|655[0-2][0-9]|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|(\d){1,4})
115- )?
116- | # host ip with port or only port
117- (?:6553[0-5]|655[0-2][0-9]|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|(\d){0,4})
118- )
119- :
120- (?:6553[0-5]|655[0-2][0-9]|65[0-4](\d){2}|6[0-4](\d){3}|[1-5](\d){4}|(\d){0,4})
121- (?:/udp|/tcp)?
122- )$
123- """ , re .VERBOSE )
92+ def check_port (port ):
93+ try :
94+ p = int (port )
95+ except ValueError as e :
96+ raise ValueError ('Port specification "{}" has '
97+ 'an invalid port.' .format (mapping ))
98+ if p > 65535 :
99+ raise ValueError ('Port specification "{}" specifies '
100+ 'a port above 65535.' .format (mapping ))
101+ return port
102+
103+ def check_port_string (p ):
104+ parts = p .split ('/' )
105+ if len (parts ) == 2 : # 134/tcp
106+ port , protocol = parts
107+ if protocol not in ('tcp' , 'udp' ):
108+ raise ValueError ('Port specification "{}" has '
109+ 'an invalid protocol.' .format (mapping ))
110+ elif len (parts ) == 1 :
111+ port = parts [0 ]
112+ protocol = 'tcp'
113+
114+ check_port (port )
115+
116+ return '/' .join ((port , protocol ))
117+
124118 ports = {}
125- if port_mapping is None :
119+ if port_mappings is None :
126120 return ports
127- for p in port_mapping :
128- if reg_regex .match (p ) is None :
129- raise Exception ('Invalid port mapping ' + str (p ))
130- # Do a reverse split twice on the separator :
131- port_host = str (p ).rsplit (':' , 2 )
132- host = None
133- if len (port_host ) == 3 :
134- # host, optional host_port and container port information given
135- host = port_host [0 ]
136- host_port = port_host [1 ]
137- container_port = port_host [2 ]
138- else :
139- host_port = port_host [0 ] if len (port_host [0 ]) > 0 else None
140- container_port = port_host [1 ]
141121
142- if host is None :
143- ports [str (container_port )] = host_port
122+ for mapping in port_mappings :
123+ parts = mapping .split (':' )
124+
125+ * host , container_port = parts
126+ # just a port
127+ if len (host ) == 1 :
128+ host = check_port (host [0 ])
144129 else :
145- ports [str (container_port )] = (host , host_port )
130+ host = tuple ((host [0 ], check_port (host [1 ])))
131+
132+ container_port = check_port_string (container_port )
133+ ports [container_port ] = host
134+
146135 return ports
147136
148137
0 commit comments