Skip to content

Commit 67a72f0

Browse files
committed
Implemented Bigtable Cluster.undelete().
Also adding utility for processing UndeleteClusterMetadata.
1 parent c4ab6de commit 67a72f0

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

gcloud/bigtable/cluster.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
_TYPE_URL_BASE = 'type.googleapis.com/google.bigtable.'
3636
_ADMIN_TYPE_URL_BASE = _TYPE_URL_BASE + 'admin.cluster.v1.'
3737
_CLUSTER_CREATE_METADATA = _ADMIN_TYPE_URL_BASE + 'CreateClusterMetadata'
38+
_UNDELETE_CREATE_METADATA = _ADMIN_TYPE_URL_BASE + 'UndeleteClusterMetadata'
3839
_TYPE_URL_MAP = {
3940
_CLUSTER_CREATE_METADATA: messages_pb2.CreateClusterMetadata,
41+
_UNDELETE_CREATE_METADATA: messages_pb2.UndeleteClusterMetadata,
4042
}
4143

4244

@@ -346,3 +348,33 @@ def delete(self):
346348
# We expect a `._generated.empty_pb2.Empty`
347349
self._client._cluster_stub.DeleteCluster(
348350
request_pb, self._client.timeout_seconds)
351+
352+
def undelete(self):
353+
"""Undelete this cluster.
354+
355+
Cancels the scheduled deletion of an cluster and begins preparing it to
356+
resume serving. The returned operation will also be embedded as the
357+
cluster's ``current_operation``.
358+
359+
Immediately upon completion of this request:
360+
361+
* The cluster's ``delete_time`` field will be unset, protecting it from
362+
automatic deletion.
363+
364+
Until completion of the returned operation:
365+
366+
* The operation cannot be cancelled.
367+
368+
Upon completion of the returned operation:
369+
370+
* Billing for the cluster's resources will resume.
371+
* All tables within the cluster will be available.
372+
"""
373+
request_pb = messages_pb2.UndeleteClusterRequest(name=self.name)
374+
# We expect a `._generated.operations_pb2.Operation`
375+
operation_pb2 = self._client._cluster_stub.UndeleteCluster(
376+
request_pb, self._client.timeout_seconds)
377+
378+
self._operation_type = 'undelete'
379+
self._operation_id, self._operation_begin = _process_operation(
380+
operation_pb2)

gcloud/bigtable/test_cluster.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,60 @@ def test_delete(self):
333333
{},
334334
)])
335335

336+
def test_undelete(self):
337+
from gcloud._testing import _Monkey
338+
from gcloud.bigtable._generated import (
339+
bigtable_cluster_service_messages_pb2 as messages_pb2)
340+
from gcloud.bigtable._generated import operations_pb2
341+
from gcloud.bigtable._testing import _FakeStub
342+
from gcloud.bigtable import cluster as MUT
343+
344+
project = 'PROJECT'
345+
zone = 'zone'
346+
cluster_id = 'cluster-id'
347+
timeout_seconds = 78
348+
349+
client = _Client(project, timeout_seconds=timeout_seconds)
350+
cluster = self._makeOne(zone, cluster_id, client)
351+
352+
# Create request_pb
353+
cluster_name = ('projects/' + project + '/zones/' + zone +
354+
'/clusters/' + cluster_id)
355+
request_pb = messages_pb2.UndeleteClusterRequest(name=cluster_name)
356+
357+
# Create response_pb
358+
response_pb = operations_pb2.Operation()
359+
360+
# Patch the stub used by the API method.
361+
client._cluster_stub = stub = _FakeStub(response_pb)
362+
363+
# Create expected_result.
364+
expected_result = None
365+
366+
# Create the mocks.
367+
op_id = 5678
368+
op_begin = object()
369+
process_operation_called = []
370+
371+
def mock_process_operation(operation_pb):
372+
process_operation_called.append(operation_pb)
373+
return op_id, op_begin
374+
375+
# Perform the method and check the result.
376+
with _Monkey(MUT, _process_operation=mock_process_operation):
377+
result = cluster.undelete()
378+
379+
self.assertEqual(result, expected_result)
380+
self.assertEqual(stub.method_calls, [(
381+
'UndeleteCluster',
382+
(request_pb, timeout_seconds),
383+
{},
384+
)])
385+
self.assertEqual(cluster._operation_type, 'undelete')
386+
self.assertEqual(cluster._operation_id, op_id)
387+
self.assertTrue(cluster._operation_begin is op_begin)
388+
self.assertEqual(process_operation_called, [response_pb])
389+
336390

337391
class Test__get_pb_property_value(unittest2.TestCase):
338392

@@ -468,6 +522,28 @@ def test_with_create_cluster_metadata(self):
468522
result = self._callFUT(any_val)
469523
self.assertEqual(result, metadata)
470524

525+
def test_with_undelete_cluster_metadata(self):
526+
from gcloud.bigtable._generated import any_pb2
527+
from gcloud.bigtable._generated import (
528+
bigtable_cluster_data_pb2 as data_pb2)
529+
from gcloud.bigtable._generated import (
530+
bigtable_cluster_service_messages_pb2 as messages_pb2)
531+
from gcloud.bigtable._generated.timestamp_pb2 import Timestamp
532+
533+
type_url = ('type.googleapis.com/' +
534+
messages_pb2._UNDELETECLUSTERMETADATA.full_name)
535+
metadata = messages_pb2.UndeleteClusterMetadata(
536+
request_time=Timestamp(seconds=1, nanos=1234),
537+
finish_time=Timestamp(seconds=10, nanos=891011),
538+
)
539+
540+
any_val = any_pb2.Any(
541+
type_url=type_url,
542+
value=metadata.SerializeToString(),
543+
)
544+
result = self._callFUT(any_val)
545+
self.assertEqual(result, metadata)
546+
471547
def test_unknown_type_url(self):
472548
from gcloud._testing import _Monkey
473549
from gcloud.bigtable._generated import any_pb2

0 commit comments

Comments
 (0)