Add cluster to cert commands

This patch will update the certificate api to use the term Cluster
instead of Bay.  Bay will still be supported, but will be deprecated
and removed in a future release.

Change-Id: Ie169162a743320813e636597240941b5dd59ded3
Implements: blueprint rename-bay-to-cluster
This commit is contained in:
Jaycen Grant 2016-08-22 08:38:10 -07:00
parent 52224c5c09
commit 8aed31a6a6
6 changed files with 106 additions and 71 deletions

View File

@ -35,31 +35,35 @@ class Certificate(base.APIBase):
certificate.
"""
_bay_uuid = None
"""uuid or logical name of bay"""
_cluster_uuid = None
"""uuid or logical name of cluster"""
_bay = None
_cluster = None
def _get_bay_uuid(self):
return self._bay_uuid
def _get_cluster_uuid(self):
return self._cluster_uuid
def _set_bay_uuid(self, value):
if value and self._bay_uuid != value:
def _set_cluster_uuid(self, value):
if value and self._cluster_uuid != value:
try:
self._bay = api_utils.get_resource('Bay', value)
self._bay_uuid = self._bay.uuid
self._cluster = api_utils.get_resource('Bay', value)
self._cluster_uuid = self._cluster.uuid
except exception.ClusterNotFound as e:
# Change error code because 404 (NotFound) is inappropriate
# response for a POST request to create a Bay
e.code = 400 # BadRequest
raise
elif value == wtypes.Unset:
self._bay_uuid = wtypes.Unset
self._cluster_uuid = wtypes.Unset
bay_uuid = wsme.wsproperty(wtypes.text, _get_bay_uuid,
_set_bay_uuid, mandatory=True)
bay_uuid = wsme.wsproperty(wtypes.text, _get_cluster_uuid,
_set_cluster_uuid)
"""The bay UUID or id"""
cluster_uuid = wsme.wsproperty(wtypes.text, _get_cluster_uuid,
_set_cluster_uuid)
"""The cluster UUID or id"""
links = wsme.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated certificate links"""
@ -80,15 +84,22 @@ class Certificate(base.APIBase):
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
def get_bay(self):
if not self._bay:
self._bay = api_utils.get_resource('Bay', self.bay_uuid)
return self._bay
# set the attribute for cluster_uuid
self.fields.append('cluster_uuid')
if 'cluster_uuid' in kwargs.keys():
setattr(self, 'cluster_uuid', kwargs.get('cluster_uuid',
wtypes.Unset))
def get_cluster(self):
if not self._cluster:
self._cluster = api_utils.get_resource('Bay', self.cluster_uuid)
return self._cluster
@staticmethod
def _convert_with_links(certificate, url, expand=True):
if not expand:
certificate.unset_fields_except(['bay_uuid', 'csr', 'pem'])
certificate.unset_fields_except(['bay_uuid', 'cluster_uuid',
'csr', 'pem'])
certificate.links = [link.Link.make_link('self', url,
'certificates',
@ -108,6 +119,7 @@ class Certificate(base.APIBase):
@classmethod
def sample(cls, expand=True):
sample = cls(bay_uuid='7ae81bb3-dec3-4289-8d6c-da80bd8001ae',
cluster_uuid='7ae81bb3-dec3-4289-8d6c-da80bd8001ae',
created_at=timeutils.utcnow(),
csr='AAA....AAA')
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
@ -124,17 +136,17 @@ class CertificateController(base.Controller):
}
@expose.expose(Certificate, types.uuid_or_name)
def get_one(self, bay_ident):
"""Retrieve CA information about the given bay.
def get_one(self, cluster_ident):
"""Retrieve CA information about the given cluster.
:param bay_ident: UUID of a bay or
logical name of the bay.
:param cluster_ident: UUID of a cluster or
logical name of the cluster.
"""
context = pecan.request.context
bay = api_utils.get_resource('Bay', bay_ident)
policy.enforce(context, 'certificate:get', bay,
cluster = api_utils.get_resource('Bay', cluster_ident)
policy.enforce(context, 'certificate:get', cluster,
action='certificate:get')
certificate = pecan.request.rpcapi.get_ca_certificate(bay)
certificate = pecan.request.rpcapi.get_ca_certificate(cluster)
return Certificate.convert_with_links(certificate)
@expose.expose(Certificate, body=Certificate, status_code=201)
@ -144,14 +156,14 @@ class CertificateController(base.Controller):
:param certificate: a certificate within the request body.
"""
context = pecan.request.context
bay = certificate.get_bay()
policy.enforce(context, 'certificate:create', bay,
cluster = certificate.get_cluster()
policy.enforce(context, 'certificate:create', cluster,
action='certificate:create')
certificate_dict = certificate.as_dict()
certificate_dict['project_id'] = context.project_id
certificate_dict['user_id'] = context.user_id
cert_obj = objects.Certificate(context, **certificate_dict)
new_cert = pecan.request.rpcapi.sign_certificate(bay,
new_cert = pecan.request.rpcapi.sign_certificate(cluster,
cert_obj)
return Certificate.convert_with_links(new_cert)

View File

@ -20,25 +20,25 @@ class CertClient(client.MagnumClient):
url = "/certificates"
@classmethod
def cert_uri(cls, bay_id):
"""Construct bay uri
def cert_uri(cls, cluster_id):
"""Construct cluster uri
:param bay_id: bay uuid or name
:param cluster_id: cluster uuid or name
:returns: url string
"""
return "{0}/{1}".format(cls.url, bay_id)
return "{0}/{1}".format(cls.url, cluster_id)
def get_cert(self, bay_id, **kwargs):
"""Makes GET /certificates/bay_id request and returns CertEntity
def get_cert(self, cluster_id, **kwargs):
"""Makes GET /certificates/cluster_id request and returns CertEntity
Abstracts REST call to return a single cert based on uuid or name
:param bay_id: bay uuid or name
:returns: response object and BayCollection object
:param cluster_id: cluster uuid or name
:returns: response object and ClusterCollection object
"""
resp, body = self.get(self.cert_uri(bay_id))
resp, body = self.get(self.cert_uri(cluster_id))
return self.deserialize(resp, body, cert_model.CertEntity)
def post_cert(self, model, **kwargs):

View File

@ -182,7 +182,7 @@ Q0uA0aVog3f5iJxCa3Hp5gxbJQ6zV6kJ0TEsuaaOhEko9sdpCoPOnRBm2i/XRD2D
resp, cert_model = self.cert_client.post_cert(cert_data_model)
self.LOG.debug("cert resp: %s" % resp)
self.assertEqual(201, resp.status)
self.assertEqual(cert_model.bay_uuid, cluster_model.uuid)
self.assertEqual(cert_model.cluster_uuid, cluster_model.uuid)
self.assertIsNotNone(cert_model.pem)
self.assertIn('-----BEGIN CERTIFICATE-----', cert_model.pem)
self.assertIn('-----END CERTIFICATE-----', cert_model.pem)

View File

@ -322,11 +322,11 @@ def bay_node_count_patch_data(node_count=2):
return baypatch_model.BayPatchCollection.from_dict(data)
def cert_data(bay_uuid, csr_data):
def cert_data(cluster_uuid, csr_data):
data = {
"bay_uuid": bay_uuid,
"csr": csr_data,
}
"cluster_uuid": cluster_uuid,
"csr": csr_data}
model = cert_model.CertEntity.from_dict(data)
return model

View File

@ -25,13 +25,13 @@ class TestCertObject(base.TestCase):
@mock.patch('magnum.api.utils.get_resource')
def test_cert_init(self, mock_get_resource):
cert_dict = api_utils.cert_post_data()
mock_bay = mock.MagicMock()
mock_bay.uuid = cert_dict['bay_uuid']
mock_get_resource.return_value = mock_bay
mock_cluster = mock.MagicMock()
mock_cluster.uuid = cert_dict['cluster_uuid']
mock_get_resource.return_value = mock_cluster
cert = api_cert.Certificate(**cert_dict)
self.assertEqual(cert_dict['bay_uuid'], cert.bay_uuid)
self.assertEqual(cert_dict['cluster_uuid'], cert.cluster_uuid)
self.assertEqual(cert_dict['csr'], cert.csr)
self.assertEqual(cert_dict['pem'], cert.pem)
@ -40,7 +40,7 @@ class TestGetCertificate(api_base.FunctionalTest):
def setUp(self):
super(TestGetCertificate, self).setUp()
self.bay = obj_utils.create_test_bay(self.context)
self.cluster = obj_utils.create_test_cluster(self.context)
conductor_api_patcher = mock.patch('magnum.conductor.api.API')
self.conductor_api_class = conductor_api_patcher.start()
@ -54,9 +54,11 @@ class TestGetCertificate(api_base.FunctionalTest):
mock_cert.as_dict.return_value = fake_cert
self.conductor_api.get_ca_certificate.return_value = mock_cert
response = self.get_json('/certificates/%s' % self.bay.uuid)
response = self.get_json('/certificates/%s' % self.cluster.uuid)
self.assertEqual(self.bay.uuid, response['bay_uuid'])
self.assertEqual(self.cluster.uuid, response['cluster_uuid'])
# check that bay is still valid as well
self.assertEqual(self.cluster.uuid, response['bay_uuid'])
self.assertEqual(fake_cert['csr'], response['csr'])
self.assertEqual(fake_cert['pem'], response['pem'])
@ -66,9 +68,11 @@ class TestGetCertificate(api_base.FunctionalTest):
mock_cert.as_dict.return_value = fake_cert
self.conductor_api.get_ca_certificate.return_value = mock_cert
response = self.get_json('/certificates/%s' % self.bay.name)
response = self.get_json('/certificates/%s' % self.cluster.name)
self.assertEqual(self.bay.uuid, response['bay_uuid'])
self.assertEqual(self.cluster.uuid, response['cluster_uuid'])
# check that bay is still valid as well
self.assertEqual(self.cluster.uuid, response['bay_uuid'])
self.assertEqual(fake_cert['csr'], response['csr'])
self.assertEqual(fake_cert['pem'], response['pem'])
@ -80,13 +84,13 @@ class TestGetCertificate(api_base.FunctionalTest):
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['errors'])
def test_get_one_by_name_multiple_bay(self):
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_bay(self.context, name='test_bay',
uuid=uuidutils.generate_uuid())
def test_get_one_by_name_multiple_cluster(self):
obj_utils.create_test_cluster(self.context, name='test_cluster',
uuid=uuidutils.generate_uuid())
obj_utils.create_test_cluster(self.context, name='test_cluster',
uuid=uuidutils.generate_uuid())
response = self.get_json('/certificates/test_bay',
response = self.get_json('/certificates/test_cluster',
expect_errors=True)
self.assertEqual(409, response.status_int)
@ -99,11 +103,11 @@ class TestGetCertificate(api_base.FunctionalTest):
mock_cert.as_dict.return_value = fake_cert
self.conductor_api.get_ca_certificate.return_value = mock_cert
response = self.get_json('/certificates/%s' % self.bay.uuid)
response = self.get_json('/certificates/%s' % self.cluster.uuid)
self.assertIn('links', response.keys())
self.assertEqual(2, len(response['links']))
self.assertIn(self.bay.uuid, response['links'][0]['href'])
self.assertIn(self.cluster.uuid, response['links'][0]['href'])
for l in response['links']:
bookmark = l['rel'] == 'bookmark'
self.assertTrue(self.validate_link(l['href'], bookmark=bookmark))
@ -113,7 +117,7 @@ class TestPost(api_base.FunctionalTest):
def setUp(self):
super(TestPost, self).setUp()
self.bay = obj_utils.create_test_bay(self.context)
self.cluster = obj_utils.create_test_cluster(self.context)
conductor_api_patcher = mock.patch('magnum.conductor.api.API')
self.conductor_api_class = conductor_api_patcher.start()
@ -124,33 +128,51 @@ class TestPost(api_base.FunctionalTest):
self.conductor_api.sign_certificate.side_effect = self._fake_sign
@staticmethod
def _fake_sign(bay, cert):
def _fake_sign(cluster, cert):
cert.pem = 'fake-pem'
return cert
def test_create_cert(self, ):
new_cert = api_utils.cert_post_data(bay_uuid=self.bay.uuid)
new_cert = api_utils.cert_post_data(cluster_uuid=self.cluster.uuid)
del new_cert['pem']
response = self.post_json('/certificates', new_cert)
self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int)
self.assertEqual(new_cert['bay_uuid'], response.json['bay_uuid'])
self.assertEqual(new_cert['cluster_uuid'],
response.json['cluster_uuid'])
# verify bay_uuid is still valid as well
self.assertEqual(new_cert['cluster_uuid'], response.json['bay_uuid'])
self.assertEqual('fake-pem', response.json['pem'])
# Test that bay_uuid is still backward compatible
def test_create_cert_by_bay_name(self, ):
new_cert = api_utils.cert_post_data(bay_uuid=self.bay.name)
new_cert = api_utils.cert_post_data(cluster_uuid=self.cluster.uuid)
del new_cert['pem']
new_cert['bay_uuid'] = new_cert['cluster_uuid']
del new_cert['cluster_uuid']
response = self.post_json('/certificates', new_cert)
self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int)
self.assertEqual(self.cluster.uuid, response.json['cluster_uuid'])
# verify bay_uuid is still valid as well
self.assertEqual(self.cluster.uuid, response.json['bay_uuid'])
self.assertEqual('fake-pem', response.json['pem'])
def test_create_cert_by_cluster_name(self, ):
new_cert = api_utils.cert_post_data(cluster_uuid=self.cluster.name)
del new_cert['pem']
response = self.post_json('/certificates', new_cert)
self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int)
self.assertEqual(self.bay.uuid, response.json['bay_uuid'])
self.assertEqual(self.cluster.uuid, response.json['cluster_uuid'])
self.assertEqual('fake-pem', response.json['pem'])
def test_create_cert_bay_not_found(self, ):
new_cert = api_utils.cert_post_data(bay_uuid='not_found')
def test_create_cert_cluster_not_found(self, ):
new_cert = api_utils.cert_post_data(cluster_uuid='not_found')
del new_cert['pem']
response = self.post_json('/certificates', new_cert,
@ -176,15 +198,15 @@ class TestCertPolicyEnforcement(api_base.FunctionalTest):
response.json['errors'][0]['detail'])
def test_policy_disallow_get_one(self):
bay = obj_utils.create_test_bay(self.context)
cluster = obj_utils.create_test_cluster(self.context)
self._common_policy_check(
"certificate:get", self.get_json,
'/certificates/%s' % bay.uuid,
'/certificates/%s' % cluster.uuid,
expect_errors=True)
def test_policy_disallow_create(self):
bay = obj_utils.create_test_bay(self.context)
cert = api_utils.cert_post_data(bay_uuid=bay.uuid)
cluster = obj_utils.create_test_cluster(self.context)
cert = api_utils.cert_post_data(cluster_uuid=cluster.uuid)
self._common_policy_check(
"certificate:create", self.post_json, '/certificates', cert,
expect_errors=True)

View File

@ -61,7 +61,8 @@ def cluster_post_data(**kw):
def cert_post_data(**kw):
return {
'bay_uuid': kw.get('bay_uuid', '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'),
'cluster_uuid': kw.get('cluster_uuid',
'5d12f6fd-a196-4bf0-ae4c-1f639a523a52'),
'csr': kw.get('csr', 'fake-csr'),
'pem': kw.get('pem', 'fake-pem')
}