Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: samples and tests for backup Admin APIs and overall spanner Admin APIs. #2882

Merged
merged 44 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
edc5bbf
fix: prevent illegal negative timeout values into thread sleep() meth…
arpan14 Feb 6, 2023
49a85df
Merge pull request #1 from arpan14/retryerror
arpan14 Feb 8, 2023
4cd497b
Fixing lint issues.
arpan14 Feb 8, 2023
4a6aa8e
Merge branch 'googleapis:main' into main
arpan14 Mar 13, 2023
b2aa09d
Merge branch 'googleapis:main' into main
arpan14 Mar 15, 2023
8d6d71e
Merge branch 'googleapis:main' into main
arpan14 May 9, 2023
77e6e7d
Merge branch 'googleapis:main' into main
arpan14 Jul 17, 2023
e8b7fad
Merge branch 'googleapis:main' into main
arpan14 Jul 25, 2023
8aa84e1
Merge branch 'googleapis:main' into main
arpan14 Oct 10, 2023
57fd405
Merge branch 'googleapis:main' into main
arpan14 Oct 27, 2023
1253563
Merge branch 'googleapis:main' into main
arpan14 Nov 20, 2023
d4f6a60
Merge branch 'googleapis:main' into main
arpan14 Dec 15, 2023
3efaf7c
Merge branch 'googleapis:main' into main
arpan14 Dec 26, 2023
f41b39f
Merge branch 'googleapis:main' into main
arpan14 Jan 3, 2024
3775996
chore: copy samples and rewrite create backup.
arpan14 Jan 10, 2024
c9d60df
chore: fix code.
arpan14 Jan 10, 2024
8989e7c
chore: fix code.
arpan14 Jan 10, 2024
1fedc6e
Merge branch 'googleapis:main' into admin-backup-samples
arpan14 Feb 13, 2024
4e84671
chore: fix code.
arpan14 Jan 11, 2024
3c0d0f6
chore: fix error.
arpan14 Feb 13, 2024
8e51bde
fix: all compilation errors.
arpan14 Feb 15, 2024
fb9ad16
fix: more compilation issues.
arpan14 Feb 15, 2024
0182569
fix: all compile issues.
arpan14 Feb 15, 2024
aa8faca
chore: compile and test PgSpannerSample.
arpan14 Feb 16, 2024
b806ef1
fix: all issues with PgSpannerSample.
arpan14 Feb 16, 2024
7d5943d
chore: compile and fix SpannerSample/SpannerSampleIT.
arpan14 Feb 17, 2024
db5cbca
chore: fix kms configs and ITs.
arpan14 Feb 19, 2024
9240fbc
chore: fix cancel backup tests.
arpan14 Feb 19, 2024
e752d32
Update samples/snippets/src/main/java/com/example/spanner/admin/gener…
arpan14 Feb 19, 2024
ca59fb6
chore: add log statements in tests.
arpan14 Feb 20, 2024
fcf4457
chore: fix lint errors and fix comments.
arpan14 Feb 20, 2024
89834e0
chore: fix lint errors.
arpan14 Feb 20, 2024
478c343
chore: fix lint errors.
arpan14 Feb 20, 2024
d719f7f
chore: fix backup samples for restore use-case.
arpan14 Feb 22, 2024
d324ed6
fix: fix restore/list backup tests.
arpan14 Feb 22, 2024
837034a
chore: fix PgSpannerSample sample and test.
arpan14 Feb 22, 2024
f7623ed
chore: fix delete backup test.
arpan14 Feb 23, 2024
3f90c1a
chore: fix lint errors.
arpan14 Feb 23, 2024
bb7a6cc
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Feb 23, 2024
6f36d93
Merge branch 'main' into admin-backup-samples
arpan14 Feb 23, 2024
01058bc
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Feb 23, 2024
0dcce23
chore: add IT for CopyBackupSample.
arpan14 Feb 23, 2024
fa88a45
chore: fix lint errors.
arpan14 Feb 23, 2024
e3630bc
chore: refactor test for delete backup.
arpan14 Feb 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: add IT for CopyBackupSample.
  • Loading branch information
