diff --git a/doc/source/users/resources/network/index.rst b/doc/source/users/resources/network/index.rst index 0335c138..ce182056 100644 --- a/doc/source/users/resources/network/index.rst +++ b/doc/source/users/resources/network/index.rst @@ -20,6 +20,7 @@ Network Resources v2/pool_member v2/port v2/quota + v2/rbac_policy v2/router v2/security_group v2/security_group_rule diff --git a/doc/source/users/resources/network/v2/rbac_policy.rst b/doc/source/users/resources/network/v2/rbac_policy.rst new file mode 100644 index 00000000..daf76007 --- /dev/null +++ b/doc/source/users/resources/network/v2/rbac_policy.rst @@ -0,0 +1,12 @@ +openstack.network.v2.rbac_policy +================================ + +.. automodule:: openstack.network.v2.rbac_policy + +The RBACPolicy Class +-------------------- + +The ``RBACPolicy`` class inherits from :class:`~openstack.resource.Resource`. + +.. autoclass:: openstack.network.v2.rbac_policy.RBACPolicy + :members: \ No newline at end of file diff --git a/openstack/network/v2/_proxy.py b/openstack/network/v2/_proxy.py index a01a1088..67834de6 100644 --- a/openstack/network/v2/_proxy.py +++ b/openstack/network/v2/_proxy.py @@ -26,6 +26,7 @@ from openstack.network.v2 import pool as _pool from openstack.network.v2 import pool_member as _pool_member from openstack.network.v2 import port as _port from openstack.network.v2 import quota as _quota +from openstack.network.v2 import rbac_policy as _rbac_policy from openstack.network.v2 import router as _router from openstack.network.v2 import security_group as _security_group from openstack.network.v2 import security_group_rule as _security_group_rule @@ -1199,6 +1200,91 @@ class Proxy(proxy.BaseProxy): """ return self._update(_quota.Quota, quota, **attrs) + def create_rbac_policy(self, **attrs): + """Create a new RBAC policy from attributes + + :param dict attrs: Keyword arguments which will be used to create a + :class:`~openstack.network.v2.rbac_policy.RBACPolicy`, + comprised of the properties on the RBACPolicy class. + + :return: The results of RBAC policy creation + :rtype: :class:`~openstack.network.v2.rbac_policy.RBACPolicy` + """ + return self._create(_rbac_policy.RBACPolicy, **attrs) + + def delete_rbac_policy(self, rbac_policy, ignore_missing=True): + """Delete a RBAC policy + + :param rbac_policy: The value can be either the ID of a RBAC policy or + a :class:`~openstack.network.v2.rbac_policy.RBACPolicy` instance. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be + raised when the RBAC policy does not exist. + When set to ``True``, no exception will be set when + attempting to delete a nonexistent RBAC policy. + + :returns: ``None`` + """ + self._delete(_rbac_policy.RBACPolicy, rbac_policy, + ignore_missing=ignore_missing) + + def find_rbac_policy(self, id, ignore_missing=True): + """Find a single RBAC policy + + :param id: The ID of a RBAC policy. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be + raised when the resource does not exist. + When set to ``True``, None will be returned when + attempting to find a nonexistent resource. + :returns: One + :class:`~openstack.network.v2.rbac_policy.RBACPolicy` or None + """ + return self._find(_rbac_policy.RBACPolicy, id, + ignore_missing=ignore_missing) + + def get_rbac_policy(self, rbac_policy): + """Get a single RBAC policy + + :param rbac_policy: The value can be the ID of a RBAC policy or a + :class:`~openstack.network.v2.rbac_policy.RBACPolicy` instance. + + :returns: One :class:`~openstack.network.v2.rbac_policy.RBACPolicy` + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._get(_rbac_policy.RBACPolicy, rbac_policy) + + def rbac_policies(self, **query): + """Return a generator of RBAC policies + + :param kwargs \*\*query: Optional query parameters to be sent to limit + the resources being returned. Available parameters include: + + * tenant_id: The owner tenant ID. + * target_tenant: ID of the tenant to which the RBAC policy + will be enforced. + * object_type: Type of the object that RBAC policy affects. + * action: Action for the RBAC policy. + + :returns: A generator of rbac objects + :rtype: :class:`~openstack.network.v2.rbac_policy.RBACPolicy` + """ + return self._list(_rbac_policy.RBACPolicy, paginated=False, **query) + + def update_rbac_policy(self, rbac_policy, **attrs): + """Update a RBAC policy + + :param rbac_policy: Either the id of a RBAC policy or a + :class:`~openstack.network.v2.rbac_policy.RBACPolicy` instance. + :attrs kwargs: The attributes to update on the RBAC policy represented + by ``value``. + + :returns: The updated RBAC policy + :rtype: :class:`~openstack.network.v2.rbac_policy.RBACPolicy` + """ + return self._update(_rbac_policy.RBACPolicy, rbac_policy, **attrs) + def create_router(self, **attrs): """Create a new router from attributes diff --git a/openstack/network/v2/rbac_policy.py b/openstack/network/v2/rbac_policy.py new file mode 100644 index 00000000..9ee9a97d --- /dev/null +++ b/openstack/network/v2/rbac_policy.py @@ -0,0 +1,40 @@ +# 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. + +from openstack.network import network_service +from openstack import resource + + +class RBACPolicy(resource.Resource): + resource_key = 'rbac_policy' + resources_key = 'rbac_policies' + base_path = '/rbac-policies' + service = network_service.NetworkService() + + # capabilities + allow_create = True + allow_retrieve = True + allow_update = True + allow_delete = True + allow_list = True + + # Properties + #: The id of RBAC object. + object_id = resource.prop('object_id') + #: The ID of the project this RBAC will be enforced. + target_project_id = resource.prop('target_tenant') + #: The owner project ID. + project_id = resource.prop('tenant_id') + #: Type of the object that RBAC policy affects. + object_type = resource.prop('object_type') + #: Action for the RBAC policy. + action = resource.prop('action') diff --git a/openstack/tests/functional/network/v2/test_rbac_policy.py b/openstack/tests/functional/network/v2/test_rbac_policy.py new file mode 100644 index 00000000..1c28b886 --- /dev/null +++ b/openstack/tests/functional/network/v2/test_rbac_policy.py @@ -0,0 +1,64 @@ +# 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 uuid + +from openstack.network.v2 import network +from openstack.network.v2 import rbac_policy +from openstack.tests.functional import base + + +class TestRBACPolicy(base.BaseFunctionalTest): + + NET_NAME = 'net-' + uuid.uuid4().hex + UPDATE_NAME = uuid.uuid4().hex + ACTION = 'access_as_shared' + OBJ_TYPE = 'network' + TARGET_TENANT_ID = '*' + NET_ID = None + ID = None + + @classmethod + def setUpClass(cls): + super(TestRBACPolicy, cls).setUpClass() + net = cls.conn.network.create_network(name=cls.NET_NAME) + assert isinstance(net, network.Network) + cls.NET_ID = net.id + + sot = cls.conn.network.\ + create_rbac_policy(action=cls.ACTION, + object_type=cls.OBJ_TYPE, + target_tenant=cls.TARGET_TENANT_ID, + object_id=cls.NET_ID) + assert isinstance(sot, rbac_policy.RBACPolicy) + cls.ID = sot.id + + @classmethod + def tearDownClass(cls): + sot = cls.conn.network.delete_rbac_policy(cls.ID, + ignore_missing=False) + cls.assertIs(None, sot) + sot = cls.conn.network.delete_network(cls.NET_ID, + ignore_missing=False) + cls.assertIs(None, sot) + + def test_find(self): + sot = self.conn.network.find_rbac_policy(self.ID) + self.assertEqual(self.ID, sot.id) + + def test_get(self): + sot = self.conn.network.get_rbac_policy(self.ID) + self.assertEqual(self.ID, sot.id) + + def test_list(self): + ids = [o.id for o in self.conn.network.rbac_policies()] + self.assertIn(self.ID, ids) diff --git a/openstack/tests/unit/network/v2/test_proxy.py b/openstack/tests/unit/network/v2/test_proxy.py index 87e8bd20..99e8245d 100644 --- a/openstack/tests/unit/network/v2/test_proxy.py +++ b/openstack/tests/unit/network/v2/test_proxy.py @@ -29,6 +29,7 @@ from openstack.network.v2 import pool from openstack.network.v2 import pool_member from openstack.network.v2 import port from openstack.network.v2 import quota +from openstack.network.v2 import rbac_policy from openstack.network.v2 import router from openstack.network.v2 import security_group from openstack.network.v2 import security_group_rule @@ -396,6 +397,32 @@ class TestNetworkProxy(test_proxy_base.TestProxyBase): def test_quota_update(self): self.verify_update(self.proxy.update_quota, quota.Quota) + def test_rbac_policy_create_attrs(self): + self.verify_create(self.proxy.create_rbac_policy, + rbac_policy.RBACPolicy) + + def test_rbac_policy_delete(self): + self.verify_delete(self.proxy.delete_rbac_policy, + rbac_policy.RBACPolicy, False) + + def test_rbac_policy_delete_ignore(self): + self.verify_delete(self.proxy.delete_rbac_policy, + rbac_policy.RBACPolicy, True) + + def test_rbac_policy_find(self): + self.verify_find(self.proxy.find_rbac_policy, rbac_policy.RBACPolicy) + + def test_rbac_policy_get(self): + self.verify_get(self.proxy.get_rbac_policy, rbac_policy.RBACPolicy) + + def test_rbac_policies(self): + self.verify_list(self.proxy.rbac_policies, + rbac_policy.RBACPolicy, paginated=False) + + def test_rbac_policy_update(self): + self.verify_update(self.proxy.update_rbac_policy, + rbac_policy.RBACPolicy) + def test_router_create_attrs(self): self.verify_create(self.proxy.create_router, router.Router) diff --git a/openstack/tests/unit/network/v2/test_rbac_policy.py b/openstack/tests/unit/network/v2/test_rbac_policy.py new file mode 100644 index 00000000..3cfb1598 --- /dev/null +++ b/openstack/tests/unit/network/v2/test_rbac_policy.py @@ -0,0 +1,48 @@ +# 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 testtools + +from openstack.network.v2 import rbac_policy + +IDENTIFIER = 'IDENTIFIER' +EXAMPLE = { + 'object_id': IDENTIFIER, + 'tenant_id': '5', + 'object_type': 'network', + 'action': 'access_as_shared', + 'target_tenant': '10', +} + + +class TestRBACPolicy(testtools.TestCase): + + def test_basic(self): + sot = rbac_policy.RBACPolicy() + self.assertEqual('rbac_policy', sot.resource_key) + self.assertEqual('rbac_policies', sot.resources_key) + self.assertEqual('/rbac-policies', sot.base_path) + self.assertEqual('network', sot.service.service_type) + self.assertTrue(sot.allow_create) + self.assertTrue(sot.allow_retrieve) + self.assertTrue(sot.allow_update) + self.assertTrue(sot.allow_delete) + self.assertTrue(sot.allow_list) + + def test_make_it(self): + sot = rbac_policy.RBACPolicy(EXAMPLE) + self.assertEqual(EXAMPLE['object_id'], + sot.object_id) + self.assertEqual(EXAMPLE['tenant_id'], sot.project_id) + self.assertEqual(EXAMPLE['object_type'], sot.object_type) + self.assertEqual(EXAMPLE['action'], sot.action) + self.assertEqual(EXAMPLE['target_tenant'], sot.target_project_id)