Skip to content

Commit 787ccad

Browse files
asthamohtaolavloitegcf-owl-bot[bot]
authored
feat: Copy backup samples (#1802)
* Revert "removing samples" This reverts commit b06a3df. * removing samples * changes to samples * linting * changes as per comments * Update samples/snippets/src/main/java/com/example/spanner/SpannerSample.java Co-authored-by: Knut Olav Løite <[email protected]> * Update samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java Co-authored-by: Knut Olav Løite <[email protected]> * don't merge * Revert "don't merge" This reverts commit cdf4d17. * linting * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * linting * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Knut Olav Løite <[email protected]> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 18ce38a commit 787ccad

File tree

4 files changed

+157
-16
lines changed

4 files changed

+157
-16
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ implementation 'com.google.cloud:google-cloud-spanner'
5656
If you are using Gradle without BOM, add this to your dependencies
5757

5858
```Groovy
59-
implementation 'com.google.cloud:google-cloud-spanner:6.23.2'
59+
implementation 'com.google.cloud:google-cloud-spanner:6.23.3'
6060
```
6161

6262
If you are using SBT, add this to your dependencies
6363

6464
```Scala
65-
libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.23.2"
65+
libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.23.3"
6666
```
6767

6868
## Authentication
@@ -252,6 +252,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
252252
| Async Runner Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AsyncRunnerExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AsyncRunnerExample.java) |
253253
| Async Transaction Manager Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AsyncTransactionManagerExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AsyncTransactionManagerExample.java) |
254254
| Batch Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/BatchSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/BatchSample.java) |
255+
| Copy Backup Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CopyBackupSample.java) |
255256
| Create Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CreateBackupWithEncryptionKey.java) |
256257
| Create Database With Default Leader Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithDefaultLeaderSample.java) |
257258
| Create Database With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithEncryptionKey.java) |
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2022 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.spanner;
18+
19+
// [START spanner_copy_backup]
20+
21+
import com.google.api.gax.longrunning.OperationFuture;
22+
import com.google.cloud.Timestamp;
23+
import com.google.cloud.spanner.Backup;
24+
import com.google.cloud.spanner.BackupId;
25+
import com.google.cloud.spanner.DatabaseAdminClient;
26+
import com.google.cloud.spanner.Spanner;
27+
import com.google.cloud.spanner.SpannerException;
28+
import com.google.cloud.spanner.SpannerExceptionFactory;
29+
import com.google.cloud.spanner.SpannerOptions;
30+
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
31+
import java.time.LocalDateTime;
32+
import java.time.OffsetDateTime;
33+
import java.util.concurrent.ExecutionException;
34+
import java.util.concurrent.TimeUnit;
35+
36+
public class CopyBackupSample {
37+
static void copyBackup() {
38+
// TODO(developer): Replace these variables before running the sample.
39+
String projectId = "my-project";
40+
String instanceId = "my-instance";
41+
String sourceBackupId = "my-backup";
42+
String destinationBackupId = "my-destination-backup";
43+
try (Spanner spanner =
44+
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
45+
DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();
46+
copyBackup(databaseAdminClient, projectId, instanceId, sourceBackupId, destinationBackupId);
47+
}
48+
}
49+
50+
static void copyBackup(
51+
DatabaseAdminClient databaseAdminClient,
52+
String projectId,
53+
String instanceId,
54+
String sourceBackupId,
55+
String destinationBackupId) {
56+
57+
Timestamp expireTime =
58+
Timestamp.ofTimeMicroseconds(
59+
TimeUnit.MICROSECONDS.convert(
60+
System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14),
61+
TimeUnit.MILLISECONDS));
62+
// Creates a copy of an existing backup.
63+
Backup destinationBackup =
64+
databaseAdminClient
65+
.newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId))
66+
.setExpireTime(expireTime)
67+
.build();
68+
69+
// Initiate the request which returns an OperationFuture.
70+
System.out.println("Copying backup [" + destinationBackup.getId() + "]...");
71+
OperationFuture<Backup, CopyBackupMetadata> operation =
72+
databaseAdminClient.copyBackup(
73+
BackupId.of(projectId, instanceId, sourceBackupId), destinationBackup);
74+
try {
75+
// Wait for the backup operation to complete.
76+
destinationBackup = operation.get();
77+
System.out.println("Copied backup [" + destinationBackup.getId() + "]");
78+
} catch (ExecutionException e) {
79+
throw (SpannerException) e.getCause();
80+
} catch (InterruptedException e) {
81+
throw SpannerExceptionFactory.propagateInterrupt(e);
82+
}
83+
// Load the metadata of the new backup from the server.
84+
destinationBackup = destinationBackup.reload();
85+
System.out.println(
86+
String.format(
87+
"Backup %s of size %d bytes was copied at %s for version of database at %s",
88+
destinationBackup.getId().getName(),
89+
destinationBackup.getSize(),
90+
LocalDateTime.ofEpochSecond(
91+
destinationBackup.getProto().getCreateTime().getSeconds(),
92+
destinationBackup.getProto().getCreateTime().getNanos(),
93+
OffsetDateTime.now().getOffset()),
94+
LocalDateTime.ofEpochSecond(
95+
destinationBackup.getProto().getVersionTime().getSeconds(),
96+
destinationBackup.getProto().getVersionTime().getNanos(),
97+
OffsetDateTime.now().getOffset())));
98+
return;
99+
}
100+
}
101+
// [END spanner_copy_backup]

