diff options
author | Zuul <zuul@review.opendev.org> | 2021-02-12 13:20:10 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2021-02-12 13:20:10 +0000 |
commit | b22429fa8bd823f10b555dc9b07c712101c80c60 (patch) | |
tree | 927a26eb55ce1b862e3fc4238bd8b32b7ecb6113 | |
parent | 71a875faccdd9a546c28eac8b89bb8d958b65a55 (diff) | |
parent | 606549c1c95b3f2c611b8bd5771e19dadeed3995 (diff) | |
download | ironic-b22429fa8bd823f10b555dc9b07c712101c80c60.tar.gz |
Merge "Populate existing policy tests"
-rw-r--r-- | doc/source/contributor/index.rst | 1 | ||||
-rw-r--r-- | doc/source/contributor/rbac-testing.rst | 119 | ||||
-rw-r--r-- | ironic/tests/unit/api/base.py | 15 | ||||
-rw-r--r-- | ironic/tests/unit/api/test_acl.py | 150 | ||||
-rw-r--r-- | ironic/tests/unit/api/test_acl_basic.yaml | 1 | ||||
-rw-r--r-- | ironic/tests/unit/api/test_rbac_legacy.yaml | 2020 |
6 files changed, 1965 insertions, 341 deletions
diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst index 0377bdb34..072490554 100644 --- a/doc/source/contributor/index.rst +++ b/doc/source/contributor/index.rst @@ -32,6 +32,7 @@ primarily for developers. Developing New Notifications <notifications> OSProfiler Tracing <osprofiler-support> Rolling Upgrades <rolling-upgrades> + Role Based Access Control Testing <rbac-testing> These pages contain information for PTLs, cross-project liaisons, and core reviewers. diff --git a/doc/source/contributor/rbac-testing.rst b/doc/source/contributor/rbac-testing.rst new file mode 100644 index 000000000..dca06b36d --- /dev/null +++ b/doc/source/contributor/rbac-testing.rst @@ -0,0 +1,119 @@ +================================== +Role Based Acces Control - Testing +================================== + +.. todo: This entire file is being added in to provide context for + reviewers so we can keep in-line comments to the necessary points + in the yaml files. It *IS* written with a forward awareness of the + later patches, but it is also broad in nature attempting to provide + context to aid in review. + +The Role Based Access control testing is a minor departure from the ironic +standard pattern of entirely python based unit testing. In part this was done +for purposes of speed and to keep the declaration of the test context. + +This also lended itself to be very useful due to the nature of A/B testing +which is requried to properly migrate the Ironic project from a project +scoped universe where an ``admin project`` is utilized as the authenticating +factor coupled with two custom roles, ``baremetal_admin``, and +``baremetal_observer``. + +As a contributor looking back after getting a over a thousand additional tests +in place using this method, it definitely helped the speed at which these +were created, and then ported to support additional. + +How these tests work +==================== + +These tests execute API calls through the API layer, using the appropriate +verb and header, which settings to prevent the ``keystonemiddleware`` from +intercepting and replacing the headers we're passing. Ultimately this is a +feature, and it helps quite a bit. + +The second aspect of how this works is we're mocking the conductor RPC +``get_topic_for`` and ``get_random_topic_for`` methods. These calls raise +Temporary Unavailable, since trying to execute the entire interaction into +the conductor is moderately pointless because all policy enforement is +located with-in the API layer. + +At the same time wiring everything up to go from API to conductor code and +back would have been a heavier lift. As such, the tests largely look for +one of the following error codes. + +* 200 - Got the item from the API - This is an database driven interaction. +* 201 - Created - This is databaes driven interaction. These are rare. +* 204 - Accepted - This is a database driven interaction. These are rare. +* 403 - Forbidden - This tells us the policy worked as expected where + access was denied. +* 404 - NotFound - This is typically when objects were not found. Before + ironic becomes scope aware, these are generally only in the drivers + API endpoint's behavior. In System scope aware Project scoped + configuration, i.e. later RBAC tests, this will become the dominant + response for project scoped users as responding with a 403 if they + could be an owner or lessee would provide insight into the existence + of a node. +* 503 - Service Unavailable - In the context of our tests, we expect this + when a request *has* been successfully authenticated and would have + been sent along to the conductor. + +How to make changes or review these tests? +========================================== + +The tests cycle through the various endpoints, and repeating patterns +are clearly visible. Typically this means a given endpoint is cycled +through with the same basic test using slightly different parameters +such as different authentication parameters. When it comes to system +scope aware tests supporting node ``owners`` and ``lessee``, these +tests will cycle a little more with slightly different attributes +as the operation is not general against a shared common node, but +different nodes. + +Some tests will test body contents, or attributes. some will validate +the number of records returned. This is important later with ``owner`` +and ``lessee`` having slightly different views of the universe. + +Some general rules apply + +* Admins can do things +* Members can do some things, but not everything +* Readers can always read, but as we get into sensitive data later on + such as fields containing infrastucture internal addresses, these values + will become hidden and additional tests will examine this. +* Third party, or external/other Admins will find nothing but sadness + in empty lists, 403, 404, or even 500 errors. + +What is/will be tested? +======================= + +The idea is to in essence test as much as possible, however as these +tests Role Based Access Control related capabilities will come in a +series of phases, styles vary a little. + +The first phase is ``"legacy"``. In essence these are partially +programatically generated and then human reviewed and values populated +with expected values. + +The second phase is remarkably similar to ``legacy``. It is the safety net +where we execute the ``legacy`` tests with the updated ``oslo.policy`` +configuration to help enforce scopes. These tests will intentionally begin to +fail in phase three. + +The third phase is the implementation of System scope awareness for the +API. In this process, as various portions of the API are made system scope +aware. The ``legacy`` tests are marked as ``deprecated`` which signals to +the second phase test sequences that they are **expected** to fail. New +``system scoped`` tests are also implemented which are matched up by name +to the ``legacy`` tests. The major difference being some header values, +and a user with a ``member`` role in the ``system`` scope now has some +rights. + +The forth phase, is implementaiton of ``owner`` and ``lessee`` aware +project scoping. The testing approach is similar, however it is much more of +a "shotgun" approach. We test what we know should work, and what know should +not work, but we do not have redundant testing for each role as ``admin`` +users are also ``members``, and since the policy rules are designed around +thresholds of access, it just made no sense to run the same test for admin +and members, where member was the threshold. These thresholds will vary with +the proposed default policy. The forth scope also tests a third party external +admin as a negative test to ensure that we are also denying access to +resources appropriately. diff --git a/ironic/tests/unit/api/base.py b/ironic/tests/unit/api/base.py index 3d80ee42f..ebf89df32 100644 --- a/ironic/tests/unit/api/base.py +++ b/ironic/tests/unit/api/base.py @@ -112,7 +112,7 @@ class BaseApiTest(db_base.DbTestCase): return response def put_json(self, path, params, expect_errors=False, headers=None, - extra_environ=None, status=None): + extra_environ=None, status=None, path_prefix=PATH_PREFIX): """Sends simulated HTTP PUT request to Pecan test app. :param path: url path of target service @@ -127,10 +127,11 @@ class BaseApiTest(db_base.DbTestCase): return self._request_json(path=path, params=params, expect_errors=expect_errors, headers=headers, extra_environ=extra_environ, - status=status, method="put") + status=status, method="put", + path_prefix=path_prefix) def post_json(self, path, params, expect_errors=False, headers=None, - extra_environ=None, status=None): + extra_environ=None, status=None, path_prefix=PATH_PREFIX): """Sends simulated HTTP POST request to Pecan test app. :param path: url path of target service @@ -145,10 +146,11 @@ class BaseApiTest(db_base.DbTestCase): return self._request_json(path=path, params=params, expect_errors=expect_errors, headers=headers, extra_environ=extra_environ, - status=status, method="post") + status=status, method="post", + path_prefix=path_prefix) def patch_json(self, path, params, expect_errors=False, headers=None, - extra_environ=None, status=None): + extra_environ=None, status=None, path_prefix=PATH_PREFIX): """Sends simulated HTTP PATCH request to Pecan test app. :param path: url path of target service @@ -163,7 +165,8 @@ class BaseApiTest(db_base.DbTestCase): return self._request_json(path=path, params=params, expect_errors=expect_errors, headers=headers, extra_environ=extra_environ, - status=status, method="patch") + status=status, method="patch", + path_prefix=path_prefix) def delete(self, path, expect_errors=False, headers=None, extra_environ=None, status=None, path_prefix=PATH_PREFIX): diff --git a/ironic/tests/unit/api/test_acl.py b/ironic/tests/unit/api/test_acl.py index aa9a74019..adea1fe4e 100644 --- a/ironic/tests/unit/api/test_acl.py +++ b/ironic/tests/unit/api/test_acl.py @@ -23,6 +23,9 @@ import ddt from keystonemiddleware import auth_token from oslo_config import cfg +from ironic.api.controllers.v1 import versions as api_versions +from ironic.common import exception +from ironic.conductor import rpcapi from ironic.tests.unit.api import base from ironic.tests.unit.db import utils as db_utils @@ -42,6 +45,17 @@ class TestACLBase(base.BaseApiTest): self.mock_auth = mock_auth.start() self.addCleanup(mock_auth.stop) + topic = mock.patch.object( + rpcapi.ConductorAPI, 'get_topic_for', autospec=True) + self.mock_topic = topic.start() + self.mock_topic.side_effect = exception.TemporaryFailure + self.addCleanup(topic.stop) + rtopic = mock.patch.object(rpcapi.ConductorAPI, 'get_random_topic', + autospec=True) + self.mock_random_topic = rtopic.start() + self.mock_random_topic.side_effect = exception.TemporaryFailure + self.addCleanup(rtopic.stop) + def _make_app(self): cfg.CONF.set_override('auth_strategy', 'keystone') return super(TestACLBase, self)._make_app() @@ -53,23 +67,70 @@ class TestACLBase(base.BaseApiTest): def _check_skip(self, **kwargs): if kwargs.get('skip_reason'): self.skipTest(kwargs.get('skip_reason')) - # Remove ASAP, but as a few hundred tests use this, we can - # rip it out later. - if kwargs.get('skip'): - self.skipTest(kwargs.get('skip_reason', 'Not implemented')) def _fake_process_request(self, request, auth_token_request): pass def _test_request(self, path, params=None, headers=None, method='get', - assert_status=None, assert_dict_contains=None): + body=None, assert_status=None, + assert_dict_contains=None, + assert_list_length=None): path = path.format(**self.format_data) self.mock_auth.side_effect = self._fake_process_request + # always request the latest api version + version = api_versions.max_version_string() + rheaders = { + 'X-OpenStack-Ironic-API-Version': version + } + # NOTE(TheJulia): Logging the test request to aid + # in troubleshooting ACL testing. This is a pattern + # followed in API unit testing in ironic, and + # really does help. + print('API ACL Testing Path %s %s' % (method, path)) + if headers: + for k, v in headers.items(): + rheaders[k] = v.format(**self.format_data) + if method == 'get': response = self.get_json( path, - headers=headers, + headers=rheaders, + expect_errors=True, + extra_environ=self.environ, + path_prefix='' + ) + elif method == 'put': + response = self.put_json( + path, + headers=rheaders, + expect_errors=True, + extra_environ=self.environ, + path_prefix='', + params=body + ) + elif method == 'post': + response = self.post_json( + path, + headers=rheaders, + expect_errors=True, + extra_environ=self.environ, + path_prefix='', + params=body + ) + elif method == 'patch': + response = self.patch_json( + path, + params=body, + headers=rheaders, + expect_errors=True, + extra_environ=self.environ, + path_prefix='' + ) + elif method == 'delete': + response = self.delete( + path, + headers=rheaders, expect_errors=True, extra_environ=self.environ, path_prefix='' @@ -77,12 +138,10 @@ class TestACLBase(base.BaseApiTest): else: assert False, 'Unimplemented test method: %s' % method - other_asserts = bool(assert_dict_contains) - if assert_status: self.assertEqual(assert_status, response.status_int) else: - self.assertIsNotNone(other_asserts, + self.assertIsNotNone(assert_status, 'Tests must include an assert_status') if assert_dict_contains: @@ -91,6 +150,22 @@ class TestACLBase(base.BaseApiTest): self.assertEqual(v.format(**self.format_data), response.json[k]) + if assert_list_length: + for root, length in assert_list_length.items(): + # root - object to look inside + # length - number of expected elements which will be + # important for owner/lessee testing. + items = response.json[root] + self.assertIsInstance(items, list) + self.assertEqual(length, len(items)) + + # NOTE(TheJulia): API tests in Ironic tend to have a pattern + # to print request and response data to aid in development + # and troubleshooting. As such the prints should remain, + # at least until we are through primary development of the + # this test suite. + print('ACL Test GOT %s' % response) + @ddt.ddt class TestRBACBasic(TestACLBase): @@ -110,8 +185,61 @@ class TestRBACBasic(TestACLBase): class TestRBACModelBeforeScopes(TestACLBase): def _create_test_data(self): - fake_db_node = db_utils.create_test_node(chassis_id=None) - self.format_data['node_ident'] = fake_db_node['uuid'] + allocated_node_id = 31 + fake_db_allocation = db_utils.create_test_allocation( + node_id=allocated_node_id, + resource_class="CUSTOM_TEST") + fake_db_node = db_utils.create_test_node( + chassis_id=None, + driver='fake-driverz') + fake_db_node_alloced = db_utils.create_test_node( + id=allocated_node_id, + chassis_id=None, + allocation_id=fake_db_allocation['id'], + uuid='22e26c0b-03f2-4d2e-ae87-c02d7f33c000', + driver='fake-driverz') + fake_vif_port_id = "ee21d58f-5de2-4956-85ff-33935ea1ca00" + fake_db_port = db_utils.create_test_port( + node_id=fake_db_node['id'], + internal_info={'tenant_vif_port_id': fake_vif_port_id}) + fake_db_portgroup = db_utils.create_test_portgroup( + node_id=fake_db_node['id']) + fake_db_chassis = db_utils.create_test_chassis() + fake_db_deploy_template = db_utils.create_test_deploy_template() + fake_db_conductor = db_utils.create_test_conductor() + fake_db_volume_target = db_utils.create_test_volume_target( + node_id=fake_db_allocation['id']) + fake_db_volume_connector = db_utils.create_test_volume_connector( + node_id=fake_db_allocation['id']) + # Trait name aligns with create_test_node_trait. + fake_trait = 'trait' + fake_setting = 'FAKE_SETTING' + db_utils.create_test_bios_setting( + node_id=fake_db_node['id'], + name=fake_setting, + value=fake_setting) + db_utils.create_test_node_trait( + node_id=fake_db_node['id']) + + self.format_data.update({ + 'node_ident': fake_db_node['uuid'], + 'allocated_node_ident': fake_db_node_alloced['uuid'], + 'port_ident': fake_db_port['uuid'], + 'portgroup_ident': fake_db_portgroup['uuid'], + 'chassis_ident': fake_db_chassis['uuid'], + 'deploy_template_ident': fake_db_deploy_template['uuid'], + 'allocation_ident': fake_db_allocation['uuid'], + 'conductor_ident': fake_db_conductor['hostname'], + 'vif_ident': fake_vif_port_id, + # Can't use the same fake-driver as other tests can + # pollute a global method cache in the API that is in the + # test runner, resulting in false positives. + 'driver_name': 'fake-driverz', + 'bios_setting': fake_setting, + 'trait': fake_trait, + 'volume_target_ident': fake_db_volume_target['uuid'], + 'volume_connector_ident': fake_db_volume_connector['uuid'], + }) @ddt.file_data('test_rbac_legacy.yaml') @ddt.unpack diff --git a/ironic/tests/unit/api/test_acl_basic.yaml b/ironic/tests/unit/api/test_acl_basic.yaml index 52be09d8e..78e860180 100644 --- a/ironic/tests/unit/api/test_acl_basic.yaml +++ b/ironic/tests/unit/api/test_acl_basic.yaml @@ -19,6 +19,7 @@ project_admin_can_get_node: assert_dict_contains: uuid: '{node_uuid}' driver: 'fake-hardware' + assert_status: 200 project_member_cannot_get_node: path: *node_path diff --git a/ironic/tests/unit/api/test_rbac_legacy.yaml b/ironic/tests/unit/api/test_rbac_legacy.yaml index 2e9b6b48a..cccb0b0db 100644 --- a/ironic/tests/unit/api/test_rbac_legacy.yaml +++ b/ironic/tests/unit/api/test_rbac_legacy.yaml @@ -1,643 +1,2015 @@ +# NOTE(TheJulia): This file is intended for legacy project RBAC testing +# and is entirely project scoped in nature. This file will not be used +# for system scoped testing, which will be kept to separate files to +# enable the legacy tests to eventually be removed once support +# for the legacy rules has been removed from Ironic. +# +# For more information on the how these tests work, see: +# doc/source/contributor/rbac-testing.rst + +values: + skip_reason: "These are fake reference values for YAML templating" + # Project scoped admin token + admin_headers: &admin_headers + X-Auth-Token: 'baremetal-admin-token' + X-Project-ID: 66140b35c7524c6da836ca834e3fd3f9 + X-Roles: baremetal_admin + X-Project-Name: baremetal + # Project scoped other member token. + member_headers: &member_headers + X-Auth-Token: 'baremetal-member-token' + X-Project-ID: 66140b35c7524c6da836ca834e3fd3f9 + X-Roles: member + X-Project-Name: baremetal + # Project scoped Observer Token + observer_headers: &observer_headers + X-Auth-Token: 'baremetal-observer-token' + X-Project-ID: 66140b35c7524c6da836ca834e3fd3f9 + X-Project-Name: baremetal + X-Roles: baremetal_observer + other_admin_headers: &other_admin_headers + X-Auth-Token: 'other-admin-token' + X-Project-ID: a1111111111111111111111111111111 + X-Roles: admin,member,reader + X-Project-Name: 'other-project' + owner_project_id: &owner_project_id '{owner_project_id}' + other_project_id: &other_project_id '{other_project_id}' + node_ident: &node_ident '{node_ident}' + # Nodes - https://docs.openstack.org/api-ref/baremetal/?expanded=#nodes-nodes -nodes_post_allow: +nodes_post_admin: + path: '/v1/nodes' + method: post + headers: *admin_headers + body: &node_post_body + name: node + driver: fake-driverz + assert_status: 503 + +nodes_post_member: path: '/v1/nodes' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + body: *node_post_body + assert_status: 403 + +nodes_post_observer: + path: '/v1/nodes' + method: post + headers: *observer_headers + body: *node_post_body + assert_status: 403 + +nodes_get_node_admin: + path: '/v1/nodes/{node_ident}' + method: get + headers: *admin_headers + assert_dict_contains: + uuid: '{node_ident}' + driver: 'fake-driverz' + assert_status: 200 + +nodes_get_node_member: + path: '/v1/nodes/{node_ident}' + method: get + headers: *member_headers + assert_status: 403 + +nodes_get_node_observer: + path: '/v1/nodes/{node_ident}' + method: get + headers: *observer_headers + assert_dict_contains: + uuid: '{node_ident}' + driver: 'fake-driverz' + assert_status: 200 -nodes_get_allow: +nodes_get_node_other_admin: + path: '/v1/nodes/{node_ident}' + method: get + headers: *other_admin_headers + # FIXME(TheJulia): So this is not great, but it is default for now + # And MUST be changed moving forward, just not in this patch. + # This just represents the *current* state, not what the world should be + # in the end. + assert_status: 200 + +nodes_get_admin: + path: '/v1/nodes' + method: get + headers: *admin_headers + assert_list_length: + nodes: 2 + assert_status: 200 + +nodes_get_other_admin: path: '/v1/nodes' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *other_admin_headers + assert_list_length: + nodes: 2 + assert_status: 200 + +nodes_detail_get_admin: + path: '/v1/nodes/detail' + method: get + headers: *admin_headers + assert_status: 200 -nodes_detail_get_allow: +nodes_detail_get_member: path: '/v1/nodes/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +nodes_detail_get_observer: + path: '/v1/nodes/detail' + method: get + headers: *observer_headers + assert_status: 200 + +nodes_node_ident_get_admin: + path: '/v1/nodes/{node_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_node_ident_get_member: + path: '/v1/nodes/{node_ident}' + method: get + headers: *member_headers + assert_status: 403 -nodes_node_ident_get_allow: +nodes_node_ident_get_observer: path: '/v1/nodes/{node_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_node_ident_patch_admin: + path: '/v1/nodes/{node_ident}' + method: patch + headers: *admin_headers + body: &extra_patch + - op: replace + path: /extra + value: {'test': 'testing'} + assert_status: 503 + +nodes_node_ident_patch_member: + path: '/v1/nodes/{node_ident}' + method: patch + headers: *member_headers + body: *extra_patch + assert_status: 403 -nodes_node_ident_patch_allow: +nodes_node_ident_patch_observer: path: '/v1/nodes/{node_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *extra_patch + assert_status: 403 + +nodes_node_ident_delete_admin: + path: '/v1/nodes/{node_ident}' + method: delete + headers: *admin_headers + assert_status: 503 + +nodes_node_ident_delete_member: + path: '/v1/nodes/{node_ident}' + method: delete + headers: *member_headers + assert_status: 403 -nodes_node_ident_delete_allow: +nodes_node_ident_delete_observer: path: '/v1/nodes/{node_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 # Node Management - https://docs.openstack.org/api-ref/baremetal/?expanded=#node-management-nodes -nodes_validate_get_allow: +nodes_validate_get_admin: + path: '/v1/nodes/{node_ident}/validate' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_validate_get_member: + path: '/v1/nodes/{node_ident}/validate' + method: get + headers: *member_headers + assert_status: 403 + +nodes_validate_get_observer: path: '/v1/nodes/{node_ident}/validate' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + +nodes_maintenance_put_admin: + path: '/v1/nodes/{node_ident}/maintenance' + method: put + headers: *admin_headers + assert_status: 503 + +nodes_maintenance_put_member: + path: '/v1/nodes/{node_ident}/maintenance' + method: put + headers: *member_headers + assert_status: 403 -nodes_maintenance_put_allow: +nodes_maintenance_put_observer: path: '/v1/nodes/{node_ident}/maintenance' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 -nodes_maintenance_delete_allow: +nodes_maintenance_delete_admin: path: '/v1/nodes/{node_ident}/maintenance' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + +nodes_maintenance_delete_member: + path: '/v1/nodes/{node_ident}/maintenance' + method: delete + headers: *member_headers + assert_status: 403 + +nodes_maintenance_delete_observer: + path: '/v1/nodes/{node_ident}/maintenance' + method: delete + headers: *observer_headers + assert_status: 403 + +nodes_management_boot_device_put_admin: + path: '/v1/nodes/{node_ident}/management/boot_device' + method: put + headers: *admin_headers + body: &boot_device_body + boot_device: pxe + assert_status: 503 + +nodes_management_boot_device_put_member: + path: '/v1/nodes/{node_ident}/management/boot_device' + method: put + headers: *member_headers + body: *boot_device_body + assert_status: 403 -nodes_management_boot_device_put_allow: +nodes_management_boot_device_put_observer: path: '/v1/nodes/{node_ident}/management/boot_device' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *boot_device_body + assert_status: 403 + +nodes_management_boot_device_get_admin: + path: '/v1/nodes/{node_ident}/management/boot_device' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_management_boot_device_get_member: + path: '/v1/nodes/{node_ident}/management/boot_device' + method: get + headers: *member_headers + assert_status: 403 -nodes_management_boot_device_get_allow: +nodes_management_boot_device_get_observer: path: '/v1/nodes/{node_ident}/management/boot_device' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 503 + +nodes_management_boot_device_supported_get_admin: + path: '/v1/nodes/{node_ident}/management/boot_device/supported' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_management_boot_device_supported_get_member: + path: '/v1/nodes/{node_ident}/management/boot_device/supported' + method: get + headers: *member_headers + assert_status: 403 -nodes_management_boot_device_supported_get_allow: +nodes_management_boot_device_supported_get_observer: path: '/v1/nodes/{node_ident}/management/boot_device/supported' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 503 -nodes_management_inject_nmi_put_allow: +nodes_management_inject_nmi_put_admin: path: '/v1/nodes/{node_ident}/management/inject_nmi' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + body: {} + assert_status: 503 -nodes_states_get_allow: +nodes_management_inject_nmi_put_member: + path: '/v1/nodes/{node_ident}/management/inject_nmi' + method: put + headers: *member_headers + body: {} + assert_status: 403 + +nodes_management_inject_nmi_put_observer: + path: '/v1/nodes/{node_ident}/management/inject_nmi' + method: put + headers: *observer_headers + body: {} + assert_status: 403 + + +nodes_states_get_admin: + path: '/v1/nodes/{node_ident}/states' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_states_get_member: + path: '/v1/nodes/{node_ident}/states' + method: get + headers: *member_headers + assert_status: 403 + +nodes_states_get_observer: path: '/v1/nodes/{node_ident}/states' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_states_power_put_admin: + path: '/v1/nodes/{node_ident}/states/power' + method: put + headers: *admin_headers + body: &power_body + target: "power on" + assert_status: 503 -nodes_states_power_put_allow: +nodes_states_power_put_member: path: '/v1/nodes/{node_ident}/states/power' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + body: *power_body + assert_status: 403 -nodes_states_provision_put_allow: +nodes_states_power_put_observer: + path: '/v1/nodes/{node_ident}/states/power' + method: put + headers: *observer_headers + body: *power_body + assert_status: 403 + +nodes_states_provision_put_admin: + path: '/v1/nodes/{node_ident}/states/provision' + method: put + headers: *admin_headers + body: &provision_body + target: deploy + assert_status: 503 + +nodes_states_provision_put_member: + path: '/v1/nodes/{node_ident}/states/provision' + method: put + headers: *member_headers + body: *provision_body + assert_status: 403 + +nodes_states_provision_put_observer: path: '/v1/nodes/{node_ident}/states/provision' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *provision_body + assert_status: 403 + +nodes_states_raid_put_admin: + path: '/v1/nodes/{node_ident}/states/raid' + method: put + headers: *admin_headers + body: &raid_body + target_raid_config: + logical_disks: + - size_gb: 500 + is_root_volume: true + raid_level: 1 + assert_status: 503 + +nodes_states_raid_put_member: + path: '/v1/nodes/{node_ident}/states/raid' + method: put + headers: *member_headers + body: *raid_body + assert_status: 403 -nodes_states_raid_put_allow: +nodes_states_raid_put_observer: path: '/v1/nodes/{node_ident}/states/raid' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *raid_body + assert_status: 403 + +nodes_states_console_get_admin: + path: '/v1/nodes/{node_ident}/states/console' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_states_console_get_member: + path: '/v1/nodes/{node_ident}/states/console' + method: get + headers: *member_headers + assert_status: 403 -nodes_states_console_get_allow: +nodes_states_console_get_admin: path: '/v1/nodes/{node_ident}/states/console' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + +nodes_states_console_put_admin: + path: '/v1/nodes/{node_ident}/states/console' + method: put + headers: *admin_headers + body: &console_body_put + enabled: true + assert_status: 503 + +nodes_states_console_put_member: + path: '/v1/nodes/{node_ident}/states/console' + method: put + headers: *member_headers + body: *console_body_put + assert_status: 403 -nodes_states_console_put_allow: +nodes_states_console_put_observer: path: '/v1/nodes/{node_ident}/states/console' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *console_body_put + assert_status: 403 # Node Traits - https://docs.openstack.org/api-ref/baremetal/?expanded=#node-vendor-passthru-nodes -nodes_vendor_passthru_methods_get_allow: +# Calls conductor upon the get as a task is required. +nodes_vendor_passthru_methods_get_admin: + path: '/v1/nodes/{node_ident}/vendor_passthru/methods' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_vendor_passthru_methods_get_member: + path: '/v1/nodes/{node_ident}/vendor_passthru/methods' + method: get + headers: *member_headers + assert_status: 403 + +nodes_vendor_passthru_methods_get_observer: path: '/v1/nodes/{node_ident}/vendor_passthru/methods' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 -nodes_vendor_passthru_get_allow: - path: '/v1/nodes/{node_ident}/vendor_passthru' +nodes_vendor_passthru_get_admin: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 -nodes_vendor_passthru_post_allow: - path: '/v1/nodes/{node_ident}/vendor_passthru' +nodes_vendor_passthru_get_member: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: get + headers: *member_headers + assert_status: 403 + +nodes_vendor_passthru_get_observer: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: get + headers: *observer_headers + assert_status: 403 + +nodes_vendor_passthru_post_admin: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: post + headers: *admin_headers + assert_status: 503 + +nodes_vendor_passthru_post_member: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: post + headers: *member_headers + assert_status: 403 + +nodes_vendor_passthru_post_observer: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 -nodes_vendor_passthru_put_allow: - path: '/v1/nodes/{node_ident}/vendor_passthru' +nodes_vendor_passthru_put_admin: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + +nodes_vendor_passthru_put_member: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: put + headers: *member_headers + assert_status: 403 + +nodes_vendor_passthru_put_observer: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: put + headers: *observer_headers + assert_status: 403 + +nodes_vendor_passthru_delete_admin: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: delete + headers: *admin_headers + assert_status: 503 + +nodes_vendor_passthru_delete_member: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' + method: delete + headers: *member_headers + assert_status: 403 -nodes_vendor_passthru_delete_allow: - path: '/v1/nodes/{node_ident}/vendor_passthru' +nodes_vendor_passthru_delete_observer: + path: '/v1/nodes/{node_ident}/vendor_passthru?method=test' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 # Node Traits - https://docs.openstack.org/api-ref/baremetal/#node-traits-nodes -nodes_traits_get_allow: +nodes_traits_get_admin: path: '/v1/nodes/{node_ident}/traits' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 200 -nodes_traits_put_allow: +nodes_traits_get_member: + path: '/v1/nodes/{node_ident}/traits' + method: get + headers: *member_headers + assert_status: 403 + +nodes_traits_get_observer: + path: '/v1/nodes/{node_ident}/traits' + method: get + headers: *observer_headers + assert_status: 200 + +nodes_traits_put_admin: + path: '/v1/nodes/{node_ident}/traits' + method: put + headers: *admin_headers + assert_status: 503 + body: &traits_body + traits: + - CUSTOM_TRAIT1 + - HW_CPU_X86_VMX + +nodes_traits_put_member: path: '/v1/nodes/{node_ident}/traits' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + body: *traits_body -nodes_traits_delete_allow: +nodes_traits_put_observer: path: '/v1/nodes/{node_ident}/traits' + method: put + headers: *observer_headers + assert_status: 403 + body: *traits_body + +nodes_traits_delete_admin: + path: '/v1/nodes/{node_ident}/traits/{trait}' + method: delete + headers: *admin_headers + assert_status: 503 + +nodes_traits_delete_member: + path: '/v1/nodes/{node_ident}/traits/{trait}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -nodes_traits_trait_put_allow: +nodes_traits_delete_observer: path: '/v1/nodes/{node_ident}/traits/{trait}' + method: delete + headers: *observer_headers + assert_status: 403 + +nodes_traits_trait_put_admin: + path: '/v1/nodes/{node_ident}/traits/CUSTOM_TRAIT2' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 -nodes_traits_trait_delete_allow: +nodes_traits_trait_put_member: + path: '/v1/nodes/{node_ident}/traits/CUSTOM_TRAIT2' + method: put + headers: *member_headers + assert_status: 403 + +nodes_traits_trait_put_observer: + path: '/v1/nodes/{node_ident}/traits/CUSTOM_TRAIT2' + method: put + headers: *observer_headers + assert_status: 403 + +nodes_traits_trait_delete_admin: + path: '/v1/nodes/{node_ident}/traits/{trait}' + method: delete + headers: *admin_headers + assert_status: 503 + +nodes_traits_trait_delete_member: + path: '/v1/nodes/{node_ident}/traits/{trait}' + method: delete + headers: *member_headers + assert_status: 403 + +nodes_traits_trait_delete_observer: path: '/v1/nodes/{node_ident}/traits/{trait}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 # VIFS - https://docs.openstack.org/api-ref/baremetal/#vifs-virtual-interfaces-of-nodes # TODO(TheJulia): VIFS will need fairly exhaustive testing given the use path. # i.e. ensure user has rights to a vif and all. -nodes_vifs_get_allow: +# Apparently the get operation hits the conductor?!? +# With mocked conductor 503 is returned. +nodes_vifs_get_admin: + path: '/v1/nodes/{node_ident}/vifs' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_vifs_get_member: + path: '/v1/nodes/{node_ident}/vifs' + method: get + headers: *member_headers + assert_status: 403 + +nodes_vifs_get_observer: path: '/v1/nodes/{node_ident}/vifs' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 -nodes_vifs_post_allow: +nodes_vifs_post_admin: path: '/v1/nodes/{node_ident}/vifs' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + body: &vif_body + id: ee21d58f-5de2-4956-85ff-33935ea1ca00 -nodes_vifs_node_vif_ident_delete_allow: - path: '/v1/nodes/{node_ident}/vifs/{node_vif_ident}' +nodes_vifs_post_member: + path: '/v1/nodes/{node_ident}/vifs' + method: post + headers: *member_headers + assert_status: 403 + body: *vif_body + +nodes_vifs_post_observer: + path: '/v1/nodes/{node_ident}/vifs' + method: post + headers: *observer_headers + assert_status: 403 + body: *vif_body + +# This calls the conductor, hence not status 403. +nodes_vifs_node_vif_ident_delete_admin: + path: '/v1/nodes/{node_ident}/vifs/{vif_ident}' + method: delete + headers: *admin_headers + assert_status: 503 + +nodes_vifs_node_vif_ident_delete_member: + path: '/v1/nodes/{node_ident}/vifs/{vif_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +nodes_vifs_node_vif_ident_delete_observer: + path: '/v1/nodes/{node_ident}/vifs/{vif_ident}' + method: delete + headers: *observer_headers + assert_status: 403 # Indicators - https://docs.openstack.org/api-ref/baremetal/#indicators-management -nodes_management_indicators_get_allow: +nodes_management_indicators_get_admin: + path: '/v1/nodes/{node_ident}/management/indicators' + method: get + headers: *admin_headers + assert_status: 503 + +nodes_management_indicators_get_member: + path: '/v1/nodes/{node_ident}/management/indicators' + method: get + headers: *member_headers + assert_status: 403 + +nodes_management_indicators_get_observer: path: '/v1/nodes/{node_ident}/management/indicators' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 503 nodes_management_indicators_component_get_allow: path: '/v1/nodes/{node_ident}/management/indicators/{component}' method: get - skip: true - skip_reason: 'Not implemented yet' + skip_reason: API appears to be broken and should be patched outside of this work. nodes_management_indicators_component_ind_ident_get_allow: path: '/v1/nodes/{node_ident}/management/indicators/{component}/{ind_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + skip_reason: API appears to be broken and should be patched outside of this work. nodes_management_indicators_component_ind_ident_put_allow: path: '/v1/nodes/{node_ident}/management/indicators/{component}/{ind_ident}' method: put - skip: true - skip_reason: 'Not implemented yet' + skip_reason: API appears to be broken and should be patched outside of this work. # Portgroups - https://docs.openstack.org/api-ref/baremetal/#portgroups-portgroups -portgroups_get_allow: +portgroups_get_admin: path: '/v1/portgroups' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 200 -portgroups_post_allow: +portgroups_get_member: + path: '/v1/portgroups' + method: get + headers: *member_headers + assert_status: 403 + +portgroups_get_observer: + path: '/v1/portgroups' + method: get + headers: *observer_headers + assert_status: 200 + +# Returns 400 as the node uuid cannot be found, but +# it is past the access controls. +portgroups_post_admin: + path: '/v1/portgroups' + method: post + headers: *admin_headers + body: &portgroup_body + node_uuid: 68a552fb-dcd2-43bf-9302-e4c93287be16 + assert_status: 400 + +portgroups_post_member: + path: '/v1/portgroups' + method: post + headers: *member_headers + body: *portgroup_body + assert_status: 403 + +portgroups_post_observer: path: '/v1/portgroups' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *portgroup_body + assert_status: 403 + +portgroups_detail_get_admin: + path: '/v1/portgroups/detail' + method: get + headers: *admin_headers + assert_status: 200 + +portgroups_detail_get_member: + path: '/v1/portgroups/detail' + method: get + headers: *member_headers + assert_status: 403 -portgroups_detail_get_allow: +portgroups_detail_get_observer: path: '/v1/portgroups/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +portgroups_portgroup_ident_get_admin: + path: '/v1/portgroups/{portgroup_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +portgroups_portgroup_ident_get_member: + path: '/v1/portgroups/{portgroup_ident}' + method: get + headers: *member_headers + assert_status: 403 -portgroups_portgroup_ident_get_allow: +portgroups_portgroup_ident_get_observer: path: '/v1/portgroups/{portgroup_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 -portgroups_portgroup_ident_patch_allow: +portgroups_portgroup_ident_patch_admin: path: '/v1/portgroups/{portgroup_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + body: &portgroup_patch_body + - op: replace + path: /extra + value: {'test': 'testing'} + assert_status: 503 + +portgroups_portgroup_ident_patch_member: + path: '/v1/portgroups/{portgroup_ident}' + method: patch + headers: *member_headers + body: *portgroup_patch_body + assert_status: 403 + +portgroups_portgroup_ident_patch_observer: + path: '/v1/portgroups/{portgroup_ident}' + method: patch + headers: *observer_headers + body: *portgroup_patch_body + assert_status: 403 + +portgroups_portgroup_ident_delete_admin: + path: '/v1/portgroups/{portgroup_ident}' + method: delete + headers: *admin_headers + assert_status: 503 -portgroups_portgroup_ident_delete_allow: +portgroups_portgroup_ident_delete_member: path: '/v1/portgroups/{portgroup_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +portgroups_portgroup_ident_delete_observer: + path: '/v1/portgroups/{portgroup_ident}' + method: delete + headers: *observer_headers + assert_status: 403 # Portgroups by node - https://docs.openstack.org/api-ref/baremetal/#listing-portgroups-by-node-nodes-portgroups -nodes_portgroups_get_allow: +nodes_portgroups_get_admin: + path: '/v1/nodes/{node_ident}/portgroups' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_portgroups_get_member: + path: '/v1/nodes/{node_ident}/portgroups' + method: get + headers: *member_headers + assert_status: 403 + +nodes_portgroups_get_observer: path: '/v1/nodes/{node_ident}/portgroups' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_portgroups_detail_get_admin: + path: '/v1/nodes/{node_ident}/portgroups/detail' + method: get + headers: *admin_headers + assert_status: 200 -nodes_portgroups_detail_get_allow: +nodes_portgroups_detail_get_member: path: '/v1/nodes/{node_ident}/portgroups/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +nodes_portgroups_detail_get_observer: + path: '/v1/nodes/{node_ident}/portgroups/detail' + method: get + headers: *observer_headers + assert_status: 200 # Ports - https://docs.openstack.org/api-ref/baremetal/#ports-ports -ports_get_allow: +ports_get_admin: + path: '/v1/ports' + method: get + headers: *admin_headers + assert_status: 200 + +ports_get_member: + path: '/v1/ports' + method: get + headers: *member_headers + assert_status: 403 + +ports_get_observer: path: '/v1/ports' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +# NOTE(TheJulia): Returns 400 when the conductor calls are +# mocked indicating node lookup failed, which means the access +# check was successful. +ports_post_admin: + path: '/v1/ports' + method: post + headers: *admin_headers + assert_status: 400 + body: &port_body + node_uuid: 68a552fb-dcd2-43bf-9302-e4c93287be16 + address: 00:01:02:03:04:05 -ports_post_allow: +ports_post_member: path: '/v1/ports' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + body: *port_body -ports_detail_get_allow: +ports_post_observer: + path: '/v1/ports' + method: post + headers: *observer_headers + assert_status: 403 + body: *port_body + +ports_detail_get_admin: + path: '/v1/ports/detail' + method: get + headers: *admin_headers + assert_status: 200 + +ports_detail_get_member: path: '/v1/ports/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -ports_port_id_get_allow: - path: '/v1/ports/{port_id}' +ports_detail_get_observer: + path: '/v1/ports/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 -ports_port_id_patch_allow: - path: '/v1/ports/{port_id}' +ports_port_id_get_admin: + path: '/v1/ports/{port_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +ports_port_id_get_member: + path: '/v1/ports/{port_ident}' + method: get + headers: *member_headers + assert_status: 403 + +ports_port_id_get_observer: + path: '/v1/ports/{port_ident}' + method: get + headers: *observer_headers + assert_status: 200 + +ports_port_id_patch_admin: + path: '/v1/ports/{port_ident}' + method: patch + headers: *admin_headers + assert_status: 503 + body: &port_patch_body + - op: replace + path: /extra + value: {'test': 'testing'} + +ports_port_id_patch_member: + path: '/v1/ports/{port_ident}' + method: patch + headers: *member_headers + assert_status: 403 + body: *port_patch_body + +ports_port_id_patch_observer: + path: '/v1/ports/{port_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + body: *port_patch_body -ports_port_id_delete_allow: - path: '/v1/ports/{port_id}' +ports_port_id_delete_admin: + path: '/v1/ports/{port_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + +ports_port_id_delete_member: + path: '/v1/ports/{port_ident}' + method: delete + headers: *member_headers + assert_status: 403 + +ports_port_id_delete_observer: + path: '/v1/ports/{port_ident}' + method: delete + headers: *observer_headers + assert_status: 403 # Ports by node - https://docs.openstack.org/api-ref/baremetal/#listing-ports-by-node-nodes-ports -nodes_ports_get_allow: +nodes_ports_get_admin: + path: '/v1/nodes/{node_ident}/ports' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_ports_get_member: + path: '/v1/nodes/{node_ident}/ports' + method: get + headers: *member_headers + assert_status: 403 + +nodes_ports_get_observer: path: '/v1/nodes/{node_ident}/ports' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_ports_detail_get_admin: + path: '/v1/nodes/{node_ident}/ports/detail' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_ports_detail_get_member: + path: '/v1/nodes/{node_ident}/ports/detail' + method: get + headers: *member_headers + assert_status: 403 -nodes_ports_detail_get_allow: +nodes_ports_detail_get_observer: path: '/v1/nodes/{node_ident}/ports/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 # Ports by portgroup - https://docs.openstack.org/api-ref/baremetal/#listing-ports-by-portgroup-portgroup-ports -portgroups_ports_get_allow: +portgroups_ports_get_admin: path: '/v1/portgroups/{portgroup_ident}/ports' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 200 + +portgroups_ports_get_member: + path: '/v1/portgroups/{portgroup_ident}/ports' + method: get + headers: *member_headers + assert_status: 403 + +portgroups_ports_get_observer: + path: '/v1/portgroups/{portgroup_ident}/ports' + method: get + headers: *observer_headers + assert_status: 200 + +portgroups_ports_detail_get_admin: + path: '/v1/portgroups/{portgroup_ident}/ports/detail' + method: get + headers: *admin_headers + assert_status: 200 + +portgroups_ports_detail_get_member: + path: '/v1/portgroups/{portgroup_ident}/ports/detail' + method: get + headers: *member_headers + assert_status: 403 -portgroups_ports_detail_get_allow: +portgroups_ports_detail_get_observer: path: '/v1/portgroups/{portgroup_ident}/ports/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + # Volume(s) - https://docs.openstack.org/api-ref/baremetal/#volume-volume # TODO(TheJulia): volumes will likely need some level of exhaustive testing. # i.e. ensure that the volume is permissible. However this may not be possible # here. -volume_get_allow: +volume_get_admin: + path: '/v1/volume' + method: get + headers: *admin_headers + assert_status: 200 + +volume_get_member: path: '/v1/volume' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +volume_get_observer: + path: '/v1/volume' + method: get + headers: *observer_headers + assert_status: 200 # Volume connectors -volume_connectors_get_allow: +volume_connectors_get_admin: + path: '/v1/volume/connectors' + method: get + headers: *admin_headers + assert_status: 200 + +volume_connectors_get_member: + path: '/v1/volume/connectors' + method: get + headers: *member_headers + assert_status: 403 + +volume_connectors_get_observer: path: '/v1/volume/connectors' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +# NOTE(TheJulia): This ends up returning a 400 due to the +# UUID not already being in ironic. +volume_connectors_post_admin: + path: '/v1/volume/connectors' + method: post + headers: *admin_headers + assert_status: 400 + body: &volume_connector_body + node_uuid: 68a552fb-dcd2-43bf-9302-e4c93287be16 + type: ip + connector_id: 192.168.1.100 + +volume_connectors_post_member: + path: '/v1/volume/connectors' + method: post + headers: *member_headers + assert_status: 403 + body: *volume_connector_body -volume_connectors_post_allow: +volume_connectors_post_observer: path: '/v1/volume/connectors' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + body: *volume_connector_body + +volume_volume_connector_id_get_admin: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: get + headers: *admin_headers + assert_status: 200 -volume_volume_connector_id_get_allow: - path: '/v1/volume/connectors/{volume_connector_id}' +volume_volume_connector_id_get_member: + path: '/v1/volume/connectors/{volume_connector_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -volume_volume_connector_id_patch_allow: - path: '/v1/volume/connectors/{volume_connector_id}' +volume_volume_connector_id_get_observer: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: get + headers: *observer_headers + assert_status: 200 + +volume_volume_connector_id_patch_admin: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: patch + headers: *admin_headers + body: &connector_patch_body + - op: replace + path: /extra + value: {'test': 'testing'} + assert_status: 503 + +volume_volume_connector_id_patch_member: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: patch + headers: *member_headers + body: *connector_patch_body + assert_status: 403 + +volume_volume_connector_id_patch_observer: + path: '/v1/volume/connectors/{volume_connector_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *connector_patch_body + assert_status: 403 + +volume_volume_connector_id_delete_admin: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: delete + headers: *admin_headers + assert_status: 503 + +volume_volume_connector_id_delete_member: + path: '/v1/volume/connectors/{volume_connector_ident}' + method: delete + headers: *member_headers + assert_status: 403 -volume_volume_connector_id_delete_allow: - path: '/v1/volume/connectors/{volume_connector_id}' +volume_volume_connector_id_delete_observer: + path: '/v1/volume/connectors/{volume_connector_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 # Volume targets -volume_targets_get_allow: +volume_targets_get_admin: + path: '/v1/volume/targets' + method: get + headers: *admin_headers + assert_status: 200 + +volume_targets_get_member: path: '/v1/volume/targets' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +volume_targets_get_observer: + path: '/v1/volume/targets' + method: get + headers: *observer_headers + assert_status: 200 + +# NOTE(TheJulia): Because we can't seem to get the uuid +# to load from an existing uuid, since we're not subsituting +# it, this will return with 400 due to the ID not matching. +volume_targets_post_admin: + path: '/v1/volume/targets' + method: post + headers: *admin_headers + assert_status: 400 + body: &volume_target_body + node_uuid: 68a552fb-dcd2-43bf-9302-e4c93287be16 + volume_type: iscsi + boot_index: 0 + volume_id: 'test-id' + +volume_targets_post_member: + path: '/v1/volume/targets' + method: post + headers: *member_headers + assert_status: 403 + body: *volume_target_body -volume_targets_post_allow: +volume_targets_post_observer: path: '/v1/volume/targets' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + body: *volume_target_body + +volume_volume_target_id_get_admin: + path: '/v1/volume/targets/{volume_target_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +volume_volume_target_id_get_member: + path: '/v1/volume/targets/{volume_target_ident}' + method: get + headers: *member_headers + assert_status: 403 -volume_volume_target_id_get_allow: - path: '/v1/volume/targets/{volume_target_id}' +volume_volume_target_id_get_observer: + path: '/v1/volume/targets/{volume_target_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 -volume_volume_target_id_patch_allow: - path: '/v1/volume/targets/{volume_target_id}' +volume_volume_target_id_patch_admin: + path: '/v1/volume/targets/{volume_target_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + body: &volume_target_patch + - op: replace + path: /extra + value: {'test': 'testing'} + headers: *admin_headers + assert_status: 503 + +volume_volume_target_id_patch_admin: + path: '/v1/volume/targets/{volume_target_ident}' + method: patch + body: *volume_target_patch + headers: *member_headers + assert_status: 403 + +volume_volume_target_id_patch_observer: + path: '/v1/volume/targets/{volume_target_ident}' + method: patch + body: *volume_target_patch + headers: *observer_headers + assert_status: 403 + +volume_volume_target_id_delete_admin: + path: '/v1/volume/targets/{volume_target_ident}' + method: delete + headers: *admin_headers + assert_status: 503 + +volume_volume_target_id_delete_member: + path: '/v1/volume/targets/{volume_target_ident}' + method: delete + headers: *member_headers + assert_status: 403 -volume_volume_target_id_delete_allow: - path: '/v1/volume/targets/{volume_target_id}' +volume_volume_target_id_delete_observer: + path: '/v1/volume/targets/{volume_target_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 # Get Volumes by Node - https://docs.openstack.org/api-ref/baremetal/#listing-volume-resources-by-node-nodes-volume -nodes_volume_get_allow: +nodes_volume_get_admin: + path: '/v1/nodes/{node_ident}/volume' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_volume_get_member: + path: '/v1/nodes/{node_ident}/volume' + method: get + headers: *member_headers + assert_status: 403 + +nodes_volume_get_observer: path: '/v1/nodes/{node_ident}/volume' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_volume_connectors_get_admin: + path: '/v1/nodes/{node_ident}/volume/connectors' + method: get + headers: *admin_headers + assert_status: 200 -nodes_volume_connectors_get_allow: +nodes_volume_connectors_get_member: path: '/v1/nodes/{node_ident}/volume/connectors' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -nodes_volume_targets_get_allow: +nodes_volume_connectors_get_observer: + path: '/v1/nodes/{node_ident}/volume/connectors' + method: get + headers: *observer_headers + assert_status: 200 + +nodes_volume_targets_get_admin: + path: '/v1/nodes/{node_ident}/volume/targets' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_volume_targets_get_member: + path: '/v1/nodes/{node_ident}/volume/targets' + method: get + headers: *member_headers + assert_status: 403 + +nodes_volume_targets_get_observer: path: '/v1/nodes/{node_ident}/volume/targets' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 # Drivers - https://docs.openstack.org/api-ref/baremetal/#drivers-drivers -drivers_get_allow: +drivers_get_admin: + path: '/v1/drivers' + method: get + headers: *admin_headers + assert_status: 200 + +drivers_get_member: path: '/v1/drivers' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +drivers_get_observer: + path: '/v1/drivers' + method: get + headers: *observer_headers + assert_status: 200 + +# TODO(TheJulia): This is presently returning a 404, +# except it should not be. :\ +drivers_driver_name_get_admin: + path: '/v1/drivers/{driver_name}' + method: get + headers: *admin_headers + assert_status: 404 + +drivers_driver_name_get_member: + path: '/v1/drivers/{driver_name}' + method: get + headers: *member_headers + assert_status: 403 -drivers_driver_name_get_allow: +# TODO(TheJulia): This is presently returning a 404, +# except it should not be. :\ +drivers_driver_name_get_observer: path: '/v1/drivers/{driver_name}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 404 + +drivers_properties_get_admin: + path: '/v1/drivers/{driver_name}/properties' + method: get + headers: *admin_headers + assert_status: 404 -drivers_properties_get_allow: +drivers_properties_get_member: path: '/v1/drivers/{driver_name}/properties' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -drivers_raid_logical_disk_properties_get_allow: +drivers_properties_get_observer: + path: '/v1/drivers/{driver_name}/properties' + method: get + headers: *observer_headers + assert_status: 404 + +drivers_raid_logical_disk_properties_get_admin: + path: '/v1/drivers/{driver_name}/raid/logical_disk_properties' + method: get + headers: *admin_headers + assert_status: 404 + +drivers_raid_logical_disk_properties_get_member: path: '/v1/drivers/{driver_name}/raid/logical_disk_properties' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +drivers_raid_logical_disk_properties_get_observer: + path: '/v1/drivers/{driver_name}/raid/logical_disk_properties' + method: get + headers: *observer_headers + assert_status: 404 # Driver vendor passthru - https://docs.openstack.org/api-ref/baremetal/#driver-vendor-passthru-drivers -drivers_vendor_passthru_methods_get_allow: +drivers_vendor_passthru_methods_get_admin: + path: '/v1/drivers/{driver_name}/vendor_passthru/methods' + method: get + headers: *admin_headers + assert_status: 404 + +drivers_vendor_passthru_methods_get_member: path: '/v1/drivers/{driver_name}/vendor_passthru/methods' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +drivers_vendor_passthru_methods_get_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru/methods' + method: get + headers: *observer_headers + assert_status: 403 + +drivers_vendor_passthru_get_admin: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: get + headers: *admin_headers + assert_status: 404 + +drivers_vendor_passthru_get_member: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: get + headers: *member_headers + assert_status: 403 -drivers_vendor_passthru_get_allow: - path: '/v1/drivers/{driver_name}/vendor_passthru' +drivers_vendor_passthru_get_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + +drivers_vendor_passthru_post_admin: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: post + headers: *admin_headers + assert_status: 404 + +drivers_vendor_passthru_post_member: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: post + headers: *member_headers + assert_status: 403 -drivers_vendor_passthru_post_allow: - path: '/v1/drivers/{driver_name}/vendor_passthru' +drivers_vendor_passthru_post_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + +drivers_vendor_passthru_put_admin: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: put + headers: *admin_headers + assert_status: 404 + +drivers_vendor_passthru_put_member: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: put + headers: *member_headers + assert_status: 403 -drivers_vendor_passthru_put_allow: - path: '/v1/drivers/{driver_name}/vendor_passthru' +drivers_vendor_passthru_put_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' method: put - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 + +# NOTE(TheJulia): Returns an error due to the driver name +# not matching, but this should be pass policy checking. +# "No conductors registered." +drivers_vendor_passthru_delete_admin: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: delete + headers: *admin_headers + assert_status: 404 -drivers_vendor_passthru_delete_allow: - path: '/v1/drivers/{driver_name}/vendor_passthru' +drivers_vendor_passthru_delete_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +drivers_vendor_passthru_delete_observer: + path: '/v1/drivers/{driver_name}/vendor_passthru?method=test' + method: delete + headers: *observer_headers + assert_status: 403 # Node Bios - https://docs.openstack.org/api-ref/baremetal/#node-bios-nodes -nodes_bios_get_allow: +nodes_bios_get_admin: + path: '/v1/nodes/{node_ident}/bios' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_bios_get_member: + path: '/v1/nodes/{node_ident}/bios' + method: get + headers: *member_headers + assert_status: 403 + +nodes_bios_get_observer: path: '/v1/nodes/{node_ident}/bios' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +nodes_bios_bios_setting_get_admin: + path: '/v1/nodes/{node_ident}/bios/{bios_setting}' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_bios_bios_setting_get_member: + path: '/v1/nodes/{node_ident}/bios/{bios_setting}' + method: get + headers: *member_headers + assert_status: 403 -nodes_bios_bios_setting_get_allow: +nodes_bios_bios_setting_get_observer: path: '/v1/nodes/{node_ident}/bios/{bios_setting}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 # Conductors - https://docs.openstack.org/api-ref/baremetal/#allocations-allocations -conductors_get_allow: +conductors_get_admin: + path: '/v1/conductors' + method: get + headers: *admin_headers + assert_status: 200 + +conductors_get_member: + path: '/v1/conductors' + method: get + headers: *member_headers + assert_status: 403 + +conductors_get_observer: path: '/v1/conductors' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 -conductors_hostname_get_allow: - path: '/v1/conductors/{hostname}' + +conductors_hostname_get_admin: + path: '/v1/conductors/{conductor_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +conductors_hostname_get_member: + path: '/v1/conductors/{conductor_ident}' + method: get + headers: *member_headers + assert_status: 403 + +conductors_hostname_get_observer: + path: '/v1/conductors/{conductor_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 # Allocations - https://docs.openstack.org/api-ref/baremetal/#allocations-allocations -allocations_post_allow: +allocations_post_admin: + path: '/v1/allocations' + method: post + headers: *admin_headers + body: &allocation_body + resource_class: CUSTOM_TEST + assert_status: 503 + +allocations_post_member: path: '/v1/allocations' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + body: *allocation_body + assert_status: 403 -allocations_get_allow: +allocations_post_observer: path: '/v1/allocations' + method: post + headers: *observer_headers + body: *allocation_body + assert_status: 403 + +allocations_get_admin: + path: '/v1/allocations' + method: get + headers: *admin_headers + assert_status: 200 + +allocations_get_member: + path: '/v1/allocations' + method: get + headers: *member_headers + assert_status: 403 + +allocations_get_observer: + path: '/v1/allocations' + method: get + headers: *observer_headers + assert_status: 200 + +allocations_allocation_id_get_admin: + path: '/v1/allocations/{allocation_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +allocations_allocation_id_get_member: + path: '/v1/allocations/{allocation_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -allocations_allocation_id_get_allow: - path: '/v1/allocations/{allocation_id}' +allocations_allocation_id_get_observer: + path: '/v1/allocations/{allocation_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +allocations_allocation_id_patch_admin: + path: '/v1/allocations/{allocation_ident}' + method: patch + headers: *admin_headers + body: &allocation_patch + - op: replace + path: /extra + value: {'test': 'testing'} + assert_status: 200 + +allocations_allocation_id_patch_member: + path: '/v1/allocations/{allocation_ident}' + method: patch + headers: *member_headers + body: *allocation_patch + assert_status: 403 -allocations_allocation_id_patch_allow: - path: '/v1/allocations/{allocation_id}' +allocations_allocation_id_patch_observer: + path: '/v1/allocations/{allocation_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *allocation_patch + assert_status: 403 -allocations_allocation_id_delete_allow: - path: '/v1/allocations/{allocation_id}' +allocations_allocation_id_delete_admin: + path: '/v1/allocations/{allocation_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + +allocations_allocation_id_delete_member: + path: '/v1/allocations/{allocation_ident}' + method: delete + headers: *member_headers + assert_status: 403 + +allocations_allocation_id_delete_observer: + path: '/v1/allocations/{allocation_ident}' + method: delete + headers: *observer_headers + assert_status: 403 # Allocations ( Node level) - https://docs.openstack.org/api-ref/baremetal/#node-allocation-allocations-nodes -nodes_allocation_get_allow: - path: '/v1/nodes/{node_ident}/allocation' +nodes_allocation_get_admin: + path: '/v1/nodes/{allocated_node_ident}/allocation' + method: get + headers: *admin_headers + assert_status: 200 + +nodes_allocation_get_member: + path: '/v1/nodes/{allocated_node_ident}/allocation' + method: get + headers: *member_headers + assert_status: 403 + +nodes_allocation_get_observer: + path: '/v1/nodes/{allocated_node_ident}/allocation' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 -nodes_allocation_delete_allow: - path: '/v1/nodes/{node_ident}/allocation' +nodes_allocation_delete_admin: + path: '/v1/nodes/{allocated_node_ident}/allocation' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 503 + +nodes_allocation_delete_member: + path: '/v1/nodes/{allocated_node_ident}/allocation' + method: delete + headers: *member_headers + assert_status: 403 + +nodes_allocation_delete_observer: + path: '/v1/nodes/{allocated_node_ident}/allocation' + method: delete + headers: *observer_headers + assert_status: 403 # Deploy Templates - https://docs.openstack.org/api-ref/baremetal/#deploy-templates-deploy-templates -deploy_templates_post_allow: +deploy_templates_post_admin: + path: '/v1/deploy_templates' + method: post + body: &deploy_template_body + name: 'CUSTOM_TEST_TEMPLATE' + steps: + - interface: 'deploy' + step: 'noop' + args: {} + priority: 0 + headers: *admin_headers + assert_status: 201 + +deploy_templates_post_member: + path: '/v1/deploy_templates' + method: post + body: *deploy_template_body + headers: *member_headers + assert_status: 403 + +deploy_templates_post_observer: path: '/v1/deploy_templates' method: post - skip: true - skip_reason: 'Not implemented yet' + body: *deploy_template_body + headers: *observer_headers + assert_status: 403 + +deploy_templates_get_admin: + path: '/v1/deploy_templates' + method: get + headers: *admin_headers + assert_status: 200 -deploy_templates_get_allow: +deploy_templates_get_member: path: '/v1/deploy_templates' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +deploy_templates_get_observer: + path: '/v1/deploy_templates' + method: get + headers: *observer_headers + assert_status: 200 + +deploy_templates_deploy_template_id_get_admin: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +deploy_templates_deploy_template_id_get_member: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: get + headers: *member_headers + assert_status: 403 -deploy_templates_deploy_template_id_get_allow: - path: '/v1/deploy_templates/{deploy_template_id}' +deploy_templates_deploy_template_id_get_observer: + path: '/v1/deploy_templates/{deploy_template_ident}' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 200 + +deploy_templates_deploy_template_id_patch_admin: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: patch + body: &template_patch + - op: replace + path: /name + value: 'CUSTOM_MAGIC' + headers: *admin_headers + assert_status: 200 + +deploy_templates_deploy_template_id_patch_member: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: patch + body: *template_patch + headers: *member_headers + assert_status: 403 -deploy_templates_deploy_template_id_patch_allow: - path: '/v1/deploy_templates/{deploy_template_id}' +deploy_templates_deploy_template_id_patch_observer: + path: '/v1/deploy_templates/{deploy_template_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + body: *template_patch + headers: *observer_headers + assert_status: 403 + +deploy_templates_deploy_template_id_delete_admin: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: delete + headers: *admin_headers + assert_status: 204 -deploy_templates_deploy_template_id_delete_allow: - path: '/v1/deploy_templates/{deploy_template_id}' +deploy_templates_deploy_template_id_delete_member: + path: '/v1/deploy_templates/{deploy_template_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 + +deploy_templates_deploy_template_id_delete_observer: + path: '/v1/deploy_templates/{deploy_template_ident}' + method: delete + headers: *observer_headers + assert_status: 403 # Chassis endpoints - https://docs.openstack.org/api-ref/baremetal/#chassis-chassis -chassis_post_allow: +chassis_post_admin: + path: '/v1/chassis' + method: post + headers: *admin_headers + body: &chassis_body + description: 'test-chassis' + assert_status: 201 + +chassis_post_member: + path: '/v1/chassis' + method: post + headers: *member_headers + body: *chassis_body + assert_status: 403 + +chassis_post_observer: path: '/v1/chassis' method: post - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + body: *chassis_body + assert_status: 403 -chassis_get_allow: +chassis_get_admin: path: '/v1/chassis' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 200 -chassis_detail_get_allow: +chassis_get_member: + path: '/v1/chassis' + method: get + headers: *member_headers + assert_status: 403 + +chassis_get_observer: + path: '/v1/chassis' + method: get + headers: *observer_headers + assert_status: 200 + +chassis_detail_get_admin: path: '/v1/chassis/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *admin_headers + assert_status: 200 -chassis_chassis_id_get_allow: - path: '/v1/chassis/{chassis_id}' +chassis_detail_get_member: + path: '/v1/chassis/detail' method: get - skip: true - skip_reason: 'Not implemented yet' + headers: *member_headers + assert_status: 403 -chassis_chassis_id_patch_allow: - path: '/v1/chassis/{chassis_id}' +chassis_detail_get_observer: + path: '/v1/chassis/detail' + method: get + headers: *observer_headers + assert_status: 200 + +chassis_chassis_id_get_admin: + path: '/v1/chassis/{chassis_ident}' + method: get + headers: *admin_headers + assert_status: 200 + +chassis_chassis_id_get_member: + path: '/v1/chassis/{chassis_ident}' + method: get + headers: *member_headers + assert_status: 403 + +chassis_chassis_id_get_observer: + path: '/v1/chassis/{chassis_ident}' + method: get + headers: *observer_headers + assert_status: 200 + +chassis_chassis_id_patch_admin: + path: '/v1/chassis/{chassis_ident}' method: patch - skip: true - skip_reason: 'Not implemented yet' + body: &chassis_patch + - op: replace + path: /description + value: meow + headers: *admin_headers + assert_status: 200 + +chassis_chassis_id_patch_member: + path: '/v1/chassis/{chassis_ident}' + method: patch + body: *chassis_patch + headers: *member_headers + assert_status: 403 + +chassis_chassis_id_patch_observer: + path: '/v1/chassis/{chassis_ident}' + method: patch + body: *chassis_patch + headers: *observer_headers + assert_status: 403 + +chassis_chassis_id_delete_admin: + path: '/v1/chassis/{chassis_ident}' + method: delete + headers: *admin_headers + assert_status: 204 + +chassis_chassis_id_delete_member: + path: '/v1/chassis/{chassis_ident}' + method: delete + headers: *member_headers + assert_status: 403 -chassis_chassis_id_delete_allow: - path: '/v1/chassis/{chassis_id}' +chassis_chassis_id_delete_observer: + path: '/v1/chassis/{chassis_ident}' method: delete - skip: true - skip_reason: 'Not implemented yet' + headers: *observer_headers + assert_status: 403 |