Skip to content

Commit 986f2f2

Browse files
committed
feat: make CopyBackup sample runnable
1 parent f7d3909 commit 986f2f2

File tree

11 files changed

+313
-244
lines changed

11 files changed

+313
-244
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/BackupInfo.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ public abstract static class Builder {
8282
*/
8383
public abstract Builder setDatabase(DatabaseId database);
8484

85-
public abstract Builder setSourceBackup(String sourceBackup);
86-
8785
/** Builds the backup from this builder. */
8886
public abstract Backup build();
8987
}
@@ -97,7 +95,6 @@ abstract static class BuilderImpl extends Builder {
9795
private long size;
9896
private BackupEncryptionConfig encryptionConfig;
9997
private EncryptionInfo encryptionInfo;
100-
private String sourceBackup;
10198
private com.google.spanner.admin.database.v1.Backup proto;
10299

103100
BuilderImpl(BackupId id) {
@@ -128,12 +125,6 @@ public Builder setExpireTime(Timestamp expireTime) {
128125
return this;
129126
}
130127

131-
@Override
132-
public Builder setSourceBackup(String sourceBackup) {
133-
this.sourceBackup = Preconditions.checkNotNull(sourceBackup);
134-
return this;
135-
}
136-
137128
@Override
138129
public Builder setVersionTime(Timestamp versionTime) {
139130
this.versionTime = versionTime;

google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClient.java

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.google.spanner.admin.database.v1.CreateDatabaseRequest;
2929
import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata;
3030
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
31-
3231
import java.util.List;
3332
import javax.annotation.Nullable;
3433

@@ -181,64 +180,68 @@ OperationFuture<Backup, CreateBackupMetadata> createBackup(
181180
OperationFuture<Backup, CreateBackupMetadata> createBackup(Backup backup) throws SpannerException;
182181

183182
/**
184-
* Creates a copy of backup from an existing database backup in a Cloud Spanner instance.
183+
* Creates a copy of backup from an existing backup in a Cloud Spanner instance.
185184
*
186185
* <p>Example to copy a backup.
187186
*
188187
* <pre>{@code
189-
* String instance = my_instance_id;
190-
* String destinationBackupId = my_backup_id;
191-
* String sourceBackup = source_backup;
188+
* String instanceId = "my_instance_id";
189+
* String sourceBackupId = "source_backup_id";
190+
* String destinationBackupId = "destination_backup_id";
192191
* Timestamp expireTime = Timestamp.ofTimeMicroseconds(micros);
193192
* OperationFuture<Backup, CopyBackupMetadata> op = dbAdminClient
194193
* .copyBackup(
195194
* instanceId,
196-
* sourceBackup,
195+
* sourceBackupId,
197196
* destinationBackupId,
198197
* expireTime);
199198
* Backup backup = op.get();
200199
* }</pre>
201200
*
202-
* @param sourceInstanceId the id of the instance where the database to backup is located and
203-
* where the backup will be created.
204-
* @param sourceBackup the source backup id.
205-
* @param destinationBackupId the id of the backup which will be created. It must conform to the regular
206-
* expression [a-z][a-z0-9_\-]*[a-z0-9] and be between 2 and 60 characters in length.
207-
* @param expireTime the time that the backup will automatically expire.
201+
* @param instanceId the id of the instance where the source backup is located and where the new
202+
* backup will be created.
203+
* @param sourceBackupId the source backup id.
204+
* @param destinationBackupId the id of the backup which will be created. It must conform to the
205+
* regular expression [a-z][a-z0-9_\-]*[a-z0-9] and be between 2 and 60 characters in length.
206+
* @param expireTime the time that the new backup will automatically expire.
208207
*/
209208
OperationFuture<Backup, CopyBackupMetadata> copyBackup(
210-
String sourceInstanceId, String sourceBackup, String destinationBackupId, Timestamp expireTime)
211-
throws SpannerException;
212-
209+
String instanceId, String sourceBackupId, String destinationBackupId, Timestamp expireTime)
210+
throws SpannerException;
213211

214212
/**
215-
* Creates a copy of backup from an existing database backup in Cloud Spanner. Any configuration options in the
216-
* {@link Backup} instance will be included in the {@link
213+
* Creates a copy of backup from an existing backup in Cloud Spanner. Any configuration options in
214+
* the {@link Backup} instance will be included in the {@link
217215
* com.google.spanner.admin.database.v1.CopyBackupRequest}.
218216
*
219-
* <p>Example to create an encrypted backup.
217+
* <p>The expire time of the new backup must be set and be at least 6 hours and at most 366 days
218+
* after the creation time of the existing backup that is being copied.
219+
*
220+
* <p>Example to create a copy of a backup.
220221
*
221222
* <pre>{@code
222-
* BackupId destinationBackupId = BackupId.of("project", "instance", "backup-id");
223+
* BackupId sourceBackupId = BackupId.of("source-project", "source-instance", "source-backup-id");
224+
* BackupId destinationBackupId = BackupId.of("destination-project", "destination-instance", "new-backup-id");
223225
* Timestamp expireTime = Timestamp.ofTimeMicroseconds(expireTimeMicros);
224226
* EncryptionConfig encryptionConfig =
225227
* EncryptionConfig.ofKey(
226228
* "projects/my-project/locations/some-location/keyRings/my-keyring/cryptoKeys/my-key"));
227229
*
228-
* Backup backupToCopy = dbAdminClient
230+
* Backup destinationBackup = dbAdminClient
229231
* .newBackupBuilder(destinationBackupId)
230232
* .setExpireTime(expireTime)
231-
* .setVersionTime(versionTime)
232233
* .setEncryptionConfig(encryptionConfig)
233234
* .build();
234235
*
235-
* OperationFuture<Backup, CopyBackupMetadata> op = dbAdminClient.copyBackUp(backupToCopy);
236+
* OperationFuture<Backup, CopyBackupMetadata> op = dbAdminClient.copyBackUp(sourceBackupId, destinationBackup);
236237
* Backup copiedBackup = op.get();
237238
* }</pre>
238239
*
239-
* @param backup the backup to be copied
240+
* @param sourceBackupId the backup to be copied
241+
* @param destinationBackup the new backup to create
240242
*/
241-
OperationFuture<Backup, CopyBackupMetadata> copyBackup(Backup backup) throws SpannerException;
243+
OperationFuture<Backup, CopyBackupMetadata> copyBackup(
244+
BackupId sourceBackupId, Backup destinationBackup) throws SpannerException;
242245

243246
/**
244247
* Restore a database from a backup. The database that is restored will be created and may not

google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
3838
import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata;
3939
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
40-
4140
import java.util.List;
4241
import java.util.UUID;
4342
import javax.annotation.Nullable;
@@ -169,46 +168,45 @@ public OperationFuture<Backup, CreateBackupMetadata> createBackup(Backup backupI
169168

170169
@Override
171170
public OperationFuture<Backup, CopyBackupMetadata> copyBackup(
172-
String instanceId, String sourceBackUp, String destinationBackupId, Timestamp expireTime)
173-
throws SpannerException {
174-
final Backup backupInfo =
175-
newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId))
176-
.setExpireTime(expireTime)
177-
.setSourceBackup(sourceBackUp)
178-
.build();
171+
String instanceId, String sourceBackupId, String destinationBackupId, Timestamp expireTime)
172+
throws SpannerException {
173+
final Backup destinationBackup =
174+
newBackupBuilder(BackupId.of(projectId, instanceId, destinationBackupId))
175+
.setExpireTime(expireTime)
176+
.build();
179177

180-
return copyBackup(backupInfo);
178+
return copyBackup(BackupId.of(projectId, instanceId, sourceBackupId), destinationBackup);
181179
}
182180

183181
@Override
184-
public OperationFuture<Backup, CopyBackupMetadata> copyBackup(Backup backupInfo)
185-
throws SpannerException {
186-
Preconditions.checkArgument(
187-
backupInfo.getId() != null, "Cannot create a backup without a source backup");
182+
public OperationFuture<Backup, CopyBackupMetadata> copyBackup(
183+
BackupId sourceBackupId, Backup destinationBackup) throws SpannerException {
184+
Preconditions.checkNotNull(sourceBackupId);
185+
Preconditions.checkNotNull(destinationBackup);
188186

189187
final OperationFuture<com.google.spanner.admin.database.v1.Backup, CopyBackupMetadata>
190-
rawOperationFuture = rpc.copyBackUp(backupInfo);
188+
rawOperationFuture = rpc.copyBackUp(sourceBackupId, destinationBackup);
191189

192190
return new OperationFutureImpl<>(
193-
rawOperationFuture.getPollingFuture(),
194-
rawOperationFuture.getInitialFuture(),
195-
snapshot -> {
196-
com.google.spanner.admin.database.v1.Backup proto =
197-
ProtoOperationTransformers.ResponseTransformer.create(
198-
com.google.spanner.admin.database.v1.Backup.class)
199-
.apply(snapshot);
200-
return Backup.fromProto(
201-
com.google.spanner.admin.database.v1.Backup.newBuilder(proto)
202-
.setName(proto.getName())
203-
.setExpireTime(proto.getExpireTime())
204-
.setEncryptionInfo(proto.getEncryptionInfo())
205-
.build(),
206-
DatabaseAdminClientImpl.this);
207-
},
208-
ProtoOperationTransformers.MetadataTransformer.create(CopyBackupMetadata.class),
209-
e -> {
210-
throw SpannerExceptionFactory.newSpannerException(e);
211-
});
191+
rawOperationFuture.getPollingFuture(),
192+
rawOperationFuture.getInitialFuture(),
193+
snapshot -> {
194+
com.google.spanner.admin.database.v1.Backup proto =
195+
ProtoOperationTransformers.ResponseTransformer.create(
196+
com.google.spanner.admin.database.v1.Backup.class)
197+
.apply(snapshot);
198+
return Backup.fromProto(
199+
com.google.spanner.admin.database.v1.Backup.newBuilder(proto)
200+
.setName(proto.getName())
201+
.setExpireTime(proto.getExpireTime())
202+
.setEncryptionInfo(proto.getEncryptionInfo())
203+
.build(),
204+
DatabaseAdminClientImpl.this);
205+
},
206+
ProtoOperationTransformers.MetadataTransformer.create(CopyBackupMetadata.class),
207+
e -> {
208+
throw SpannerExceptionFactory.newSpannerException(e);
209+
});
212210
}
213211

214212
@Override

google-cloud-spanner/src/main/java/com/google/cloud/spanner/encryption/EncryptionConfigProtoMapper.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,21 @@ public static CreateBackupEncryptionConfig createBackupEncryptionConfig(
5353

5454
/** Returns an encryption config to be used for a copy backup. */
5555
public static CopyBackupEncryptionConfig copyBackupEncryptionConfig(
56-
BackupEncryptionConfig config) {
56+
BackupEncryptionConfig config) {
5757
if (config instanceof CustomerManagedEncryption) {
5858
return CopyBackupEncryptionConfig.newBuilder()
59-
.setEncryptionType(
60-
CopyBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION)
61-
.setKmsKeyName(((CustomerManagedEncryption) config).getKmsKeyName())
62-
.build();
59+
.setEncryptionType(CopyBackupEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION)
60+
.setKmsKeyName(((CustomerManagedEncryption) config).getKmsKeyName())
61+
.build();
6362
} else if (config instanceof GoogleDefaultEncryption) {
6463
return CopyBackupEncryptionConfig.newBuilder()
65-
.setEncryptionType(CopyBackupEncryptionConfig.EncryptionType.GOOGLE_DEFAULT_ENCRYPTION)
66-
.build();
64+
.setEncryptionType(CopyBackupEncryptionConfig.EncryptionType.GOOGLE_DEFAULT_ENCRYPTION)
65+
.build();
6766
} else if (config instanceof UseBackupEncryption) {
6867
return CopyBackupEncryptionConfig.newBuilder()
69-
.setEncryptionType(CopyBackupEncryptionConfig.EncryptionType.USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION)
70-
.build();
68+
.setEncryptionType(
69+
CopyBackupEncryptionConfig.EncryptionType.USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION)
70+
.build();
7171
} else {
7272
throw new IllegalArgumentException("Unknown backup encryption configuration " + config);
7373
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import com.google.cloud.grpc.GcpManagedChannelOptions.GcpMetricsOptions;
6161
import com.google.cloud.grpc.GrpcTransportOptions;
6262
import com.google.cloud.spanner.AdminRequestsPerMinuteExceededException;
63+
import com.google.cloud.spanner.BackupId;
6364
import com.google.cloud.spanner.ErrorCode;
6465
import com.google.cloud.spanner.Restore;
6566
import com.google.cloud.spanner.SpannerException;
@@ -1266,69 +1267,63 @@ public OperationFuture<Backup, CreateBackupMetadata> createBackup(
12661267
NanoClock.getDefaultClock());
12671268
}
12681269

1269-
12701270
@Override
12711271
public OperationFuture<Backup, CopyBackupMetadata> copyBackUp(
1272-
final com.google.cloud.spanner.Backup backupInfo) throws SpannerException {
1273-
final String instanceName = backupInfo.getInstanceId().getName();
1274-
final String databaseName = backupInfo.getDatabase().getName();
1275-
final String backupId = backupInfo.getId().getBackup();
1276-
final Backup.Builder backupBuilder =
1277-
com.google.spanner.admin.database.v1.Backup.newBuilder()
1278-
.setDatabase(databaseName)
1279-
.setExpireTime(backupInfo.getExpireTime().toProto());
1280-
if (backupInfo.getVersionTime() != null) {
1281-
backupBuilder.setVersionTime(backupInfo.getVersionTime().toProto());
1282-
}
1272+
BackupId sourceBackupId, final com.google.cloud.spanner.Backup destinationBackup)
1273+
throws SpannerException {
1274+
Preconditions.checkNotNull(sourceBackupId);
1275+
Preconditions.checkNotNull(destinationBackup);
1276+
final String instanceName = destinationBackup.getInstanceId().getName();
1277+
final String backupId = destinationBackup.getId().getBackup();
12831278

12841279
final CopyBackupRequest.Builder requestBuilder =
1285-
CopyBackupRequest.newBuilder()
1286-
.setParent(instanceName)
1287-
.setBackupId(backupId)
1288-
.setSourceBackup(backupId)
1289-
.setExpireTime(backupInfo.getExpireTime().toProto()) ;
1280+
CopyBackupRequest.newBuilder()
1281+
.setParent(instanceName)
1282+
.setBackupId(backupId)
1283+
.setSourceBackup(sourceBackupId.getName())
1284+
.setExpireTime(destinationBackup.getExpireTime().toProto());
12901285

1291-
if (backupInfo.getEncryptionConfig() != null) {
1286+
if (destinationBackup.getEncryptionConfig() != null) {
12921287
requestBuilder.setEncryptionConfig(
1293-
EncryptionConfigProtoMapper.copyBackupEncryptionConfig(
1294-
backupInfo.getEncryptionConfig()));
1288+
EncryptionConfigProtoMapper.copyBackupEncryptionConfig(
1289+
destinationBackup.getEncryptionConfig()));
12951290
}
12961291
final CopyBackupRequest request = requestBuilder.build();
12971292
final OperationFutureCallable<CopyBackupRequest, Backup, CopyBackupMetadata> callable =
1298-
new OperationFutureCallable<>(
1299-
databaseAdminStub.copyBackupOperationCallable(),
1300-
request,
1301-
//calling copy backup method of dbClientImpl
1302-
DatabaseAdminGrpc.getCopyBackupMethod(),
1293+
new OperationFutureCallable<>(
1294+
databaseAdminStub.copyBackupOperationCallable(),
1295+
request,
1296+
// calling copy backup method of dbClientImpl
1297+
DatabaseAdminGrpc.getCopyBackupMethod(),
1298+
instanceName,
1299+
nextPageToken ->
1300+
listBackupOperations(
13031301
instanceName,
1304-
nextPageToken ->
1305-
listBackupOperations(
1306-
instanceName,
1307-
0,
1308-
String.format(
1309-
"(metadata.@type:type.googleapis.com/%s) AND (metadata.name:%s)",
1310-
CopyBackupMetadata.getDescriptor().getFullName(),
1311-
String.format("%s/backups/%s", instanceName, backupId)),
1312-
nextPageToken),
1313-
input -> {
1314-
try {
1315-
return input
1316-
.getMetadata()
1317-
.unpack(CopyBackupMetadata.class)
1318-
.getProgress()
1319-
.getStartTime();
1320-
} catch (InvalidProtocolBufferException e) {
1321-
return null;
1322-
}
1323-
});
1302+
0,
1303+
String.format(
1304+
"(metadata.@type:type.googleapis.com/%s) AND (metadata.name:%s)",
1305+
CopyBackupMetadata.getDescriptor().getFullName(),
1306+
String.format("%s/backups/%s", instanceName, backupId)),
1307+
nextPageToken),
1308+
input -> {
1309+
try {
1310+
return input
1311+
.getMetadata()
1312+
.unpack(CopyBackupMetadata.class)
1313+
.getProgress()
1314+
.getStartTime();
1315+
} catch (InvalidProtocolBufferException e) {
1316+
return null;
1317+
}
1318+
});
13241319
return RetryHelper.runWithRetries(
1325-
callable,
1326-
databaseAdminStubSettings
1327-
.copyBackupOperationSettings()
1328-
.getInitialCallSettings()
1329-
.getRetrySettings(),
1330-
new OperationFutureRetryAlgorithm<>(),
1331-
NanoClock.getDefaultClock());
1320+
callable,
1321+
databaseAdminStubSettings
1322+
.copyBackupOperationSettings()
1323+
.getInitialCallSettings()
1324+
.getRetrySettings(),
1325+
new OperationFutureRetryAlgorithm<>(),
1326+
NanoClock.getDefaultClock());
13321327
}
13331328

13341329
@Override

0 commit comments

Comments
 (0)