Add tests for secret consumers

This patch adds microversion support to the plugin.  It adds two new
configuration values in tempest.conf for selecting which tests to run.
See [1] for more details.

[1] https://docs.openstack.org/tempest/latest/microversion_testing.html

Depends-On: https://review.opendev.org/c/openstack/barbican/+/840712
Change-Id: Iba604f74fb645bec2f03fd4ffb771d8f051dccfe
This commit is contained in:
Ade Lee 2022-05-06 12:33:06 -04:00 committed by Douglas Mendizábal
parent 44c9ed2bc4
commit 519aa80cab
10 changed files with 278 additions and 2 deletions

View File

@ -48,6 +48,9 @@
api_v1: False
ephemeral_storage_encryption:
enabled: True
key_manager:
min_microversion: '1.0'
max_microversion: latest
tox_envlist: all
tempest_test_regex: barbican
tempest_plugins:
@ -72,16 +75,25 @@
name: barbican-tempest-plugin-simple-crypto-yoga
parent: barbican-tempest-plugin-simple-crypto
override-checkout: stable/yoga
vars: &microversion_v1_0
devstack_local_conf:
test-config:
$TEMPEST_CONFIG:
key_manager:
min_microversion: '1.0'
max_microversion: '1.0'
- job:
name: barbican-tempest-plugin-simple-crypto-xena
parent: barbican-tempest-plugin-simple-crypto
override-checkout: stable/xena
vars: *microversion_v1_0
- job:
name: barbican-tempest-plugin-simple-crypto-wallaby
parent: barbican-tempest-plugin-simple-crypto
override-checkout: stable/wallaby
vars: *microversion_v1_0
- job:
name: barbican-tempest-plugin-simple-crypto-ipv6-only

View File

@ -20,6 +20,32 @@ service_option = cfg.BoolOpt("barbican",
help="Whether or not barbican is expected to be "
"available")
key_manager_group = cfg.OptGroup(
name='key_manager',
title='Key Manager (Barbican) service options'
)
KeyManagerOpts = [
cfg.StrOpt('min_microversion',
default=None,
help="Lower version of the test target microversion range. "
"The format is 'X.Y', where 'X' and 'Y' are int values. "
"Tempest selects tests based on the range between "
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
"with format 'X.Y' or string 'latest'"),
cfg.StrOpt('max_microversion',
default=None,
help="Upper version of the test target microversion range. "
"The format is 'X.Y', where 'X' and 'Y' are int values. "
"Tempest selects tests based on the range between "
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
"with format 'X.Y' or string 'latest'")
]
barbican_tempest_group = cfg.OptGroup(
name='barbican_tempest',
title='Key Manager (Barbican) service options'

View File

@ -33,6 +33,10 @@ class BarbicanTempestPlugin(plugins.TempestPlugin):
conf.register_opt(project_config.service_option,
group='service_available')
conf.register_group(project_config.key_manager_group)
conf.register_opts(project_config.KeyManagerOpts,
project_config.key_manager_group)
conf.register_group(project_config.barbican_tempest_group)
conf.register_opts(project_config.BarbicanGroupOpts,
project_config.barbican_tempest_group)
@ -69,4 +73,13 @@ class BarbicanTempestPlugin(plugins.TempestPlugin):
'TransportKeyClient'
],
}
return [v1_params]
v1_1_params = {
'name': 'secret_v1_1',
'service_version': 'secret.v1_1',
'module_path': 'barbican_tempest_plugin.services.key_manager.v1_1',
'client_names': [
'SecretConsumerClient',
'VersionClient'
],
}
return [v1_params, v1_1_params]

View File

@ -13,14 +13,24 @@ from tempest.lib.common import rest_client
_DEFAULT_SERVICE_TYPE = 'key-manager'
_MICROVERSION_HEADER = 'OpenStack-API-Version'
class BarbicanTempestClient(rest_client.RestClient):
_microversion = None
def __init__(self, *args, **kwargs):
kwargs['service'] = _DEFAULT_SERVICE_TYPE
super().__init__(*args, **kwargs)
def get_headers(self, accept_type=None, send_type=None):
headers = super().get_headers(accept_type, send_type)
if self._microversion:
headers[_MICROVERSION_HEADER] = \
f'{_DEFAULT_SERVICE_TYPE} {self._microversion}'
return headers
@classmethod
def ref_to_uuid(cls, href):
return href.split('/')[-1]

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 Red Hat Inc.
#
# 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 barbican_tempest_plugin.services.key_manager.v1_1.secret_consumer_client \
import SecretConsumerClient # noqa: F401
from barbican_tempest_plugin.services.key_manager.v1_1.version_client \
import VersionClient # noqa: F401
__all__ = [
'SecretConsumerClient'
'VersionClient'
]

View File

@ -0,0 +1,53 @@
# Copyright (c) 2022 Red Hat Inc.
#
# 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 json
from urllib import parse as urllib
from tempest import config
from barbican_tempest_plugin.services.key_manager.json import base
CONF = config.CONF
class SecretConsumerClient(base.BarbicanTempestClient):
_microversion = '1.1'
def list_consumers_in_secret(self, secret_id, **kwargs):
uri = "/v1/secrets/%s/consumers" % secret_id
if kwargs:
uri += "?%s" % urllib.urlencode(kwargs)
response, body = self.get(uri)
self.expected_success(200, response.status)
return json.loads(body.decode("utf-8"))
def add_consumer_to_secret(self, secret_id, **kwargs):
uri = "/v1/secrets/%s/consumers" % secret_id
response, body = self.post(uri, json.dumps(kwargs))
self.expected_success(200, response.status)
return json.loads(body.decode("utf-8"))
def delete_consumer_from_secret(self, secret_id, **kwargs):
uri = "/v1/secrets/%s/consumers" % secret_id
response, body = self.delete(uri, body=json.dumps(kwargs))
self.expected_success(200, response.status)
return json.loads(body.decode("utf-8"))

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 Red Hat Inc.
#
# 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 tempest import config
from barbican_tempest_plugin.services.key_manager.json import base
CONF = config.CONF
class VersionClient(base.BarbicanTempestClient):
pass