arpan14 committed Feb 23, 2024
commit 0dcce23c944609e847b8454ccdfceca17ac8c1e6
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
// [START spanner_copy_backup]

import com.google.cloud.Timestamp;
import com.google.cloud.spanner.Backup;
import com.google.cloud.spanner.BackupId;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupName;
import com.google.spanner.admin.database.v1.InstanceName;
import java.io.IOException;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
Expand All @@ -34,15 +34,14 @@

public class CopyBackupSample {

static void copyBackup() {
static void copyBackup() throws IOException {
// TODO(developer): Replace these variables before running the sample.
String projectId = "my-project";
String instanceId = "my-instance";
String sourceBackupId = "my-backup";
String destinationBackupId = "my-destination-backup";
try (Spanner spanner =
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();

try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
copyBackup(databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId);
}
}
Expand All @@ -59,39 +58,36 @@ static void copyBackup(
TimeUnit.MICROSECONDS.convert(
System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14),
TimeUnit.MILLISECONDS));
Backup destinationBackup =
databaseAdminClient
.newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId))
.setExpireTime(expireTime)
.build();

// Initiate the request which returns an OperationFuture.
System.out.println("Copying backup [" + destinationBackup.getId() + "]...");
System.out.println("Copying backup [" + destinationBackupId + "]...");
Backup destinationBackup;
try {
// Creates a copy of an existing backup.
// Wait for the backup operation to complete.
destinationBackup = databaseAdminClient.copyBackup(
BackupId.of(projectId, instanceId, sourceBackupId), destinationBackup).get();
System.out.println("Copied backup [" + destinationBackup.getId() + "]");
destinationBackup = databaseAdminClient.copyBackupAsync(
InstanceName.of(projectId, instanceId), destinationBackupId,
BackupName.of(projectId, instanceId, sourceBackupId), expireTime.toProto()).get();
System.out.println("Copied backup [" + destinationBackup.getName() + "]");
} catch (ExecutionException e) {
throw (SpannerException) e.getCause();
} catch (InterruptedException e) {
throw SpannerExceptionFactory.propagateInterrupt(e);
}
// Load the metadata of the new backup from the server.
destinationBackup = destinationBackup.reload();
destinationBackup = databaseAdminClient.getBackup(destinationBackup.getName());
System.out.println(
String.format(
"Backup %s of size %d bytes was copied at %s for version of database at %s",
destinationBackup.getId().getName(),
destinationBackup.getSize(),
destinationBackup.getName(),
destinationBackup.getSizeBytes(),
OffsetDateTime.ofInstant(
Instant.ofEpochSecond(destinationBackup.getProto().getCreateTime().getSeconds(),
destinationBackup.getProto().getCreateTime().getNanos()),
Instant.ofEpochSecond(destinationBackup.getCreateTime().getSeconds(),
destinationBackup.getCreateTime().getNanos()),
ZoneId.systemDefault()),
OffsetDateTime.ofInstant(
Instant.ofEpochSecond(destinationBackup.getProto().getVersionTime().getSeconds(),
destinationBackup.getProto().getVersionTime().getNanos()),
Instant.ofEpochSecond(destinationBackup.getVersionTime().getSeconds(),
destinationBackup.getVersionTime().getNanos()),
ZoneId.systemDefault())));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
import com.google.spanner.admin.database.v1.RestoreDatabaseRequest;
import com.google.spanner.admin.database.v1.RestoreInfo;
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.ZoneId;
Expand Down Expand Up @@ -1920,8 +1922,8 @@ static void deleteBackup(DatabaseAdminClient dbAdminClient,
// Verify that the backup is deleted.
try {
dbAdminClient.getBackup(backupName);
} catch (SpannerException e) {
if (e.getErrorCode() == ErrorCode.NOT_FOUND) {
} catch (StatusRuntimeException e) {
if (e.getStatus().getCode() == Status.Code.NOT_FOUND) {
System.out.println("Deleted backup [" + backupId + "]");
} else {
System.out.println("Delete backup [" + backupId + "] failed");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.spanner.admin.generated;

import static com.google.common.truth.Truth.assertThat;

import com.example.spanner.SampleRunner;
import com.google.cloud.spanner.ErrorCode;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.spanner.admin.database.v1.BackupName;
import com.google.spanner.admin.database.v1.DatabaseName;
import com.google.spanner.admin.database.v1.InstanceName;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
@Ignore
public class CopyBackupIT extends SampleTestBaseV2 {

private static String key;

@BeforeClass
public static void setUp() {
String keyLocation = Preconditions
.checkNotNull(System.getProperty("spanner.test.key.location"));
String keyRing = Preconditions.checkNotNull(System.getProperty("spanner.test.key.ring"));
String keyName = Preconditions.checkNotNull(System.getProperty("spanner.test.key.name"));
key = "projects/" + projectId + "/locations/" + keyLocation + "/keyRings/" + keyRing
+ "/cryptoKeys/" + keyName;
}

@Test
public void testEncryptedDatabaseAndBackupAndRestore() throws Exception {
final String databaseId = idGenerator.generateDatabaseId();
final String sourceBackupId = idGenerator.generateBackupId();
final String destinationBackupId = idGenerator.generateBackupId();

String out = SampleRunner.runSample(() ->
SpannerSample.createDatabase(
databaseAdminClient, InstanceName.of(projectId, instanceId), databaseId));
assertThat(out).contains(String.format(
"Created database [%s]", DatabaseName.of(projectId, instanceId, databaseId)));

out = SampleRunner.runSampleWithRetry(() ->
CreateBackupWithEncryptionKey.createBackupWithEncryptionKey(
databaseAdminClient, projectId, instanceId, databaseId, sourceBackupId, key
), new ShouldRetryBackupOperation());
assertThat(out).contains("Created backup [" +
BackupName.of(projectId, instanceId, sourceBackupId) + "]");

out = SampleRunner.runSampleWithRetry(() ->
CopyBackupSample.copyBackup(
databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId
), new ShouldRetryBackupOperation());

assertThat(out).contains("Copied backup [" + BackupName.of(
projectId, instanceId, destinationBackupId).toString() + "]");
assertThat(out).containsMatch(String.format(
"Backup projects/%s/instances/%s/backups/%s of size \\d+ bytes was copied at (.*)",
projectId, instanceId, destinationBackupId, key));
}

static class ShouldRetryBackupOperation implements Predicate<SpannerException> {

private static final int MAX_ATTEMPTS = 20;
private int attempts = 0;

@Override
public boolean test(SpannerException e) {
if (e.getErrorCode() == ErrorCode.FAILED_PRECONDITION
&& e.getMessage().contains("Please retry the operation once the pending")) {
attempts++;
if (attempts == MAX_ATTEMPTS) {
// Throw custom exception so it is easier to locate in the log why it went wrong.
throw SpannerExceptionFactory.newSpannerException(ErrorCode.DEADLINE_EXCEEDED,
String.format("Operation failed %d times because of other pending operations. "
+ "Giving up operation.\n", attempts),
e);
}
// Wait one minute before retrying.
Uninterruptibles.sleepUninterruptibly(60L, TimeUnit.SECONDS);
return true;
}
return false;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ public void testBackupSamples_withoutEncryption() {
String databaseId = idGenerator.generateDatabaseId();
DatabaseId dbId = DatabaseId.of(projectId, instanceId, databaseId);
String restoreDatabaseId = idGenerator.generateDatabaseId();
String backupId = idGenerator.generateBackupId();

try {
assertThat(instanceId).isNotNull();
Expand All @@ -385,7 +386,6 @@ public void testBackupSamples_withoutEncryption() {
assertThat(out).contains("Created database");
assertThat(out).contains(dbId.getName());

String backupId = idGenerator.generateBackupId();
BackupName backupName = BackupName.of(projectId, instanceId, backupId);

System.out.println("Creating Backup ...");
Expand Down