From a385656802e3b22ad3ff6b31e7a1bedc497fb9e1 Mon Sep 17 00:00:00 2001 From: German Eichberger Date: Wed, 30 May 2018 16:19:14 -0700 Subject: [PATCH] Adds the destination and source fwg to fwr This will add the source and destination firewall group id to firewall rules. Change-Id: If69b87fc58d36aa7d879ace8e73bc0f7534a1ef4 --- neutronclient/osc/v2/fwaas/firewallrule.py | 49 +++++++ .../tests/unit/osc/v2/fwaas/fakes.py | 4 + .../unit/osc/v2/fwaas/test_firewallrule.py | 131 +++++++++++++++++- .../notes/remote_fwg-0f5362e5be8b2e84.yaml | 5 + 4 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml diff --git a/neutronclient/osc/v2/fwaas/firewallrule.py b/neutronclient/osc/v2/fwaas/firewallrule.py index 964e7e16e..f72beded7 100644 --- a/neutronclient/osc/v2/fwaas/firewallrule.py +++ b/neutronclient/osc/v2/fwaas/firewallrule.py @@ -47,6 +47,10 @@ _attr_map = ( ('destination_port', 'Destination Port', column_util.LIST_LONG_ONLY), ('shared', 'Shared', column_util.LIST_LONG_ONLY), ('tenant_id', 'Project', column_util.LIST_LONG_ONLY), + ('source_firewall_group_id', 'Source Firewall Group ID', + column_util.LIST_LONG_ONLY), + ('destination_firewall_group_id', 'Destination Firewall Group ID', + column_util.LIST_LONG_ONLY), ) @@ -145,11 +149,30 @@ def _get_common_parser(parser): '--disable-rule', action='store_true', help=_('Disable this rule')) + src_fwg_group = parser.add_mutually_exclusive_group() + src_fwg_group.add_argument( + '--source-firewall-group', + metavar='', + help=_('Source firewall group (name or ID)')) + src_fwg_group.add_argument( + '--no-source-firewall-group', + action='store_true', + help=_('No associated destination firewall group')) + dst_fwg_group = parser.add_mutually_exclusive_group() + dst_fwg_group.add_argument( + '--destination-firewall-group', + metavar='', + help=_('Destination firewall group (name or ID)')) + dst_fwg_group.add_argument( + '--no-destination-firewall-group', + action='store_true', + help=_('No associated destination firewall group')) return parser def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs = {} + client = client_manager.neutronclient if is_create: if 'project' in parsed_args and parsed_args.project is not None: attrs['tenant_id'] = osc_utils.find_project( @@ -193,6 +216,18 @@ def _get_common_attrs(client_manager, parsed_args, is_create=True): attrs['shared'] = True if parsed_args.no_share or parsed_args.private: attrs['shared'] = False + if parsed_args.source_firewall_group: + attrs['source_firewall_group_id'] = client.find_resource( + const.FWG, parsed_args.source_firewall_group, + cmd_resource=const.CMD_FWG)['id'] + if parsed_args.no_source_firewall_group: + attrs['source_firewall_group_id'] = None + if parsed_args.destination_firewall_group: + attrs['destination_firewall_group_id'] = client.find_resource( + const.FWG, parsed_args.destination_firewall_group, + cmd_resource=const.CMD_FWG)['id'] + if parsed_args.no_destination_firewall_group: + attrs['destination_firewall_group_id'] = None return attrs @@ -391,6 +426,16 @@ class UnsetFirewallRule(command.Command): '--enable-rule', action='store_true', help=_('Disable this rule')) + + parser.add_argument( + '--source-firewall-group', + action='store_true', + help=_('Source firewall group (name or ID)')) + + parser.add_argument( + '--destination-firewall-group', + action='store_true', + help=_('Destination firewall group (name or ID)')) return parser def _get_attrs(self, client_manager, parsed_args): @@ -407,6 +452,10 @@ class UnsetFirewallRule(command.Command): attrs['shared'] = False if parsed_args.enable_rule: attrs['enabled'] = False + if parsed_args.source_firewall_group: + attrs['source_firewall_group_id'] = None + if parsed_args.source_firewall_group: + attrs['destination_firewall_group_id'] = None return attrs def take_action(self, parsed_args): diff --git a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py index 61bc11244..6475392c4 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/fakes.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/fakes.py @@ -127,4 +127,8 @@ class FirewallRule(FakeFWaaS): ('shared', False), ('tenant_id', 'tenant-id-' + uuidutils.generate_uuid(dashed=False)), + ('source_firewall_group_id', 'firewall-group-id-' + + uuidutils.generate_uuid(dashed=False)), + ('destination_firewall_group_id', 'firewall-group-id-' + + uuidutils.generate_uuid(dashed=False)), )) diff --git a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py index a512f3b3f..a8b25c304 100644 --- a/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py +++ b/neutronclient/tests/unit/osc/v2/fwaas/test_firewallrule.py @@ -37,6 +37,10 @@ CONVERT_MAP = { 'disable_rule': 'enabled', 'share': 'shared', 'no_share': 'shared', + 'source_firewall_group': 'source_firewall_group_id', + 'destination_firewall_group': 'destination_firewall_group_id', + 'no_source_firewall_group': 'source_firewall_group_id', + 'no_destination_firewall_group': 'destination_firewall_group_id', } @@ -114,11 +118,14 @@ class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): 'Destination Port', 'Shared', 'Project', + 'Source Firewall Group ID', + 'Destination Firewall Group ID', ) self.data = _generate_data() self.ordered_headers = ( 'Action', 'Description', + 'Destination Firewall Group ID', 'Destination IP Address', 'Destination Port', 'Enabled', @@ -128,12 +135,14 @@ class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): 'Project', 'Protocol', 'Shared', + 'Source Firewall Group ID', 'Source IP Address', 'Source Port', ) self.ordered_data = ( _fwr['action'], _fwr['description'], + _fwr['destination_firewall_group_id'], _fwr['destination_ip_address'], _fwr['destination_port'], _fwr['enabled'], @@ -143,12 +152,14 @@ class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): _fwr['tenant_id'], _replace_display_columns('protocol', _fwr['protocol']), _fwr['shared'], + _fwr['source_firewall_group_id'], _fwr['source_ip_address'], _fwr['source_port'], ) self.ordered_columns = ( 'action', 'description', + 'destination_firewall_group_id', 'destination_ip_address', 'destination_port', 'enabled', @@ -158,6 +169,7 @@ class TestFirewallRule(test_fakes.TestNeutronClientOSCV2): 'tenant_id', 'protocol', 'shared', + 'source_firewall_group_id', 'source_ip_address', 'source_port', ) @@ -201,6 +213,10 @@ class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): action = args.get('action') or 'deny' ip_version = args.get('ip_version') or '4' destination_port = args.get('destination_port') or '0:65535' + destination_firewall_group = args.get( + 'destination_firewall_group') or 'my-dst-fwg' + source_firewall_group = args.get( + 'source_firewall_group') or 'my-src-fwg' tenant_id = args.get('tenant_id') or 'my-tenant' arglist = [ '--description', description, @@ -215,7 +231,10 @@ class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): '--project', tenant_id, '--disable-rule', '--share', + '--source-firewall-group', source_firewall_group, + '--destination-firewall-group', destination_firewall_group ] + verifylist = [ ('name', name), ('description', description), @@ -229,10 +248,23 @@ class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): ('action', action), ('disable_rule', True), ('project', tenant_id), + ('source_firewall_group', source_firewall_group), + ('destination_firewall_group', destination_firewall_group) ] return arglist, verifylist def _test_create_with_all_params(self, args={}): + def _mock_fwr(*args, **kwargs): + if self.neutronclient.find_resource.call_count == 1: + self.neutronclient.find_resource.assert_called_once_with( + const.FWG, 'my-src-fwg', cmd_resource=const.CMD_FWG) + if self.neutronclient.find_resource.call_count == 2: + self.neutronclient.find_resource.assert_called_with( + const.FWG, 'my-dst-fwg', cmd_resource=const.CMD_FWG) + return {'id': args[1]} + + self.neutronclient.find_resource.side_effect = mock.Mock( + side_effect=_mock_fwr) arglist, verifylist = self._set_all_params(args) request, response = _generate_req_and_res(verifylist) self._update_expect_response(request, response) @@ -278,6 +310,34 @@ class TestCreateFirewallRule(TestFirewallRule, common.TestCreateFWaaS): testtools.matchers._impl.MismatchError, self.check_parser, self.cmd, arglist, verifylist) + def test_create_with_src_fwg_and_no(self): + fwg = 'my-fwg' + arglist = [ + '--source-firewall-group', fwg, + '--no-source-firewall-group', + ] + verifylist = [ + ('source_firewall_group', fwg), + ('no_source_firewall_group', True), + ] + self.assertRaises( + utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_create_with_dst_fwg_and_no(self): + fwg = 'my-fwg' + arglist = [ + '--destination-firewall-group', fwg, + '--no-destination-firewall-group', + ] + verifylist = [ + ('destination_firewall_group', fwg), + ('no_destination_firewall_group', True), + ] + self.assertRaises( + utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + class TestListFirewallRule(TestFirewallRule): @@ -326,7 +386,8 @@ class TestListFirewallRule(TestFirewallRule): self.mocked.assert_called_once_with() self.assertEqual(list(self.headers), headers) - self.assertListItemEqual([self.data], list(data)) + m = list(data) + self.assertListItemEqual([self.data], m) def test_list_with_no_option(self): arglist = [] @@ -646,6 +707,74 @@ class TestSetFirewallRule(TestFirewallRule, common.TestSetFWaaS): self.assertRaises( exceptions.CommandError, self.cmd.take_action, parsed_args) + def test_set_no_destination_fwg(self): + target = self.resource['id'] + arglist = [ + target, + '--no-destination-firewall-group', + ] + verifylist = [ + (self.res, target), + ('no_destination_firewall_group', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + self.mocked.assert_called_once_with( + target, {self.res: {'destination_firewall_group_id': None}}) + self.assertIsNone(result) + + def test_set_no_source_fwg(self): + target = self.resource['id'] + arglist = [ + target, + '--no-source-firewall-group', + ] + verifylist = [ + (self.res, target), + ('no_source_firewall_group', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + self.mocked.assert_called_once_with( + target, {self.res: {'source_firewall_group_id': None}}) + self.assertIsNone(result) + + def test_create_with_src_fwg_and_no(self): + target = self.resource['id'] + fwg = 'my-fwg' + arglist = [ + target, + '--source-firewall-group', fwg, + '--no-source-firewall-group', + ] + verifylist = [ + (self.res, target), + ('source_firewall_group', fwg), + ('no_source_firewall_group', True), + ] + self.assertRaises( + utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + + def test_create_with_dst_fwg_and_no(self): + target = self.resource['id'] + fwg = 'my-fwg' + arglist = [ + target, + '--destination-firewall-group', fwg, + '--no-destination-firewall-group', + ] + verifylist = [ + (self.res, target), + ('destination_firewall_group', fwg), + ('no_destination_firewall_group', True), + ] + self.assertRaises( + utils.ParserException, + self.check_parser, self.cmd, arglist, verifylist) + class TestUnsetFirewallRule(TestFirewallRule, common.TestUnsetFWaaS): diff --git a/releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml b/releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml new file mode 100644 index 000000000..5f5073aee --- /dev/null +++ b/releasenotes/notes/remote_fwg-0f5362e5be8b2e84.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds the remote source firewall group and the remote destination + firewall group field to the firewall rules.