View File

@ -16,6 +16,7 @@
import functools
from tempest import config
from tempest.lib.common import api_version_utils
from tempest import test
from barbican_tempest_plugin import clients
@ -56,7 +57,8 @@ def creates(resource):
return decorator
class BaseKeyManagerTest(test.BaseTestCase):
class BaseKeyManagerTest(test.BaseTestCase,
api_version_utils.BaseMicroversionTest):
"""Base class for all api tests."""
# Why do I have to be an admin to create secrets? No idea...
@ -64,6 +66,15 @@ class BaseKeyManagerTest(test.BaseTestCase):
client_manager = clients.Clients
created_objects = {}
@classmethod
def skip_checks(cls):
super().skip_checks()
api_version_utils.check_skip_with_microversion(
cls.min_microversion,
cls.max_microversion,
CONF.key_manager.min_microversion,
CONF.key_manager.max_microversion)
@classmethod
def setup_clients(cls):
super(BaseKeyManagerTest, cls).setup_clients()
@ -76,9 +87,11 @@ class BaseKeyManagerTest(test.BaseTestCase):
)
cls.order_client = os.secret_v1.OrderClient(service='key-manager')
cls.secret_client = os.secret_v1.SecretClient(service='key-manager')
cls.secret_consumer_client = os.secret_v1_1.SecretConsumerClient()
cls.secret_metadata_client = os.secret_v1.SecretMetadataClient(
service='key-manager'
)
cls.version_client = os.secret_v1_1.VersionClient()
os = getattr(cls, 'os_roles_%s' % cls.credentials[1][0])
cls.quota_client = os.secret_v1.QuotaClient(service='key-manager')

View File

@ -0,0 +1,101 @@
# Copyright (c) 2022 Red Hat Inc.
#
# 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 tempest.lib import decorators
from barbican_tempest_plugin.tests.api import base
class SecretConsumersTest(base.BaseKeyManagerTest):
"""Secret Consumers API tests."""
min_microversion = '1.1'
@decorators.idempotent_id('07a47f8b-e454-4dd0-afb6-bfa12677cd8e')
def test_add_delete_consumers_in_secret(self):
# Create a secret to test against
sec = self.create_secret(name='secret_1')
secret_id = self.secret_consumer_client.ref_to_uuid(sec['secret_ref'])
# Confirm that the secret has no consumers
body = self.secret_consumer_client.list_consumers_in_secret(secret_id)
self.assertEqual(0, body.get('total'))
self.assertEmpty(body.get('consumers'))
# Add some consumers to the secret
body = self.secret_consumer_client.add_consumer_to_secret(
secret_id,
service="service1",
resource_id="resource_id1",
resource_type="resource_type1"
)
self.assertEqual(
secret_id,
self.secret_consumer_client.ref_to_uuid(body.get('secret_ref'))
)
self.assertEqual(1, len(body.get('consumers')))
body = self.secret_consumer_client.add_consumer_to_secret(
secret_id,
service="service2",
resource_id="resource_id2",
resource_type="resource_type2"
)
self.assertEqual(
secret_id,
self.secret_consumer_client.ref_to_uuid(body.get('secret_ref'))
)
self.assertEqual(2, len(body.get('consumers')))
# Confirm that the consumers are in the secret
body = self.secret_consumer_client.list_consumers_in_secret(secret_id)
self.assertEqual(2, body.get('total'))
self.assertEqual(2, len(body.get('consumers')))
for consumer in body.get('consumers'):
self.assertIn(consumer.get('service'), ("service1", "service2"))
self.assertIn(consumer.get('resource_id'),
("resource_id1", "resource_id2"))
self.assertIn(consumer.get('resource_type'),
("resource_type1", "resource_type2"))
# Remove the consumers from the secret
body = self.secret_consumer_client.delete_consumer_from_secret(
secret_id,
service="service1",
resource_id="resource_id1",
resource_type="resource_type1"
)
self.assertEqual(
secret_id,
self.secret_consumer_client.ref_to_uuid(body.get('secret_ref'))
)
self.assertEqual(1, len(body.get('consumers')))
body = self.secret_consumer_client.delete_consumer_from_secret(
secret_id,
service="service2",
resource_id="resource_id2",
resource_type="resource_type2"
)
self.assertEqual(
secret_id,
self.secret_consumer_client.ref_to_uuid(body.get('secret_ref'))
)
self.assertEqual(0, len(body.get('consumers')))
# Confirm that the secret has no consumers
body = self.secret_consumer_client.list_consumers_in_secret(secret_id)
self.assertEqual(0, body.get('total'))
self.assertEqual(0, len(body.get('consumers')))
# Clean up the secret
self.delete_secret(secret_id)

View File

@ -106,9 +106,11 @@ class BarbicanScenarioTest(mgr.ScenarioTest):
)
cls.order_client = os.secret_v1.OrderClient(service='key-manager')
cls.secret_client = os.secret_v1.SecretClient(service='key-manager')
cls.secret_consumer_client = os.secret_v1_1.SecretConsumerClient()
cls.secret_metadata_client = os.secret_v1.SecretMetadataClient(
service='key-manager'
)
cls.secret_consumer_client = os.secret_v1_1.VersionClient()
if CONF.compute_feature_enabled.attach_encrypted_volume:
cls.admin_encryption_types_client =\