Skip to content

Commit

Permalink
feat: implement cross-project table restore (#1536)
Browse files Browse the repository at this point in the history
* feat: implement cross-project table restore

* move test case around.

* 🦉 Updates from OwlBot post-processor

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

Co-authored-by: Tracy Cui <tracycui@google.com>
Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Dec 5, 2022
1 parent 7f7c478 commit 335977c
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 10 deletions.
Expand Up @@ -29,37 +29,57 @@ public final class RestoreTableRequest {
private final String sourceBackupId;
private final String sourceClusterId;
private final String sourceInstanceId;
private final String sourceProjectId;

/**
* Create a {@link RestoreTableRequest} object. It assumes the source backup locates in the same
* instance as the destination table. To restore a table from a backup in another instance, use
* {@link #of(String, String, String) of} method.
* instance and project as the destination table. To restore a table from a backup in another
* instance, use {@link #of(String, String, String) of} method. To restore a table from a backup
* in another project, use {@link #of(String, String, String, String) of} method.
*/
public static RestoreTableRequest of(String sourceClusterId, String sourceBackupId) {
RestoreTableRequest request = new RestoreTableRequest(null, sourceClusterId, sourceBackupId);
RestoreTableRequest request =
new RestoreTableRequest(null, sourceClusterId, sourceBackupId, null);
return request;
}

/**
* Create a {@link RestoreTableRequest} object. The source backup could locate in a the same or a
* different instance.
* Create a {@link RestoreTableRequest} object. The source backup could locate in the same or a
* different instance but the same project as the destination table. To restore a table from a
* backup in another project, use {@link #of(String, String, String, String) of} method.
*/
public static RestoreTableRequest of(
String sourceInstanceId, String sourceClusterId, String sourceBackupId) {
RestoreTableRequest request =
new RestoreTableRequest(sourceInstanceId, sourceClusterId, sourceBackupId);
new RestoreTableRequest(sourceInstanceId, sourceClusterId, sourceBackupId, null);
return request;
}

/**
* Create a {@link RestoreTableRequest} object. The source backup could locate in the same or a
* different instance and/or project.
*/
public static RestoreTableRequest of(
String sourceInstanceId,
String sourceClusterId,
String sourceBackupId,
String sourceProjectId) {
RestoreTableRequest request =
new RestoreTableRequest(sourceInstanceId, sourceClusterId, sourceBackupId, sourceProjectId);
return request;
}

private RestoreTableRequest(
@Nullable String sourceInstanceId,
@Nonnull String sourceClusterId,
@Nonnull String sourceBackupId) {
@Nonnull String sourceBackupId,
@Nullable String sourceProjectId) {
Preconditions.checkNotNull(sourceClusterId);
Preconditions.checkNotNull(sourceBackupId);
this.sourceBackupId = sourceBackupId;
this.sourceInstanceId = sourceInstanceId;
this.sourceClusterId = sourceClusterId;
this.sourceProjectId = sourceProjectId;
}

public RestoreTableRequest setTableId(String tableId) {
Expand All @@ -80,13 +100,18 @@ public boolean equals(Object o) {
return Objects.equal(requestBuilder.getTableId(), that.requestBuilder.getTableId())
&& Objects.equal(sourceInstanceId, that.sourceInstanceId)
&& Objects.equal(sourceClusterId, that.sourceClusterId)
&& Objects.equal(sourceBackupId, that.sourceBackupId);
&& Objects.equal(sourceBackupId, that.sourceBackupId)
&& Objects.equal(sourceProjectId, that.sourceProjectId);
}

@Override
public int hashCode() {
return Objects.hashCode(
requestBuilder.getTableId(), sourceInstanceId, sourceClusterId, sourceBackupId);
requestBuilder.getTableId(),
sourceInstanceId,
sourceClusterId,
sourceBackupId,
sourceProjectId);
}

@InternalApi
Expand All @@ -99,7 +124,7 @@ public com.google.bigtable.admin.v2.RestoreTableRequest toProto(
.setParent(NameUtil.formatInstanceName(projectId, instanceId))
.setBackup(
NameUtil.formatBackupName(
projectId,
sourceProjectId == null ? projectId : sourceProjectId,
sourceInstanceId == null ? instanceId : sourceInstanceId,
sourceClusterId,
sourceBackupId))
Expand Down
Expand Up @@ -613,6 +613,54 @@ public void testRestoreTable() throws ExecutionException, InterruptedException {
assertThat(actualResult.getTable().getId()).isEqualTo(TABLE_ID);
}

@Test
public void testRestoreTableCrossProject() throws ExecutionException, InterruptedException {
// Setup
Mockito.when(mockStub.restoreTableOperationCallable())
.thenReturn(mockRestoreTableOperationCallable);

Timestamp startTime = Timestamp.newBuilder().setSeconds(1234).build();
Timestamp endTime = Timestamp.newBuilder().setSeconds(5678).build();
String operationName = "my-operation";

// Use existing adminClient as destination project:
String dstProjectId = PROJECT_ID;
String dstInstanceId = INSTANCE_ID;
String dstTableName = TABLE_NAME;

// Create RestoreTableRequest from different source project:
String srcProjectId = "src-project";
String srcInstanceId = "src-instance";
String srcClusterId = "src-cluster";

RestoreTableRequest req =
RestoreTableRequest.of(srcInstanceId, srcClusterId, BACKUP_ID, srcProjectId)
.setTableId(TABLE_ID);
mockOperationResult(
mockRestoreTableOperationCallable,
req.toProto(dstProjectId, dstInstanceId),
com.google.bigtable.admin.v2.Table.newBuilder().setName(dstTableName).build(),
RestoreTableMetadata.newBuilder()
.setName(dstTableName)
.setOptimizeTableOperationName(operationName)
.setSourceType(RestoreSourceType.BACKUP)
.setBackupInfo(
BackupInfo.newBuilder()
.setBackup(BACKUP_ID)
.setSourceTable(NameUtil.formatTableName(srcProjectId, srcInstanceId, TABLE_ID))
.setStartTime(startTime)
.setEndTime(endTime)
.build())
.build());

// Execute
RestoredTableResult actualResult = adminClient.restoreTable(req);

// Verify
assertThat(actualResult.getTable().getId()).isEqualTo(TABLE_ID);
assertThat(actualResult.getTable().getInstanceId()).isEqualTo(dstInstanceId);
}

@Test
public void testDeleteBackup() {
// Setup
Expand Down
Expand Up @@ -31,6 +31,7 @@ public class RestoreTableRequestTest {
private static final String INSTANCE_ID = "my-instance";
private static final String CLUSTER_ID = "my-cluster";
private static final String SOURCE_INSTANCE_ID = "source-instance-id";
private static final String SOURCE_PROJECT_ID = "source-project-id";

@Test
public void testToProto() {
Expand Down Expand Up @@ -61,6 +62,23 @@ public void testToProtoCrossInstance() {
assertThat(request.toProto(PROJECT_ID, INSTANCE_ID)).isEqualTo(requestProto);
}

@Test
public void testToProtoCrossProject() {
RestoreTableRequest request =
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId(TABLE_ID);

com.google.bigtable.admin.v2.RestoreTableRequest requestProto =
com.google.bigtable.admin.v2.RestoreTableRequest.newBuilder()
.setParent(NameUtil.formatInstanceName(PROJECT_ID, INSTANCE_ID))
.setBackup(
NameUtil.formatBackupName(
SOURCE_PROJECT_ID, SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID))
.setTableId(TABLE_ID)
.build();
assertThat(request.toProto(PROJECT_ID, INSTANCE_ID)).isEqualTo(requestProto);
}

@Test
public void testEquality() {
RestoreTableRequest request =
Expand Down Expand Up @@ -88,6 +106,24 @@ public void testEqualityCrossInstance() {
.setTableId("another-table"));
}

@Test
public void testEqualityCrossProject() {
RestoreTableRequest request =
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId(TABLE_ID);

assertThat(request)
.isEqualTo(
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId(TABLE_ID));
assertThat(request)
.isNotEqualTo(RestoreTableRequest.of(CLUSTER_ID, BACKUP_ID).setTableId(TABLE_ID));
assertThat(request)
.isNotEqualTo(
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId("another-table"));
}

@Test
public void testHashCode() {
RestoreTableRequest request =
Expand Down Expand Up @@ -117,4 +153,24 @@ public void testHashCodeCrossInstance() {
.setTableId("another-table")
.hashCode());
}

@Test
public void testHashCodeCrossProject() {
RestoreTableRequest request =
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId(TABLE_ID);
assertThat(request.hashCode())
.isEqualTo(
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId(TABLE_ID)
.hashCode());
assertThat(request.hashCode())
.isNotEqualTo(
RestoreTableRequest.of(CLUSTER_ID, BACKUP_ID).setTableId(TABLE_ID).hashCode());
assertThat(request.hashCode())
.isNotEqualTo(
RestoreTableRequest.of(SOURCE_INSTANCE_ID, CLUSTER_ID, BACKUP_ID, SOURCE_PROJECT_ID)
.setTableId("another-table")
.hashCode());
}
}

0 comments on commit 335977c

Please sign in to comment.