@@ -178,11 +178,16 @@ def find_or_create_floating_ip(self, address):
178178
179179 return fip
180180
181- def find_port (self , address ):
181+ def find_port (self , address , internal_ip_network ):
182182 connection = self .app .client_manager .sdk_connection
183183 if isinstance (address , (ipaddress .IPv4Address , ipaddress .IPv6Address )):
184184 # see if there exists a port with the given internal ip
185- ports = list (connection .network .ports (fixed_ips = f"ip_address={ address } " ))
185+ ports = list (
186+ connection .network .ports (
187+ network_id = internal_ip_network .id if internal_ip_network else None ,
188+ fixed_ips = f"ip_address={ address } " ,
189+ )
190+ )
186191
187192 # error out if we find multiple matches
188193 if len (ports ) > 1 :
@@ -191,49 +196,51 @@ def find_port(self, address):
191196 # if there was a single port, use it
192197 if len (ports ) == 1 :
193198 return ports [0 ]
194-
195- raise KeyError (f"unable to find port with address { address } " )
196199 else :
197200 # we already have a port, so just return it
198201 return address
199202
203+ # we found nothing
204+ return None
205+
200206 def find_or_create_port (
201207 self , address , internal_ip_network = None , internal_ip_subnet = None
202208 ):
203209 connection = self .app .client_manager .sdk_connection
204- try :
205- return self .find_port (address )
206- except KeyError :
207- # we need to create a port, which means we need to know the appropriate internal network
208- if internal_ip_network is None :
209- if internal_ip_subnet is None :
210- raise ValueError (
211- "unable to create a port because --internal-ip-network is unset"
212- )
213- internal_network_id = internal_ip_subnet .network_id
214- else :
215- internal_network_id = internal_ip_network .id
216210
217- # if we were given a subnet name, use it, otherwise search through subnets for an appropriate match
218- if internal_ip_subnet :
219- subnet = internal_ip_subnet
220- else :
221- for subnet in connection .network .subnets (
222- network_id = internal_network_id ,
223- ):
224- if subnet .ip_version != address .version :
225- continue
226- cidr = ipaddress .ip_network (subnet .cidr )
227- if address in cidr :
228- break
229- else :
230- raise KeyError (f"unable to find a subnet for address { address } " )
231-
232- return connection .network .create_port (
233- name = f"esi-autocreated-{ address } " ,
211+ if port := self .find_port (address , internal_ip_network ):
212+ return port
213+
214+ # we need to know the appropriate network in order to find or create a port
215+ if internal_ip_network is None :
216+ if internal_ip_subnet is None :
217+ raise ValueError (
218+ "unable to create a port because --internal-ip-network is unset"
219+ )
220+ internal_network_id = internal_ip_subnet .network_id
221+ else :
222+ internal_network_id = internal_ip_network .id
223+
224+ # if we were given a subnet name, use it, otherwise search through subnets for an appropriate match
225+ if internal_ip_subnet :
226+ subnet = internal_ip_subnet
227+ else :
228+ for subnet in connection .network .subnets (
234229 network_id = internal_network_id ,
235- fixed_ips = [{"subnet_id" : subnet .id , "ip_address" : str (address )}],
236- )
230+ ):
231+ if subnet .ip_version != address .version :
232+ continue
233+ cidr = ipaddress .ip_network (subnet .cidr )
234+ if address in cidr :
235+ break
236+ else :
237+ raise KeyError (f"unable to find a subnet for address { address } " )
238+
239+ return connection .network .create_port (
240+ name = f"esi-autocreated-{ address } " ,
241+ network_id = internal_network_id ,
242+ fixed_ips = [{"subnet_id" : subnet .id , "ip_address" : str (address )}],
243+ )
237244
238245
239246def port_forwarding_exists (fip , internal_ip_address , port ):
@@ -375,8 +382,8 @@ def get_parser(self, prog_name: str):
375382 parser .add_argument ("--port" , "-p" , type = PortSpec .from_spec , action = "append" )
376383 parser .add_argument (
377384 "internal_ip_descriptor" ,
378- type = AddressOrPortArg ( self ) ,
379- help = "ip address, port name, or port uuid " ,
385+ type = ipaddress . ip_address ,
386+ help = "ip address" ,
380387 )
381388 parser .add_argument (
382389 "external_ip_descriptor" ,
@@ -391,18 +398,7 @@ def take_action(self, parsed_args: argparse.Namespace):
391398 forwards = []
392399
393400 fip = self .find_floating_ip (parsed_args .external_ip_descriptor )
394- internal_port = self .find_port (parsed_args .internal_ip_descriptor )
395-
396- if isinstance (
397- parsed_args .internal_ip_descriptor ,
398- (ipaddress .IPv4Address , ipaddress .IPv6Address ),
399- ):
400- internal_ip_address = str (parsed_args .internal_ip_descriptor )
401- else :
402- # if we were given a port name, always pick the first fixed ip. if the user
403- # wants to forward to a specific address, they should specify the address
404- # rather than the port.
405- internal_ip_address = internal_port .fixed_ips [0 ]["ip_address" ]
401+ internal_ip_address = str (parsed_args .internal_ip_descriptor )
406402
407403 for port in parsed_args .port :
408404 for fwd in self .app .client_manager .sdk_connection .network .floating_ip_port_forwardings (
@@ -411,7 +407,6 @@ def take_action(self, parsed_args: argparse.Namespace):
411407 if (
412408 fwd .external_port == port .external_port
413409 and fwd .internal_ip_address == internal_ip_address
414- and fwd .internal_port == port .internal_port
415410 ):
416411 forwards .append ((fip , fwd ))
417412 break
0 commit comments