Merge "Add port ranges on floating ip portforwardings cli"

This commit is contained in:
Zuul 2023-02-22 12:32:14 +00:00 committed by Gerrit Code Review
commit 02acd27c6a
4 changed files with 317 additions and 56 deletions

@ -25,6 +25,61 @@ from openstackclient.network import common
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def validate_ports_diff(ports):
if len(ports) == 0:
return 0
ports_diff = ports[-1] - ports[0]
if ports_diff < 0:
msg = _("The last number in port range must be"
" greater or equal to the first")
raise exceptions.CommandError(msg)
return ports_diff
def validate_ports_match(internal_ports, external_ports):
internal_ports_diff = validate_ports_diff(internal_ports)
external_ports_diff = validate_ports_diff(external_ports)
if internal_ports_diff != 0 and internal_ports_diff != external_ports_diff:
msg = _("The relation between internal and external ports does not "
"match the pattern 1:N and N:N")
raise exceptions.CommandError(msg)
def validate_and_assign_port_ranges(parsed_args, attrs):
internal_port_range = parsed_args.internal_protocol_port
external_port_range = parsed_args.external_protocol_port
external_ports = internal_ports = []
if external_port_range:
external_ports = list(map(int, str(external_port_range).split(':')))
if internal_port_range:
internal_ports = list(map(int, str(internal_port_range).split(':')))
validate_ports_match(internal_ports, external_ports)
for port in external_ports + internal_ports:
validate_port(port)
if internal_port_range:
if ':' in internal_port_range:
attrs['internal_port_range'] = internal_port_range
else:
attrs['internal_port'] = int(internal_port_range)
if external_port_range:
if ':' in external_port_range:
attrs['external_port_range'] = external_port_range
else:
attrs['external_port'] = int(external_port_range)
def validate_port(port):
if port <= 0 or port > 65535:
msg = _("The port number range is <1-65535>")
raise exceptions.CommandError(msg)
def _get_columns(item): def _get_columns(item):
column_map = {} column_map = {}
hidden_columns = ['location', 'tenant_id'] hidden_columns = ['location', 'tenant_id']
@ -58,7 +113,6 @@ class CreateFloatingIPPortForwarding(command.ShowOne,
) )
parser.add_argument( parser.add_argument(
'--internal-protocol-port', '--internal-protocol-port',
type=int,
metavar='<port-number>', metavar='<port-number>',
required=True, required=True,
help=_("The protocol port number " help=_("The protocol port number "
@ -67,7 +121,6 @@ class CreateFloatingIPPortForwarding(command.ShowOne,
) )
parser.add_argument( parser.add_argument(
'--external-protocol-port', '--external-protocol-port',
type=int,
metavar='<port-number>', metavar='<port-number>',
required=True, required=True,
help=_("The protocol port number of " help=_("The protocol port number of "
@ -92,6 +145,7 @@ class CreateFloatingIPPortForwarding(command.ShowOne,
help=_("Floating IP that the port forwarding belongs to " help=_("Floating IP that the port forwarding belongs to "
"(IP address or ID)") "(IP address or ID)")
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
@ -102,19 +156,7 @@ class CreateFloatingIPPortForwarding(command.ShowOne,
ignore_missing=False, ignore_missing=False,
) )
if parsed_args.internal_protocol_port is not None: validate_and_assign_port_ranges(parsed_args, attrs)
if (parsed_args.internal_protocol_port <= 0 or
parsed_args.internal_protocol_port > 65535):
msg = _("The port number range is <1-65535>")
raise exceptions.CommandError(msg)
attrs['internal_port'] = parsed_args.internal_protocol_port
if parsed_args.external_protocol_port is not None:
if (parsed_args.external_protocol_port <= 0 or
parsed_args.external_protocol_port > 65535):
msg = _("The port number range is <1-65535>")
raise exceptions.CommandError(msg)
attrs['external_port'] = parsed_args.external_protocol_port
if parsed_args.port: if parsed_args.port:
port = client.find_port(parsed_args.port, port = client.find_port(parsed_args.port,
@ -226,7 +268,9 @@ class ListFloatingIPPortForwarding(command.Lister):
'internal_port_id', 'internal_port_id',
'internal_ip_address', 'internal_ip_address',
'internal_port', 'internal_port',
'internal_port_range',
'external_port', 'external_port',
'external_port_range',
'protocol', 'protocol',
'description', 'description',
) )
@ -235,7 +279,9 @@ class ListFloatingIPPortForwarding(command.Lister):
'Internal Port ID', 'Internal Port ID',
'Internal IP Address', 'Internal IP Address',
'Internal Port', 'Internal Port',
'Internal Port Range',
'External Port', 'External Port',
'External Port Range',
'Protocol', 'Protocol',
'Description', 'Description',
) )
@ -246,8 +292,13 @@ class ListFloatingIPPortForwarding(command.Lister):
port = client.find_port(parsed_args.port, port = client.find_port(parsed_args.port,
ignore_missing=False) ignore_missing=False)
query['internal_port_id'] = port.id query['internal_port_id'] = port.id
if parsed_args.external_protocol_port is not None: external_port = parsed_args.external_protocol_port
query['external_port'] = parsed_args.external_protocol_port if external_port:
if ':' in external_port:
query['external_port_range'] = external_port
else:
query['external_port'] = int(
parsed_args.external_protocol_port)
if parsed_args.protocol is not None: if parsed_args.protocol is not None:
query['protocol'] = parsed_args.protocol query['protocol'] = parsed_args.protocol
@ -297,14 +348,12 @@ class SetFloatingIPPortForwarding(common.NeutronCommandWithExtraArgs):
parser.add_argument( parser.add_argument(
'--internal-protocol-port', '--internal-protocol-port',
metavar='<port-number>', metavar='<port-number>',
type=int,
help=_("The TCP/UDP/other protocol port number of the " help=_("The TCP/UDP/other protocol port number of the "
"network port fixed IPv4 address associated to " "network port fixed IPv4 address associated to "
"the floating IP port forwarding") "the floating IP port forwarding")
) )
parser.add_argument( parser.add_argument(
'--external-protocol-port', '--external-protocol-port',
type=int,
metavar='<port-number>', metavar='<port-number>',
help=_("The TCP/UDP/other protocol port number of the " help=_("The TCP/UDP/other protocol port number of the "
"port forwarding's floating IP address") "port forwarding's floating IP address")
@ -339,19 +388,8 @@ class SetFloatingIPPortForwarding(common.NeutronCommandWithExtraArgs):
if parsed_args.internal_ip_address: if parsed_args.internal_ip_address:
attrs['internal_ip_address'] = parsed_args.internal_ip_address attrs['internal_ip_address'] = parsed_args.internal_ip_address
if parsed_args.internal_protocol_port is not None:
if (parsed_args.internal_protocol_port <= 0 or
parsed_args.internal_protocol_port > 65535):
msg = _("The port number range is <1-65535>")
raise exceptions.CommandError(msg)
attrs['internal_port'] = parsed_args.internal_protocol_port
if parsed_args.external_protocol_port is not None: validate_and_assign_port_ranges(parsed_args, attrs)
if (parsed_args.external_protocol_port <= 0 or
parsed_args.external_protocol_port > 65535):
msg = _("The port number range is <1-65535>")
raise exceptions.CommandError(msg)
attrs['external_port'] = parsed_args.external_protocol_port
if parsed_args.protocol: if parsed_args.protocol:
attrs['protocol'] = parsed_args.protocol attrs['protocol'] = parsed_args.protocol

@ -1066,11 +1066,13 @@ class FakeFloatingIPPortForwarding(object):
""""Fake one or more Port forwarding""" """"Fake one or more Port forwarding"""
@staticmethod @staticmethod
def create_one_port_forwarding(attrs=None): def create_one_port_forwarding(attrs=None, use_range=False):
"""Create a fake Port Forwarding. """Create a fake Port Forwarding.
:param Dictionary attrs: :param Dictionary attrs:
A dictionary with all attributes A dictionary with all attributes
:param Boolean use_range:
A boolean which defines if we will use ranges or not
:return: :return:
A FakeResource object with name, id, etc. A FakeResource object with name, id, etc.
""" """
@ -1084,13 +1086,29 @@ class FakeFloatingIPPortForwarding(object):
'floatingip_id': floatingip_id, 'floatingip_id': floatingip_id,
'internal_port_id': 'internal-port-id-' + uuid.uuid4().hex, 'internal_port_id': 'internal-port-id-' + uuid.uuid4().hex,
'internal_ip_address': '192.168.1.2', 'internal_ip_address': '192.168.1.2',
'internal_port': randint(1, 65535),
'external_port': randint(1, 65535),
'protocol': 'tcp', 'protocol': 'tcp',
'description': 'some description', 'description': 'some description',
'location': 'MUNCHMUNCHMUNCH', 'location': 'MUNCHMUNCHMUNCH',
} }
if use_range:
port_range = randint(0, 100)
internal_start = randint(1, 65535 - port_range)
internal_end = internal_start + port_range
internal_range = ':'.join(map(str, [internal_start, internal_end]))
external_start = randint(1, 65535 - port_range)
external_end = external_start + port_range
external_range = ':'.join(map(str, [external_start, external_end]))
port_forwarding_attrs['internal_port_range'] = internal_range
port_forwarding_attrs['external_port_range'] = external_range
port_forwarding_attrs['internal_port'] = None
port_forwarding_attrs['external_port'] = None
else:
port_forwarding_attrs['internal_port'] = randint(1, 65535)
port_forwarding_attrs['external_port'] = randint(1, 65535)
port_forwarding_attrs['internal_port_range'] = ''
port_forwarding_attrs['external_port_range'] = ''
# Overwrite default attributes. # Overwrite default attributes.
port_forwarding_attrs.update(attrs) port_forwarding_attrs.update(attrs)
@ -1101,25 +1119,28 @@ class FakeFloatingIPPortForwarding(object):
return port_forwarding return port_forwarding
@staticmethod @staticmethod
def create_port_forwardings(attrs=None, count=2): def create_port_forwardings(attrs=None, count=2, use_range=False):
"""Create multiple fake Port Forwarding. """Create multiple fake Port Forwarding.
:param Dictionary attrs: :param Dictionary attrs:
A dictionary with all attributes A dictionary with all attributes
:param int count: :param int count:
The number of Port Forwarding rule to fake The number of Port Forwarding rule to fake
:param Boolean use_range:
A boolean which defines if we will use ranges or not
:return: :return:
A list of FakeResource objects faking the Port Forwardings A list of FakeResource objects faking the Port Forwardings
""" """
port_forwardings = [] port_forwardings = []
for i in range(0, count): for i in range(0, count):
port_forwardings.append( port_forwardings.append(
FakeFloatingIPPortForwarding.create_one_port_forwarding(attrs) FakeFloatingIPPortForwarding.create_one_port_forwarding(
attrs, use_range=use_range)
) )
return port_forwardings return port_forwardings
@staticmethod @staticmethod
def get_port_forwardings(port_forwardings=None, count=2): def get_port_forwardings(port_forwardings=None, count=2, use_range=False):
"""Get a list of faked Port Forwardings. """Get a list of faked Port Forwardings.
If port forwardings list is provided, then initialize the Mock object If port forwardings list is provided, then initialize the Mock object
@ -1129,13 +1150,16 @@ class FakeFloatingIPPortForwarding(object):
A list of FakeResource objects faking port forwardings A list of FakeResource objects faking port forwardings
:param int count: :param int count:
The number of Port Forwardings to fake The number of Port Forwardings to fake
:param Boolean use_range:
A boolean which defines if we will use ranges or not
:return: :return:
An iterable Mock object with side_effect set to a list of faked An iterable Mock object with side_effect set to a list of faked
Port Forwardings Port Forwardings
""" """
if port_forwardings is None: if port_forwardings is None:
port_forwardings = ( port_forwardings = (
FakeFloatingIPPortForwarding.create_port_forwardings(count) FakeFloatingIPPortForwarding.create_port_forwardings(
count, use_range=use_range)
) )
return mock.Mock(side_effect=port_forwardings) return mock.Mock(side_effect=port_forwardings)

@ -49,6 +49,18 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
} }
) )
) )
self.new_port_forwarding_with_ranges = (
network_fakes.FakeFloatingIPPortForwarding.
create_one_port_forwarding(
use_range=True,
attrs={
'internal_port_id': self.port.id,
'floatingip_id': self.floating_ip.id,
}
)
)
self.network.create_floating_ip_port_forwarding = mock.Mock( self.network.create_floating_ip_port_forwarding = mock.Mock(
return_value=self.new_port_forwarding) return_value=self.new_port_forwarding)
@ -63,22 +75,26 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self.columns = ( self.columns = (
'description', 'description',
'external_port', 'external_port',
'external_port_range',
'floatingip_id', 'floatingip_id',
'id', 'id',
'internal_ip_address', 'internal_ip_address',
'internal_port', 'internal_port',
'internal_port_id', 'internal_port_id',
'internal_port_range',
'protocol' 'protocol'
) )
self.data = ( self.data = (
self.new_port_forwarding.description, self.new_port_forwarding.description,
self.new_port_forwarding.external_port, self.new_port_forwarding.external_port,
self.new_port_forwarding.external_port_range,
self.new_port_forwarding.floatingip_id, self.new_port_forwarding.floatingip_id,
self.new_port_forwarding.id, self.new_port_forwarding.id,
self.new_port_forwarding.internal_ip_address, self.new_port_forwarding.internal_ip_address,
self.new_port_forwarding.internal_port, self.new_port_forwarding.internal_port,
self.new_port_forwarding.internal_port_id, self.new_port_forwarding.internal_port_id,
self.new_port_forwarding.internal_port_range,
self.new_port_forwarding.protocol, self.new_port_forwarding.protocol,
) )
@ -90,6 +106,160 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self.assertRaises(tests_utils.ParserException, self.check_parser, self.assertRaises(tests_utils.ParserException, self.check_parser,
self.cmd, arglist, verifylist) self.cmd, arglist, verifylist)
def test_create_all_options_with_range(self):
arglist = [
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
'--internal-protocol-port',
self.new_port_forwarding_with_ranges.internal_port_range,
'--external-protocol-port',
self.new_port_forwarding_with_ranges.external_port_range,
'--protocol', self.new_port_forwarding_with_ranges.protocol,
self.new_port_forwarding_with_ranges.floatingip_id,
'--internal-ip-address',
self.new_port_forwarding_with_ranges.internal_ip_address,
'--description',
self.new_port_forwarding_with_ranges.description,
]
verifylist = [
('port', self.new_port_forwarding_with_ranges.internal_port_id),
('internal_protocol_port',
self.new_port_forwarding_with_ranges.internal_port_range),
('external_protocol_port',
self.new_port_forwarding_with_ranges.external_port_range),
('protocol', self.new_port_forwarding_with_ranges.protocol),
('floating_ip',
self.new_port_forwarding_with_ranges.floatingip_id),
('internal_ip_address', self.new_port_forwarding_with_ranges.
internal_ip_address),
('description', self.new_port_forwarding_with_ranges.description),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.create_floating_ip_port_forwarding.\
assert_called_once_with(
self.new_port_forwarding.floatingip_id,
**{
'external_port_range':
self.new_port_forwarding_with_ranges.
external_port_range,
'internal_ip_address':
self.new_port_forwarding_with_ranges.
internal_ip_address,
'internal_port_range':
self.new_port_forwarding_with_ranges.
internal_port_range,
'internal_port_id':
self.new_port_forwarding_with_ranges.internal_port_id,
'protocol': self.new_port_forwarding_with_ranges.protocol,
'description':
self.new_port_forwarding_with_ranges.description,
})
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
def test_create_all_options_with_range_invalid_port_exception(self):
invalid_port_range = '999999:999999'
arglist = [
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
'--internal-protocol-port', invalid_port_range,
'--external-protocol-port', invalid_port_range,
'--protocol', self.new_port_forwarding_with_ranges.protocol,
self.new_port_forwarding_with_ranges.floatingip_id,
'--internal-ip-address',
self.new_port_forwarding_with_ranges.internal_ip_address,
'--description',
self.new_port_forwarding_with_ranges.description,
]
verifylist = [
('port', self.new_port_forwarding_with_ranges.internal_port_id),
('internal_protocol_port', invalid_port_range),
('external_protocol_port', invalid_port_range),
('protocol', self.new_port_forwarding_with_ranges.protocol),
('floating_ip',
self.new_port_forwarding_with_ranges.floatingip_id),
('internal_ip_address', self.new_port_forwarding_with_ranges.
internal_ip_address),
('description', self.new_port_forwarding_with_ranges.description),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
msg = 'The port number range is <1-65535>'
try:
self.cmd.take_action(parsed_args)
self.fail('CommandError should be raised.')
except exceptions.CommandError as e:
self.assertEqual(msg, str(e))
self.network.create_floating_ip_port_forwarding.assert_not_called()
def test_create_all_options_with_invalid_range_exception(self):
invalid_port_range = '80:70'
arglist = [
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
'--internal-protocol-port', invalid_port_range,
'--external-protocol-port', invalid_port_range,
'--protocol', self.new_port_forwarding_with_ranges.protocol,
self.new_port_forwarding_with_ranges.floatingip_id,
'--internal-ip-address',
self.new_port_forwarding_with_ranges.internal_ip_address,
'--description',
self.new_port_forwarding_with_ranges.description,
]
verifylist = [
('port', self.new_port_forwarding_with_ranges.internal_port_id),
('internal_protocol_port', invalid_port_range),
('external_protocol_port', invalid_port_range),
('protocol', self.new_port_forwarding_with_ranges.protocol),
('floating_ip',
self.new_port_forwarding_with_ranges.floatingip_id),
('internal_ip_address', self.new_port_forwarding_with_ranges.
internal_ip_address),
('description', self.new_port_forwarding_with_ranges.description),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
msg = 'The last number in port range must be greater or equal to ' \
'the first'
try:
self.cmd.take_action(parsed_args)
self.fail('CommandError should be raised.')
except exceptions.CommandError as e:
self.assertEqual(msg, str(e))
self.network.create_floating_ip_port_forwarding.assert_not_called()
def test_create_all_options_with_unmatch_ranges_exception(self):
internal_range = '80:90'
external_range = '8080:8100'
arglist = [
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
'--internal-protocol-port', internal_range,
'--external-protocol-port', external_range,
'--protocol', self.new_port_forwarding_with_ranges.protocol,
self.new_port_forwarding_with_ranges.floatingip_id,
'--internal-ip-address',
self.new_port_forwarding_with_ranges.internal_ip_address,
'--description',
self.new_port_forwarding_with_ranges.description,
]
verifylist = [
('port', self.new_port_forwarding_with_ranges.internal_port_id),
('internal_protocol_port', internal_range),
('external_protocol_port', external_range),
('protocol', self.new_port_forwarding_with_ranges.protocol),
('floating_ip',
self.new_port_forwarding_with_ranges.floatingip_id),
('internal_ip_address', self.new_port_forwarding_with_ranges.
internal_ip_address),
('description', self.new_port_forwarding_with_ranges.description),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
msg = "The relation between internal and external ports does not " \
"match the pattern 1:N and N:N"
try:
self.cmd.take_action(parsed_args)
self.fail('CommandError should be raised.')
except exceptions.CommandError as e:
self.assertEqual(msg, str(e))
self.network.create_floating_ip_port_forwarding.assert_not_called()
def test_create_all_options(self): def test_create_all_options(self):
arglist = [ arglist = [
'--port', self.new_port_forwarding.internal_port_id, '--port', self.new_port_forwarding.internal_port_id,
@ -106,8 +276,10 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
] ]
verifylist = [ verifylist = [
('port', self.new_port_forwarding.internal_port_id), ('port', self.new_port_forwarding.internal_port_id),
('internal_protocol_port', self.new_port_forwarding.internal_port), ('internal_protocol_port',
('external_protocol_port', self.new_port_forwarding.external_port), str(self.new_port_forwarding.internal_port)),
('external_protocol_port',
str(self.new_port_forwarding.external_port)),
('protocol', self.new_port_forwarding.protocol), ('protocol', self.new_port_forwarding.protocol),
('floating_ip', self.new_port_forwarding.floatingip_id), ('floating_ip', self.new_port_forwarding.floatingip_id),
('internal_ip_address', self.new_port_forwarding. ('internal_ip_address', self.new_port_forwarding.
@ -253,7 +425,9 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
'Internal Port ID', 'Internal Port ID',
'Internal IP Address', 'Internal IP Address',
'Internal Port', 'Internal Port',
'Internal Port Range',
'External Port', 'External Port',
'External Port Range',
'Protocol', 'Protocol',
'Description', 'Description',
) )
@ -275,7 +449,9 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
port_forwarding.internal_port_id, port_forwarding.internal_port_id,
port_forwarding.internal_ip_address, port_forwarding.internal_ip_address,
port_forwarding.internal_port, port_forwarding.internal_port,
port_forwarding.internal_port_range,
port_forwarding.external_port, port_forwarding.external_port,
port_forwarding.external_port_range,
port_forwarding.protocol, port_forwarding.protocol,
port_forwarding.description, port_forwarding.description,
)) ))
@ -330,7 +506,7 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
query = { query = {
'internal_port_id': self.port_forwardings[0].internal_port_id, 'internal_port_id': self.port_forwardings[0].internal_port_id,
'external_port': str(self.port_forwardings[0].external_port), 'external_port': self.port_forwardings[0].external_port,
'protocol': self.port_forwardings[0].protocol, 'protocol': self.port_forwardings[0].protocol,
} }
@ -392,7 +568,7 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self.assertIsNone(result) self.assertIsNone(result)
def test_set_all_thing(self): def test_set_all_thing(self):
arglist = [ arglist_single = [
'--port', self.port.id, '--port', self.port.id,
'--internal-ip-address', 'new_internal_ip_address', '--internal-ip-address', 'new_internal_ip_address',
'--internal-protocol-port', '100', '--internal-protocol-port', '100',
@ -402,21 +578,23 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self._port_forwarding.floatingip_id, self._port_forwarding.floatingip_id,
self._port_forwarding.id, self._port_forwarding.id,
] ]
verifylist = [ arglist_range = list(arglist_single)
arglist_range[5] = '100:110'
arglist_range[7] = '200:210'
verifylist_single = [
('port', self.port.id), ('port', self.port.id),
('internal_ip_address', 'new_internal_ip_address'), ('internal_ip_address', 'new_internal_ip_address'),
('internal_protocol_port', 100), ('internal_protocol_port', '100'),
('external_protocol_port', 200), ('external_protocol_port', '200'),
('protocol', 'tcp'), ('protocol', 'tcp'),
('description', 'some description'), ('description', 'some description'),
('floating_ip', self._port_forwarding.floatingip_id), ('floating_ip', self._port_forwarding.floatingip_id),
('port_forwarding_id', self._port_forwarding.id), ('port_forwarding_id', self._port_forwarding.id),
] ]
verifylist_range = list(verifylist_single)
parsed_args = self.check_parser(self.cmd, arglist, verifylist) verifylist_range[2] = ('internal_protocol_port', '100:110')
verifylist_range[3] = ('external_protocol_port', '200:210')
result = self.cmd.take_action(parsed_args) attrs_single = {
attrs = {
'internal_port_id': self.port.id, 'internal_port_id': self.port.id,
'internal_ip_address': 'new_internal_ip_address', 'internal_ip_address': 'new_internal_ip_address',
'internal_port': 100, 'internal_port': 100,
@ -424,12 +602,25 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
'protocol': 'tcp', 'protocol': 'tcp',
'description': 'some description', 'description': 'some description',
} }
self.network.update_floating_ip_port_forwarding.assert_called_with( attrs_range = dict(attrs_single, internal_port_range='100:110',
self._port_forwarding.floatingip_id, external_port_range='200:210')
self._port_forwarding.id, attrs_range.pop('internal_port')
**attrs attrs_range.pop('external_port')
)
self.assertIsNone(result) def run_and_validate(arglist, verifylist, attrs):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.network.update_floating_ip_port_forwarding.assert_called_with(
self._port_forwarding.floatingip_id,
self._port_forwarding.id,
**attrs
)
self.assertIsNone(result)
run_and_validate(arglist_single, verifylist_single, attrs_single)
run_and_validate(arglist_range, verifylist_range, attrs_range)
class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding): class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
@ -438,11 +629,13 @@ class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
columns = ( columns = (
'description', 'description',
'external_port', 'external_port',
'external_port_range',
'floatingip_id', 'floatingip_id',
'id', 'id',
'internal_ip_address', 'internal_ip_address',
'internal_port', 'internal_port',
'internal_port_id', 'internal_port_id',
'internal_port_range',
'protocol', 'protocol',
) )
@ -459,11 +652,13 @@ class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self.data = ( self.data = (
self._port_forwarding.description, self._port_forwarding.description,
self._port_forwarding.external_port, self._port_forwarding.external_port,
self._port_forwarding.external_port_range,
self._port_forwarding.floatingip_id, self._port_forwarding.floatingip_id,
self._port_forwarding.id, self._port_forwarding.id,
self._port_forwarding.internal_ip_address, self._port_forwarding.internal_ip_address,
self._port_forwarding.internal_port, self._port_forwarding.internal_port,
self._port_forwarding.internal_port_id, self._port_forwarding.internal_port_id,
self._port_forwarding.internal_port_range,
self._port_forwarding.protocol, self._port_forwarding.protocol,
) )
self.network.find_floating_ip_port_forwarding = mock.Mock( self.network.find_floating_ip_port_forwarding = mock.Mock(

@ -0,0 +1,4 @@
---
features:
- |
Add port ranges support to the ``floating ip port forwarding`` commands.