From 6c7a30ab381e79f21767898f0a235276839f8ef2 Mon Sep 17 00:00:00 2001 From: ting wang Date: Thu, 26 May 2016 19:55:11 +0800 Subject: [PATCH] Implement rbac list and show command 1. implement "openstack network rbac list" 2. implement "openstack network rbac show" 3. also add FakeRBACPolicy to test "network rbac xxx" command The unit test class similar to FakeRouter, which is able to fake one or more rbac policies. It will be used by the rbac CRUD patches. Change-Id: I6c97bc8819698546895fd530464a2cbb347bf77d Co-Authored-By: Huanxuan Ao Partially-Implements: blueprint neutron-client-rbac Depends-On: I88f409a24947b67146c0f93ec8480834cef56d2f --- doc/source/command-objects/network-rbac.rst | 35 +++++ doc/source/commands.rst | 1 + openstackclient/network/v2/network_rbac.py | 75 +++++++++++ openstackclient/tests/network/v2/fakes.py | 51 ++++++++ .../tests/network/v2/test_network_rbac.py | 122 ++++++++++++++++++ ...-neutron-client-rbac-bbd7b545b50d2bdf.yaml | 4 + setup.cfg | 3 + 7 files changed, 291 insertions(+) create mode 100644 doc/source/command-objects/network-rbac.rst create mode 100644 openstackclient/network/v2/network_rbac.py create mode 100644 openstackclient/tests/network/v2/test_network_rbac.py create mode 100644 releasenotes/notes/bp-neutron-client-rbac-bbd7b545b50d2bdf.yaml diff --git a/doc/source/command-objects/network-rbac.rst b/doc/source/command-objects/network-rbac.rst new file mode 100644 index 0000000000..0cf2127fc2 --- /dev/null +++ b/doc/source/command-objects/network-rbac.rst @@ -0,0 +1,35 @@ +============ +network rbac +============ + +A **network rbac** is a Role-Based Access Control (RBAC) policy for +network resources. It enables both operators and users to grant access +to network resources for specific projects. + +Network v2 + +network rbac list +----------------- + +List network RBAC policies + +.. program:: network rbac list +.. code:: bash + + os network rbac list + +network rbac show +----------------- + +Display network RBAC policy details + +.. program:: network rbac show +.. code:: bash + + os network rbac show + + +.. _network_rbac_show-rbac-policy: +.. describe:: + + RBAC policy (ID only) diff --git a/doc/source/commands.rst b/doc/source/commands.rst index 9fb0555d7c..a2e8712a9d 100644 --- a/doc/source/commands.rst +++ b/doc/source/commands.rst @@ -105,6 +105,7 @@ referring to both Compute and Volume quotas. * ``mapping``: (**Identity**) a definition to translate identity provider attributes to Identity concepts * ``module``: (**Internal**) - installed Python modules in the OSC process * ``network``: (**Compute**, **Network**) - a virtual network for connecting servers and other resources +* ``network rbac``: (**Network**) - an RBAC policy for network resources * ``network segment``: (**Network**) - a segment of a virtual network * ``object``: (**Object Storage**) a single file in the Object Storage * ``object store account``: (**Object Storage**) owns a group of Object Storage resources diff --git a/openstackclient/network/v2/network_rbac.py b/openstackclient/network/v2/network_rbac.py new file mode 100644 index 0000000000..7a759449b6 --- /dev/null +++ b/openstackclient/network/v2/network_rbac.py @@ -0,0 +1,75 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +"""RBAC action implementations""" + +from osc_lib.command import command +from osc_lib import utils + +from openstackclient.i18n import _ + + +def _get_columns(item): + columns = list(item.keys()) + if 'tenant_id' in columns: + columns.remove('tenant_id') + columns.append('project_id') + if 'target_tenant' in columns: + columns.remove('target_tenant') + columns.append('target_project') + return tuple(sorted(columns)) + + +class ListNetworkRBAC(command.Lister): + """List network RBAC policies""" + + def take_action(self, parsed_args): + client = self.app.client_manager.network + + columns = ( + 'id', + 'object_type', + 'object_id', + ) + column_headers = ( + 'ID', + 'Object Type', + 'Object ID', + ) + + data = client.rbac_policies() + return (column_headers, + (utils.get_item_properties( + s, columns, + ) for s in data)) + + +class ShowNetworkRBAC(command.ShowOne): + """Display network RBAC policy details""" + + def get_parser(self, prog_name): + parser = super(ShowNetworkRBAC, self).get_parser(prog_name) + parser.add_argument( + 'rbac_policy', + metavar="", + help=_("RBAC policy (ID only)") + ) + return parser + + def take_action(self, parsed_args): + client = self.app.client_manager.network + obj = client.find_rbac_policy(parsed_args.rbac_policy, + ignore_missing=False) + columns = _get_columns(obj) + data = utils.get_item_properties(obj, columns) + return columns, data diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py index 50d9899cb0..786d0d59ca 100644 --- a/openstackclient/tests/network/v2/fakes.py +++ b/openstackclient/tests/network/v2/fakes.py @@ -480,6 +480,57 @@ class FakePort(object): return mock.MagicMock(side_effect=ports) +class FakeNetworkRBAC(object): + """Fake one or more network rbac policies.""" + + @staticmethod + def create_one_network_rbac(attrs=None): + """Create a fake network rbac + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object, with id, action, target_tenant, + tenant_id, type + """ + attrs = attrs or {} + + # Set default attributes + rbac_attrs = { + 'id': 'rbac-id-' + uuid.uuid4().hex, + 'object_type': 'network', + 'object_id': 'object-id-' + uuid.uuid4().hex, + 'action': 'access_as_shared', + 'target_tenant': 'target-tenant-' + uuid.uuid4().hex, + 'tenant_id': 'tenant-id-' + uuid.uuid4().hex, + } + rbac_attrs.update(attrs) + rbac = fakes.FakeResource(info=copy.deepcopy(rbac_attrs), + loaded=True) + # Set attributes with special mapping in OpenStack SDK. + rbac.project_id = rbac_attrs['tenant_id'] + rbac.target_project = rbac_attrs['target_tenant'] + return rbac + + @staticmethod + def create_network_rbacs(attrs=None, count=2): + """Create multiple fake network rbac policies. + + :param Dictionary attrs: + A dictionary with all attributes + :param int count: + The number of rbac policies to fake + :return: + A list of FakeResource objects faking the rbac policies + """ + rbac_policies = [] + for i in range(0, count): + rbac_policies.append(FakeNetworkRBAC. + create_one_network_rbac(attrs)) + + return rbac_policies + + class FakeRouter(object): """Fake one or more routers.""" diff --git a/openstackclient/tests/network/v2/test_network_rbac.py b/openstackclient/tests/network/v2/test_network_rbac.py new file mode 100644 index 0000000000..057e0adc74 --- /dev/null +++ b/openstackclient/tests/network/v2/test_network_rbac.py @@ -0,0 +1,122 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import mock + +from openstackclient.network.v2 import network_rbac +from openstackclient.tests.network.v2 import fakes as network_fakes +from openstackclient.tests import utils as tests_utils + + +class TestNetworkRBAC(network_fakes.TestNetworkV2): + + def setUp(self): + super(TestNetworkRBAC, self).setUp() + + # Get a shortcut to the network client + self.network = self.app.client_manager.network + + +class TestListNetworkRABC(TestNetworkRBAC): + + # The network rbac policies going to be listed up. + rbac_policies = network_fakes.FakeNetworkRBAC.create_network_rbacs(count=3) + + columns = ( + 'ID', + 'Object Type', + 'Object ID', + ) + + data = [] + for r in rbac_policies: + data.append(( + r.id, + r.object_type, + r.object_id, + )) + + def setUp(self): + super(TestListNetworkRABC, self).setUp() + + # Get the command object to test + self.cmd = network_rbac.ListNetworkRBAC(self.app, self.namespace) + + self.network.rbac_policies = mock.Mock(return_value=self.rbac_policies) + + def test_network_rbac_list(self): + arglist = [] + verifylist = [] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.network.rbac_policies.assert_called_with() + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + +class TestShowNetworkRBAC(TestNetworkRBAC): + + rbac_policy = network_fakes.FakeNetworkRBAC.create_one_network_rbac() + + columns = ( + 'action', + 'id', + 'object_id', + 'object_type', + 'project_id', + 'target_project', + ) + + data = [ + rbac_policy.action, + rbac_policy.id, + rbac_policy.object_id, + rbac_policy.object_type, + rbac_policy.tenant_id, + rbac_policy.target_tenant, + ] + + def setUp(self): + super(TestShowNetworkRBAC, self).setUp() + + # Get the command object to test + self.cmd = network_rbac.ShowNetworkRBAC(self.app, self.namespace) + + self.network.find_rbac_policy = mock.Mock( + return_value=self.rbac_policy) + + def test_show_no_options(self): + arglist = [] + verifylist = [] + + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_network_rbac_show_all_options(self): + arglist = [ + self.rbac_policy.object_id, + ] + verifylist = [] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.network.find_rbac_policy.assert_called_with( + self.rbac_policy.object_id, ignore_missing=False + ) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) diff --git a/releasenotes/notes/bp-neutron-client-rbac-bbd7b545b50d2bdf.yaml b/releasenotes/notes/bp-neutron-client-rbac-bbd7b545b50d2bdf.yaml new file mode 100644 index 0000000000..ad5c02bad3 --- /dev/null +++ b/releasenotes/notes/bp-neutron-client-rbac-bbd7b545b50d2bdf.yaml @@ -0,0 +1,4 @@ +--- +features: + - Add ``network rbac list`` and ``network rbac show`` commands. + [Blueprint `neutron-client-rbac `_] diff --git a/setup.cfg b/setup.cfg index 5e26d38dbd..c3d3f34e6c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -348,6 +348,9 @@ openstack.network.v2 = network_set = openstackclient.network.v2.network:SetNetwork network_show = openstackclient.network.v2.network:ShowNetwork + network_rbac_list = openstackclient.network.v2.network_rbac:ListNetworkRBAC + network_rbac_show = openstackclient.network.v2.network_rbac:ShowNetworkRBAC + network_segment_list = openstackclient.network.v2.network_segment:ListNetworkSegment network_segment_show = openstackclient.network.v2.network_segment:ShowNetworkSegment