Skip to content

Commit 14da4de

Browse files
committed
Implemented Bigtable Cluster.undelete().
Also adding utility for processing UndeleteClusterMetadata.
1 parent a04840b commit 14da4de

2 files changed

Lines changed: 108 additions & 0 deletions

File tree

gcloud/bigtable/cluster.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
_TYPE_URL_BASE = 'type.googleapis.com/google.bigtable.'
3939
_ADMIN_TYPE_URL_BASE = _TYPE_URL_BASE + 'admin.cluster.v1.'
4040
_CLUSTER_CREATE_METADATA = _ADMIN_TYPE_URL_BASE + 'CreateClusterMetadata'
41+
_UNDELETE_CREATE_METADATA = _ADMIN_TYPE_URL_BASE + 'UndeleteClusterMetadata'
4142
_TYPE_URL_MAP = {
4243
_CLUSTER_CREATE_METADATA: messages_pb2.CreateClusterMetadata,
44+
_UNDELETE_CREATE_METADATA: messages_pb2.UndeleteClusterMetadata,
4345
}
4446

4547

@@ -414,6 +416,39 @@ def delete(self):
414416
self._client._cluster_stub.DeleteCluster(
415417
request_pb, self._client.timeout_seconds)
416418

419+
def undelete(self):
420+
"""Undelete this cluster.
421+
422+
Cancels the scheduled deletion of an cluster and begins preparing it to
423+
resume serving. The returned operation will also be embedded as the
424+
cluster's ``current_operation``.
425+
426+
Immediately upon completion of this request:
427+
428+
* The cluster's ``delete_time`` field will be unset, protecting it from
429+
automatic deletion.
430+
431+
Until completion of the returned operation:
432+
433+
* The operation cannot be cancelled.
434+
435+
Upon completion of the returned operation:
436+
437+
* Billing for the cluster's resources will resume.
438+
* All tables within the cluster will be available.
439+
440+
:rtype: :class:`Operation`
441+
:returns: The long-running operation corresponding to the
442+
undelete operation.
443+
"""
444+
request_pb = messages_pb2.UndeleteClusterRequest(name=self.name)
445+
# We expect a `._generated.operations_pb2.Operation`
446+
operation_pb2 = self._client._cluster_stub.UndeleteCluster(
447+
request_pb, self._client.timeout_seconds)
448+
449+
op_id, op_begin = _process_operation(operation_pb2)
450+
return Operation('undelete', op_id, op_begin)
451+
417452
def list_tables(self):
418453
"""List the tables in this cluster.
419454

gcloud/bigtable/test_cluster.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,57 @@ def test_delete(self):
451451
{},
452452
)])
453453

454+
def test_undelete(self):
455+
from gcloud._testing import _Monkey
456+
from gcloud.bigtable._generated import (
457+
bigtable_cluster_service_messages_pb2 as messages_pb2)
458+
from gcloud.bigtable._generated import operations_pb2
459+
from gcloud.bigtable._testing import _FakeStub
460+
from gcloud.bigtable import cluster as MUT
461+
462+
project = 'PROJECT'
463+
zone = 'zone'
464+
cluster_id = 'cluster-id'
465+
timeout_seconds = 78
466+
467+
client = _Client(project, timeout_seconds=timeout_seconds)
468+
cluster = self._makeOne(zone, cluster_id, client)
469+
470+
# Create request_pb
471+
cluster_name = ('projects/' + project + '/zones/' + zone +
472+
'/clusters/' + cluster_id)
473+
request_pb = messages_pb2.UndeleteClusterRequest(name=cluster_name)
474+
475+
# Create response_pb
476+
response_pb = operations_pb2.Operation()
477+
478+
# Patch the stub used by the API method.
479+
client._cluster_stub = stub = _FakeStub(response_pb)
480+
481+
# Create expected_result.
482+
op_id = 5678
483+
op_begin = object()
484+
expected_result = MUT.Operation('undelete', op_id, op_begin)
485+
486+
# Create the mocks.
487+
process_operation_called = []
488+
489+
def mock_process_operation(operation_pb):
490+
process_operation_called.append(operation_pb)
491+
return op_id, op_begin
492+
493+
# Perform the method and check the result.
494+
with _Monkey(MUT, _process_operation=mock_process_operation):
495+
result = cluster.undelete()
496+
497+
self.assertEqual(result, expected_result)
498+
self.assertEqual(stub.method_calls, [(
499+
'UndeleteCluster',
500+
(request_pb, timeout_seconds),
501+
{},
502+
)])
503+
self.assertEqual(process_operation_called, [response_pb])
504+
454505
def _list_tables_helper(self, table_id, table_name=None):
455506
from gcloud.bigtable._generated import (
456507
bigtable_table_data_pb2 as table_data_pb2)
@@ -651,6 +702,28 @@ def test_with_create_cluster_metadata(self):
651702
result = self._callFUT(any_val)
652703
self.assertEqual(result, metadata)
653704

705+
def test_with_undelete_cluster_metadata(self):
706+
from gcloud.bigtable._generated import any_pb2
707+
from gcloud.bigtable._generated import (
708+
bigtable_cluster_data_pb2 as data_pb2)
709+
from gcloud.bigtable._generated import (
710+
bigtable_cluster_service_messages_pb2 as messages_pb2)
711+
from gcloud.bigtable._generated.timestamp_pb2 import Timestamp
712+
713+
type_url = ('type.googleapis.com/' +
714+
messages_pb2._UNDELETECLUSTERMETADATA.full_name)
715+
metadata = messages_pb2.UndeleteClusterMetadata(
716+
request_time=Timestamp(seconds=1, nanos=1234),
717+
finish_time=Timestamp(seconds=10, nanos=891011),
718+
)
719+
720+
any_val = any_pb2.Any(
721+
type_url=type_url,
722+
value=metadata.SerializeToString(),
723+
)
724+
result = self._callFUT(any_val)
725+
self.assertEqual(result, metadata)
726+
654727
def test_unknown_type_url(self):
655728
from gcloud._testing import _Monkey
656729
from gcloud.bigtable._generated import any_pb2

0 commit comments

Comments
 (0)