samples/snippets/src/main/java/com/example/spanner/SpannerSample.java

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import com.google.common.io.BaseEncoding;
5757
import com.google.longrunning.Operation;
5858
import com.google.protobuf.InvalidProtocolBufferException;
59+
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
5960
import com.google.spanner.admin.database.v1.CreateBackupMetadata;
6061
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
6162
import com.google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata;
@@ -1659,21 +1660,23 @@ static void cancelCreateBackup(
16591660
// [END spanner_cancel_backup_create]
16601661

16611662
// [START spanner_list_backup_operations]
1662-
static void listBackupOperations(InstanceAdminClient instanceAdminClient, DatabaseId databaseId) {
1663+
static void listBackupOperations(
1664+
InstanceAdminClient instanceAdminClient, DatabaseId databaseId, BackupId backupId) {
16631665
Instance instance = instanceAdminClient.getInstance(databaseId.getInstanceId().getInstance());
16641666
// Get create backup operations for the sample database.
16651667
Timestamp last24Hours = Timestamp.ofTimeSecondsAndNanos(TimeUnit.SECONDS.convert(
16661668
TimeUnit.HOURS.convert(Timestamp.now().getSeconds(), TimeUnit.SECONDS) - 24,
16671669
TimeUnit.HOURS), 0);
16681670
String filter =
16691671
String.format(
1670-
"(metadata.database:%s) AND "
1671-
+ "(metadata.@type:type.googleapis.com/"
1672-
+ "google.spanner.admin.database.v1.CreateBackupMetadata) AND "
1673-
+ "(metadata.progress.start_time > \"%s\")",
1674-
databaseId.getName(), last24Hours);
1675-
Page<Operation> operations = instance.listBackupOperations(Options.filter(filter));
1676-
for (Operation op : operations.iterateAll()) {
1672+
"(metadata.@type:type.googleapis.com/"
1673+
+ "google.spanner.admin.database.v1.CreateBackupMetadata) "
1674+
+ "AND (metadata.database:%s)",
1675+
databaseId.getName());
1676+
Page<Operation> createBackupOperations = instance.listBackupOperations(
1677+
Options.filter(filter));
1678+
System.out.println("Create Backup Operations:");
1679+
for (Operation op : createBackupOperations.iterateAll()) {
16771680
try {
16781681
CreateBackupMetadata metadata = op.getMetadata().unpack(CreateBackupMetadata.class);
16791682
System.out.println(
@@ -1687,6 +1690,30 @@ static void listBackupOperations(InstanceAdminClient instanceAdminClient, Databa
16871690
System.err.println(e.getMessage());
16881691
}
16891692
}
1693+
// Get copy backup operations for the sample database.
1694+
filter =
1695+
String.format(
1696+
"(metadata.@type:type.googleapis.com/"
1697+
+ "google.spanner.admin.database.v1.CopyBackupMetadata) "
1698+
+ "AND (metadata.source_backup:%s)",
1699+
backupId.getName());
1700+
Page<Operation> copyBackupOperations = instance.listBackupOperations(Options.filter(filter));
1701+
System.out.println("Copy Backup Operations:");
1702+
for (Operation op : copyBackupOperations.iterateAll()) {
1703+
try {
1704+
CopyBackupMetadata copyBackupMetadata =
1705+
op.getMetadata().unpack(CopyBackupMetadata.class);
1706+
System.out.println(
1707+
String.format(
1708+
"Copy Backup %s on backup %s pending: %d%% complete",
1709+
copyBackupMetadata.getName(),
1710+
copyBackupMetadata.getSourceBackup(),
1711+
copyBackupMetadata.getProgress().getProgressPercent()));
1712+
} catch (InvalidProtocolBufferException e) {
1713+
// The returned operation does not contain CopyBackupMetadata.
1714+
System.err.println(e.getMessage());
1715+
}
1716+
}
16901717
}
16911718
// [END spanner_list_backup_operations]
16921719

@@ -1840,13 +1867,19 @@ static void updateBackup(DatabaseAdminClient dbAdminClient, BackupId backupId) {
18401867
TimeUnit.SECONDS.toMicros(backup.getExpireTime().getSeconds())
18411868
+ TimeUnit.NANOSECONDS.toMicros(backup.getExpireTime().getNanos())
18421869
+ TimeUnit.DAYS.toMicros(30L));
1870+
// New Expire Time must be less than Max Expire Time
1871+
expireTime = expireTime.compareTo(backup.getMaxExpireTime())
1872+
< 0 ? expireTime : backup.getMaxExpireTime();
1873+
int timeDiff = expireTime.compareTo(backup.getExpireTime());
1874+
Timestamp newExpireTime = (timeDiff < 0) ? expireTime : backup.getExpireTime();
1875+
18431876
System.out.println(String.format(
18441877
"Updating expire time of backup [%s] to %s...",
18451878
backupId.toString(),
18461879
LocalDateTime.ofEpochSecond(
1847-
expireTime.getSeconds(),
1848-
expireTime.getNanos(),
1849-
OffsetDateTime.now().getOffset()).toString()));
1880+
expireTime.getSeconds(),
1881+
expireTime.getNanos(),
1882+
OffsetDateTime.now().getOffset()).toString()));
18501883

18511884
// Update expire time.
18521885
backup = backup.toBuilder().setExpireTime(expireTime).build();
@@ -2048,7 +2081,7 @@ static void run(
20482081
BackupId.of(backup.getInstanceId(), backup.getBackup() + "_cancel"));
20492082
break;
20502083
case "listbackupoperations":
2051-
listBackupOperations(instanceAdminClient, database);
2084+
listBackupOperations(instanceAdminClient, database, backup);
20522085
break;
20532086
case "listdatabaseoperations":
20542087
listDatabaseOperations(instanceAdminClient, dbAdminClient, database.getInstanceId());
@@ -2144,14 +2177,14 @@ static void printUsageAndExit() {
21442177
System.err.println(" SpannerExample querywithqueryoptions my-instance example-db");
21452178
System.err.println(" SpannerExample createbackup my-instance example-db");
21462179
System.err.println(" SpannerExample listbackups my-instance example-db");
2147-
System.err.println(" SpannerExample listbackupoperations my-instance example-db");
2180+
System.err.println(" SpannerExample listbackupoperations my-instance example-db backup-id");
21482181
System.err.println(" SpannerExample listdatabaseoperations my-instance example-db");
21492182
System.err.println(" SpannerExample restorebackup my-instance example-db");
21502183
System.exit(1);
21512184
}
21522185

21532186
public static void main(String[] args) throws Exception {
2154-
if (args.length != 3) {
2187+
if (args.length != 3 && args.length != 4) {
21552188
printUsageAndExit();
21562189
}
21572190
// [START init_client]
@@ -2176,6 +2209,9 @@ public static void main(String[] args) throws Exception {
21762209
"%s_%02d",
21772210
db.getDatabase(), LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR));
21782211
BackupId backup = BackupId.of(db.getInstanceId(), backupName);
2212+
if (args.length == 4) {
2213+
backupName = args[3];
2214+
}
21792215

21802216
// [START init_client]
21812217
DatabaseClient dbClient = spanner.getDatabaseClient(db);

samples/snippets/src/test/java/com/example/spanner/SpannerSampleIT.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.example.spanner;
1818

1919
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.assertTrue;
2021

2122
import com.google.cloud.Timestamp;
2223
import com.google.cloud.spanner.Backup;
@@ -328,6 +329,8 @@ public void testSample() throws Exception {
328329
"Backup %s on database %s pending:",
329330
backupId.getName(),
330331
dbId.getName()));
332+
assertTrue("Out does not contain copy backup operations", out.contains(
333+
"Copy Backup Operations"));
331334
} catch (SpannerException e) {
332335
assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT);
333336
assertThat(e.getMessage()).contains("Cannot evaluate filter expression");

0 commit comments

Comments
 (0)