diff --git a/magnumclient/common/base.py b/magnumclient/common/base.py index 7a2b031..7dd948f 100644 --- a/magnumclient/common/base.py +++ b/magnumclient/common/base.py @@ -126,11 +126,14 @@ class Manager(object): data = self._format_body_data(body, response_key) return [obj_class(self, res, loaded=True) for res in data if res] - def _update(self, url, body, method='PATCH', response_key=None): - resp, body = self.api.json_request(method, url, body=body) - # PATCH/PUT requests may not return a body + def _update(self, url, body=None, method='PATCH', response_key=None): if body: - return self.resource_class(self, body) + resp, resp_body = self.api.json_request(method, url, body=body) + else: + resp, resp_body = self.api.raw_request(method, url) + # PATCH/PUT requests may not return a body + if resp_body: + return self.resource_class(self, resp_body) def _delete(self, url): self.api.raw_request('DELETE', url) diff --git a/magnumclient/common/httpclient.py b/magnumclient/common/httpclient.py index b76fba9..957cb17 100644 --- a/magnumclient/common/httpclient.py +++ b/magnumclient/common/httpclient.py @@ -398,6 +398,11 @@ class ResponseBodyIterator(object): while True: yield self.next() + def __bool__(self): + return hasattr(self, 'items') + + __nonzero__ = __bool__ # Python 2.x compatibility + def next(self): chunk = self.resp.read(CHUNKSIZE) if chunk: diff --git a/magnumclient/tests/v1/test_certificates.py b/magnumclient/tests/v1/test_certificates.py index fd63846..dabb6e7 100644 --- a/magnumclient/tests/v1/test_certificates.py +++ b/magnumclient/tests/v1/test_certificates.py @@ -52,6 +52,10 @@ fake_responses = { 'GET': ( {}, CERT1 + ), + 'PATCH': ( + {}, + None, ) } } @@ -102,3 +106,10 @@ class CertificateManagerTest(testtools.TestCase): ','.join(certificates.CREATION_ATTRIBUTES)), self.mgr.create, **create_cert_fail) self.assertEqual([], self.api.calls) + + def test_rotate_ca(self): + self.mgr.rotate_ca(cluster_uuid=CERT1['cluster_uuid']) + expect = [ + ('PATCH', '/v1/certificates/%s' % CERT1['cluster_uuid'], {}, None) + ] + self.assertEqual(expect, self.api.calls) diff --git a/magnumclient/tests/v1/test_certificates_shell.py b/magnumclient/tests/v1/test_certificates_shell.py index 77b4b95..f7760cd 100644 --- a/magnumclient/tests/v1/test_certificates_shell.py +++ b/magnumclient/tests/v1/test_certificates_shell.py @@ -142,3 +142,17 @@ class ShellTest(shell_test_base.TestCommandLineArgument): _error_msg) mock_cert_get.assert_not_called() mock_cluster_get.assert_not_called() + + @mock.patch('magnumclient.v1.clusters.ClusterManager.get') + @mock.patch('magnumclient.v1.certificates.CertificateManager.rotate_ca') + def test_ca_rotate(self, mock_rotate_ca, mock_cluster_get): + mockcluster = mock.MagicMock() + mockcluster.status = "CREATE_COMPLETE" + mockcluster.uuid = "xxx" + mock_cluster_get.return_value = mockcluster + mock_rotate_ca.return_value = None + self._test_arg_success('ca-rotate ' + '--cluster xxx') + expected_args = {} + expected_args['cluster_uuid'] = mockcluster.uuid + mock_rotate_ca.assert_called_once_with(**expected_args) diff --git a/magnumclient/v1/certificates.py b/magnumclient/v1/certificates.py index 1939820..4bcd711 100644 --- a/magnumclient/v1/certificates.py +++ b/magnumclient/v1/certificates.py @@ -48,3 +48,6 @@ class CertificateManager(base.Manager): raise exceptions.InvalidAttribute( "Key must be in %s" % ",".join(CREATION_ATTRIBUTES)) return self._create(self._path(), new) + + def rotate_ca(self, **kwargs): + return self._update(self._path(id=kwargs['cluster_uuid'])) diff --git a/magnumclient/v1/certificates_shell.py b/magnumclient/v1/certificates_shell.py index c186241..56c7577 100644 --- a/magnumclient/v1/certificates_shell.py +++ b/magnumclient/v1/certificates_shell.py @@ -84,3 +84,16 @@ def do_ca_sign(cs, args): cert = cs.certificates.create(**opts) _show_cert(cert) + + +@utils.arg('--cluster', + required=False, + metavar='', + help=_('ID or name of the cluster.')) +def do_ca_rotate(cs, args): + """Rotate the CA certificate for a bay or cluster to revoke access.""" + opts = { + 'cluster_uuid': _get_target_uuid(cs, args) + } + + cs.certificates.rotate_ca(**opts)