From e01e59caeb56cb7bf4f38403b82d0a265b163098 Mon Sep 17 00:00:00 2001 From: Hang Yang Date: Wed, 14 Oct 2020 11:35:22 -0500 Subject: [PATCH] Support remote-address-group in SG rules Add support for using remote-address-group in security group rules. Change-Id: Ib1972244d484839943bc3cda07519a6c6d4b945a Implements: blueprint address-groups-in-sg-rules Depends-On: https://review.opendev.org/755644 --- .../network/v2/security_group_rule.py | 14 ++++++ .../tests/unit/network/v2/fakes.py | 1 + .../v2/test_security_group_rule_network.py | 43 +++++++++++++++++++ ...s-groups-in-sg-rules-b3b7742e4e6f5745.yaml | 9 ++++ 4 files changed, 67 insertions(+) create mode 100644 releasenotes/notes/bp-address-groups-in-sg-rules-b3b7742e4e6f5745.yaml diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py index a770393313..17241ed256 100644 --- a/openstackclient/network/v2/security_group_rule.py +++ b/openstackclient/network/v2/security_group_rule.py @@ -126,6 +126,12 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): metavar="", help=_("Remote security group (name or ID)"), ) + if self.is_neutron: + remote_group.add_argument( + "--remote-address-group", + metavar="", + help=_("Remote address group (name or ID)"), + ) # NOTE(efried): The --dst-port, --protocol, and --proto options exist # for both nova-network and neutron, but differ slightly. For the sake @@ -328,6 +334,11 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): parsed_args.remote_group, ignore_missing=False ).id + elif parsed_args.remote_address_group is not None: + attrs['remote_address_group_id'] = client.find_address_group( + parsed_args.remote_address_group, + ignore_missing=False + ).id elif parsed_args.remote_ip is not None: attrs['remote_ip_prefix'] = parsed_args.remote_ip elif attrs['ethertype'] == 'IPv4': @@ -507,6 +518,8 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister): 'Direction', 'Remote Security Group', ) + if self.is_neutron: + column_headers = column_headers + ('Remote Address Group',) if parsed_args.group is None: column_headers = column_headers + ('Security Group',) return column_headers @@ -526,6 +539,7 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister): 'port_range', 'direction', 'remote_group_id', + 'remote_address_group_id', ) # Get the security group rules using the requested query. diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index 798cfd967b..d690669038 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -1382,6 +1382,7 @@ class FakeSecurityGroupRule(object): 'port_range_min': None, 'protocol': None, 'remote_group_id': None, + 'remote_address_group_id': None, 'remote_ip_prefix': '0.0.0.0/0', 'security_group_id': 'security-group-id-' + uuid.uuid4().hex, 'tenant_id': 'project-id-' + uuid.uuid4().hex, diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py index 0141161134..bcdb0c2618 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py @@ -46,6 +46,9 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): _security_group = \ network_fakes.FakeSecurityGroup.create_one_security_group() + # The address group to be used in security group rules + _address_group = network_fakes.FakeAddressGroup.create_one_address_group() + expected_columns = ( 'description', 'direction', @@ -55,6 +58,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'port_range_min', 'project_id', 'protocol', + 'remote_address_group_id', 'remote_group_id', 'remote_ip_prefix', 'security_group_id', @@ -77,6 +81,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self._security_group_rule.port_range_min, self._security_group_rule.project_id, self._security_group_rule.protocol, + self._security_group_rule.remote_address_group_id, self._security_group_rule.remote_group_id, self._security_group_rule.remote_ip_prefix, self._security_group_rule.security_group_id, @@ -88,6 +93,9 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.network.find_security_group = mock.Mock( return_value=self._security_group) + self.network.find_address_group = mock.Mock( + return_value=self._address_group) + self.projects_mock.get.return_value = self.project self.domains_mock.get.return_value = self.domain @@ -103,6 +111,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): arglist = [ '--remote-ip', '10.10.0.0/24', '--remote-group', self._security_group.id, + '--remote-address-group', self._address_group.id, self._security_group.id, ] self.assertRaises(tests_utils.ParserException, @@ -258,6 +267,34 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) + def test_create_remote_address_group(self): + self._setup_security_group_rule({ + 'protocol': 'icmp', + 'remote_address_group_id': self._address_group.id, + }) + arglist = [ + '--protocol', 'icmp', + '--remote-address-group', self._address_group.name, + self._security_group.id, + ] + verifylist = [ + ('remote_address_group', self._address_group.name), + ('group', self._security_group.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.network.create_security_group_rule.assert_called_once_with(**{ + 'direction': self._security_group_rule.direction, + 'ethertype': self._security_group_rule.ether_type, + 'protocol': self._security_group_rule.protocol, + 'remote_address_group_id': self._address_group.id, + 'security_group_id': self._security_group.id, + }) + self.assertEqual(self.expected_columns, columns) + self.assertEqual(self.expected_data, data) + def test_create_remote_group(self): self._setup_security_group_rule({ 'protocol': 'tcp', @@ -878,6 +915,7 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'Port Range', 'Direction', 'Remote Security Group', + 'Remote Address Group', ) expected_columns_no_group = ( 'ID', @@ -887,6 +925,7 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'Port Range', 'Direction', 'Remote Security Group', + 'Remote Address Group', 'Security Group', ) @@ -902,6 +941,7 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): _security_group_rule), _security_group_rule.direction, _security_group_rule.remote_group_id, + _security_group_rule.remote_address_group_id, )) expected_data_no_group.append(( _security_group_rule.id, @@ -912,6 +952,7 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): _security_group_rule), _security_group_rule.direction, _security_group_rule.remote_group_id, + _security_group_rule.remote_address_group_id, _security_group_rule.security_group_id, )) @@ -1041,6 +1082,7 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'port_range_min', 'project_id', 'protocol', + 'remote_address_group_id', 'remote_group_id', 'remote_ip_prefix', 'security_group_id', @@ -1055,6 +1097,7 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): _security_group_rule.port_range_min, _security_group_rule.project_id, _security_group_rule.protocol, + _security_group_rule.remote_address_group_id, _security_group_rule.remote_group_id, _security_group_rule.remote_ip_prefix, _security_group_rule.security_group_id, diff --git a/releasenotes/notes/bp-address-groups-in-sg-rules-b3b7742e4e6f5745.yaml b/releasenotes/notes/bp-address-groups-in-sg-rules-b3b7742e4e6f5745.yaml new file mode 100644 index 0000000000..a962eadf6f --- /dev/null +++ b/releasenotes/notes/bp-address-groups-in-sg-rules-b3b7742e4e6f5745.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Add ``--remote-address-group`` option to ``security group rule create`` + command for using an address group as the source/destination in security + group rules. Also add field ``remote_address_group_id`` to the output of + ``security group rule show`` and add column ``Remote Address Group`` to + the output of ``security group rule list``. + [Blueprint `address-groups-in-sg-rules `_]