diff --git a/README.md b/README.md index 993c814ccb..ad61822f8b 100644 --- a/README.md +++ b/README.md @@ -505,9 +505,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | 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) | | Batch Write At Least Once Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/BatchWriteAtLeastOnceSample.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/BatchWriteAtLeastOnceSample.java) | | 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) | +| Copy Backup With Multi Region Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CopyBackupWithMultiRegionEncryptionKey.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/CopyBackupWithMultiRegionEncryptionKey.java) | | 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) | +| Create Backup With Multi Region Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithMultiRegionEncryptionKey.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/CreateBackupWithMultiRegionEncryptionKey.java) | | 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) | | 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) | +| Create Database With Multi Region Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithMultiRegionEncryptionKey.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/CreateDatabaseWithMultiRegionEncryptionKey.java) | | Create Database With Version Retention Period Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithVersionRetentionPeriodSample.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/CreateDatabaseWithVersionRetentionPeriodSample.java) | | Create Full Backup Schedule Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateFullBackupScheduleSample.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/CreateFullBackupScheduleSample.java) | | Create Incremental Backup Schedule Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateIncrementalBackupScheduleSample.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/CreateIncrementalBackupScheduleSample.java) | @@ -560,6 +563,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Quickstart Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/QuickstartSample.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/QuickstartSample.java) | | Read Data With Database Role | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/ReadDataWithDatabaseRole.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/ReadDataWithDatabaseRole.java) | | Restore Backup With Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithEncryptionKey.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/RestoreBackupWithEncryptionKey.java) | +| Restore Backup With Multi Region Encryption Key | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithMultiRegionEncryptionKey.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/RestoreBackupWithMultiRegionEncryptionKey.java) | | Set Max Commit Delay Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/SetMaxCommitDelaySample.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/SetMaxCommitDelaySample.java) | | Singer Proto | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/SingerProto.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/SingerProto.java) | | Spanner Graph Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/SpannerGraphSample.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/SpannerGraphSample.java) | diff --git a/samples/snippets/src/main/java/com/example/spanner/CopyBackupWithMultiRegionEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/CopyBackupWithMultiRegionEncryptionKey.java new file mode 100644 index 0000000000..4fe60a775e --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/CopyBackupWithMultiRegionEncryptionKey.java @@ -0,0 +1,125 @@ +/* + * Copyright 2024 Google Inc. + * + * 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; + +// [START spanner_copy_backup_with_MR_CMEK] + +import com.google.cloud.Timestamp; +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.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.CopyBackupEncryptionConfig; +import com.google.spanner.admin.database.v1.CopyBackupEncryptionConfig.EncryptionType; +import com.google.spanner.admin.database.v1.CopyBackupRequest; +import com.google.spanner.admin.database.v1.InstanceName; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class CopyBackupWithMultiRegionEncryptionKey { + + static void copyBackupWithMultiRegionEncryptionKey() { + // 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"; + String[] kmsKeyNames = + new String[] { + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/" + }; + + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + copyBackupWithMultiRegionEncryptionKey( + databaseAdminClient, + projectId, + instanceId, + sourceBackupId, + destinationBackupId, + kmsKeyNames); + } + } + + static void copyBackupWithMultiRegionEncryptionKey( + DatabaseAdminClient databaseAdminClient, + String projectId, + String instanceId, + String sourceBackupId, + String destinationBackupId, + String[] kmsKeyNames) { + + Timestamp expireTime = + Timestamp.ofTimeMicroseconds( + TimeUnit.MICROSECONDS.convert( + System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14), TimeUnit.MILLISECONDS)); + + // Initiate the request which returns an OperationFuture. + System.out.println("Copying backup [" + destinationBackupId + "]..."); + CopyBackupRequest request = + CopyBackupRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setBackupId(destinationBackupId) + .setSourceBackup(BackupName.of(projectId, instanceId, sourceBackupId).toString()) + .setExpireTime(expireTime.toProto()) + .setEncryptionConfig( + CopyBackupEncryptionConfig.newBuilder() + .setEncryptionType(EncryptionType.CUSTOMER_MANAGED_ENCRYPTION) + .addAllKmsKeyNames(ImmutableList.copyOf(kmsKeyNames)) + .build()) + .build(); + Backup destinationBackup; + try { + // Creates a copy of an existing backup. + // Wait for the backup operation to complete. + destinationBackup = databaseAdminClient.copyBackupAsync(request).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 = 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.getName(), + destinationBackup.getSizeBytes(), + OffsetDateTime.ofInstant( + Instant.ofEpochSecond( + destinationBackup.getCreateTime().getSeconds(), + destinationBackup.getCreateTime().getNanos()), + ZoneId.systemDefault()), + OffsetDateTime.ofInstant( + Instant.ofEpochSecond( + destinationBackup.getVersionTime().getSeconds(), + destinationBackup.getVersionTime().getNanos()), + ZoneId.systemDefault()))); + } +} +// [END spanner_copy_backup_with_MR_CMEK] diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithMultiRegionEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithMultiRegionEncryptionKey.java new file mode 100644 index 0000000000..eb8f669ded --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/CreateBackupWithMultiRegionEncryptionKey.java @@ -0,0 +1,123 @@ +/* + * 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; + +// [START spanner_create_backup_with_MR_CMEK] + +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.ImmutableList; +import com.google.protobuf.Timestamp; +import com.google.spanner.admin.database.v1.Backup; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig; +import com.google.spanner.admin.database.v1.CreateBackupEncryptionConfig.EncryptionType; +import com.google.spanner.admin.database.v1.CreateBackupRequest; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.InstanceName; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.threeten.bp.LocalDateTime; +import org.threeten.bp.OffsetDateTime; + +public class CreateBackupWithMultiRegionEncryptionKey { + + static void createBackupWithMultiRegionEncryptionKey() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + String backupId = "my-backup"; + String[] kmsKeyNames = + new String[] { + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/" + }; + + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + createBackupWithMultiRegionEncryptionKey( + adminClient, projectId, instanceId, databaseId, backupId, kmsKeyNames); + } + } + + static Void createBackupWithMultiRegionEncryptionKey( + DatabaseAdminClient adminClient, + String projectId, + String instanceId, + String databaseId, + String backupId, + String[] kmsKeyNames) { + // Set expire time to 14 days from now. + final Timestamp expireTime = + Timestamp.newBuilder() + .setSeconds( + TimeUnit.MILLISECONDS.toSeconds( + (System.currentTimeMillis() + TimeUnit.DAYS.toMillis(14)))) + .build(); + final BackupName backupName = BackupName.of(projectId, instanceId, backupId); + Backup backup = + Backup.newBuilder() + .setName(backupName.toString()) + .setDatabase(DatabaseName.of(projectId, instanceId, databaseId).toString()) + .setExpireTime(expireTime) + .build(); + + final CreateBackupRequest request = + CreateBackupRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setBackupId(backupId) + .setBackup(backup) + .setEncryptionConfig( + CreateBackupEncryptionConfig.newBuilder() + .setEncryptionType(EncryptionType.CUSTOMER_MANAGED_ENCRYPTION) + .addAllKmsKeyNames(ImmutableList.copyOf(kmsKeyNames)) + .build()) + .build(); + try { + System.out.println("Waiting for operation to complete..."); + backup = adminClient.createBackupAsync(request).get(1200, TimeUnit.SECONDS); + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + // Throw when a thread is waiting, sleeping, or otherwise occupied, + // and the thread is interrupted, either before or during the activity. + throw SpannerExceptionFactory.propagateInterrupt(e); + } catch (TimeoutException e) { + // If the operation timed out propagates the timeout + throw SpannerExceptionFactory.propagateTimeout(e); + } + System.out.printf( + "Backup %s of size %d bytes was created at %s using encryption keys %s%n", + backup.getName(), + backup.getSizeBytes(), + LocalDateTime.ofEpochSecond( + backup.getCreateTime().getSeconds(), + backup.getCreateTime().getNanos(), + OffsetDateTime.now().getOffset()), + ImmutableList.copyOf(kmsKeyNames)); + + return null; + } +} +// [END spanner_create_backup_with_MR_CMEK] diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithMultiRegionEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithMultiRegionEncryptionKey.java new file mode 100644 index 0000000000..962b5b1d5d --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/CreateDatabaseWithMultiRegionEncryptionKey.java @@ -0,0 +1,106 @@ +/* + * 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; + +// [START spanner_create_database_with_MR_CMEK] + +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.CreateDatabaseRequest; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.EncryptionConfig; +import com.google.spanner.admin.database.v1.InstanceName; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateDatabaseWithMultiRegionEncryptionKey { + + static void createDatabaseWithEncryptionKey() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + String[] kmsKeyNames = + new String[] { + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/" + }; + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + createDatabaseWithMultiRegionEncryptionKey( + adminClient, projectId, instanceId, databaseId, kmsKeyNames); + } + } + + static void createDatabaseWithMultiRegionEncryptionKey( + DatabaseAdminClient adminClient, + String projectId, + String instanceId, + String databaseId, + String[] kmsKeyNames) { + InstanceName instanceName = InstanceName.of(projectId, instanceId); + CreateDatabaseRequest request = + CreateDatabaseRequest.newBuilder() + .setParent(instanceName.toString()) + .setCreateStatement("CREATE DATABASE `" + databaseId + "`") + .setEncryptionConfig( + EncryptionConfig.newBuilder() + .addAllKmsKeyNames(ImmutableList.copyOf(kmsKeyNames)) + .build()) + .addAllExtraStatements( + ImmutableList.of( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)", + "CREATE TABLE Albums (" + + " SingerId INT64 NOT NULL," + + " AlbumId INT64 NOT NULL," + + " AlbumTitle STRING(MAX)" + + ") PRIMARY KEY (SingerId, AlbumId)," + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE")) + .build(); + try { + System.out.println("Waiting for operation to complete..."); + Database createdDatabase = + adminClient.createDatabaseAsync(request).get(120, TimeUnit.SECONDS); + + System.out.printf( + "Database %s created with encryption keys %s%n", + createdDatabase.getName(), createdDatabase.getEncryptionConfig().getKmsKeyNamesList()); + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + // Throw when a thread is waiting, sleeping, or otherwise occupied, + // and the thread is interrupted, either before or during the activity. + throw SpannerExceptionFactory.propagateInterrupt(e); + } catch (TimeoutException e) { + // If the operation timed out propagates the timeout + throw SpannerExceptionFactory.propagateTimeout(e); + } + } +} +// [END spanner_create_database_with_MR_CMEK] diff --git a/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithMultiRegionEncryptionKey.java b/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithMultiRegionEncryptionKey.java new file mode 100644 index 0000000000..a13ff4b8cd --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/RestoreBackupWithMultiRegionEncryptionKey.java @@ -0,0 +1,98 @@ +/* + * 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; + +// [START spanner_restore_backup_with_MR_CMEK] + +import static com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig.EncryptionType.CUSTOMER_MANAGED_ENCRYPTION; + +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.common.collect.ImmutableList; +import com.google.spanner.admin.database.v1.BackupName; +import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.InstanceName; +import com.google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig; +import com.google.spanner.admin.database.v1.RestoreDatabaseRequest; +import java.util.concurrent.ExecutionException; + +public class RestoreBackupWithMultiRegionEncryptionKey { + + static void restoreBackupWithMultiRegionEncryptionKey() { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + String backupId = "my-backup"; + String[] kmsKeyNames = + new String[] { + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/", + "projects/" + projectId + "/locations//keyRings//cryptoKeys/" + }; + + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient adminClient = spanner.createDatabaseAdminClient()) { + restoreBackupWithMultiRegionEncryptionKey( + adminClient, projectId, instanceId, backupId, databaseId, kmsKeyNames); + } + } + + static Void restoreBackupWithMultiRegionEncryptionKey( + DatabaseAdminClient adminClient, + String projectId, + String instanceId, + String backupId, + String restoreId, + String[] kmsKeyNames) { + RestoreDatabaseRequest request = + RestoreDatabaseRequest.newBuilder() + .setParent(InstanceName.of(projectId, instanceId).toString()) + .setDatabaseId(restoreId) + .setBackup(BackupName.of(projectId, instanceId, backupId).toString()) + .setEncryptionConfig( + RestoreDatabaseEncryptionConfig.newBuilder() + .setEncryptionType(CUSTOMER_MANAGED_ENCRYPTION) + .addAllKmsKeyNames(ImmutableList.copyOf(kmsKeyNames))) + .build(); + Database database; + try { + System.out.println("Waiting for operation to complete..."); + database = adminClient.restoreDatabaseAsync(request).get(); + ; + } catch (ExecutionException e) { + // If the operation failed during execution, expose the cause. + throw SpannerExceptionFactory.asSpannerException(e.getCause()); + } catch (InterruptedException e) { + // Throw when a thread is waiting, sleeping, or otherwise occupied, + // and the thread is interrupted, either before or during the activity. + throw SpannerExceptionFactory.propagateInterrupt(e); + } + + System.out.printf( + "Database %s restored to %s from backup %s using encryption keys %s%n", + database.getRestoreInfo().getBackupInfo().getSourceDatabase(), + database.getName(), + database.getRestoreInfo().getBackupInfo().getBackup(), + database.getEncryptionConfig().getKmsKeyNamesList()); + return null; + } +} +// [END spanner_restore_backup_with_MR_CMEK]