Skip to content

Commit 25eadd3

Browse files
committed
Use --internal-ip-network if provided
Previously, if --internal-ip-network was provided, we would find ports on the wrong network because we were only searching for ports by address. With this change, ports must match both the address and the network in order to be considered.
1 parent e2f928f commit 25eadd3

2 files changed

Lines changed: 50 additions & 57 deletions

File tree

esiclient/tests/unit/v1/test_port_forwarding.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,22 +144,20 @@ def setUp(self):
144144
self.netops.app.client_manager.sdk_connection = self.connection
145145

146146
def test_find_port_given_port(self):
147-
assert self.netops.find_port("myport") == "myport"
147+
assert self.netops.find_port("myport", None) == "myport"
148148

149149
def test_find_port_given_address(self):
150150
self.connection.network.ports.return_value = [self.port_1]
151-
assert self.netops.find_port(ipaddress.ip_address("10.10.10.10")) == self.port_1
151+
assert self.netops.find_port(ipaddress.ip_address("10.10.10.10"), None) == self.port_1
152152

153153
def test_find_port_given_missing_address(self):
154154
self.connection.network.ports.return_value = []
155-
self.assertRaises(
156-
KeyError, self.netops.find_port, ipaddress.ip_address("10.10.10.10")
157-
)
155+
self.assertIsNone(self.netops.find_port(ipaddress.ip_address("10.10.10.10"), None))
158156

159157
def test_find_port_given_multiple_matches(self):
160158
self.connection.network.ports.return_value = [self.port_1, self.port_1]
161159
self.assertRaises(
162-
ValueError, self.netops.find_port, ipaddress.ip_address("10.10.10.10")
160+
ValueError, self.netops.find_port, ipaddress.ip_address("10.10.10.10"), None
163161
)
164162

165163
def test_find_or_create_port_given_existing_address(self):
@@ -276,7 +274,7 @@ def test_create_take_action(self):
276274
self.forward_1
277275
)
278276
parser = self.cmd.get_parser("test")
279-
args = parser.parse_args(["-p", "22", "10.10.10.10", "111.111.111.111"])
277+
args = parser.parse_args(["--internal-ip-network", "testnetwork", "-p", "22", "10.10.10.10", "111.111.111.111"])
280278
res = self.cmd.take_action(args)
281279
assert res == (
282280
[

esiclient/v1/port_forwarding.py

Lines changed: 45 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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

239246
def 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

Comments
 (0)