Merge "Add cluster to cert commands"

This commit is contained in:
Jenkins 2016-08-25 01:04:25 +00:00 committed by Gerrit Code Review
commit abafc6ef1c
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',
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_bay(self.context, name='test_bay',
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')
}