1# Copyright 2020 Google LLC All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15 16import datetime 17import mock 18import unittest 19 20from ._testing import _make_credentials 21from google.cloud._helpers import UTC 22 23 24class TestBackup(unittest.TestCase): 25 PROJECT_ID = "project-id" 26 INSTANCE_ID = "instance-id" 27 INSTANCE_NAME = "projects/" + PROJECT_ID + "/instances/" + INSTANCE_ID 28 CLUSTER_ID = "cluster-id" 29 CLUSTER_NAME = INSTANCE_NAME + "/clusters/" + CLUSTER_ID 30 TABLE_ID = "table-id" 31 TABLE_NAME = INSTANCE_NAME + "/tables/" + TABLE_ID 32 BACKUP_ID = "backup-id" 33 BACKUP_NAME = CLUSTER_NAME + "/backups/" + BACKUP_ID 34 35 ALT_INSTANCE = "other-instance-id" 36 ALT_INSTANCE_NAME = "projects/" + PROJECT_ID + "/instances/" + ALT_INSTANCE 37 ALT_CLUSTER_NAME = ALT_INSTANCE_NAME + "/clusters/" + CLUSTER_ID 38 ALT_BACKUP_NAME = ALT_CLUSTER_NAME + "/backups/" + BACKUP_ID 39 40 @staticmethod 41 def _get_target_class(): 42 from google.cloud.bigtable.backup import Backup 43 44 return Backup 45 46 @staticmethod 47 def _make_table_admin_client(): 48 from google.cloud.bigtable_admin_v2 import BigtableTableAdminClient 49 50 return mock.create_autospec(BigtableTableAdminClient, instance=True) 51 52 def _make_one(self, *args, **kwargs): 53 return self._get_target_class()(*args, **kwargs) 54 55 def _make_timestamp(self): 56 return datetime.datetime.utcnow().replace(tzinfo=UTC) 57 58 def test_constructor_defaults(self): 59 instance = _Instance(self.INSTANCE_NAME) 60 backup = self._make_one(self.BACKUP_ID, instance) 61 62 self.assertEqual(backup.backup_id, self.BACKUP_ID) 63 self.assertIs(backup._instance, instance) 64 self.assertIsNone(backup._cluster) 65 self.assertIsNone(backup.table_id) 66 self.assertIsNone(backup._expire_time) 67 68 self.assertIsNone(backup._parent) 69 self.assertIsNone(backup._source_table) 70 self.assertIsNone(backup._start_time) 71 self.assertIsNone(backup._end_time) 72 self.assertIsNone(backup._size_bytes) 73 self.assertIsNone(backup._state) 74 self.assertIsNone(backup._encryption_info) 75 76 def test_constructor_non_defaults(self): 77 instance = _Instance(self.INSTANCE_NAME) 78 expire_time = self._make_timestamp() 79 80 backup = self._make_one( 81 self.BACKUP_ID, 82 instance, 83 cluster_id=self.CLUSTER_ID, 84 table_id=self.TABLE_ID, 85 expire_time=expire_time, 86 encryption_info="encryption_info", 87 ) 88 89 self.assertEqual(backup.backup_id, self.BACKUP_ID) 90 self.assertIs(backup._instance, instance) 91 self.assertIs(backup._cluster, self.CLUSTER_ID) 92 self.assertEqual(backup.table_id, self.TABLE_ID) 93 self.assertEqual(backup._expire_time, expire_time) 94 self.assertEqual(backup._encryption_info, "encryption_info") 95 96 self.assertIsNone(backup._parent) 97 self.assertIsNone(backup._source_table) 98 self.assertIsNone(backup._start_time) 99 self.assertIsNone(backup._end_time) 100 self.assertIsNone(backup._size_bytes) 101 self.assertIsNone(backup._state) 102 103 def test_from_pb_project_mismatch(self): 104 from google.cloud.bigtable_admin_v2.types import table 105 106 alt_project_id = "alt-project-id" 107 client = _Client(project=alt_project_id) 108 instance = _Instance(self.INSTANCE_NAME, client) 109 backup_pb = table.Backup(name=self.BACKUP_NAME) 110 klasse = self._get_target_class() 111 112 with self.assertRaises(ValueError): 113 klasse.from_pb(backup_pb, instance) 114 115 def test_from_pb_instance_mismatch(self): 116 from google.cloud.bigtable_admin_v2.types import table 117 118 alt_instance = "/projects/%s/instances/alt-instance" % self.PROJECT_ID 119 client = _Client() 120 instance = _Instance(alt_instance, client) 121 backup_pb = table.Backup(name=self.BACKUP_NAME) 122 klasse = self._get_target_class() 123 124 with self.assertRaises(ValueError): 125 klasse.from_pb(backup_pb, instance) 126 127 def test_from_pb_bad_name(self): 128 from google.cloud.bigtable_admin_v2.types import table 129 130 client = _Client() 131 instance = _Instance(self.INSTANCE_NAME, client) 132 backup_pb = table.Backup(name="invalid_name") 133 klasse = self._get_target_class() 134 135 with self.assertRaises(ValueError): 136 klasse.from_pb(backup_pb, instance) 137 138 def test_from_pb_success(self): 139 from google.cloud.bigtable.encryption_info import EncryptionInfo 140 from google.cloud.bigtable.error import Status 141 from google.cloud.bigtable_admin_v2.types import table 142 from google.cloud._helpers import _datetime_to_pb_timestamp 143 from google.rpc.code_pb2 import Code 144 145 client = _Client() 146 instance = _Instance(self.INSTANCE_NAME, client) 147 timestamp = _datetime_to_pb_timestamp(self._make_timestamp()) 148 size_bytes = 1234 149 state = table.Backup.State.READY 150 GOOGLE_DEFAULT_ENCRYPTION = ( 151 table.EncryptionInfo.EncryptionType.GOOGLE_DEFAULT_ENCRYPTION 152 ) 153 backup_pb = table.Backup( 154 name=self.BACKUP_NAME, 155 source_table=self.TABLE_NAME, 156 expire_time=timestamp, 157 start_time=timestamp, 158 end_time=timestamp, 159 size_bytes=size_bytes, 160 state=state, 161 encryption_info=table.EncryptionInfo( 162 encryption_type=GOOGLE_DEFAULT_ENCRYPTION, 163 encryption_status=_StatusPB(Code.OK, "Status OK"), 164 kms_key_version="2", 165 ), 166 ) 167 klasse = self._get_target_class() 168 169 backup = klasse.from_pb(backup_pb, instance) 170 171 self.assertTrue(isinstance(backup, klasse)) 172 self.assertEqual(backup._instance, instance) 173 self.assertEqual(backup.backup_id, self.BACKUP_ID) 174 self.assertEqual(backup.cluster, self.CLUSTER_ID) 175 self.assertEqual(backup.table_id, self.TABLE_ID) 176 self.assertEqual(backup._expire_time, timestamp) 177 self.assertEqual(backup.start_time, timestamp) 178 self.assertEqual(backup.end_time, timestamp) 179 self.assertEqual(backup._size_bytes, size_bytes) 180 self.assertEqual(backup._state, state) 181 self.assertEqual( 182 backup.encryption_info, 183 EncryptionInfo( 184 encryption_type=GOOGLE_DEFAULT_ENCRYPTION, 185 encryption_status=Status(_StatusPB(Code.OK, "Status OK")), 186 kms_key_version="2", 187 ), 188 ) 189 190 def test_property_name(self): 191 from google.cloud.bigtable.client import Client 192 from google.cloud.bigtable_admin_v2.services.bigtable_instance_admin import ( 193 BigtableInstanceAdminClient, 194 ) 195 196 api = mock.create_autospec(BigtableInstanceAdminClient) 197 credentials = _make_credentials() 198 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 199 client._table_admin_client = api 200 instance = _Instance(self.INSTANCE_NAME, client) 201 202 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 203 self.assertEqual(backup.name, self.BACKUP_NAME) 204 205 def test_property_cluster(self): 206 backup = self._make_one( 207 self.BACKUP_ID, _Instance(self.INSTANCE_NAME), cluster_id=self.CLUSTER_ID 208 ) 209 self.assertEqual(backup.cluster, self.CLUSTER_ID) 210 211 def test_property_cluster_setter(self): 212 backup = self._make_one(self.BACKUP_ID, _Instance(self.INSTANCE_NAME)) 213 backup.cluster = self.CLUSTER_ID 214 self.assertEqual(backup.cluster, self.CLUSTER_ID) 215 216 def test_property_parent_none(self): 217 backup = self._make_one(self.BACKUP_ID, _Instance(self.INSTANCE_NAME),) 218 self.assertIsNone(backup.parent) 219 220 def test_property_parent_w_cluster(self): 221 from google.cloud.bigtable.client import Client 222 from google.cloud.bigtable_admin_v2.services.bigtable_instance_admin import ( 223 BigtableInstanceAdminClient, 224 ) 225 226 api = mock.create_autospec(BigtableInstanceAdminClient) 227 credentials = _make_credentials() 228 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 229 client._table_admin_client = api 230 instance = _Instance(self.INSTANCE_NAME, client) 231 232 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 233 self.assertEqual(backup._cluster, self.CLUSTER_ID) 234 self.assertEqual(backup.parent, self.CLUSTER_NAME) 235 236 def test_property_source_table_none(self): 237 from google.cloud.bigtable.client import Client 238 from google.cloud.bigtable_admin_v2.services.bigtable_instance_admin import ( 239 BigtableInstanceAdminClient, 240 ) 241 242 api = mock.create_autospec(BigtableInstanceAdminClient) 243 credentials = _make_credentials() 244 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 245 client._table_admin_client = api 246 instance = _Instance(self.INSTANCE_NAME, client) 247 248 backup = self._make_one(self.BACKUP_ID, instance) 249 self.assertIsNone(backup.source_table) 250 251 def test_property_source_table_valid(self): 252 from google.cloud.bigtable.client import Client 253 from google.cloud.bigtable_admin_v2.services.bigtable_instance_admin import ( 254 BigtableInstanceAdminClient, 255 ) 256 257 api = mock.create_autospec(BigtableInstanceAdminClient) 258 credentials = _make_credentials() 259 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 260 client._table_admin_client = api 261 instance = _Instance(self.INSTANCE_NAME, client) 262 263 backup = self._make_one(self.BACKUP_ID, instance, table_id=self.TABLE_ID) 264 self.assertEqual(backup.source_table, self.TABLE_NAME) 265 266 def test_property_expire_time(self): 267 instance = _Instance(self.INSTANCE_NAME) 268 expire_time = self._make_timestamp() 269 backup = self._make_one(self.BACKUP_ID, instance, expire_time=expire_time) 270 self.assertEqual(backup.expire_time, expire_time) 271 272 def test_property_expire_time_setter(self): 273 instance = _Instance(self.INSTANCE_NAME) 274 expire_time = self._make_timestamp() 275 backup = self._make_one(self.BACKUP_ID, instance) 276 backup.expire_time = expire_time 277 self.assertEqual(backup.expire_time, expire_time) 278 279 def test_property_start_time(self): 280 instance = _Instance(self.INSTANCE_NAME) 281 backup = self._make_one(self.BACKUP_ID, instance) 282 expected = backup._start_time = self._make_timestamp() 283 self.assertEqual(backup.start_time, expected) 284 285 def test_property_end_time(self): 286 instance = _Instance(self.INSTANCE_NAME) 287 backup = self._make_one(self.BACKUP_ID, instance) 288 expected = backup._end_time = self._make_timestamp() 289 self.assertEqual(backup.end_time, expected) 290 291 def test_property_size(self): 292 instance = _Instance(self.INSTANCE_NAME) 293 backup = self._make_one(self.BACKUP_ID, instance) 294 expected = backup._size_bytes = 10 295 self.assertEqual(backup.size_bytes, expected) 296 297 def test_property_state(self): 298 from google.cloud.bigtable_admin_v2.types import table 299 300 instance = _Instance(self.INSTANCE_NAME) 301 backup = self._make_one(self.BACKUP_ID, instance) 302 expected = backup._state = table.Backup.State.READY 303 self.assertEqual(backup.state, expected) 304 305 def test___eq__(self): 306 instance = object() 307 backup1 = self._make_one(self.BACKUP_ID, instance) 308 backup2 = self._make_one(self.BACKUP_ID, instance) 309 self.assertTrue(backup1 == backup2) 310 311 def test___eq__different_types(self): 312 instance = object() 313 backup1 = self._make_one(self.BACKUP_ID, instance) 314 backup2 = object() 315 self.assertFalse(backup1 == backup2) 316 317 def test___ne__same_value(self): 318 instance = object() 319 backup1 = self._make_one(self.BACKUP_ID, instance) 320 backup2 = self._make_one(self.BACKUP_ID, instance) 321 self.assertFalse(backup1 != backup2) 322 323 def test___ne__(self): 324 backup1 = self._make_one("backup_1", "instance1") 325 backup2 = self._make_one("backup_2", "instance2") 326 self.assertTrue(backup1 != backup2) 327 328 def test_create_grpc_error(self): 329 from google.api_core.exceptions import GoogleAPICallError 330 from google.api_core.exceptions import Unknown 331 from google.cloud._helpers import _datetime_to_pb_timestamp 332 from google.cloud.bigtable_admin_v2.types import table 333 334 client = _Client() 335 api = client.table_admin_client = self._make_table_admin_client() 336 api.create_backup.side_effect = Unknown("testing") 337 338 timestamp = self._make_timestamp() 339 backup = self._make_one( 340 self.BACKUP_ID, 341 _Instance(self.INSTANCE_NAME, client=client), 342 table_id=self.TABLE_ID, 343 expire_time=timestamp, 344 ) 345 346 backup_pb = table.Backup( 347 source_table=self.TABLE_NAME, 348 expire_time=_datetime_to_pb_timestamp(timestamp), 349 ) 350 351 with self.assertRaises(GoogleAPICallError): 352 backup.create(self.CLUSTER_ID) 353 354 api.create_backup.assert_called_once_with( 355 request={ 356 "parent": self.CLUSTER_NAME, 357 "backup_id": self.BACKUP_ID, 358 "backup": backup_pb, 359 } 360 ) 361 362 def test_create_already_exists(self): 363 from google.cloud._helpers import _datetime_to_pb_timestamp 364 from google.cloud.bigtable_admin_v2.types import table 365 from google.cloud.exceptions import Conflict 366 367 client = _Client() 368 api = client.table_admin_client = self._make_table_admin_client() 369 api.create_backup.side_effect = Conflict("testing") 370 371 timestamp = self._make_timestamp() 372 backup = self._make_one( 373 self.BACKUP_ID, 374 _Instance(self.INSTANCE_NAME, client=client), 375 table_id=self.TABLE_ID, 376 expire_time=timestamp, 377 ) 378 379 backup_pb = table.Backup( 380 source_table=self.TABLE_NAME, 381 expire_time=_datetime_to_pb_timestamp(timestamp), 382 ) 383 384 with self.assertRaises(Conflict): 385 backup.create(self.CLUSTER_ID) 386 387 api.create_backup.assert_called_once_with( 388 request={ 389 "parent": self.CLUSTER_NAME, 390 "backup_id": self.BACKUP_ID, 391 "backup": backup_pb, 392 } 393 ) 394 395 def test_create_instance_not_found(self): 396 from google.cloud._helpers import _datetime_to_pb_timestamp 397 from google.cloud.bigtable_admin_v2.types import table 398 from google.cloud.exceptions import NotFound 399 400 client = _Client() 401 api = client.table_admin_client = self._make_table_admin_client() 402 api.create_backup.side_effect = NotFound("testing") 403 404 timestamp = self._make_timestamp() 405 backup = self._make_one( 406 self.BACKUP_ID, 407 _Instance(self.INSTANCE_NAME, client=client), 408 table_id=self.TABLE_ID, 409 expire_time=timestamp, 410 ) 411 412 backup_pb = table.Backup( 413 source_table=self.TABLE_NAME, 414 expire_time=_datetime_to_pb_timestamp(timestamp), 415 ) 416 417 with self.assertRaises(NotFound): 418 backup.create(self.CLUSTER_ID) 419 420 api.create_backup.assert_called_once_with( 421 request={ 422 "parent": self.CLUSTER_NAME, 423 "backup_id": self.BACKUP_ID, 424 "backup": backup_pb, 425 } 426 ) 427 428 def test_create_cluster_not_set(self): 429 backup = self._make_one( 430 self.BACKUP_ID, 431 _Instance(self.INSTANCE_NAME), 432 table_id=self.TABLE_ID, 433 expire_time=self._make_timestamp(), 434 ) 435 436 with self.assertRaises(ValueError): 437 backup.create() 438 439 def test_create_table_not_set(self): 440 backup = self._make_one( 441 self.BACKUP_ID, 442 _Instance(self.INSTANCE_NAME), 443 expire_time=self._make_timestamp(), 444 ) 445 446 with self.assertRaises(ValueError): 447 backup.create(self.CLUSTER_ID) 448 449 def test_create_expire_time_not_set(self): 450 backup = self._make_one( 451 self.BACKUP_ID, _Instance(self.INSTANCE_NAME), table_id=self.TABLE_ID, 452 ) 453 454 with self.assertRaises(ValueError): 455 backup.create(self.CLUSTER_ID) 456 457 def test_create_success(self): 458 from google.cloud._helpers import _datetime_to_pb_timestamp 459 from google.cloud.bigtable_admin_v2.types import table 460 from google.cloud.bigtable import Client 461 462 op_future = object() 463 credentials = _make_credentials() 464 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 465 api = client._table_admin_client = self._make_table_admin_client() 466 api.create_backup.return_value = op_future 467 468 timestamp = self._make_timestamp() 469 backup = self._make_one( 470 self.BACKUP_ID, 471 _Instance(self.INSTANCE_NAME, client=client), 472 table_id=self.TABLE_ID, 473 expire_time=timestamp, 474 ) 475 476 backup_pb = table.Backup( 477 source_table=self.TABLE_NAME, 478 expire_time=_datetime_to_pb_timestamp(timestamp), 479 ) 480 481 future = backup.create(self.CLUSTER_ID) 482 self.assertEqual(backup._cluster, self.CLUSTER_ID) 483 self.assertIs(future, op_future) 484 485 api.create_backup.assert_called_once_with( 486 request={ 487 "parent": self.CLUSTER_NAME, 488 "backup_id": self.BACKUP_ID, 489 "backup": backup_pb, 490 } 491 ) 492 493 def test_exists_grpc_error(self): 494 from google.api_core.exceptions import Unknown 495 496 client = _Client() 497 api = client.table_admin_client = self._make_table_admin_client() 498 api.get_backup.side_effect = Unknown("testing") 499 500 instance = _Instance(self.INSTANCE_NAME, client=client) 501 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 502 503 with self.assertRaises(Unknown): 504 backup.exists() 505 506 request = {"name": self.BACKUP_NAME} 507 api.get_backup.assert_called_once_with(request) 508 509 def test_exists_not_found(self): 510 from google.api_core.exceptions import NotFound 511 512 client = _Client() 513 api = client.table_admin_client = self._make_table_admin_client() 514 api.get_backup.side_effect = NotFound("testing") 515 516 instance = _Instance(self.INSTANCE_NAME, client=client) 517 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 518 519 self.assertFalse(backup.exists()) 520 521 api.get_backup.assert_called_once_with(request={"name": self.BACKUP_NAME}) 522 523 def test_get(self): 524 from google.cloud.bigtable_admin_v2.types import table 525 from google.cloud._helpers import _datetime_to_pb_timestamp 526 527 timestamp = _datetime_to_pb_timestamp(self._make_timestamp()) 528 state = table.Backup.State.READY 529 530 client = _Client() 531 backup_pb = table.Backup( 532 name=self.BACKUP_NAME, 533 source_table=self.TABLE_NAME, 534 expire_time=timestamp, 535 start_time=timestamp, 536 end_time=timestamp, 537 size_bytes=0, 538 state=state, 539 ) 540 api = client.table_admin_client = self._make_table_admin_client() 541 api.get_backup.return_value = backup_pb 542 543 instance = _Instance(self.INSTANCE_NAME, client=client) 544 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 545 546 self.assertEqual(backup.get(), backup_pb) 547 548 def test_reload(self): 549 from google.cloud.bigtable_admin_v2.types import table 550 from google.cloud._helpers import _datetime_to_pb_timestamp 551 552 timestamp = _datetime_to_pb_timestamp(self._make_timestamp()) 553 state = table.Backup.State.READY 554 555 client = _Client() 556 backup_pb = table.Backup( 557 name=self.BACKUP_NAME, 558 source_table=self.TABLE_NAME, 559 expire_time=timestamp, 560 start_time=timestamp, 561 end_time=timestamp, 562 size_bytes=0, 563 state=state, 564 ) 565 api = client.table_admin_client = self._make_table_admin_client() 566 api.get_backup.return_value = backup_pb 567 568 instance = _Instance(self.INSTANCE_NAME, client=client) 569 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 570 571 backup.reload() 572 self.assertEqual(backup._source_table, self.TABLE_NAME) 573 self.assertEqual(backup._expire_time, timestamp) 574 self.assertEqual(backup._start_time, timestamp) 575 self.assertEqual(backup._end_time, timestamp) 576 self.assertEqual(backup._size_bytes, 0) 577 self.assertEqual(backup._state, state) 578 579 def test_exists_success(self): 580 from google.cloud.bigtable_admin_v2.types import table 581 582 client = _Client() 583 backup_pb = table.Backup(name=self.BACKUP_NAME) 584 api = client.table_admin_client = self._make_table_admin_client() 585 api.get_backup.return_value = backup_pb 586 587 instance = _Instance(self.INSTANCE_NAME, client=client) 588 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 589 590 self.assertTrue(backup.exists()) 591 592 api.get_backup.assert_called_once_with(request={"name": self.BACKUP_NAME}) 593 594 def test_delete_grpc_error(self): 595 from google.api_core.exceptions import Unknown 596 597 client = _Client() 598 api = client.table_admin_client = self._make_table_admin_client() 599 api.delete_backup.side_effect = Unknown("testing") 600 instance = _Instance(self.INSTANCE_NAME, client=client) 601 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 602 603 with self.assertRaises(Unknown): 604 backup.delete() 605 606 api.delete_backup.assert_called_once_with(request={"name": self.BACKUP_NAME}) 607 608 def test_delete_not_found(self): 609 from google.api_core.exceptions import NotFound 610 611 client = _Client() 612 api = client.table_admin_client = self._make_table_admin_client() 613 api.delete_backup.side_effect = NotFound("testing") 614 instance = _Instance(self.INSTANCE_NAME, client=client) 615 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 616 617 with self.assertRaises(NotFound): 618 backup.delete() 619 620 api.delete_backup.assert_called_once_with(request={"name": self.BACKUP_NAME}) 621 622 def test_delete_success(self): 623 from google.protobuf.empty_pb2 import Empty 624 625 client = _Client() 626 api = client.table_admin_client = self._make_table_admin_client() 627 api.delete_backup.return_value = Empty() 628 instance = _Instance(self.INSTANCE_NAME, client=client) 629 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 630 631 backup.delete() 632 633 api.delete_backup.assert_called_once_with(request={"name": self.BACKUP_NAME}) 634 635 def test_update_expire_time_grpc_error(self): 636 from google.api_core.exceptions import Unknown 637 from google.cloud._helpers import _datetime_to_pb_timestamp 638 from google.cloud.bigtable_admin_v2.types import table 639 from google.protobuf import field_mask_pb2 640 641 client = _Client() 642 api = client.table_admin_client = self._make_table_admin_client() 643 api.update_backup.side_effect = Unknown("testing") 644 instance = _Instance(self.INSTANCE_NAME, client=client) 645 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 646 expire_time = self._make_timestamp() 647 648 with self.assertRaises(Unknown): 649 backup.update_expire_time(expire_time) 650 651 backup_update = table.Backup( 652 name=self.BACKUP_NAME, expire_time=_datetime_to_pb_timestamp(expire_time), 653 ) 654 update_mask = field_mask_pb2.FieldMask(paths=["expire_time"]) 655 api.update_backup.assert_called_once_with( 656 request={"backup": backup_update, "update_mask": update_mask} 657 ) 658 659 def test_update_expire_time_not_found(self): 660 from google.api_core.exceptions import NotFound 661 from google.cloud._helpers import _datetime_to_pb_timestamp 662 from google.cloud.bigtable_admin_v2.types import table 663 from google.protobuf import field_mask_pb2 664 665 client = _Client() 666 api = client.table_admin_client = self._make_table_admin_client() 667 api.update_backup.side_effect = NotFound("testing") 668 instance = _Instance(self.INSTANCE_NAME, client=client) 669 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 670 expire_time = self._make_timestamp() 671 672 with self.assertRaises(NotFound): 673 backup.update_expire_time(expire_time) 674 675 backup_update = table.Backup( 676 name=self.BACKUP_NAME, expire_time=_datetime_to_pb_timestamp(expire_time), 677 ) 678 update_mask = field_mask_pb2.FieldMask(paths=["expire_time"]) 679 api.update_backup.assert_called_once_with( 680 request={"backup": backup_update, "update_mask": update_mask} 681 ) 682 683 def test_update_expire_time_success(self): 684 from google.cloud._helpers import _datetime_to_pb_timestamp 685 from google.cloud.bigtable_admin_v2.types import table 686 from google.protobuf import field_mask_pb2 687 688 client = _Client() 689 api = client.table_admin_client = self._make_table_admin_client() 690 api.update_backup.return_type = table.Backup(name=self.BACKUP_NAME) 691 instance = _Instance(self.INSTANCE_NAME, client=client) 692 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 693 expire_time = self._make_timestamp() 694 695 backup.update_expire_time(expire_time) 696 697 backup_update = table.Backup( 698 name=self.BACKUP_NAME, expire_time=_datetime_to_pb_timestamp(expire_time), 699 ) 700 update_mask = field_mask_pb2.FieldMask(paths=["expire_time"]) 701 api.update_backup.assert_called_once_with( 702 request={"backup": backup_update, "update_mask": update_mask} 703 ) 704 705 def test_restore_grpc_error(self): 706 from google.api_core.exceptions import GoogleAPICallError 707 from google.api_core.exceptions import Unknown 708 709 client = _Client() 710 api = client.table_admin_client = self._make_table_admin_client() 711 api.restore_table.side_effect = Unknown("testing") 712 713 timestamp = self._make_timestamp() 714 backup = self._make_one( 715 self.BACKUP_ID, 716 _Instance(self.INSTANCE_NAME, client=client), 717 cluster_id=self.CLUSTER_ID, 718 table_id=self.TABLE_NAME, 719 expire_time=timestamp, 720 ) 721 722 with self.assertRaises(GoogleAPICallError): 723 backup.restore(self.TABLE_ID) 724 725 api.restore_table.assert_called_once_with( 726 request={ 727 "parent": self.INSTANCE_NAME, 728 "table_id": self.TABLE_ID, 729 "backup": self.BACKUP_NAME, 730 } 731 ) 732 733 def test_restore_cluster_not_set(self): 734 client = _Client() 735 client.table_admin_client = self._make_table_admin_client() 736 backup = self._make_one( 737 self.BACKUP_ID, 738 _Instance(self.INSTANCE_NAME, client=client), 739 table_id=self.TABLE_ID, 740 expire_time=self._make_timestamp(), 741 ) 742 743 with self.assertRaises(ValueError): 744 backup.restore(self.TABLE_ID) 745 746 def _restore_helper(self, instance_id=None, instance_name=None): 747 op_future = object() 748 client = _Client() 749 api = client.table_admin_client = self._make_table_admin_client() 750 api.restore_table.return_value = op_future 751 752 timestamp = self._make_timestamp() 753 backup = self._make_one( 754 self.BACKUP_ID, 755 _Instance(self.INSTANCE_NAME, client=client), 756 cluster_id=self.CLUSTER_ID, 757 table_id=self.TABLE_NAME, 758 expire_time=timestamp, 759 ) 760 761 future = backup.restore(self.TABLE_ID, instance_id) 762 self.assertEqual(backup._cluster, self.CLUSTER_ID) 763 self.assertIs(future, op_future) 764 765 api.restore_table.assert_called_once_with( 766 request={ 767 "parent": instance_name or self.INSTANCE_NAME, 768 "table_id": self.TABLE_ID, 769 "backup": self.BACKUP_NAME, 770 } 771 ) 772 api.restore_table.reset_mock() 773 774 def test_restore_default(self): 775 self._restore_helper() 776 777 def test_restore_to_another_instance(self): 778 self._restore_helper(self.ALT_INSTANCE, self.ALT_INSTANCE_NAME) 779 780 def test_get_iam_policy(self): 781 from google.cloud.bigtable.client import Client 782 from google.cloud.bigtable_admin_v2.services.bigtable_table_admin import ( 783 BigtableTableAdminClient, 784 ) 785 from google.iam.v1 import policy_pb2 786 from google.cloud.bigtable.policy import BIGTABLE_ADMIN_ROLE 787 788 credentials = _make_credentials() 789 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 790 791 instance = client.instance(instance_id=self.INSTANCE_ID) 792 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 793 794 version = 1 795 etag = b"etag_v1" 796 members = ["serviceAccount:service_acc1@test.com", "user:user1@test.com"] 797 bindings = [{"role": BIGTABLE_ADMIN_ROLE, "members": members}] 798 iam_policy = policy_pb2.Policy(version=version, etag=etag, bindings=bindings) 799 800 table_api = mock.create_autospec(BigtableTableAdminClient) 801 client._table_admin_client = table_api 802 table_api.get_iam_policy.return_value = iam_policy 803 804 result = backup.get_iam_policy() 805 806 table_api.get_iam_policy.assert_called_once_with( 807 request={"resource": backup.name} 808 ) 809 self.assertEqual(result.version, version) 810 self.assertEqual(result.etag, etag) 811 812 admins = result.bigtable_admins 813 self.assertEqual(len(admins), len(members)) 814 for found, expected in zip(sorted(admins), sorted(members)): 815 self.assertEqual(found, expected) 816 817 def test_set_iam_policy(self): 818 from google.cloud.bigtable.client import Client 819 from google.cloud.bigtable_admin_v2.services.bigtable_table_admin import ( 820 BigtableTableAdminClient, 821 ) 822 from google.iam.v1 import policy_pb2 823 from google.cloud.bigtable.policy import Policy 824 from google.cloud.bigtable.policy import BIGTABLE_ADMIN_ROLE 825 826 credentials = _make_credentials() 827 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 828 829 instance = client.instance(instance_id=self.INSTANCE_ID) 830 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 831 832 version = 1 833 etag = b"etag_v1" 834 members = ["serviceAccount:service_acc1@test.com", "user:user1@test.com"] 835 bindings = [{"role": BIGTABLE_ADMIN_ROLE, "members": sorted(members)}] 836 iam_policy_pb = policy_pb2.Policy(version=version, etag=etag, bindings=bindings) 837 838 table_api = mock.create_autospec(BigtableTableAdminClient) 839 client._table_admin_client = table_api 840 table_api.set_iam_policy.return_value = iam_policy_pb 841 842 iam_policy = Policy(etag=etag, version=version) 843 iam_policy[BIGTABLE_ADMIN_ROLE] = [ 844 Policy.user("user1@test.com"), 845 Policy.service_account("service_acc1@test.com"), 846 ] 847 848 result = backup.set_iam_policy(iam_policy) 849 850 table_api.set_iam_policy.assert_called_once_with( 851 request={"resource": backup.name, "policy": iam_policy_pb} 852 ) 853 self.assertEqual(result.version, version) 854 self.assertEqual(result.etag, etag) 855 856 admins = result.bigtable_admins 857 self.assertEqual(len(admins), len(members)) 858 for found, expected in zip(sorted(admins), sorted(members)): 859 self.assertEqual(found, expected) 860 861 def test_test_iam_permissions(self): 862 from google.cloud.bigtable.client import Client 863 from google.cloud.bigtable_admin_v2.services.bigtable_table_admin import ( 864 BigtableTableAdminClient, 865 ) 866 from google.iam.v1 import iam_policy_pb2 867 868 credentials = _make_credentials() 869 client = Client(project=self.PROJECT_ID, credentials=credentials, admin=True) 870 871 instance = client.instance(instance_id=self.INSTANCE_ID) 872 backup = self._make_one(self.BACKUP_ID, instance, cluster_id=self.CLUSTER_ID) 873 874 permissions = ["bigtable.backups.create", "bigtable.backups.list"] 875 876 response = iam_policy_pb2.TestIamPermissionsResponse(permissions=permissions) 877 878 table_api = mock.create_autospec(BigtableTableAdminClient) 879 table_api.test_iam_permissions.return_value = response 880 client._table_admin_client = table_api 881 882 result = backup.test_iam_permissions(permissions) 883 884 self.assertEqual(result, permissions) 885 table_api.test_iam_permissions.assert_called_once_with( 886 request={"resource": backup.name, "permissions": permissions} 887 ) 888 889 890class _Client(object): 891 def __init__(self, project=TestBackup.PROJECT_ID): 892 self.project = project 893 self.project_name = "projects/" + self.project 894 895 896class _Instance(object): 897 def __init__(self, name, client=None): 898 self.name = name 899 self.instance_id = name.rsplit("/", 1)[1] 900 self._client = client 901 902 903def _StatusPB(code, message): 904 from google.rpc import status_pb2 905 906 status_pb = status_pb2.Status() 907 status_pb.code = code 908 status_pb.message = message 909 910 return status_pb 911