From 4371db440f0f696f42bcfc6a2e0107d0c20d274d Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:48:52 -0700 Subject: [PATCH 01/66] Add CreateDatabaseWithMRCMEKAsync.cs --- .../CreateDatabaseWithMRCMEKAsync.cs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs new file mode 100644 index 00000000000..21e89a45225 --- /dev/null +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs @@ -0,0 +1,74 @@ +// Copyright 2021 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. + +// [START spanner_create_database_with_MR_CMEK] + +using Google.Cloud.Spanner.Admin.Database.V1; +using Google.Cloud.Spanner.Common.V1; +using System; +using System.Threading.Tasks; + +public class CreateDatabaseWithEncryptionKeyAsyncSample +{ + public async Task CreateDatabaseWithEncryptionKeyAsync(string projectId, string instanceId, string databaseId, CryptoKeyName[] kmsKeyNames) + { + // Create a DatabaseAdminClient instance that can be used to execute a + // CreateDatabaseRequest with custom encryption configuration options. + DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); + // Define create table statement for table #1. + var createSingersTable = + @"CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + ComposerInfo BYTES(MAX) + ) PRIMARY KEY (SingerId)"; + // Define create table statement for table #2. + var createAlbumsTable = + @"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"; + + // Create the CreateDatabase request with encryption configuration and execute it. + var request = new CreateDatabaseRequest + { + ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId), + CreateStatement = $"CREATE DATABASE `{databaseId}`", + ExtraStatements = { createSingersTable, createAlbumsTable }, + EncryptionConfig = new EncryptionConfig + { + KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + }, + }; + var operation = await databaseAdminClient.CreateDatabaseAsync(request); + + // Wait until the operation has finished. + Console.WriteLine("Waiting for the operation to finish."); + var completedResponse = await operation.PollUntilCompletedAsync(); + if (completedResponse.IsFaulted) + { + Console.WriteLine($"Error while creating database: {completedResponse.Exception}"); + throw completedResponse.Exception; + } + + var database = completedResponse.Result; + Console.WriteLine($"Database {database.Name} created with encryption key {0}", string.Join(", ", kmsKeyNames)); + + return database; + } +} +// [END spanner_create_database_with_MR_CMEK] From eb4ee80ac2370dd89f268b2d42666a1b8f6d45f0 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:52:03 -0700 Subject: [PATCH 02/66] Update CreateDatabaseWithMRCMEKAsync.cs --- .../api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs index 21e89a45225..5531eab379c 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs @@ -19,9 +19,9 @@ using System; using System.Threading.Tasks; -public class CreateDatabaseWithEncryptionKeyAsyncSample +public class CreateDatabaseWithMRCMEKAsyncSample { - public async Task CreateDatabaseWithEncryptionKeyAsync(string projectId, string instanceId, string databaseId, CryptoKeyName[] kmsKeyNames) + public async Task CreateDatabaseWithMRCMEKAsync(string projectId, string instanceId, string databaseId, CryptoKeyName[] kmsKeyNames) { // Create a DatabaseAdminClient instance that can be used to execute a // CreateDatabaseRequest with custom encryption configuration options. @@ -66,7 +66,7 @@ AlbumTitle STRING(MAX) } var database = completedResponse.Result; - Console.WriteLine($"Database {database.Name} created with encryption key {0}", string.Join(", ", kmsKeyNames)); + Console.WriteLine($"Database {database.Name} created with encryption keys {0}", string.Join(", ", kmsKeyNames)); return database; } From 9f88bf8c39e8fdfee1fb0f4fc95abc4fe6e510ea Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:54:28 -0700 Subject: [PATCH 03/66] Add CreateBackupWithMRCMEKAsync.cs --- .../CreateBackupWithMRCMEKAsync.cs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs new file mode 100644 index 00000000000..487dc454450 --- /dev/null +++ b/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs @@ -0,0 +1,66 @@ +// Copyright 2021 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. + +// [START spanner_create_backup_with_MR_CMEK] + +using Google.Cloud.Spanner.Admin.Database.V1; +using Google.Cloud.Spanner.Common.V1; +using Google.Protobuf.WellKnownTypes; +using System; +using System.Threading.Tasks; + +public class CreateBackupWithMRCMEKAsyncSample +{ + public async Task CreateBackupWithMRCMEKAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) + { + // Create a DatabaseAdminClient instance. + DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); + + // Create the CreateBackupRequest with encryption configuration. + CreateBackupRequest request = new CreateBackupRequest + { + ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId), + BackupId = backupId, + Backup = new Backup + { + DatabaseAsDatabaseName = DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId), + ExpireTime = DateTime.UtcNow.AddDays(14).ToTimestamp(), + }, + EncryptionConfig = new CreateBackupEncryptionConfig + { + EncryptionType = CreateBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, + KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + }, + }; + // Execute the CreateBackup request. + var operation = await databaseAdminClient.CreateBackupAsync(request); + + Console.WriteLine("Waiting for the operation to finish."); + + // Poll until the returned long-running operation is complete. + var completedResponse = await operation.PollUntilCompletedAsync(); + if (completedResponse.IsFaulted) + { + Console.WriteLine($"Error while creating backup: {completedResponse.Exception}"); + throw completedResponse.Exception; + } + + var backup = completedResponse.Result; + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes " + + $"was created at {backup.CreateTime} " + + $"using encryption keys {0}", string.Join(", ", kmsKeyNames)); + return backup; + } +} +// [END spanner_create_backup_with_MR_CMEK] From d4dc0ef419aa9be8275739c5b4ef2d3ad32588d9 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:57:13 -0700 Subject: [PATCH 04/66] Add RestoreDatabaseWithMRCMEKAsync.cs --- .../RestoreDatabaseWithMRCMEKAsync.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs new file mode 100644 index 00000000000..0bcf3677adc --- /dev/null +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs @@ -0,0 +1,63 @@ +// Copyright 2021 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. + +// [START spanner_restore_backup_with_MR_CMEK] + +using Google.Cloud.Spanner.Admin.Database.V1; +using Google.Cloud.Spanner.Common.V1; +using System; +using System.Threading.Tasks; + +public class RestoreDatabaseWithMRCMEKAsyncSample +{ + public async Task RestoreDatabaseWithMRCMEKAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) + { + // Create a DatabaseAdminClient instance. + DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); + + // Create the RestoreDatabaseRequest with encryption configuration. + RestoreDatabaseRequest request = new RestoreDatabaseRequest + { + ParentAsInstanceName = InstanceName.FromProjectInstance(projectId, instanceId), + DatabaseId = databaseId, + BackupAsBackupName = BackupName.FromProjectInstanceBackup(projectId, instanceId, backupId), + EncryptionConfig = new RestoreDatabaseEncryptionConfig + { + EncryptionType = RestoreDatabaseEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, + KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + } + }; + // Execute the RestoreDatabase request. + var operation = await databaseAdminClient.RestoreDatabaseAsync(request); + + Console.WriteLine("Waiting for the operation to finish."); + + // Poll until the returned long-running operation is complete. + var completedResponse = await operation.PollUntilCompletedAsync(); + if (completedResponse.IsFaulted) + { + Console.WriteLine($"Error while restoring database: {completedResponse.Exception}"); + throw completedResponse.Exception; + } + + var database = completedResponse.Result; + var restoreInfo = database.RestoreInfo; + Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} " + + $"restored to {database.Name} " + + $"from backup {restoreInfo.BackupInfo.Backup} " + + $"using encryption keys {}", string.Join(", ", kmsKeyNames)); + return database; + } +} +// [END spanner_restore_backup_with_MR_CMEK] From d041cc5a49d3c92119a3019a9ed95b9961a547a6 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:06:56 -0700 Subject: [PATCH 05/66] Add CopyBackupWithMRCMEK.cs --- .../Spanner.Samples/CopyBackupWithMRCMEK.cs | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs b/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs new file mode 100644 index 00000000000..7e91cded70b --- /dev/null +++ b/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs @@ -0,0 +1,64 @@ +// Copyright 2022 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. + +// [START spanner_copy_backup_with_MR_CMEK] + +using Google.Api.Gax; +using Google.Cloud.Spanner.Admin.Database.V1; +using Google.Cloud.Spanner.Common.V1; +using Google.Protobuf.WellKnownTypes; +using System; + +public class CopyBackupWithMRCMEKSample +{ + public Backup CopyBackupWithMRCMEK(string sourceInstanceId, string sourceProjectId, string sourceBackupId, + string targetInstanceId, string targetProjectId, string targetBackupId, + DateTimeOffset expireTime, CryptoKeyName[] kmsKeyNames) + { + DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); + + var request = new CopyBackupRequest + { + SourceBackupAsBackupName = new BackupName(sourceProjectId, sourceInstanceId, sourceBackupId), + ParentAsInstanceName = new InstanceName(targetProjectId, targetInstanceId), + BackupId = targetBackupId, + ExpireTime = Timestamp.FromDateTimeOffset(expireTime) , + EncryptionConfig = new CopyBackupEncryptionConfig + { + EncryptionType = CopyBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, + KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + } + }; + + var response = databaseAdminClient.CopyBackup(request); + Console.WriteLine("Waiting for the operation to finish."); + var completedResponse = response.PollUntilCompleted(new PollSettings(Expiration.FromTimeout(TimeSpan.FromMinutes(15)), TimeSpan.FromMinutes(2))); + + if (completedResponse.IsFaulted) + { + Console.WriteLine($"Error while creating backup: {completedResponse.Exception}"); + throw completedResponse.Exception; + } + + Backup backup = completedResponse.Result; + + Console.WriteLine($"Backup created successfully."); + Console.WriteLine($"Backup with Id {sourceBackupId} has been copied from {sourceProjectId}/{sourceInstanceId} to {targetProjectId}/{targetInstanceId} Backup {targetBackupId}"); + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {0} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}", string.Join(", ", kmsKeyNames)); + + return backup; + } +} + +// [END spanner_copy_backup_with_MR_CMEK] From 10582b00b8276558eeb84b59811944c87adafc3c Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:11:39 -0700 Subject: [PATCH 06/66] Add CreateDatabaseWithMRCMEKAsyncTest.cs --- .../CreateDatabaseWithMRCMEKAsyncTest.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs new file mode 100644 index 00000000000..d494a0a497f --- /dev/null +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs @@ -0,0 +1,44 @@ +// Copyright 2021 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. + +using System.Threading.Tasks; +using Xunit; +using Google.Cloud.Spanner.Admin.Database.V1; + +/// +/// Tests creating a databases using MR CMEK. +/// +[Collection(nameof(SpannerFixture))] +public class CreateDatabaseWithMRCMEKAsyncTest +{ + private readonly SpannerFixture _fixture; + + public CreateDatabaseWithMRCMEKAsyncTest(SpannerFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task TestCreateDatabaseWithMRCMEKAsync() + { + // Create a database with custom encryption keys. + var sample = new CreateDatabaseWithMRCMEKAsyncSample(); + var database = await sample.CreateDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); + Assert.Equal(_fixture.KmsKeyName.Length, database.EncryptionConfig.KmsKeyNames.Length); + foreach (CryptoKeyName KmsKey in _fixture.KmsKeyNames) + { + Assert.True(database.EncryptionConfig.KmsKeyNames.contains(KmsKey)); + } + } +} From 46dbc731e1ae788bb6c661367ec3ab0ad5b7bfdf Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:38:12 -0700 Subject: [PATCH 07/66] Update CreateDatabaseWithMRCMEKAsyncTest.cs Change KmsKeyName to KmsKeyNames --- .../Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs index d494a0a497f..59dc04e5e81 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs @@ -35,7 +35,7 @@ public async Task TestCreateDatabaseWithMRCMEKAsync() // Create a database with custom encryption keys. var sample = new CreateDatabaseWithMRCMEKAsyncSample(); var database = await sample.CreateDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); - Assert.Equal(_fixture.KmsKeyName.Length, database.EncryptionConfig.KmsKeyNames.Length); + Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); foreach (CryptoKeyName KmsKey in _fixture.KmsKeyNames) { Assert.True(database.EncryptionConfig.KmsKeyNames.contains(KmsKey)); From 0c76ecf0e2e6fbf5924eff6439926dc1ce1b1eaa Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:29:03 -0700 Subject: [PATCH 08/66] Add CreateBackupWithMRCMEKAsyncTest.cs --- .../CreateBackupWithMRCMEKAsyncTest.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs new file mode 100644 index 00000000000..86095f993f9 --- /dev/null +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs @@ -0,0 +1,45 @@ +// Copyright 2021 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. + +using System; +using System.Threading.Tasks; +using Xunit; + +/// +/// Tests creating a backup using MR CMEK. +/// +[Collection(nameof(SpannerFixture))] +public class CreateBackupWithMRCMEKAsyncTest +{ + private readonly SpannerFixture _fixture; + + public CreateBackupWithMRCMEKAsyncTest(SpannerFixture fixture) + { + _fixture = fixture; + } + + [SkippableFact] + public async Task TestCreatBackupWithMRCMEKAsync() + { + Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); + // Create a backup with custom encryption keys. + var sample = new CreateBackupWithMRCMEKAsyncSample(); + var backup = await sample.CreateBackupWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedEncryptedDatabaseId, _fixture.EncryptedBackupId, _fixture.KmsKeyNames); + Assert.Equal(_fixture.KmsKeyNames.Length, backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames.Length); + foreach (CryptoKeyVersionName KmsKeyVersion in backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames) + { + Assert.True(_fixture.KmsKeyNames.contains(KmsKeyVersion.CryptoKeyId)); + } + } +} From caac81781d77474be6ab39ece232ca7fa273a4cd Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:30:57 -0700 Subject: [PATCH 09/66] Update CreateDatabaseWithMRCMEKAsync.cs Change KmsKeyNamesAsCryptoKeyName to KmsKeyNamesAsCryptoKeyNames --- spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs index 5531eab379c..018347f3da2 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs @@ -51,7 +51,7 @@ AlbumTitle STRING(MAX) ExtraStatements = { createSingersTable, createAlbumsTable }, EncryptionConfig = new EncryptionConfig { - KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, }, }; var operation = await databaseAdminClient.CreateDatabaseAsync(request); From ef24b05bf3da0e7e83cf777e2ead78697ae852a7 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:31:41 -0700 Subject: [PATCH 10/66] Update CopyBackupWithMRCMEK.cs Change KmsKeyNamesAsCryptoKeyName to be KmsKeyNamesAsCryptoKeyNames --- spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs b/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs index 7e91cded70b..3523d39e749 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs @@ -37,7 +37,7 @@ public Backup CopyBackupWithMRCMEK(string sourceInstanceId, string sourceProject EncryptionConfig = new CopyBackupEncryptionConfig { EncryptionType = CopyBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, } }; From d6fc8e708d9a01e421104e679585e1a066ff342b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:32:13 -0700 Subject: [PATCH 11/66] Update CreateBackupWithMRCMEKAsync.cs Change KmsKeyNamesAsCryptoKeyName to be KmsKeyNamesAsCryptoKeyNames --- spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs index 487dc454450..456a8ac9412 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs @@ -40,7 +40,7 @@ public async Task CreateBackupWithMRCMEKAsync(string projectId, string i EncryptionConfig = new CreateBackupEncryptionConfig { EncryptionType = CreateBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, }, }; // Execute the CreateBackup request. From 79c19080745c85ecfc87349f831952d12ce7219f Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:34:46 -0700 Subject: [PATCH 12/66] Update RestoreDatabaseWithMRCMEKAsync.cs Change KmsKeyNamesAsCryptoKeyName to be KmsKeyNamesAsCryptoKeyNames and use database encryption config to print --- spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs index 0bcf3677adc..f4786bfcab6 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs @@ -35,7 +35,7 @@ public async Task RestoreDatabaseWithMRCMEKAsync(string projectId, str EncryptionConfig = new RestoreDatabaseEncryptionConfig { EncryptionType = RestoreDatabaseEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyName = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, } }; // Execute the RestoreDatabase request. @@ -56,7 +56,7 @@ public async Task RestoreDatabaseWithMRCMEKAsync(string projectId, str Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} " + $"restored to {database.Name} " + $"from backup {restoreInfo.BackupInfo.Backup} " + - $"using encryption keys {}", string.Join(", ", kmsKeyNames)); + $"using encryption keys {$0}", string.Join(", ", database.EncryptionConfig.KmsKeyNames)); return database; } } From 8ad9af39781cffa499aba5caa55a2b88f808433a Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:35:25 -0700 Subject: [PATCH 13/66] Update CreateDatabaseWithMRCMEKAsync.cs Use database encryption config to print --- spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs index 018347f3da2..124ff7f2d36 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs @@ -66,7 +66,7 @@ AlbumTitle STRING(MAX) } var database = completedResponse.Result; - Console.WriteLine($"Database {database.Name} created with encryption keys {0}", string.Join(", ", kmsKeyNames)); + Console.WriteLine($"Database {database.Name} created with encryption keys {0}", string.Join(", ", database.EncryptionConfig.KmsKeyNames)); return database; } From b0fff8bf0af12fc23750734b1ecf60c92dd6c4ef Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:41:18 -0700 Subject: [PATCH 14/66] Add CopyBackupWithMRCMEKTest.cs --- .../CopyBackupWithMRCMEKTest.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs new file mode 100644 index 00000000000..62d9bfb5aa0 --- /dev/null +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs @@ -0,0 +1,47 @@ +// Copyright 2022 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. + +using Google.Cloud.Spanner.Admin.Database.V1; +using System; +using Xunit; + +[Collection(nameof(SpannerFixture))] +public class CopyBackupWithMRCMEKTest +{ + private readonly SpannerFixture _spannerFixture; + + public CopyBackupWithMRCMEKTest(SpannerFixture spannerFixture) + { + _spannerFixture = spannerFixture; + } + + [Fact] + public void CopyBackupWithMRCMEK() + { + CopyBackupWithMRCMEKSample copyBackupWithMRCMEKSample = new CopyBackupWithMRCMEKSample(); + string source_Project_id = _spannerFixture.ProjectId; + string source_Instance_id = _spannerFixture.InstanceId; + string source_backupId = _spannerFixture.BackupId; + string target_Project_id = _spannerFixture.ProjectId; + string target_Instance_id = _spannerFixture.InstanceId; + string target_backupId = SpannerFixture.GenerateId("test_", 16); + DateTimeOffset expireTime = DateTimeOffset.UtcNow.AddHours(12); + CryptoKeyName[] kmsKeyNames = _fixture.KmsKeyNames; + + Backup backup = copyBackupWithMRCMEKSample.CopyBackupWithMRCMEK(source_Instance_id, source_Project_id, source_backupId, + target_Instance_id, target_Project_id, target_backupId, expireTime, kmsKeyNames); + + Assert.NotNull(backup); + } +} From 2aae2df0e61849062d7056a9bb1668c5b09ff5c0 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:25:50 -0700 Subject: [PATCH 15/66] Create RestoreDatabaseWithMRCMEKAsyncTest.cs --- .../RestoreDatabaseWithMRCMEKAsyncTest.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs new file mode 100644 index 00000000000..c9e8c3735e6 --- /dev/null +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs @@ -0,0 +1,45 @@ +// Copyright 2021 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. + +using Google.Cloud.Spanner.Admin.Database.V1; +using System; +using System.Threading.Tasks; +using Xunit; + +/// +/// Tests restoring a databases using customer managed encryption. +/// +[Collection(nameof(SpannerFixture))] +public class RestoreDatabaseWithMRCMEKAsyncTest +{ + private readonly SpannerFixture _fixture; + + public RestoreDatabaseWithMRCMEKAsyncTest(SpannerFixture fixture) + { + _fixture = fixture; + } + + [SkippableFact] + public async Task TestRestoreDatabaseWithMRCMEKAsync() + { + Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); + var sample = new RestoreDatabaseWithMRCMEKAsyncSample(); + var database = await sample.RestoreDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedRestoreDatabaseId, _fixture.FixedEncryptedBackupId, _fixture.KmsKeyName); + Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); + foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) + { + Assert.True(_fixture.KmsKeyNames.contains(CryptoKeyName.Parse(KmsKey))); + } + } +} From c6257a90f63f81761400a357ea8a5185a84db310 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:26:22 -0700 Subject: [PATCH 16/66] Update CreateDatabaseWithMRCMEKAsyncTest.cs --- .../CreateDatabaseWithMRCMEKAsyncTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs index 59dc04e5e81..0f6effa2816 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs @@ -36,9 +36,9 @@ public async Task TestCreateDatabaseWithMRCMEKAsync() var sample = new CreateDatabaseWithMRCMEKAsyncSample(); var database = await sample.CreateDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); - foreach (CryptoKeyName KmsKey in _fixture.KmsKeyNames) + foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) { - Assert.True(database.EncryptionConfig.KmsKeyNames.contains(KmsKey)); + Assert.True(_fixture.KmsKeyNames.contains(CryptoKeyName.Parse(KmsKey))); } } } From 5ebb6bddf2f5c042bb19cb8c02ce798f4b9e48f8 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:27:03 -0700 Subject: [PATCH 17/66] Update SpannerFixture.cs to include multiple keys --- .../Spanner.Samples.Tests/SpannerFixture.cs | 1342 +++++++++-------- 1 file changed, 730 insertions(+), 612 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs index 705a4276f18..2129467a9c2 100644 --- a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs +++ b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs @@ -1,524 +1,642 @@ -// Copyright 2020 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. - -using Google.Api.Gax.ResourceNames; -using Google.Cloud.Kms.V1; -using Google.Cloud.Spanner.Admin.Database.V1; -using Google.Cloud.Spanner.Admin.Instance.V1; -using Google.Cloud.Spanner.Common.V1; -using Google.Cloud.Spanner.Data; -using Google.Rpc; -using GoogleCloudSamples; -using Grpc.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Xunit; -using CryptoKeyName = Google.Cloud.Spanner.Admin.Database.V1.CryptoKeyName; - -[CollectionDefinition(nameof(SpannerFixture))] -public class SpannerFixture : IAsyncLifetime, ICollectionFixture +// Copyright 2020 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. + +using Google.Api.Gax.ResourceNames; +using Google.Cloud.Kms.V1; +using Google.Cloud.Spanner.Admin.Database.V1; +using Google.Cloud.Spanner.Admin.Instance.V1; +using Google.Cloud.Spanner.Common.V1; +using Google.Cloud.Spanner.Data; +using Google.Rpc; +using GoogleCloudSamples; +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using CryptoKeyName = Google.Cloud.Spanner.Admin.Database.V1.CryptoKeyName; + +[CollectionDefinition(nameof(SpannerFixture))] +public class SpannerFixture : IAsyncLifetime, ICollectionFixture { public const string CreateSingersTableStatement = - @"CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024) + @"CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024) ) PRIMARY KEY (SingerId)"; public const string CreateAlbumsTableStatement = - @"CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX) - ) PRIMARY KEY (SingerId, AlbumId)"; - - public string ProjectId { get; } = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"); - // Allow environment variables to override the default instance and database names. - public string InstanceId { get; } = Environment.GetEnvironmentVariable("TEST_SPANNER_INSTANCE") ?? "my-instance"; - - public string DatabaseId { get; private set; } - public string PostgreSqlDatabaseId { get; private set; } - - public string BackupDatabaseId { get; } = "my-test-database"; - public string BackupId { get; } = "my-test-database-backup"; - public string CreateCustomInstanceConfigId { get; } = $"custom-name-create-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; - public string UpdateCustomInstanceConfigId { get; } = $"custom-name-update-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; - public string DeleteCustomInstanceConfigId { get; } = $"custom-name-delete-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; - public string ToBeCancelledBackupId { get; } = GenerateId("my-backup-"); - public string RestoredDatabaseId { get; private set; } - - public bool RunCmekBackupSampleTests { get; private set; } - public const string SkipCmekBackupSamplesMessage = "Spanner CMEK backup sample tests are disabled by default for performance reasons. Set the environment variable RUN_SPANNER_CMEK_BACKUP_SAMPLES_TESTS=true to enable the test."; - - public string EncryptedDatabaseId { get; private set; } - public string EncryptedBackupId { get; } = GenerateId("my-enc-backup-"); - // 'restore' is abbreviated to prevent the name from becoming longer than 30 characters. - public string EncryptedRestoreDatabaseId { get; private set; } - - // These are intentionally kept on the instance to avoid the need to create a new encrypted database and backup for each run. - public string FixedEncryptedDatabaseId { get; } = "fixed-enc-backup-db"; - public string FixedEncryptedBackupId { get; } = "fixed-enc-backup"; - - public CryptoKeyName KmsKeyName { get; } = new CryptoKeyName( - Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), - Environment.GetEnvironmentVariable("spanner.test.key.location") ?? "us-central1", - Environment.GetEnvironmentVariable("spanner.test.key.ring") ?? "spanner-test-keyring", - Environment.GetEnvironmentVariable("spanner.test.key.name") ?? "spanner-test-key"); - - public string InstanceIdWithProcessingUnits { get; } = GenerateId("my-ins-pu-"); - public string InstanceIdWithMultiRegion { get; } = GenerateId("my-ins-mr-"); - public string InstanceConfigId { get; } = "nam6"; - - private IList TempDbIds { get; } = new List(); - - public DatabaseAdminClient DatabaseAdminClient { get; private set; } - public InstanceAdminClient InstanceAdminClient { get; private set; } - public SpannerConnection AdminSpannerConnection { get; private set; } - public SpannerConnection SpannerConnection { get; private set; } - public SpannerConnection PgSpannerConnection { get; private set; } - - public RetryRobot Retryable { get; } = new RetryRobot - { - ShouldRetry = ex => ex.IsTransientSpannerFault() - }; - - public async Task InitializeAsync() - { - DatabaseId = Environment.GetEnvironmentVariable("TEST_SPANNER_DATABASE") ?? GenerateTempDatabaseId(); - PostgreSqlDatabaseId = Environment.GetEnvironmentVariable("TEST_SPANNER_POSTGRESQL_DATABASE") ?? GenerateTempDatabaseId("my-db-pg-"); - RestoredDatabaseId = GenerateTempDatabaseId("my-restore-db-"); - EncryptedDatabaseId = GenerateTempDatabaseId("my-enc-db-"); - EncryptedRestoreDatabaseId = GenerateTempDatabaseId("my-enc-r-db-"); - - DatabaseAdminClient = await DatabaseAdminClient.CreateAsync(); - InstanceAdminClient = await InstanceAdminClient.CreateAsync(); - AdminSpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}"); - SpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{DatabaseId}"); - PgSpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{PostgreSqlDatabaseId}"); - - bool.TryParse(Environment.GetEnvironmentVariable("RUN_SPANNER_CMEK_BACKUP_SAMPLES_TESTS"), out var runCmekBackupSampleTests); - RunCmekBackupSampleTests = runCmekBackupSampleTests; - - await InitializeInstanceAsync(); - await CreateInstanceWithMultiRegionAsync(); - await InitializeDatabaseAsync(); - await InitializeBackupAsync(); - await InitializePostgreSqlDatabaseAsync(); - - // Create encryption key for creating an encrypted database and optionally backing up and restoring an encrypted database. - await InitializeEncryptionKeys(); - if (RunCmekBackupSampleTests) - { - await InitializeEncryptedBackupAsync(); - } - } - - public async Task DisposeAsync() - { - try - { - IList cleanupTasks = new List(); - - cleanupTasks.Add(DeleteInstanceAsync(InstanceIdWithMultiRegion)); - cleanupTasks.Add(DeleteInstanceAsync(InstanceIdWithProcessingUnits)); - - cleanupTasks.Add(DeleteBackupAsync(ToBeCancelledBackupId)); - cleanupTasks.Add(DeleteBackupAsync(EncryptedBackupId)); - - DeleteInstanceConfig(CreateCustomInstanceConfigId); - DeleteInstanceConfig(UpdateCustomInstanceConfigId); - DeleteInstanceConfig(DeleteCustomInstanceConfigId); - - foreach (string id in TempDbIds) - { - cleanupTasks.Add(DeleteDatabaseAsync(id)); - } - - await Task.WhenAll(cleanupTasks); - } - finally - { - AdminSpannerConnection?.Dispose(); - SpannerConnection?.Dispose(); - PgSpannerConnection?.Dispose(); - } - } - - private void DeleteInstanceConfig(string instanceConfigId) - { - InstanceAdminClient instanceAdminClient = InstanceAdminClient.Create(); - var instanceConfigName = new InstanceConfigName(ProjectId, instanceConfigId); - - try - { - instanceAdminClient.DeleteInstanceConfig(new DeleteInstanceConfigRequest - { - InstanceConfigName = instanceConfigName - }); - } - catch (Exception) - { - // Silently ignore errors to prevent tests from failing. - } - } - - private async Task InitializeInstanceAsync() - { - InstanceName instanceName = InstanceName.FromProjectInstance(ProjectId, InstanceId); - try - { - Instance response = await InstanceAdminClient.GetInstanceAsync(instanceName); - return true; - } - catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) - { - CreateInstanceSample createInstanceSample = new CreateInstanceSample(); - await SafeCreateInstanceAsync(() => Task.FromResult(createInstanceSample.CreateInstance(ProjectId, InstanceId))); - return false; - } - } - - private async Task CreateInstanceWithMultiRegionAsync() - { - var projectName = ProjectName.FromProject(ProjectId); - Instance instance = new Instance - { - DisplayName = "Multi-region samples test", - ConfigAsInstanceConfigName = InstanceConfigName.FromProjectInstanceConfig(ProjectId, InstanceConfigId), - InstanceName = InstanceName.FromProjectInstance(ProjectId, InstanceIdWithMultiRegion), - NodeCount = 1, - }; - - await SafeCreateInstanceAsync(async () => - { - var response = await InstanceAdminClient.CreateInstanceAsync(projectName, InstanceIdWithMultiRegion, instance); - // Poll until the returned long-running operation is complete - response = await response.PollUntilCompletedAsync(); - return response.Result; - }); - } - - private async Task InitializeDatabaseAsync() - { - // If the database has not been initialized, retry. - CreateDatabaseAsyncSample createDatabaseAsyncSample = new CreateDatabaseAsyncSample(); - InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - InsertStructSampleDataAsyncSample insertStructSampleDataAsyncSample = new InsertStructSampleDataAsyncSample(); - AddColumnAsyncSample addColumnAsyncSample = new AddColumnAsyncSample(); - AddCommitTimestampAsyncSample addCommitTimestampAsyncSample = new AddCommitTimestampAsyncSample(); - AddIndexAsyncSample addIndexAsyncSample = new AddIndexAsyncSample(); - AddStoringIndexAsyncSample addStoringIndexAsyncSample = new AddStoringIndexAsyncSample(); - CreateTableWithDataTypesAsyncSample createTableWithDataTypesAsyncSample = new CreateTableWithDataTypesAsyncSample(); - InsertDataTypesDataAsyncSample insertDataTypesDataAsyncSample = new InsertDataTypesDataAsyncSample(); - CreateTableWithTimestampColumnAsyncSample createTableWithTimestampColumnAsyncSample = - new CreateTableWithTimestampColumnAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseAsync(ProjectId, InstanceId, DatabaseId); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, DatabaseId); - await insertStructSampleDataAsyncSample.InsertStructSampleDataAsync(ProjectId, InstanceId, DatabaseId); - await addColumnAsyncSample.AddColumnAsync(ProjectId, InstanceId, DatabaseId); - await addCommitTimestampAsyncSample.AddCommitTimestampAsync(ProjectId, InstanceId, DatabaseId); - await addIndexAsyncSample.AddIndexAsync(ProjectId, InstanceId, DatabaseId); - // Create a new table that includes supported datatypes. - await createTableWithDataTypesAsyncSample.CreateTableWithDataTypesAsync(ProjectId, InstanceId, DatabaseId); - // Write data to the new table. - await insertDataTypesDataAsyncSample.InsertDataTypesDataAsync(ProjectId, InstanceId, DatabaseId); - // Add storing Index on table. - await addStoringIndexAsyncSample.AddStoringIndexAsync(ProjectId, InstanceId, DatabaseId); - // Update the value of MarketingBudgets. - await RefillMarketingBudgetsAsync(300000, 300000); - // Create table with Timestamp column - await createTableWithTimestampColumnAsyncSample.CreateTableWithTimestampColumnAsync(ProjectId, InstanceId, DatabaseId); - } - + @"CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX) + ) PRIMARY KEY (SingerId, AlbumId)"; + + public string ProjectId { get; } = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"); + // Allow environment variables to override the default instance and database names. + public string InstanceId { get; } = Environment.GetEnvironmentVariable("TEST_SPANNER_INSTANCE") ?? "my-instance"; + + public string DatabaseId { get; private set; } + public string PostgreSqlDatabaseId { get; private set; } + + public string BackupDatabaseId { get; } = "my-test-database"; + public string BackupId { get; } = "my-test-database-backup"; + public string CreateCustomInstanceConfigId { get; } = $"custom-name-create-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; + public string UpdateCustomInstanceConfigId { get; } = $"custom-name-update-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; + public string DeleteCustomInstanceConfigId { get; } = $"custom-name-delete-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"; + public string ToBeCancelledBackupId { get; } = GenerateId("my-backup-"); + public string RestoredDatabaseId { get; private set; } + + public bool RunCmekBackupSampleTests { get; private set; } + public const string SkipCmekBackupSamplesMessage = "Spanner CMEK backup sample tests are disabled by default for performance reasons. Set the environment variable RUN_SPANNER_CMEK_BACKUP_SAMPLES_TESTS=true to enable the test."; + + public string EncryptedDatabaseId { get; private set; } + public string EncryptedBackupId { get; } = GenerateId("my-enc-backup-"); + // 'restore' is abbreviated to prevent the name from becoming longer than 30 characters. + public string EncryptedRestoreDatabaseId { get; private set; } + + // These are intentionally kept on the instance to avoid the need to create a new encrypted database and backup for each run. + public string FixedEncryptedDatabaseId { get; } = "fixed-enc-backup-db"; + public string FixedEncryptedBackupId { get; } = "fixed-enc-backup"; + + public string MRCMEKDatabaseId { get; private set; } + public string MRCMEKBackupId { get; } = GenerateId("my-mr-cmek-backup-"); + // 'restore' is abbreviated to prevent the name from becoming longer than 30 characters. + public string MRCMEKRestoreDatabaseId { get; private set; } + + // These are intentionally kept on the instance to avoid the need to create a new encrypted database and backup for each run. + public string FixedMRCMEKDatabaseId { get; } = "fixed-mr-cmek-backup-db"; + public string FixedMRCMEKBackupId { get; } = "fixed-mr-cmek-backup"; + + public CryptoKeyName KmsKeyName { get; } = new CryptoKeyName( + Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), + Environment.GetEnvironmentVariable("spanner.test.key.location") ?? "us-central1", + Environment.GetEnvironmentVariable("spanner.test.key.ring") ?? "spanner-test-keyring", + Environment.GetEnvironmentVariable("spanner.test.key.name") ?? "spanner-test-key"); + public CryptoKeyName KmsKeyName2 { get; } = new CryptoKeyName( + Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), + Environment.GetEnvironmentVariable("spanner.test.key.location2") ?? "us-east1", + Environment.GetEnvironmentVariable("spanner.test.key.ring2") ?? "spanner-test-keyring2", + Environment.GetEnvironmentVariable("spanner.test.key.name2") ?? "spanner-test-key2"); + public CryptoKeyName KmsKeyName3 { get; } = new CryptoKeyName( + Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), + Environment.GetEnvironmentVariable("spanner.test.key.location3") ?? "us-east4", + Environment.GetEnvironmentVariable("spanner.test.key.ring3") ?? "spanner-test-keyring3", + Environment.GetEnvironmentVariable("spanner.test.key.name3") ?? "spanner-test-key3"); + public CryptoKeyName[] KmsKeyNames = {KmsKeyName, KmsKeyName2, KmsKeyName3}; + + public string InstanceIdWithProcessingUnits { get; } = GenerateId("my-ins-pu-"); + public string InstanceIdWithMultiRegion { get; } = GenerateId("my-ins-mr-"); + public string InstanceConfigId { get; } = "nam6"; + + private IList TempDbIds { get; } = new List(); + + public DatabaseAdminClient DatabaseAdminClient { get; private set; } + public InstanceAdminClient InstanceAdminClient { get; private set; } + public SpannerConnection AdminSpannerConnection { get; private set; } + public SpannerConnection SpannerConnection { get; private set; } + public SpannerConnection PgSpannerConnection { get; private set; } + + public RetryRobot Retryable { get; } = new RetryRobot + { + ShouldRetry = ex => ex.IsTransientSpannerFault() + }; + + public async Task InitializeAsync() + { + DatabaseId = Environment.GetEnvironmentVariable("TEST_SPANNER_DATABASE") ?? GenerateTempDatabaseId(); + PostgreSqlDatabaseId = Environment.GetEnvironmentVariable("TEST_SPANNER_POSTGRESQL_DATABASE") ?? GenerateTempDatabaseId("my-db-pg-"); + RestoredDatabaseId = GenerateTempDatabaseId("my-restore-db-"); + EncryptedDatabaseId = GenerateTempDatabaseId("my-enc-db-"); + EncryptedRestoreDatabaseId = GenerateTempDatabaseId("my-enc-r-db-"); + MRCMEKDatabaseId = GenerateTempDatabaseId("my-mr-cmek-db-"); + MRCMEKRestoreDatabaseId = GenerateTempDatabaseId("my-mr-cmek-r-db-"); + + DatabaseAdminClient = await DatabaseAdminClient.CreateAsync(); + InstanceAdminClient = await InstanceAdminClient.CreateAsync(); + AdminSpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}"); + SpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{DatabaseId}"); + PgSpannerConnection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{PostgreSqlDatabaseId}"); + + bool.TryParse(Environment.GetEnvironmentVariable("RUN_SPANNER_CMEK_BACKUP_SAMPLES_TESTS"), out var runCmekBackupSampleTests); + RunCmekBackupSampleTests = runCmekBackupSampleTests; + + await InitializeInstanceAsync(); + await CreateInstanceWithMultiRegionAsync(); + await InitializeDatabaseAsync(); + await InitializeBackupAsync(); + await InitializePostgreSqlDatabaseAsync(); + + // Create encryption key for creating an encrypted database and optionally backing up and restoring an encrypted database. + await InitializeEncryptionKeys(); + if (RunCmekBackupSampleTests) + { + await InitializeEncryptedBackupAsync(); + await InitializeMRCMEKBackupAsync(); + } + } + + public async Task DisposeAsync() + { + try + { + IList cleanupTasks = new List(); + + cleanupTasks.Add(DeleteInstanceAsync(InstanceIdWithMultiRegion)); + cleanupTasks.Add(DeleteInstanceAsync(InstanceIdWithProcessingUnits)); + + cleanupTasks.Add(DeleteBackupAsync(ToBeCancelledBackupId)); + cleanupTasks.Add(DeleteBackupAsync(EncryptedBackupId)); + cleanupTasks.Add(DeleteBackupAsync(MRCMEKBackupId)); + + DeleteInstanceConfig(CreateCustomInstanceConfigId); + DeleteInstanceConfig(UpdateCustomInstanceConfigId); + DeleteInstanceConfig(DeleteCustomInstanceConfigId); + + foreach (string id in TempDbIds) + { + cleanupTasks.Add(DeleteDatabaseAsync(id)); + } + + await Task.WhenAll(cleanupTasks); + } + finally + { + AdminSpannerConnection?.Dispose(); + SpannerConnection?.Dispose(); + PgSpannerConnection?.Dispose(); + } + } + + private void DeleteInstanceConfig(string instanceConfigId) + { + InstanceAdminClient instanceAdminClient = InstanceAdminClient.Create(); + var instanceConfigName = new InstanceConfigName(ProjectId, instanceConfigId); + + try + { + instanceAdminClient.DeleteInstanceConfig(new DeleteInstanceConfigRequest + { + InstanceConfigName = instanceConfigName + }); + } + catch (Exception) + { + // Silently ignore errors to prevent tests from failing. + } + } + + private async Task InitializeInstanceAsync() + { + InstanceName instanceName = InstanceName.FromProjectInstance(ProjectId, InstanceId); + try + { + Instance response = await InstanceAdminClient.GetInstanceAsync(instanceName); + return true; + } + catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) + { + CreateInstanceSample createInstanceSample = new CreateInstanceSample(); + await SafeCreateInstanceAsync(() => Task.FromResult(createInstanceSample.CreateInstance(ProjectId, InstanceId))); + return false; + } + } + + private async Task CreateInstanceWithMultiRegionAsync() + { + var projectName = ProjectName.FromProject(ProjectId); + Instance instance = new Instance + { + DisplayName = "Multi-region samples test", + ConfigAsInstanceConfigName = InstanceConfigName.FromProjectInstanceConfig(ProjectId, InstanceConfigId), + InstanceName = InstanceName.FromProjectInstance(ProjectId, InstanceIdWithMultiRegion), + NodeCount = 1, + }; + + await SafeCreateInstanceAsync(async () => + { + var response = await InstanceAdminClient.CreateInstanceAsync(projectName, InstanceIdWithMultiRegion, instance); + // Poll until the returned long-running operation is complete + response = await response.PollUntilCompletedAsync(); + return response.Result; + }); + } + + private async Task InitializeDatabaseAsync() + { + // If the database has not been initialized, retry. + CreateDatabaseAsyncSample createDatabaseAsyncSample = new CreateDatabaseAsyncSample(); + InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); + InsertStructSampleDataAsyncSample insertStructSampleDataAsyncSample = new InsertStructSampleDataAsyncSample(); + AddColumnAsyncSample addColumnAsyncSample = new AddColumnAsyncSample(); + AddCommitTimestampAsyncSample addCommitTimestampAsyncSample = new AddCommitTimestampAsyncSample(); + AddIndexAsyncSample addIndexAsyncSample = new AddIndexAsyncSample(); + AddStoringIndexAsyncSample addStoringIndexAsyncSample = new AddStoringIndexAsyncSample(); + CreateTableWithDataTypesAsyncSample createTableWithDataTypesAsyncSample = new CreateTableWithDataTypesAsyncSample(); + InsertDataTypesDataAsyncSample insertDataTypesDataAsyncSample = new InsertDataTypesDataAsyncSample(); + CreateTableWithTimestampColumnAsyncSample createTableWithTimestampColumnAsyncSample = + new CreateTableWithTimestampColumnAsyncSample(); + await createDatabaseAsyncSample.CreateDatabaseAsync(ProjectId, InstanceId, DatabaseId); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, DatabaseId); + await insertStructSampleDataAsyncSample.InsertStructSampleDataAsync(ProjectId, InstanceId, DatabaseId); + await addColumnAsyncSample.AddColumnAsync(ProjectId, InstanceId, DatabaseId); + await addCommitTimestampAsyncSample.AddCommitTimestampAsync(ProjectId, InstanceId, DatabaseId); + await addIndexAsyncSample.AddIndexAsync(ProjectId, InstanceId, DatabaseId); + // Create a new table that includes supported datatypes. + await createTableWithDataTypesAsyncSample.CreateTableWithDataTypesAsync(ProjectId, InstanceId, DatabaseId); + // Write data to the new table. + await insertDataTypesDataAsyncSample.InsertDataTypesDataAsync(ProjectId, InstanceId, DatabaseId); + // Add storing Index on table. + await addStoringIndexAsyncSample.AddStoringIndexAsync(ProjectId, InstanceId, DatabaseId); + // Update the value of MarketingBudgets. + await RefillMarketingBudgetsAsync(300000, 300000); + // Create table with Timestamp column + await createTableWithTimestampColumnAsyncSample.CreateTableWithTimestampColumnAsync(ProjectId, InstanceId, DatabaseId); + } + public async Task InitializeTempDatabaseAsync(string databaseId) { InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); AddColumnAsyncSample addColumnAsyncSample = new AddColumnAsyncSample(); await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, databaseId); await addColumnAsyncSample.AddColumnAsync(ProjectId, InstanceId, databaseId); - } - - private async Task InitializeBackupAsync() - { - // Sample database for backup and restore tests. - try - { - CreateDatabaseAsyncSample createDatabaseAsyncSample = new CreateDatabaseAsyncSample(); - InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseAsync(ProjectId, InstanceId, BackupDatabaseId); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, BackupDatabaseId); - } - catch (Exception e) when (e.ToString().Contains("Database already exists")) - { - // We intentionally keep an existing database around to reduce - // the likelihood of test timeouts when creating a backup so - // it's ok to get an AlreadyExists error. - Console.WriteLine($"Database {BackupDatabaseId} already exists."); - } - - try - { - CreateBackupSample createBackupSample = new CreateBackupSample(); - createBackupSample.CreateBackup(ProjectId, InstanceId, BackupDatabaseId, BackupId, DateTime.UtcNow.AddMilliseconds(-500)); - } - catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) - { - // We intentionally keep an existing backup around to reduce - // the likelihood of test timeouts when creating a backup so - // it's ok to get an AlreadyExists error. - Console.WriteLine($"Backup {BackupId} already exists."); - } - catch (RpcException e) when (e.StatusCode == StatusCode.FailedPrecondition - && e.Message.Contains("maximum number of pending backups (1) for the database has been reached")) - { - // It's ok backup has been in progress in another test cycle. - Console.WriteLine($"Backup {BackupId} already in progress."); - } - } - - private async Task InitializePostgreSqlDatabaseAsync() - { - CreateDatabaseAsyncPostgresSample createDatabaseAsyncSample = new CreateDatabaseAsyncPostgresSample(); - await createDatabaseAsyncSample.CreateDatabaseAsyncPostgres(ProjectId, InstanceId, PostgreSqlDatabaseId); - await CreateVenueTablesAndInsertDataAsyncPostgres(); - } - - private async Task InitializeEncryptionKeys() - { - var client = await KeyManagementServiceClient.CreateAsync(); - var keyRingName = KeyRingName.FromProjectLocationKeyRing(KmsKeyName.ProjectId, KmsKeyName.LocationId, KmsKeyName.KeyRingId); - try - { - await client.GetKeyRingAsync(keyRingName); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateKeyRingAsync(new CreateKeyRingRequest - { - ParentAsLocationName = LocationName.FromProjectLocation(keyRingName.ProjectId, keyRingName.LocationId), - KeyRingId = KmsKeyName.KeyRingId, - KeyRing = new KeyRing(), - }); - } - - var keyName = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName.ProjectId, KmsKeyName.LocationId, KmsKeyName.KeyRingId, KmsKeyName.CryptoKeyId); - try - { - await client.GetCryptoKeyAsync(keyName); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest - { - ParentAsKeyRingName = keyRingName, - CryptoKeyId = keyName.CryptoKeyId, - CryptoKey = new CryptoKey - { - Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, - }, - }); - } - } - - private async Task InitializeEncryptedBackupAsync() - { - // Sample backup for encrypted restore test. - try - { - CreateDatabaseWithEncryptionKeyAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithEncryptionKeyAsyncSample(); - InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseWithEncryptionKeyAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId, KmsKeyName); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId); - } - catch (Exception e) when (e.ToString().Contains("Database already exists")) - { - // We intentionally keep an existing database around to reduce - // the likelihood of test timeouts when creating a backup so - // it's ok to get an AlreadyExists error. - Console.WriteLine($"Database {FixedEncryptedDatabaseId} already exists."); - } - - try - { - CreateBackupWithEncryptionKeyAsyncSample createBackupSample = new CreateBackupWithEncryptionKeyAsyncSample(); - await createBackupSample.CreateBackupWithEncryptionKeyAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId, FixedEncryptedBackupId, KmsKeyName); - } - catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) - { - // We intentionally keep an existing backup around to reduce - // the likelihood of test timeouts when creating a backup so - // it's ok to get an AlreadyExists error. - Console.WriteLine($"Backup {FixedEncryptedBackupId} already exists."); - } - } - - private async Task DeleteInstanceAsync(string instanceId) - { - try - { - await InstanceAdminClient.DeleteInstanceAsync(InstanceName.FromProjectInstance(ProjectId, instanceId)); - } - catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) - { - Console.WriteLine($"Instance {instanceId} was not found for deletion."); - } - catch (Exception ex) - { - Console.WriteLine($"Exception while attempting to delete instance {instanceId}"); - Console.WriteLine(ex); - } - } - - private async Task DeleteBackupAsync(string backupId) - { - try - { - await DatabaseAdminClient.DeleteBackupAsync(BackupName.FromProjectInstanceBackup(ProjectId, InstanceId, backupId)); - } - catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) - { - Console.WriteLine($"Backup {backupId} was not found for deletion."); - } - catch (Exception ex) - { - Console.WriteLine($"Exception while attempting to delete backup {backupId}"); - Console.WriteLine(ex); - } - } - - private async Task DeleteDatabaseAsync(string databaseId) - { - try - { - using var cmd = AdminSpannerConnection.CreateDdlCommand($@"DROP DATABASE {databaseId}"); - await cmd.ExecuteNonQueryAsync(); - } - catch (Exception ex) - { - Console.WriteLine($"Exception while attempting to delete database {databaseId}"); - Console.WriteLine(ex); - } - } - + } + + private async Task InitializeBackupAsync() + { + // Sample database for backup and restore tests. + try + { + CreateDatabaseAsyncSample createDatabaseAsyncSample = new CreateDatabaseAsyncSample(); + InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); + await createDatabaseAsyncSample.CreateDatabaseAsync(ProjectId, InstanceId, BackupDatabaseId); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, BackupDatabaseId); + } + catch (Exception e) when (e.ToString().Contains("Database already exists")) + { + // We intentionally keep an existing database around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Database {BackupDatabaseId} already exists."); + } + + try + { + CreateBackupSample createBackupSample = new CreateBackupSample(); + createBackupSample.CreateBackup(ProjectId, InstanceId, BackupDatabaseId, BackupId, DateTime.UtcNow.AddMilliseconds(-500)); + } + catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) + { + // We intentionally keep an existing backup around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Backup {BackupId} already exists."); + } + catch (RpcException e) when (e.StatusCode == StatusCode.FailedPrecondition + && e.Message.Contains("maximum number of pending backups (1) for the database has been reached")) + { + // It's ok backup has been in progress in another test cycle. + Console.WriteLine($"Backup {BackupId} already in progress."); + } + } + + private async Task InitializePostgreSqlDatabaseAsync() + { + CreateDatabaseAsyncPostgresSample createDatabaseAsyncSample = new CreateDatabaseAsyncPostgresSample(); + await createDatabaseAsyncSample.CreateDatabaseAsyncPostgres(ProjectId, InstanceId, PostgreSqlDatabaseId); + await CreateVenueTablesAndInsertDataAsyncPostgres(); + } + + private async Task InitializeEncryptionKeys() + { + var client = await KeyManagementServiceClient.CreateAsync(); + var keyRingName = KeyRingName.FromProjectLocationKeyRing(KmsKeyName.ProjectId, KmsKeyName.LocationId, KmsKeyName.KeyRingId); + try + { + await client.GetKeyRingAsync(keyRingName); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateKeyRingAsync(new CreateKeyRingRequest + { + ParentAsLocationName = LocationName.FromProjectLocation(keyRingName.ProjectId, keyRingName.LocationId), + KeyRingId = KmsKeyName.KeyRingId, + KeyRing = new KeyRing(), + }); + } + var keyRingName2 = KeyRingName.FromProjectLocationKeyRing(KmsKeyName2.ProjectId, KmsKeyName2.LocationId, KmsKeyName2.KeyRingId); + try + { + await client.GetKeyRingAsync(keyRingName2); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateKeyRingAsync(new CreateKeyRingRequest + { + ParentAsLocationName = LocationName.FromProjectLocation(keyRingName2.ProjectId, keyRingName2.LocationId), + KeyRingId = KmsKeyName2.KeyRingId, + KeyRing = new KeyRing(), + }); + } + var keyRingName3 = KeyRingName.FromProjectLocationKeyRing(KmsKeyName3.ProjectId, KmsKeyName3.LocationId, KmsKeyName3.KeyRingId); + try + { + await client.GetKeyRingAsync(keyRingName3); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateKeyRingAsync(new CreateKeyRingRequest + { + ParentAsLocationName = LocationName.FromProjectLocation(keyRingName3.ProjectId, keyRingName3.LocationId), + KeyRingId = KmsKeyName3.KeyRingId, + KeyRing = new KeyRing(), + }); + } + + var keyName = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName.ProjectId, KmsKeyName.LocationId, KmsKeyName.KeyRingId, KmsKeyName.CryptoKeyId); + try + { + await client.GetCryptoKeyAsync(keyName); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest + { + ParentAsKeyRingName = keyRingName, + CryptoKeyId = keyName.CryptoKeyId, + CryptoKey = new CryptoKey + { + Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, + }, + }); + } + var keyName2 = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName2.ProjectId, KmsKeyName2.LocationId, KmsKeyName2.KeyRingId, KmsKeyName2.CryptoKeyId); + try + { + await client.GetCryptoKeyAsync(keyName2); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest + { + ParentAsKeyRingName = keyRingName2, + CryptoKeyId = keyName2.CryptoKeyId, + CryptoKey = new CryptoKey + { + Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, + }, + }); + } + var keyName3 = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName3.ProjectId, KmsKeyName3.LocationId, KmsKeyName3.KeyRingId, KmsKeyName3.CryptoKeyId); + try + { + await client.GetCryptoKeyAsync(keyName3); + } + catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) + { + await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest + { + ParentAsKeyRingName = keyRingName3, + CryptoKeyId = keyName3.CryptoKeyId, + CryptoKey = new CryptoKey + { + Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, + }, + }); + } + } + + private async Task InitializeEncryptedBackupAsync() + { + // Sample backup for encrypted restore test. + try + { + CreateDatabaseWithEncryptionKeyAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithEncryptionKeyAsyncSample(); + InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); + await createDatabaseAsyncSample.CreateDatabaseWithEncryptionKeyAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId, KmsKeyName); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId); + } + catch (Exception e) when (e.ToString().Contains("Database already exists")) + { + // We intentionally keep an existing database around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Database {FixedEncryptedDatabaseId} already exists."); + } + + try + { + CreateBackupWithEncryptionKeyAsyncSample createBackupSample = new CreateBackupWithEncryptionKeyAsyncSample(); + await createBackupSample.CreateBackupWithEncryptionKeyAsync(ProjectId, InstanceId, FixedEncryptedDatabaseId, FixedEncryptedBackupId, KmsKeyName); + } + catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) + { + // We intentionally keep an existing backup around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Backup {FixedEncryptedBackupId} already exists."); + } + } + + private async Task InitializeMRCMEKBackupAsync() + { + // Sample backup for MR CMEK restore test. + try + { + CreateDatabaseWithMRCMEKAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithMRCMEKAsyncSample(); + InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); + await createDatabaseAsyncSample.CreateDatabaseWithMRCMEKAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId, KmsKeyNames); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId); + } + catch (Exception e) when (e.ToString().Contains("Database already exists")) + { + // We intentionally keep an existing database around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Database {FixedMRCMEKDatabaseId} already exists."); + } + + try + { + CreateBackupWithMRCMEKAsyncSample createBackupSample = new CreateBackupWithMRCMEKAsyncSample(); + await createBackupSample.CreateBackupWithMRCMEKAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId, FixedMRCMEKBackupId, KmsKeyNames); + } + catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) + { + // We intentionally keep an existing backup around to reduce + // the likelihood of test timeouts when creating a backup so + // it's ok to get an AlreadyExists error. + Console.WriteLine($"Backup {FixedMRCMEKBackupId} already exists."); + } + } + + private async Task DeleteInstanceAsync(string instanceId) + { + try + { + await InstanceAdminClient.DeleteInstanceAsync(InstanceName.FromProjectInstance(ProjectId, instanceId)); + } + catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) + { + Console.WriteLine($"Instance {instanceId} was not found for deletion."); + } + catch (Exception ex) + { + Console.WriteLine($"Exception while attempting to delete instance {instanceId}"); + Console.WriteLine(ex); + } + } + + private async Task DeleteBackupAsync(string backupId) + { + try + { + await DatabaseAdminClient.DeleteBackupAsync(BackupName.FromProjectInstanceBackup(ProjectId, InstanceId, backupId)); + } + catch (RpcException ex) when (ex.Status.StatusCode == StatusCode.NotFound) + { + Console.WriteLine($"Backup {backupId} was not found for deletion."); + } + catch (Exception ex) + { + Console.WriteLine($"Exception while attempting to delete backup {backupId}"); + Console.WriteLine(ex); + } + } + + private async Task DeleteDatabaseAsync(string databaseId) + { + try + { + using var cmd = AdminSpannerConnection.CreateDdlCommand($@"DROP DATABASE {databaseId}"); + await cmd.ExecuteNonQueryAsync(); + } + catch (Exception ex) + { + Console.WriteLine($"Exception while attempting to delete database {databaseId}"); + Console.WriteLine(ex); + } + } + public static string GenerateId(string prefix, int maxLength = 30) => // Guid.ToString("N") returns a string of 32 digits. - $"{prefix}{Guid.NewGuid().ToString("N").Substring(prefix.Length + (32 - maxLength))}"; - - public string GenerateTempDatabaseId(string prefix = "my-db-") - { - string tempDatabaseId = GenerateId(prefix); - TempDbIds.Add(tempDatabaseId); - return tempDatabaseId; - } - - private static readonly string s_retryInfoMetadataKey = RetryInfo.Descriptor.FullName + "-bin"; - public async Task SafeCreateInstanceAsync(Func> createInstanceAsync) - { - int attempt = 0; - do - { - try - { - attempt++; - return await createInstanceAsync(); - } - catch (RpcException ex) when (attempt <= 10) - { - if (StatusCode.Unavailable == ex.StatusCode) - { - await RecommendedDelayAsync(ex); - } - else if (StatusCode.ResourceExhausted == ex.StatusCode && ex.Status.Detail.Contains("requests per minute")) - { - await RecommendedDelayAsync(ex, 60); - } - else - { - throw; - } - } - } - while (true); - - static async Task RecommendedDelayAsync(RpcException exception, int fallbackSeconds = 5) - { - TimeSpan delay = TimeSpan.FromSeconds(fallbackSeconds); - var retryInfoEntry = exception.Trailers.FirstOrDefault( - entry => s_retryInfoMetadataKey.Equals(entry.Key, StringComparison.InvariantCultureIgnoreCase)); - if (retryInfoEntry != null) - { - var retryInfo = RetryInfo.Parser.ParseFrom(retryInfoEntry.ValueBytes); - var recommended = retryInfo.RetryDelay.ToTimeSpan(); - if (recommended != TimeSpan.Zero) - { - delay = recommended; - } - } - await Task.Delay(delay); - } - } - - public async Task RunWithTemporaryDatabaseAsync(Func testFunction, params string[] extraStatements) - => await RunWithTemporaryDatabaseAsync(InstanceId, testFunction, extraStatements); - - public async Task RunWithTemporaryDatabaseAsync(string instanceId, Func testFunction, - params string[] extraStatements) - { - // For temporary DBs we don't need a time based ID, as we delete them inmediately. - var databaseId = GenerateId("temp-db-"); - await RunWithTemporaryDatabaseAsync(instanceId, databaseId, testFunction, extraStatements); - } - - public async Task RunWithTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction, params string[] extraStatements) - => await RunWithTemporaryDatabaseAsync(instanceId, databaseId, testFunction, DatabaseDialect.GoogleStandardSql, extraStatements); - - private async Task RunWithTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction, DatabaseDialect databaseDialect, params string[] extraStatements) - { + $"{prefix}{Guid.NewGuid().ToString("N").Substring(prefix.Length + (32 - maxLength))}"; + + public string GenerateTempDatabaseId(string prefix = "my-db-") + { + string tempDatabaseId = GenerateId(prefix); + TempDbIds.Add(tempDatabaseId); + return tempDatabaseId; + } + + private static readonly string s_retryInfoMetadataKey = RetryInfo.Descriptor.FullName + "-bin"; + public async Task SafeCreateInstanceAsync(Func> createInstanceAsync) + { + int attempt = 0; + do + { + try + { + attempt++; + return await createInstanceAsync(); + } + catch (RpcException ex) when (attempt <= 10) + { + if (StatusCode.Unavailable == ex.StatusCode) + { + await RecommendedDelayAsync(ex); + } + else if (StatusCode.ResourceExhausted == ex.StatusCode && ex.Status.Detail.Contains("requests per minute")) + { + await RecommendedDelayAsync(ex, 60); + } + else + { + throw; + } + } + } + while (true); + + static async Task RecommendedDelayAsync(RpcException exception, int fallbackSeconds = 5) + { + TimeSpan delay = TimeSpan.FromSeconds(fallbackSeconds); + var retryInfoEntry = exception.Trailers.FirstOrDefault( + entry => s_retryInfoMetadataKey.Equals(entry.Key, StringComparison.InvariantCultureIgnoreCase)); + if (retryInfoEntry != null) + { + var retryInfo = RetryInfo.Parser.ParseFrom(retryInfoEntry.ValueBytes); + var recommended = retryInfo.RetryDelay.ToTimeSpan(); + if (recommended != TimeSpan.Zero) + { + delay = recommended; + } + } + await Task.Delay(delay); + } + } + + public async Task RunWithTemporaryDatabaseAsync(Func testFunction, params string[] extraStatements) + => await RunWithTemporaryDatabaseAsync(InstanceId, testFunction, extraStatements); + + public async Task RunWithTemporaryDatabaseAsync(string instanceId, Func testFunction, + params string[] extraStatements) + { + // For temporary DBs we don't need a time based ID, as we delete them inmediately. + var databaseId = GenerateId("temp-db-"); + await RunWithTemporaryDatabaseAsync(instanceId, databaseId, testFunction, extraStatements); + } + + public async Task RunWithTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction, params string[] extraStatements) + => await RunWithTemporaryDatabaseAsync(instanceId, databaseId, testFunction, DatabaseDialect.GoogleStandardSql, extraStatements); + + private async Task RunWithTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction, DatabaseDialect databaseDialect, params string[] extraStatements) + { if(databaseDialect == DatabaseDialect.Postgresql && extraStatements?.Length >=1) { throw new ArgumentException("Postgres does not accept extra statements for DB creation"); - } - var databaseCreateRequest = new CreateDatabaseRequest - { - ParentAsInstanceName = InstanceName.FromProjectInstance(ProjectId, instanceId), - CreateStatement = databaseDialect == DatabaseDialect.GoogleStandardSql ? $"CREATE DATABASE `{databaseId}`" : $"CREATE DATABASE \"{databaseId}\"", - DatabaseDialect = databaseDialect, - }; + } + var databaseCreateRequest = new CreateDatabaseRequest + { + ParentAsInstanceName = InstanceName.FromProjectInstance(ProjectId, instanceId), + CreateStatement = databaseDialect == DatabaseDialect.GoogleStandardSql ? $"CREATE DATABASE `{databaseId}`" : $"CREATE DATABASE \"{databaseId}\"", + DatabaseDialect = databaseDialect, + }; if (databaseDialect == DatabaseDialect.GoogleStandardSql) { databaseCreateRequest.ExtraStatements.Add(extraStatements); - } - + } + var operation = await DatabaseAdminClient.CreateDatabaseAsync(databaseCreateRequest); - var completedResponse = await operation.PollUntilCompletedAsync(); - if (completedResponse.IsFaulted) - { - throw completedResponse.Exception; - } - - try - { - await testFunction(databaseId); - } - finally - { - // Cleanup the test database. - await DatabaseAdminClient.DropDatabaseAsync(DatabaseName.FormatProjectInstanceDatabase(ProjectId, instanceId, databaseId)); - } + var completedResponse = await operation.PollUntilCompletedAsync(); + if (completedResponse.IsFaulted) + { + throw completedResponse.Exception; + } + + try + { + await testFunction(databaseId); + } + finally + { + // Cleanup the test database. + await DatabaseAdminClient.DropDatabaseAsync(DatabaseName.FormatProjectInstanceDatabase(ProjectId, instanceId, databaseId)); + } } public async Task RunWithPostgresqlTemporaryDatabaseAsync(Func testFunction) => @@ -528,117 +646,117 @@ public async Task RunWithPostgresqlTemporaryDatabaseAsync(string instanceId, Fun { var databaseId = GenerateTempDatabaseId(); await RunWithPostgresqlTemporaryDatabaseAsync(instanceId, databaseId, testFunction); - } - - public async Task RunWithPostgresqlTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction) => + } + + public async Task RunWithPostgresqlTemporaryDatabaseAsync(string instanceId, string databaseId, Func testFunction) => await RunWithTemporaryDatabaseAsync(instanceId, databaseId, testFunction, DatabaseDialect.Postgresql); - - public async Task CreateVenuesTableAndInsertDataAsync(string databaseId) - { - // Create connection to Cloud Spanner. - using var connection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{databaseId}"); - - // Define create table statement for Venues. - string createTableStatement = - @"CREATE TABLE Venues ( - VenueId INT64 NOT NULL, - VenueName STRING(1024), - ) PRIMARY KEY (VenueId)"; - - using var cmd = connection.CreateDdlCommand(createTableStatement); - await cmd.ExecuteNonQueryAsync(); - - int[] ids = new int[] { 4, 19, 42 }; - await Task.WhenAll(ids.Select(id => - { - // Insert rows into the Venues table. - - using var cmd = connection.CreateInsertCommand("Venues", new SpannerParameterCollection - { - { "VenueId", SpannerDbType.Int64, id }, - { "VenueName", SpannerDbType.String, $"Venue {id}" } - }); - return cmd.ExecuteNonQueryAsync(); - })); - } - - public async Task CreateSingersAndAlbumsTableAsync(string projectId, string instanceId, string databaseId) - { + + public async Task CreateVenuesTableAndInsertDataAsync(string databaseId) + { + // Create connection to Cloud Spanner. + using var connection = new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{databaseId}"); + + // Define create table statement for Venues. + string createTableStatement = + @"CREATE TABLE Venues ( + VenueId INT64 NOT NULL, + VenueName STRING(1024), + ) PRIMARY KEY (VenueId)"; + + using var cmd = connection.CreateDdlCommand(createTableStatement); + await cmd.ExecuteNonQueryAsync(); + + int[] ids = new int[] { 4, 19, 42 }; + await Task.WhenAll(ids.Select(id => + { + // Insert rows into the Venues table. + + using var cmd = connection.CreateInsertCommand("Venues", new SpannerParameterCollection + { + { "VenueId", SpannerDbType.Int64, id }, + { "VenueName", SpannerDbType.String, $"Venue {id}" } + }); + return cmd.ExecuteNonQueryAsync(); + })); + } + + public async Task CreateSingersAndAlbumsTableAsync(string projectId, string instanceId, string databaseId) + { using var connection = new SpannerConnection($"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"); - ; - var createSingersTable = - @"CREATE TABLE Singers ( - SingerId INT64 NOT NULL, - FirstName STRING(1024), - LastName STRING(1024), - ComposerInfo BYTES(MAX), - FullName STRING(2048) AS (ARRAY_TO_STRING([FirstName, LastName], "" "")) STORED - ) PRIMARY KEY (SingerId)"; - - var createAlbumsTable = - @"CREATE TABLE Albums ( - SingerId INT64 NOT NULL, - AlbumId INT64 NOT NULL, - AlbumTitle STRING(MAX), - MarketingBudget INT64 - ) PRIMARY KEY (SingerId, AlbumId), - INTERLEAVE IN PARENT Singers ON DELETE CASCADE"; - - using var createDdlCommand = connection.CreateDdlCommand(createSingersTable, createAlbumsTable); - await createDdlCommand.ExecuteNonQueryAsync(); - } - - public async Task RefillMarketingBudgetsAsync(int firstAlbumBudget, int secondAlbumBudget, string databaseId = null) - { - var spannerConnection = databaseId is null ? SpannerConnection : new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{databaseId}"); - for (int i = 1; i <= 2; ++i) - { - var cmd = spannerConnection.CreateUpdateCommand("Albums", new SpannerParameterCollection - { - { "SingerId", SpannerDbType.Int64, i }, - { "AlbumId", SpannerDbType.Int64, i }, - { "MarketingBudget", SpannerDbType.Int64, i == 1 ? firstAlbumBudget : secondAlbumBudget }, - }); - await cmd.ExecuteNonQueryAsync(); - } - } - - public IEnumerable GetDatabases() - { - InstanceName instanceName = InstanceName.FromProjectInstance(ProjectId, InstanceId); - var databases = DatabaseAdminClient.ListDatabases(instanceName); - return databases; - } - - private async Task CreateVenueTablesAndInsertDataAsyncPostgres() - { - // We create VenueInformation table so that update and query jsonb data sample can run out of order. - - // Define create table statement for VenueInformation. - const string createVenueInformationTableStatement = - @"CREATE TABLE VenueInformation ( - VenueId BIGINT NOT NULL PRIMARY KEY, - VenueName VARCHAR(1024), - Details JSONB)"; - - await CreateTableAsyncPostgres(createVenueInformationTableStatement); - - // Insert data in VenueInformation table. - int[] ids = new int[] { 4, 19, 42 }; - await Task.WhenAll(ids.Select(id => - { - using var cmd = PgSpannerConnection.CreateInsertCommand("VenueInformation", new SpannerParameterCollection - { - { "VenueId", SpannerDbType.Int64, id }, - { "VenueName", SpannerDbType.String, $"Venue {id}" } - }); - return cmd.ExecuteNonQueryAsync(); - })); - } - - public async Task CreateTableAsyncPostgres(string createTableStatement) - { - using var cmd = PgSpannerConnection.CreateDdlCommand(createTableStatement); - await cmd.ExecuteNonQueryAsync(); - } -} + ; + var createSingersTable = + @"CREATE TABLE Singers ( + SingerId INT64 NOT NULL, + FirstName STRING(1024), + LastName STRING(1024), + ComposerInfo BYTES(MAX), + FullName STRING(2048) AS (ARRAY_TO_STRING([FirstName, LastName], "" "")) STORED + ) PRIMARY KEY (SingerId)"; + + var createAlbumsTable = + @"CREATE TABLE Albums ( + SingerId INT64 NOT NULL, + AlbumId INT64 NOT NULL, + AlbumTitle STRING(MAX), + MarketingBudget INT64 + ) PRIMARY KEY (SingerId, AlbumId), + INTERLEAVE IN PARENT Singers ON DELETE CASCADE"; + + using var createDdlCommand = connection.CreateDdlCommand(createSingersTable, createAlbumsTable); + await createDdlCommand.ExecuteNonQueryAsync(); + } + + public async Task RefillMarketingBudgetsAsync(int firstAlbumBudget, int secondAlbumBudget, string databaseId = null) + { + var spannerConnection = databaseId is null ? SpannerConnection : new SpannerConnection($"Data Source=projects/{ProjectId}/instances/{InstanceId}/databases/{databaseId}"); + for (int i = 1; i <= 2; ++i) + { + var cmd = spannerConnection.CreateUpdateCommand("Albums", new SpannerParameterCollection + { + { "SingerId", SpannerDbType.Int64, i }, + { "AlbumId", SpannerDbType.Int64, i }, + { "MarketingBudget", SpannerDbType.Int64, i == 1 ? firstAlbumBudget : secondAlbumBudget }, + }); + await cmd.ExecuteNonQueryAsync(); + } + } + + public IEnumerable GetDatabases() + { + InstanceName instanceName = InstanceName.FromProjectInstance(ProjectId, InstanceId); + var databases = DatabaseAdminClient.ListDatabases(instanceName); + return databases; + } + + private async Task CreateVenueTablesAndInsertDataAsyncPostgres() + { + // We create VenueInformation table so that update and query jsonb data sample can run out of order. + + // Define create table statement for VenueInformation. + const string createVenueInformationTableStatement = + @"CREATE TABLE VenueInformation ( + VenueId BIGINT NOT NULL PRIMARY KEY, + VenueName VARCHAR(1024), + Details JSONB)"; + + await CreateTableAsyncPostgres(createVenueInformationTableStatement); + + // Insert data in VenueInformation table. + int[] ids = new int[] { 4, 19, 42 }; + await Task.WhenAll(ids.Select(id => + { + using var cmd = PgSpannerConnection.CreateInsertCommand("VenueInformation", new SpannerParameterCollection + { + { "VenueId", SpannerDbType.Int64, id }, + { "VenueName", SpannerDbType.String, $"Venue {id}" } + }); + return cmd.ExecuteNonQueryAsync(); + })); + } + + public async Task CreateTableAsyncPostgres(string createTableStatement) + { + using var cmd = PgSpannerConnection.CreateDdlCommand(createTableStatement); + await cmd.ExecuteNonQueryAsync(); + } +} From dd5a28a23623359b4ae8021f67c2752131d73ac3 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:47:16 -0700 Subject: [PATCH 18/66] Update and rename CopyBackupWithMRCMEKTest.cs to CopyBackupWithMrCmekTest.cs Change naming from MRCMEK to MrCmek --- ...upWithMRCMEKTest.cs => CopyBackupWithMrCmekTest.cs} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename spanner/api/Spanner.Samples.Tests/{CopyBackupWithMRCMEKTest.cs => CopyBackupWithMrCmekTest.cs} (80%) diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs similarity index 80% rename from spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs rename to spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs index 62d9bfb5aa0..966f6456daf 100644 --- a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMRCMEKTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs @@ -17,19 +17,19 @@ using Xunit; [Collection(nameof(SpannerFixture))] -public class CopyBackupWithMRCMEKTest +public class CopyBackupWithMrCmekTest { private readonly SpannerFixture _spannerFixture; - public CopyBackupWithMRCMEKTest(SpannerFixture spannerFixture) + public CopyBackupWithMrCmekTest(SpannerFixture spannerFixture) { _spannerFixture = spannerFixture; } [Fact] - public void CopyBackupWithMRCMEK() + public void CopyBackupWithMrCmek() { - CopyBackupWithMRCMEKSample copyBackupWithMRCMEKSample = new CopyBackupWithMRCMEKSample(); + CopyBackupWithMrCmekSample copyBackupWithMrCmekSample = new CopyBackupWithMrCmekSample(); string source_Project_id = _spannerFixture.ProjectId; string source_Instance_id = _spannerFixture.InstanceId; string source_backupId = _spannerFixture.BackupId; @@ -39,7 +39,7 @@ public void CopyBackupWithMRCMEK() DateTimeOffset expireTime = DateTimeOffset.UtcNow.AddHours(12); CryptoKeyName[] kmsKeyNames = _fixture.KmsKeyNames; - Backup backup = copyBackupWithMRCMEKSample.CopyBackupWithMRCMEK(source_Instance_id, source_Project_id, source_backupId, + Backup backup = copyBackupWithMrCmekSample.CopyBackupWithMrCmek(source_Instance_id, source_Project_id, source_backupId, target_Instance_id, target_Project_id, target_backupId, expireTime, kmsKeyNames); Assert.NotNull(backup); From 197ef1590086b297f79d03dcbbb341c8219df3d9 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:51:21 -0700 Subject: [PATCH 19/66] Update and rename CreateBackupWithMRCMEKAsyncTest.cs to CreateBackupWithMrCmekAsyncTest.cs Change naming from MRCMEK to MrCmek --- ...AsyncTest.cs => CreateBackupWithMrCmekAsyncTest.cs} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename spanner/api/Spanner.Samples.Tests/{CreateBackupWithMRCMEKAsyncTest.cs => CreateBackupWithMrCmekAsyncTest.cs} (83%) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs similarity index 83% rename from spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs rename to spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index 86095f993f9..d8c61ae5cc2 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMRCMEKAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -20,22 +20,22 @@ /// Tests creating a backup using MR CMEK. /// [Collection(nameof(SpannerFixture))] -public class CreateBackupWithMRCMEKAsyncTest +public class CreateBackupWithMrCmekAsyncTest { private readonly SpannerFixture _fixture; - public CreateBackupWithMRCMEKAsyncTest(SpannerFixture fixture) + public CreateBackupWithMrCmekAsyncTest(SpannerFixture fixture) { _fixture = fixture; } [SkippableFact] - public async Task TestCreatBackupWithMRCMEKAsync() + public async Task TestCreatBackupWithMrCmekAsync() { Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); // Create a backup with custom encryption keys. - var sample = new CreateBackupWithMRCMEKAsyncSample(); - var backup = await sample.CreateBackupWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedEncryptedDatabaseId, _fixture.EncryptedBackupId, _fixture.KmsKeyNames); + var sample = new CreateBackupWithMrCmekAsyncSample(); + var backup = await sample.CreateBackupWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedEncryptedDatabaseId, _fixture.EncryptedBackupId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames.Length); foreach (CryptoKeyVersionName KmsKeyVersion in backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames) { From bffdead04903228476d9aec5b1334edc2d8935e0 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:04:42 -0700 Subject: [PATCH 20/66] Update and rename CreateDatabaseWithMRCMEKAsyncTest.cs to CreateDatabaseWithMrCmekAsyncTest.cs Change from MRCMEK to MrCmek --- ...yncTest.cs => CreateDatabaseWithMrCmekAsyncTest.cs} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename spanner/api/Spanner.Samples.Tests/{CreateDatabaseWithMRCMEKAsyncTest.cs => CreateDatabaseWithMrCmekAsyncTest.cs} (81%) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs similarity index 81% rename from spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs rename to spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index 0f6effa2816..a664f4e7625 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMRCMEKAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -20,21 +20,21 @@ /// Tests creating a databases using MR CMEK. /// [Collection(nameof(SpannerFixture))] -public class CreateDatabaseWithMRCMEKAsyncTest +public class CreateDatabaseWithMrCmekAsyncTest { private readonly SpannerFixture _fixture; - public CreateDatabaseWithMRCMEKAsyncTest(SpannerFixture fixture) + public CreateDatabaseWithMrCmekAsyncTest(SpannerFixture fixture) { _fixture = fixture; } [Fact] - public async Task TestCreateDatabaseWithMRCMEKAsync() + public async Task TestCreateDatabaseWithMrCmekAsync() { // Create a database with custom encryption keys. - var sample = new CreateDatabaseWithMRCMEKAsyncSample(); - var database = await sample.CreateDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); + var sample = new CreateDatabaseWithMrCmekAsyncSample(); + var database = await sample.CreateDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) { From f426968ac4d4286c773727bba42aef646b8d5c25 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:07:05 -0700 Subject: [PATCH 21/66] Update and rename RestoreDatabaseWithMRCMEKAsyncTest.cs to RestoreDatabaseWithMrCmekAsyncTest.cs Change from MRCMEK to MrCmek --- ...ncTest.cs => RestoreDatabaseWithMrCmekAsyncTest.cs} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename spanner/api/Spanner.Samples.Tests/{RestoreDatabaseWithMRCMEKAsyncTest.cs => RestoreDatabaseWithMrCmekAsyncTest.cs} (83%) diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs similarity index 83% rename from spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs rename to spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs index c9e8c3735e6..b4a5d0e1c0c 100644 --- a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMRCMEKAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs @@ -21,21 +21,21 @@ /// Tests restoring a databases using customer managed encryption. /// [Collection(nameof(SpannerFixture))] -public class RestoreDatabaseWithMRCMEKAsyncTest +public class RestoreDatabaseWithMrCmekAsyncTest { private readonly SpannerFixture _fixture; - public RestoreDatabaseWithMRCMEKAsyncTest(SpannerFixture fixture) + public RestoreDatabaseWithMrCmekAsyncTest(SpannerFixture fixture) { _fixture = fixture; } [SkippableFact] - public async Task TestRestoreDatabaseWithMRCMEKAsync() + public async Task TestRestoreDatabaseWithMrCmekAsync() { Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); - var sample = new RestoreDatabaseWithMRCMEKAsyncSample(); - var database = await sample.RestoreDatabaseWithMRCMEKAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedRestoreDatabaseId, _fixture.FixedEncryptedBackupId, _fixture.KmsKeyName); + var sample = new RestoreDatabaseWithMrCmekAsyncSample(); + var database = await sample.RestoreDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedRestoreDatabaseId, _fixture.FixedEncryptedBackupId, _fixture.KmsKeyName); Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) { From 93ee32cb653b9722de725fe780384b4b1f54739b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:08:44 -0700 Subject: [PATCH 22/66] Update and rename CopyBackupWithMRCMEK.cs to CopyBackupWithMrCmek.cs Change from MRCMEK to MrCmek --- .../{CopyBackupWithMRCMEK.cs => CopyBackupWithMrCmek.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename spanner/api/Spanner.Samples/{CopyBackupWithMRCMEK.cs => CopyBackupWithMrCmek.cs} (96%) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs similarity index 96% rename from spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs rename to spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index 3523d39e749..41fb6d4c83f 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMRCMEK.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -20,9 +20,9 @@ using Google.Protobuf.WellKnownTypes; using System; -public class CopyBackupWithMRCMEKSample +public class CopyBackupWithMrCmekSample { - public Backup CopyBackupWithMRCMEK(string sourceInstanceId, string sourceProjectId, string sourceBackupId, + public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProjectId, string sourceBackupId, string targetInstanceId, string targetProjectId, string targetBackupId, DateTimeOffset expireTime, CryptoKeyName[] kmsKeyNames) { From 194b59c4e3853996d39a287b1bd88c6c415ddc0b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:10:13 -0700 Subject: [PATCH 23/66] Update and rename CreateBackupWithMRCMEKAsync.cs to CreateBackupWithMrCmekAsync.cs Change from MRCMEK to MrCmek --- ...ackupWithMRCMEKAsync.cs => CreateBackupWithMrCmekAsync.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename spanner/api/Spanner.Samples/{CreateBackupWithMRCMEKAsync.cs => CreateBackupWithMrCmekAsync.cs} (96%) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs similarity index 96% rename from spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs rename to spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index 456a8ac9412..e7278bf098d 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -20,9 +20,9 @@ using System; using System.Threading.Tasks; -public class CreateBackupWithMRCMEKAsyncSample +public class CreateBackupWithMrCmekAsyncSample { - public async Task CreateBackupWithMRCMEKAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) + public async Task CreateBackupWithMrCmekAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) { // Create a DatabaseAdminClient instance. DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); From 5a487bb7682f414f98c1debff8d878f88e0e1ba1 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:11:33 -0700 Subject: [PATCH 24/66] Update and rename CreateDatabaseWithMRCMEKAsync.cs to CreateDatabaseWithMrCmekAsync.cs Change from MRCMEK to MrCmek --- ...aseWithMRCMEKAsync.cs => CreateDatabaseWithMrCmekAsync.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename spanner/api/Spanner.Samples/{CreateDatabaseWithMRCMEKAsync.cs => CreateDatabaseWithMrCmekAsync.cs} (96%) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs similarity index 96% rename from spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs rename to spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs index 124ff7f2d36..414ebd5230f 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs @@ -19,9 +19,9 @@ using System; using System.Threading.Tasks; -public class CreateDatabaseWithMRCMEKAsyncSample +public class CreateDatabaseWithMrCmekAsyncSample { - public async Task CreateDatabaseWithMRCMEKAsync(string projectId, string instanceId, string databaseId, CryptoKeyName[] kmsKeyNames) + public async Task CreateDatabaseWithMrCmekAsync(string projectId, string instanceId, string databaseId, CryptoKeyName[] kmsKeyNames) { // Create a DatabaseAdminClient instance that can be used to execute a // CreateDatabaseRequest with custom encryption configuration options. From 6b07ecf406fd1dde6c081c0283f017020b5b65a4 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:12:16 -0700 Subject: [PATCH 25/66] Update and rename RestoreDatabaseWithMRCMEKAsync.cs to RestoreDatabaseWithMrCmekAsync.cs Change from MRCMEK to MrCmek --- ...seWithMRCMEKAsync.cs => RestoreDatabaseWithMrCmekAsync.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename spanner/api/Spanner.Samples/{RestoreDatabaseWithMRCMEKAsync.cs => RestoreDatabaseWithMrCmekAsync.cs} (95%) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs similarity index 95% rename from spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs rename to spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs index f4786bfcab6..2ae29745b8a 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMRCMEKAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs @@ -19,9 +19,9 @@ using System; using System.Threading.Tasks; -public class RestoreDatabaseWithMRCMEKAsyncSample +public class RestoreDatabaseWithMrCmekAsyncSample { - public async Task RestoreDatabaseWithMRCMEKAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) + public async Task RestoreDatabaseWithMrCmekAsync(string projectId, string instanceId, string databaseId, string backupId, CryptoKeyName[] kmsKeyNames) { // Create a DatabaseAdminClient instance. DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); From 00b30760109f0a4b7a4b2b9a421c450f447972e1 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:13:39 -0700 Subject: [PATCH 26/66] Update CopyBackupWithMrCmekTest.cs Update copyright --- spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs index 966f6456daf..34b5754b765 100644 --- a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs @@ -1,4 +1,4 @@ -// Copyright 2022 Google Inc. +// 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. From b3b8330909f2b710157aac78fc270e93707c1043 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:13:59 -0700 Subject: [PATCH 27/66] Update CreateBackupWithMrCmekAsyncTest.cs Update copyright --- .../Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index d8c61ae5cc2..693d56a6e57 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From 99672895c9fdf766bc46837534fefdf7320c878d Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:14:14 -0700 Subject: [PATCH 28/66] Update CreateDatabaseWithMrCmekAsyncTest.cs Update copyright --- .../Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index a664f4e7625..8cd9f8a9c60 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From 9f3348115dec32cacd447fd11207d5d85649c339 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:14:26 -0700 Subject: [PATCH 29/66] Update RestoreDatabaseWithMrCmekAsyncTest.cs Update copyright --- .../Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs index b4a5d0e1c0c..4f35434f7c1 100644 --- a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From 187157f6e0ef884cba479d7e8ba94ade69cdfb4b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:14:38 -0700 Subject: [PATCH 30/66] Update CopyBackupWithMrCmek.cs Update copyright --- spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index 41fb6d4c83f..89fcd8dd638 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -1,4 +1,4 @@ -// Copyright 2022 Google Inc. +// 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. From d37be25ce0d0f5c6e9037af60578c2daf587fd1b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:14:57 -0700 Subject: [PATCH 31/66] Update CreateBackupWithMrCmekAsync.cs Update copyright --- spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index e7278bf098d..25dfae14c30 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From 68a2f8635a02ce51e4295b14bf2bbf6de15a49a0 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:15:16 -0700 Subject: [PATCH 32/66] Update CreateDatabaseWithMrCmekAsync.cs Update copyright --- spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs index 414ebd5230f..2a5ac817d49 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From d405eb7ef92e6ebb3bb9833135c41bef2545f2d2 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:15:42 -0700 Subject: [PATCH 33/66] Update RestoreDatabaseWithMrCmekAsync.cs Update copyright --- spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs index 2ae29745b8a..e29b5e7790a 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2021 Google Inc. +// 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. From f32a8c125c25efd00dbdb2d070f5dfb1b4d90a38 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:04:05 -0700 Subject: [PATCH 34/66] Update CopyBackupWithMrCmekTest.cs Use MrCmekBackupId --- spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs index 34b5754b765..a7d0f6d1597 100644 --- a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs @@ -32,7 +32,7 @@ public void CopyBackupWithMrCmek() CopyBackupWithMrCmekSample copyBackupWithMrCmekSample = new CopyBackupWithMrCmekSample(); string source_Project_id = _spannerFixture.ProjectId; string source_Instance_id = _spannerFixture.InstanceId; - string source_backupId = _spannerFixture.BackupId; + string source_backupId = _spannerFixture.MrCmekBackupId; string target_Project_id = _spannerFixture.ProjectId; string target_Instance_id = _spannerFixture.InstanceId; string target_backupId = SpannerFixture.GenerateId("test_", 16); From fe995c0b62885d8abc6136b4531dd1c996d67703 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:06:22 -0700 Subject: [PATCH 35/66] Update CreateBackupWithMrCmekAsyncTest.cs Use FixedMrCmekDatabaseId and MrCmekBackupId --- .../Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index 693d56a6e57..fc491a4e88a 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -35,7 +35,7 @@ public async Task TestCreatBackupWithMrCmekAsync() Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); // Create a backup with custom encryption keys. var sample = new CreateBackupWithMrCmekAsyncSample(); - var backup = await sample.CreateBackupWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedEncryptedDatabaseId, _fixture.EncryptedBackupId, _fixture.KmsKeyNames); + var backup = await sample.CreateBackupWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedMrCmekDatabaseId, _fixture.MrCmekBackupId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames.Length); foreach (CryptoKeyVersionName KmsKeyVersion in backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames) { From e740ee98cb2f5a12ba09c331b3d1fa3d8c154207 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:07:27 -0700 Subject: [PATCH 36/66] Update CreateDatabaseWithMrCmekAsyncTest.cs Use MrCmekDatabaseId --- .../Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index 8cd9f8a9c60..56ea108fdd6 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -34,7 +34,7 @@ public async Task TestCreateDatabaseWithMrCmekAsync() { // Create a database with custom encryption keys. var sample = new CreateDatabaseWithMrCmekAsyncSample(); - var database = await sample.CreateDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedDatabaseId, _fixture.KmsKeyNames); + var database = await sample.CreateDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.MrCmekDatabaseId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) { From e548d4991b1e4747f876fc919b9861610c6e2377 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:09:47 -0700 Subject: [PATCH 37/66] Update RestoreDatabaseWithMrCmekAsyncTest.cs Use MrCmekRestoreDatabaseId and FixedMrCmekBackupId. Use KmsKeyNames instead of KmsKeyName --- .../Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs index 4f35434f7c1..f136f5633c7 100644 --- a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs @@ -35,7 +35,7 @@ public async Task TestRestoreDatabaseWithMrCmekAsync() { Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); var sample = new RestoreDatabaseWithMrCmekAsyncSample(); - var database = await sample.RestoreDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.EncryptedRestoreDatabaseId, _fixture.FixedEncryptedBackupId, _fixture.KmsKeyName); + var database = await sample.RestoreDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.MrCmekRestoreDatabaseId, _fixture.FixedMrCmekBackupId, _fixture.KmsKeyNames); Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) { From 46eeb4b004eaeaf23698d88741f2187691e9f52e Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:12:31 -0700 Subject: [PATCH 38/66] Update CopyBackupWithMrCmek.cs Use default poll settings --- spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index 89fcd8dd638..d48b4e5257f 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -43,7 +43,7 @@ public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProject var response = databaseAdminClient.CopyBackup(request); Console.WriteLine("Waiting for the operation to finish."); - var completedResponse = response.PollUntilCompleted(new PollSettings(Expiration.FromTimeout(TimeSpan.FromMinutes(15)), TimeSpan.FromMinutes(2))); + var completedResponse = await operation.PollUntilCompletedAsync(); if (completedResponse.IsFaulted) { From 16f0b198c43a2fd536d281201846b6db982fade5 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:15:44 -0700 Subject: [PATCH 39/66] Update CopyBackupWithMrCmek.cs Change log --- spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index d48b4e5257f..da34044c5b6 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -55,7 +55,7 @@ public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProject Console.WriteLine($"Backup created successfully."); Console.WriteLine($"Backup with Id {sourceBackupId} has been copied from {sourceProjectId}/{sourceInstanceId} to {targetProjectId}/{targetInstanceId} Backup {targetBackupId}"); - Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {0} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}", string.Join(", ", kmsKeyNames)); + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", kmsKeyNames)} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}" ); return backup; } From 40591ac5044e48d2070b0ee2b91b85fdb2f9ee06 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:17:02 -0700 Subject: [PATCH 40/66] Update CreateBackupWithMrCmekAsync.cs Change log --- spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index 25dfae14c30..50b1a31bc58 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -60,6 +60,7 @@ public async Task CreateBackupWithMrCmekAsync(string projectId, string i Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes " + $"was created at {backup.CreateTime} " + $"using encryption keys {0}", string.Join(", ", kmsKeyNames)); + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", kmsKeyNames)} at {backup.CreateTime}" ); return backup; } } From 266ca6035200c265ca07ebfaecdfa868f16282cc Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:17:32 -0700 Subject: [PATCH 41/66] Update CreateBackupWithMrCmekAsync.cs Remove old log --- spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index 50b1a31bc58..dc02f8eecbf 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -57,9 +57,6 @@ public async Task CreateBackupWithMrCmekAsync(string projectId, string i } var backup = completedResponse.Result; - Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes " + - $"was created at {backup.CreateTime} " + - $"using encryption keys {0}", string.Join(", ", kmsKeyNames)); Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", kmsKeyNames)} at {backup.CreateTime}" ); return backup; } From a34244e2d7cfdb56e8e278eaf129ec872d87f4d2 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:18:40 -0700 Subject: [PATCH 42/66] Update CreateDatabaseWithMrCmekAsync.cs Change log --- spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs index 2a5ac817d49..645d54c35c6 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs @@ -66,7 +66,7 @@ AlbumTitle STRING(MAX) } var database = completedResponse.Result; - Console.WriteLine($"Database {database.Name} created with encryption keys {0}", string.Join(", ", database.EncryptionConfig.KmsKeyNames)); + Console.WriteLine($"Database {database.Name} created with encryption keys {string.Join(", ", kmsKeyNames)}" ); return database; } From dcd1750629e97f722648535d537676a6c830863a Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:22:12 -0700 Subject: [PATCH 43/66] Update RestoreDatabaseWithMrCmekAsync.cs Change logs --- .../api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs index e29b5e7790a..19382c1c200 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs @@ -53,10 +53,7 @@ public async Task RestoreDatabaseWithMrCmekAsync(string projectId, str var database = completedResponse.Result; var restoreInfo = database.RestoreInfo; - Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} " + - $"restored to {database.Name} " + - $"from backup {restoreInfo.BackupInfo.Backup} " + - $"using encryption keys {$0}", string.Join(", ", database.EncryptionConfig.KmsKeyNames)); + Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} restored to {database.Name} from backup {restoreInfo.BackupInfo.Backup} using encryption keys {string.Join(", ", kmsKeyNames)}" ); return database; } } From ef7265d318b53a4640f9ed141d77a5618d3e9860 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:24:20 -0700 Subject: [PATCH 44/66] Update CopyBackupWithMrCmekTest.cs Assert keys match --- spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs index a7d0f6d1597..83004d73dea 100644 --- a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs @@ -42,6 +42,6 @@ public void CopyBackupWithMrCmek() Backup backup = copyBackupWithMrCmekSample.CopyBackupWithMrCmek(source_Instance_id, source_Project_id, source_backupId, target_Instance_id, target_Project_id, target_backupId, expireTime, kmsKeyNames); - Assert.NotNull(backup); + Assert.All(backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames, keyName => _fixture.KmsKeyNames.Contains(keyName.CryptoKeyId)); } } From 2c5683dc22cf7dc490a09dd8a10cdfb8ea820ecd Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:24:58 -0700 Subject: [PATCH 45/66] Update CreateBackupWithMrCmekAsyncTest.cs Change assert --- .../CreateBackupWithMrCmekAsyncTest.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index fc491a4e88a..ba18d7d46d9 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -36,10 +36,6 @@ public async Task TestCreatBackupWithMrCmekAsync() // Create a backup with custom encryption keys. var sample = new CreateBackupWithMrCmekAsyncSample(); var backup = await sample.CreateBackupWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedMrCmekDatabaseId, _fixture.MrCmekBackupId, _fixture.KmsKeyNames); - Assert.Equal(_fixture.KmsKeyNames.Length, backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames.Length); - foreach (CryptoKeyVersionName KmsKeyVersion in backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames) - { - Assert.True(_fixture.KmsKeyNames.contains(KmsKeyVersion.CryptoKeyId)); - } + Assert.All(backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames, keyName => _fixture.KmsKeyNames.Contains(keyName.CryptoKeyId)); } } From 919b655f49edefa792466db6cada41b842b845c3 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:27:13 -0700 Subject: [PATCH 46/66] Update CreateDatabaseWithMrCmekAsyncTest.cs Change assert --- .../Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index 56ea108fdd6..a4d1e6662b0 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -40,5 +40,6 @@ public async Task TestCreateDatabaseWithMrCmekAsync() { Assert.True(_fixture.KmsKeyNames.contains(CryptoKeyName.Parse(KmsKey))); } + Assert.All(database.EncryptionConfig.KmsKeyNames, keyName => _fixture.KmsKeyNames.Contains(CryptoKeyName.Parse(keyName))); } } From 9c729d908c286b1f034e8221d6b9b243743da857 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:27:29 -0700 Subject: [PATCH 47/66] Update CreateDatabaseWithMrCmekAsyncTest.cs Remove old assert --- .../CreateDatabaseWithMrCmekAsyncTest.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index a4d1e6662b0..0aea3f3e68e 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -35,11 +35,6 @@ public async Task TestCreateDatabaseWithMrCmekAsync() // Create a database with custom encryption keys. var sample = new CreateDatabaseWithMrCmekAsyncSample(); var database = await sample.CreateDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.MrCmekDatabaseId, _fixture.KmsKeyNames); - Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); - foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) - { - Assert.True(_fixture.KmsKeyNames.contains(CryptoKeyName.Parse(KmsKey))); - } Assert.All(database.EncryptionConfig.KmsKeyNames, keyName => _fixture.KmsKeyNames.Contains(CryptoKeyName.Parse(keyName))); } } From c0be0ff10ebc605dd4e9133b5a49b96c8e71aad1 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:28:46 -0700 Subject: [PATCH 48/66] Update RestoreDatabaseWithMrCmekAsyncTest.cs Change assert --- .../RestoreDatabaseWithMrCmekAsyncTest.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs index f136f5633c7..390bfa8d505 100644 --- a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs @@ -36,10 +36,6 @@ public async Task TestRestoreDatabaseWithMrCmekAsync() Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); var sample = new RestoreDatabaseWithMrCmekAsyncSample(); var database = await sample.RestoreDatabaseWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.MrCmekRestoreDatabaseId, _fixture.FixedMrCmekBackupId, _fixture.KmsKeyNames); - Assert.Equal(_fixture.KmsKeyNames.Length, database.EncryptionConfig.KmsKeyNames.Length); - foreach (string KmsKey in database.EncryptionConfig.KmsKeyNames) - { - Assert.True(_fixture.KmsKeyNames.contains(CryptoKeyName.Parse(KmsKey))); - } + Assert.All(database.EncryptionConfig.KmsKeyNames, keyName => _fixture.KmsKeyNames.Contains(CryptoKeyName.Parse(keyName))); } } From 3a5bf85d31b025c3b2e4391c527fd4f247751b3d Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:40:42 -0700 Subject: [PATCH 49/66] Update SpannerFixture.cs Fix naming --- .../Spanner.Samples.Tests/SpannerFixture.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs index 2129467a9c2..dabcfe6103c 100644 --- a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs +++ b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs @@ -72,14 +72,14 @@ AlbumTitle STRING(MAX) public string FixedEncryptedDatabaseId { get; } = "fixed-enc-backup-db"; public string FixedEncryptedBackupId { get; } = "fixed-enc-backup"; - public string MRCMEKDatabaseId { get; private set; } - public string MRCMEKBackupId { get; } = GenerateId("my-mr-cmek-backup-"); + public string MrCmekDatabaseId { get; private set; } + public string MrCmekBackupId { get; } = GenerateId("my-mr-cmek-backup-"); // 'restore' is abbreviated to prevent the name from becoming longer than 30 characters. - public string MRCMEKRestoreDatabaseId { get; private set; } + public string MrCmekRestoreDatabaseId { get; private set; } // These are intentionally kept on the instance to avoid the need to create a new encrypted database and backup for each run. - public string FixedMRCMEKDatabaseId { get; } = "fixed-mr-cmek-backup-db"; - public string FixedMRCMEKBackupId { get; } = "fixed-mr-cmek-backup"; + public string FixedMrCmekDatabaseId { get; } = "fixed-mr-cmek-backup-db"; + public string FixedMrCmekBackupId { get; } = "fixed-mr-cmek-backup"; public CryptoKeyName KmsKeyName { get; } = new CryptoKeyName( Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), @@ -122,8 +122,8 @@ public async Task InitializeAsync() RestoredDatabaseId = GenerateTempDatabaseId("my-restore-db-"); EncryptedDatabaseId = GenerateTempDatabaseId("my-enc-db-"); EncryptedRestoreDatabaseId = GenerateTempDatabaseId("my-enc-r-db-"); - MRCMEKDatabaseId = GenerateTempDatabaseId("my-mr-cmek-db-"); - MRCMEKRestoreDatabaseId = GenerateTempDatabaseId("my-mr-cmek-r-db-"); + MrCmekDatabaseId = GenerateTempDatabaseId("my-mr-cmek-db-"); + MrCmekRestoreDatabaseId = GenerateTempDatabaseId("my-mr-cmek-r-db-"); DatabaseAdminClient = await DatabaseAdminClient.CreateAsync(); InstanceAdminClient = await InstanceAdminClient.CreateAsync(); @@ -145,7 +145,7 @@ public async Task InitializeAsync() if (RunCmekBackupSampleTests) { await InitializeEncryptedBackupAsync(); - await InitializeMRCMEKBackupAsync(); + await InitializeMrCmekBackupAsync(); } } @@ -160,7 +160,7 @@ public async Task DisposeAsync() cleanupTasks.Add(DeleteBackupAsync(ToBeCancelledBackupId)); cleanupTasks.Add(DeleteBackupAsync(EncryptedBackupId)); - cleanupTasks.Add(DeleteBackupAsync(MRCMEKBackupId)); + cleanupTasks.Add(DeleteBackupAsync(MrCmekBackupId)); DeleteInstanceConfig(CreateCustomInstanceConfigId); DeleteInstanceConfig(UpdateCustomInstanceConfigId); @@ -451,35 +451,35 @@ private async Task InitializeEncryptedBackupAsync() } } - private async Task InitializeMRCMEKBackupAsync() + private async Task InitializeMrCmekBackupAsync() { // Sample backup for MR CMEK restore test. try { - CreateDatabaseWithMRCMEKAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithMRCMEKAsyncSample(); + CreateDatabaseWithMrCmekAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithMrCmekAsyncSample(); InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseWithMRCMEKAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId, KmsKeyNames); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId); + await createDatabaseAsyncSample.CreateDatabaseWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, KmsKeyNames); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId); } catch (Exception e) when (e.ToString().Contains("Database already exists")) { // We intentionally keep an existing database around to reduce // the likelihood of test timeouts when creating a backup so // it's ok to get an AlreadyExists error. - Console.WriteLine($"Database {FixedMRCMEKDatabaseId} already exists."); + Console.WriteLine($"Database {FixedMrCmekDatabaseId} already exists."); } try { - CreateBackupWithMRCMEKAsyncSample createBackupSample = new CreateBackupWithMRCMEKAsyncSample(); - await createBackupSample.CreateBackupWithMRCMEKAsync(ProjectId, InstanceId, FixedMRCMEKDatabaseId, FixedMRCMEKBackupId, KmsKeyNames); + CreateBackupWithMrCmekAsyncSample createBackupSample = new CreateBackupWithMrCmekAsyncSample(); + await createBackupSample.CreateBackupWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, FixedMrCmekBackupId, KmsKeyNames); } catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) { // We intentionally keep an existing backup around to reduce // the likelihood of test timeouts when creating a backup so // it's ok to get an AlreadyExists error. - Console.WriteLine($"Backup {FixedMRCMEKBackupId} already exists."); + Console.WriteLine($"Backup {FixedMrCmekBackupId} already exists."); } } From b826e31afc7c87a785f93c11e2ffa1b129b6846d Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:50:17 -0700 Subject: [PATCH 50/66] Update CreateDatabaseWithMrCmekAsync.cs Change kmsKeyNames to { kmsKeyNames } --- spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs index 645d54c35c6..c64318f417f 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs @@ -51,7 +51,7 @@ AlbumTitle STRING(MAX) ExtraStatements = { createSingersTable, createAlbumsTable }, EncryptionConfig = new EncryptionConfig { - KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = { kmsKeyNames }, }, }; var operation = await databaseAdminClient.CreateDatabaseAsync(request); From 775114d7f8981e3eb6d4ee824f7bed310ca2820e Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:51:17 -0700 Subject: [PATCH 51/66] Update CreateBackupWithMrCmekAsync.cs Change kmsKeyNames to { kmsKeyNames } --- spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index dc02f8eecbf..f483c1161c2 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -40,7 +40,7 @@ public async Task CreateBackupWithMrCmekAsync(string projectId, string i EncryptionConfig = new CreateBackupEncryptionConfig { EncryptionType = CreateBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = { kmsKeyNames }, }, }; // Execute the CreateBackup request. From 36b23158d25bc0520b2a79054041d526bad15d28 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:51:57 -0700 Subject: [PATCH 52/66] Update CopyBackupWithMrCmek.cs Change kmsKeyNames to { kmsKeyNames } --- spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index da34044c5b6..59b7929f205 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -37,7 +37,7 @@ public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProject EncryptionConfig = new CopyBackupEncryptionConfig { EncryptionType = CopyBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = { kmsKeyNames }, } }; From f2c5d364bcfedd7d4df2de3fe0f5903ed4e23659 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:52:29 -0700 Subject: [PATCH 53/66] Update RestoreDatabaseWithMrCmekAsync.cs Change kmsKeyNames to { kmsKeyNames } --- spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs index 19382c1c200..2d9060c966a 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs @@ -35,7 +35,7 @@ public async Task RestoreDatabaseWithMrCmekAsync(string projectId, str EncryptionConfig = new RestoreDatabaseEncryptionConfig { EncryptionType = RestoreDatabaseEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, - KmsKeyNamesAsCryptoKeyNames = kmsKeyNames, + KmsKeyNamesAsCryptoKeyNames = { kmsKeyNames }, } }; // Execute the RestoreDatabase request. From 53e08c2317adf09d27410d4393b12bab75539c1a Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:54:55 -0700 Subject: [PATCH 54/66] Update RestoreDatabaseWithMrCmekAsync.cs Make join explicit, fix format --- spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs index 2d9060c966a..889f4a5a8ed 100644 --- a/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/RestoreDatabaseWithMrCmekAsync.cs @@ -53,7 +53,7 @@ public async Task RestoreDatabaseWithMrCmekAsync(string projectId, str var database = completedResponse.Result; var restoreInfo = database.RestoreInfo; - Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} restored to {database.Name} from backup {restoreInfo.BackupInfo.Backup} using encryption keys {string.Join(", ", kmsKeyNames)}" ); + Console.WriteLine($"Database {restoreInfo.BackupInfo.SourceDatabase} restored to {database.Name} from backup {restoreInfo.BackupInfo.Backup} using encryption keys {string.Join(", ", (object[]) kmsKeyNames)}"); return database; } } From 45781a9085e513600dd0fdb13d99137bd77ce0f0 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:56:12 -0700 Subject: [PATCH 55/66] Update CreateBackupWithMrCmekAsync.cs Make join explicit, fix formatting --- spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs index f483c1161c2..64bf08b81be 100644 --- a/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateBackupWithMrCmekAsync.cs @@ -57,7 +57,7 @@ public async Task CreateBackupWithMrCmekAsync(string projectId, string i } var backup = completedResponse.Result; - Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", kmsKeyNames)} at {backup.CreateTime}" ); + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", (object[]) kmsKeyNames)} at {backup.CreateTime}"); return backup; } } From 6f2197524e0cd1d6113d457e01e8dad59eb9a7dc Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:56:55 -0700 Subject: [PATCH 56/66] Update CreateDatabaseWithMrCmekAsync.cs Make join explicit, fix formatting --- spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs index c64318f417f..4f00238e017 100644 --- a/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs +++ b/spanner/api/Spanner.Samples/CreateDatabaseWithMrCmekAsync.cs @@ -66,7 +66,7 @@ AlbumTitle STRING(MAX) } var database = completedResponse.Result; - Console.WriteLine($"Database {database.Name} created with encryption keys {string.Join(", ", kmsKeyNames)}" ); + Console.WriteLine($"Database {database.Name} created with encryption keys {string.Join(", ", (object[]) kmsKeyNames)}"); return database; } From 5d8e65d6d0a08cab2804cc7327a9890f5a77b7a1 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:57:27 -0700 Subject: [PATCH 57/66] Update CopyBackupWithMrCmek.cs Make join explicit, fix formatting --- spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs index 59b7929f205..acbe1bdc7fc 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs @@ -55,7 +55,7 @@ public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProject Console.WriteLine($"Backup created successfully."); Console.WriteLine($"Backup with Id {sourceBackupId} has been copied from {sourceProjectId}/{sourceInstanceId} to {targetProjectId}/{targetInstanceId} Backup {targetBackupId}"); - Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", kmsKeyNames)} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}" ); + Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", (object[]) kmsKeyNames)} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}"); return backup; } From 3d11bb96d2f6fa631718cc55130037b584c8797b Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:03:25 -0700 Subject: [PATCH 58/66] Update and rename CopyBackupWithMrCmek.cs to CopyBackupWithMrCmekAsync.cs Change copy to async --- ...MrCmek.cs => CopyBackupWithMrCmekAsync.cs} | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) rename spanner/api/Spanner.Samples/{CopyBackupWithMrCmek.cs => CopyBackupWithMrCmekAsync.cs} (80%) diff --git a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs b/spanner/api/Spanner.Samples/CopyBackupWithMrCmekAsync.cs similarity index 80% rename from spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs rename to spanner/api/Spanner.Samples/CopyBackupWithMrCmekAsync.cs index acbe1bdc7fc..849a4fa694d 100644 --- a/spanner/api/Spanner.Samples/CopyBackupWithMrCmek.cs +++ b/spanner/api/Spanner.Samples/CopyBackupWithMrCmekAsync.cs @@ -19,21 +19,22 @@ using Google.Cloud.Spanner.Common.V1; using Google.Protobuf.WellKnownTypes; using System; +using System.Threading.Tasks; -public class CopyBackupWithMrCmekSample +public class CopyBackupWithMrCmekAsyncSample { - public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProjectId, string sourceBackupId, - string targetInstanceId, string targetProjectId, string targetBackupId, + public async Task CopyBackupWithMrCmekAsync(string sourceInstanceId, string sourceProjectId, string sourceBackupId, + string targetInstanceId, string targetProjectId, string targetBackupId, DateTimeOffset expireTime, CryptoKeyName[] kmsKeyNames) { DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.Create(); var request = new CopyBackupRequest { - SourceBackupAsBackupName = new BackupName(sourceProjectId, sourceInstanceId, sourceBackupId), + SourceBackupAsBackupName = new BackupName(sourceProjectId, sourceInstanceId, sourceBackupId), ParentAsInstanceName = new InstanceName(targetProjectId, targetInstanceId), BackupId = targetBackupId, - ExpireTime = Timestamp.FromDateTimeOffset(expireTime) , + ExpireTime = Timestamp.FromDateTimeOffset(expireTime), EncryptionConfig = new CopyBackupEncryptionConfig { EncryptionType = CopyBackupEncryptionConfig.Types.EncryptionType.CustomerManagedEncryption, @@ -41,19 +42,23 @@ public Backup CopyBackupWithMrCmek(string sourceInstanceId, string sourceProject } }; - var response = databaseAdminClient.CopyBackup(request); + // Execute the CopyBackup request. + var operation = await databaseAdminClient.CopyBackupAsync(request); + Console.WriteLine("Waiting for the operation to finish."); + + // Poll until the returned long-running operation is complete. var completedResponse = await operation.PollUntilCompletedAsync(); if (completedResponse.IsFaulted) { - Console.WriteLine($"Error while creating backup: {completedResponse.Exception}"); + Console.WriteLine($"Error while copying backup: {completedResponse.Exception}"); throw completedResponse.Exception; } Backup backup = completedResponse.Result; - Console.WriteLine($"Backup created successfully."); + Console.WriteLine($"Backup copied successfully."); Console.WriteLine($"Backup with Id {sourceBackupId} has been copied from {sourceProjectId}/{sourceInstanceId} to {targetProjectId}/{targetInstanceId} Backup {targetBackupId}"); Console.WriteLine($"Backup {backup.Name} of size {backup.SizeBytes} bytes was created with encryption keys {string.Join(", ", (object[]) kmsKeyNames)} at {backup.CreateTime} from {backup.Database} and is in state {backup.State} and has version time {backup.VersionTime.ToDateTime()}"); From 33f32a582d8d9d697a1c8236a033419f5ee2c7ca Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:16:48 -0700 Subject: [PATCH 59/66] Update SpannerFixture.cs Shorten names and use MR instance --- .../api/Spanner.Samples.Tests/SpannerFixture.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs index 10ff07fa0cd..37aff964575 100644 --- a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs +++ b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs @@ -73,13 +73,13 @@ AlbumTitle STRING(MAX) public string FixedEncryptedBackupId { get; } = "fixed-enc-backup"; public string MrCmekDatabaseId { get; private set; } - public string MrCmekBackupId { get; } = GenerateId("my-mr-cmek-backup-"); + public string MrCmekBackupId { get; } = GenerateId("my-mr-backup-"); // 'restore' is abbreviated to prevent the name from becoming longer than 30 characters. public string MrCmekRestoreDatabaseId { get; private set; } // These are intentionally kept on the instance to avoid the need to create a new encrypted database and backup for each run. - public string FixedMrCmekDatabaseId { get; } = "fixed-mr-cmek-backup-db"; - public string FixedMrCmekBackupId { get; } = "fixed-mr-cmek-backup"; + public string FixedMrCmekDatabaseId { get; } = "fixed-mr-backup-db"; + public string FixedMrCmekBackupId { get; } = "fixed-mr-backup"; public CryptoKeyName KmsKeyName { get; } = new CryptoKeyName( Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), @@ -123,8 +123,8 @@ public async Task InitializeAsync() RestoredDatabaseId = GenerateTempDatabaseId("my-restore-db-"); EncryptedDatabaseId = GenerateTempDatabaseId("my-enc-db-"); EncryptedRestoreDatabaseId = GenerateTempDatabaseId("my-enc-r-db-"); - MrCmekDatabaseId = GenerateTempDatabaseId("my-mr-cmek-db-"); - MrCmekRestoreDatabaseId = GenerateTempDatabaseId("my-mr-cmek-r-db-"); + MrCmekDatabaseId = GenerateTempDatabaseId("my-mr-db-"); + MrCmekRestoreDatabaseId = GenerateTempDatabaseId("my-mr-r-db-"); DatabaseAdminClient = await DatabaseAdminClient.CreateAsync(); InstanceAdminClient = await InstanceAdminClient.CreateAsync(); @@ -460,8 +460,8 @@ private async Task InitializeMrCmekBackupAsync() { CreateDatabaseWithMrCmekAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithMrCmekAsyncSample(); InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, KmsKeyNames); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId); + await createDatabaseAsyncSample.CreateDatabaseWithMrCmekAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId, KmsKeyNames); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId); } catch (Exception e) when (e.ToString().Contains("Database already exists")) { @@ -474,7 +474,7 @@ private async Task InitializeMrCmekBackupAsync() try { CreateBackupWithMrCmekAsyncSample createBackupSample = new CreateBackupWithMrCmekAsyncSample(); - await createBackupSample.CreateBackupWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, FixedMrCmekBackupId, KmsKeyNames); + await createBackupSample.CreateBackupWithMrCmekAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId, FixedMrCmekBackupId, KmsKeyNames); } catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) { From 03b6bcce6a5af28f57849c77b8171f1e99c57619 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:40:07 -0700 Subject: [PATCH 60/66] Update CreateBackupWithMrCmekAsyncTest.cs Fix Assert --- .../Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index ba18d7d46d9..dd54f9925f7 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Google.Cloud.Spanner.Admin.Database.V1; using System; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -36,6 +38,6 @@ public async Task TestCreatBackupWithMrCmekAsync() // Create a backup with custom encryption keys. var sample = new CreateBackupWithMrCmekAsyncSample(); var backup = await sample.CreateBackupWithMrCmekAsync(_fixture.ProjectId, _fixture.InstanceId, _fixture.FixedMrCmekDatabaseId, _fixture.MrCmekBackupId, _fixture.KmsKeyNames); - Assert.All(backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames, keyName => _fixture.KmsKeyNames.Contains(keyName.CryptoKeyId)); + Assert.All(backup.EncryptionInformation, encryptionInfo => _fixture.KmsKeyNames.Contains(CryptoKeyName.Parse(encryptionInfo.KmsKeyVersionAsCryptoKeyVersionName.CryptoKeyId))); } } From a63aa0e7484bdedfd4d2df49095665ddafbb46fe Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:40:41 -0700 Subject: [PATCH 61/66] Update CreateDatabaseWithMrCmekAsyncTest.cs Fix Assert --- .../Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs index 0aea3f3e68e..690e9e42929 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateDatabaseWithMrCmekAsyncTest.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using Xunit; using Google.Cloud.Spanner.Admin.Database.V1; +using System.Linq; /// /// Tests creating a databases using MR CMEK. From 1d14bb22b31497c8a0ac1ddc2c335f9940b5b969 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:41:13 -0700 Subject: [PATCH 62/66] Update RestoreDatabaseWithMrCmekAsyncTest.cs Fix Assert --- .../Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs index 390bfa8d505..b50133a2901 100644 --- a/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/RestoreDatabaseWithMrCmekAsyncTest.cs @@ -14,6 +14,7 @@ using Google.Cloud.Spanner.Admin.Database.V1; using System; +using System.Linq; using System.Threading.Tasks; using Xunit; From 8032f51772d392acc05fd9979a07066bd13278f5 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:45:15 -0700 Subject: [PATCH 63/66] Update and rename CopyBackupWithMrCmekTest.cs to CopyBackupWithMrCmekAsyncTest.cs Fix Assert --- ...st.cs => CopyBackupWithMrCmekAsyncTest.cs} | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) rename spanner/api/Spanner.Samples.Tests/{CopyBackupWithMrCmekTest.cs => CopyBackupWithMrCmekAsyncTest.cs} (60%) diff --git a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekAsyncTest.cs similarity index 60% rename from spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs rename to spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekAsyncTest.cs index 83004d73dea..12cc4247d1a 100644 --- a/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CopyBackupWithMrCmekAsyncTest.cs @@ -14,22 +14,24 @@ using Google.Cloud.Spanner.Admin.Database.V1; using System; +using System.Linq; +using System.Threading.Tasks; using Xunit; [Collection(nameof(SpannerFixture))] -public class CopyBackupWithMrCmekTest +public class CopyBackupWithMrCmekAsyncTest { private readonly SpannerFixture _spannerFixture; - public CopyBackupWithMrCmekTest(SpannerFixture spannerFixture) + public CopyBackupWithMrCmekAsyncTest(SpannerFixture spannerFixture) { _spannerFixture = spannerFixture; } - [Fact] - public void CopyBackupWithMrCmek() + [SkippableFact] + public async Task TestCopyBackupWithMrCmekAsync() { - CopyBackupWithMrCmekSample copyBackupWithMrCmekSample = new CopyBackupWithMrCmekSample(); + CopyBackupWithMrCmekAsyncSample copyBackupWithMrCmekAsyncSample = new CopyBackupWithMrCmekAsyncSample(); string source_Project_id = _spannerFixture.ProjectId; string source_Instance_id = _spannerFixture.InstanceId; string source_backupId = _spannerFixture.MrCmekBackupId; @@ -37,11 +39,11 @@ public void CopyBackupWithMrCmek() string target_Instance_id = _spannerFixture.InstanceId; string target_backupId = SpannerFixture.GenerateId("test_", 16); DateTimeOffset expireTime = DateTimeOffset.UtcNow.AddHours(12); - CryptoKeyName[] kmsKeyNames = _fixture.KmsKeyNames; + CryptoKeyName[] kmsKeyNames = _spannerFixture.KmsKeyNames; - Backup backup = copyBackupWithMrCmekSample.CopyBackupWithMrCmek(source_Instance_id, source_Project_id, source_backupId, - target_Instance_id, target_Project_id, target_backupId, expireTime, kmsKeyNames); + var backup = await copyBackupWithMrCmekAsyncSample.CopyBackupWithMrCmekAsync(source_Instance_id, source_Project_id, source_backupId, + target_Instance_id, target_Project_id, target_backupId, expireTime, kmsKeyNames); - Assert.All(backup.EncryptionInfo.KmsKeyVersionsAsCryptoKeyVersionNames, keyName => _fixture.KmsKeyNames.Contains(keyName.CryptoKeyId)); + Assert.All(backup.EncryptionInformation, encryptionInfo => _spannerFixture.KmsKeyNames.Contains(CryptoKeyName.Parse(encryptionInfo.KmsKeyVersionAsCryptoKeyVersionName.CryptoKeyId))); } } From 30492d9492c4f9347adad868f24c5f3f8e60e37d Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:45:46 -0700 Subject: [PATCH 64/66] Update CreateBackupWithMrCmekAsyncTest.cs Missing e in create --- .../Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs index dd54f9925f7..a3472090a89 100644 --- a/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs +++ b/spanner/api/Spanner.Samples.Tests/CreateBackupWithMrCmekAsyncTest.cs @@ -32,7 +32,7 @@ public CreateBackupWithMrCmekAsyncTest(SpannerFixture fixture) } [SkippableFact] - public async Task TestCreatBackupWithMrCmekAsync() + public async Task TestCreateBackupWithMrCmekAsync() { Skip.If(!_fixture.RunCmekBackupSampleTests, SpannerFixture.SkipCmekBackupSamplesMessage); // Create a backup with custom encryption keys. From 3d9b0272979d1a36236bd957f7f6ddca4c02b7fe Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:52:15 -0700 Subject: [PATCH 65/66] Update SpannerFixture.cs Initialize KmsKeyNames --- spanner/api/Spanner.Samples.Tests/SpannerFixture.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs index 37aff964575..0b53d59cfaa 100644 --- a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs +++ b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs @@ -96,7 +96,7 @@ AlbumTitle STRING(MAX) Environment.GetEnvironmentVariable("spanner.test.key.location3") ?? "us-east4", Environment.GetEnvironmentVariable("spanner.test.key.ring3") ?? "spanner-test-keyring3", Environment.GetEnvironmentVariable("spanner.test.key.name3") ?? "spanner-test-key3"); - public CryptoKeyName[] KmsKeyNames = {KmsKeyName, KmsKeyName2, KmsKeyName3}; + public CryptoKeyName[] KmsKeyNames { get; private set; } public string InstanceIdWithProcessingUnits { get; } = GenerateId("my-ins-pu-"); public string InstanceIdWithMultiRegion { get; } = GenerateId("my-ins-mr-"); @@ -143,6 +143,9 @@ public async Task InitializeAsync() // Create encryption key for creating an encrypted database and optionally backing up and restoring an encrypted database. await InitializeEncryptionKeys(); + KmsKeyNames.Append(KmsKeyName); + KmsKeyNames.Append(KmsKeyName2); + KmsKeyNames.Append(KmsKeyName3); if (RunCmekBackupSampleTests) { await InitializeEncryptedBackupAsync(); From f1499f34ea313d22d664f1976df0fc71312bfbb6 Mon Sep 17 00:00:00 2001 From: panerorenn9541 <36008213+panerorenn9541@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:26:36 -0700 Subject: [PATCH 66/66] Update SpannerFixture.cs Use only 1 key --- .../Spanner.Samples.Tests/SpannerFixture.cs | 81 +------------------ 1 file changed, 3 insertions(+), 78 deletions(-) diff --git a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs index 0b53d59cfaa..0c41b89783d 100644 --- a/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs +++ b/spanner/api/Spanner.Samples.Tests/SpannerFixture.cs @@ -86,16 +86,6 @@ AlbumTitle STRING(MAX) Environment.GetEnvironmentVariable("spanner.test.key.location") ?? "us-central1", Environment.GetEnvironmentVariable("spanner.test.key.ring") ?? "spanner-test-keyring", Environment.GetEnvironmentVariable("spanner.test.key.name") ?? "spanner-test-key"); - public CryptoKeyName KmsKeyName2 { get; } = new CryptoKeyName( - Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), - Environment.GetEnvironmentVariable("spanner.test.key.location2") ?? "us-east1", - Environment.GetEnvironmentVariable("spanner.test.key.ring2") ?? "spanner-test-keyring2", - Environment.GetEnvironmentVariable("spanner.test.key.name2") ?? "spanner-test-key2"); - public CryptoKeyName KmsKeyName3 { get; } = new CryptoKeyName( - Environment.GetEnvironmentVariable("spanner.test.key.project") ?? Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID"), - Environment.GetEnvironmentVariable("spanner.test.key.location3") ?? "us-east4", - Environment.GetEnvironmentVariable("spanner.test.key.ring3") ?? "spanner-test-keyring3", - Environment.GetEnvironmentVariable("spanner.test.key.name3") ?? "spanner-test-key3"); public CryptoKeyName[] KmsKeyNames { get; private set; } public string InstanceIdWithProcessingUnits { get; } = GenerateId("my-ins-pu-"); @@ -143,9 +133,6 @@ public async Task InitializeAsync() // Create encryption key for creating an encrypted database and optionally backing up and restoring an encrypted database. await InitializeEncryptionKeys(); - KmsKeyNames.Append(KmsKeyName); - KmsKeyNames.Append(KmsKeyName2); - KmsKeyNames.Append(KmsKeyName3); if (RunCmekBackupSampleTests) { await InitializeEncryptedBackupAsync(); @@ -342,34 +329,6 @@ await client.CreateKeyRingAsync(new CreateKeyRingRequest KeyRing = new KeyRing(), }); } - var keyRingName2 = KeyRingName.FromProjectLocationKeyRing(KmsKeyName2.ProjectId, KmsKeyName2.LocationId, KmsKeyName2.KeyRingId); - try - { - await client.GetKeyRingAsync(keyRingName2); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateKeyRingAsync(new CreateKeyRingRequest - { - ParentAsLocationName = LocationName.FromProjectLocation(keyRingName2.ProjectId, keyRingName2.LocationId), - KeyRingId = KmsKeyName2.KeyRingId, - KeyRing = new KeyRing(), - }); - } - var keyRingName3 = KeyRingName.FromProjectLocationKeyRing(KmsKeyName3.ProjectId, KmsKeyName3.LocationId, KmsKeyName3.KeyRingId); - try - { - await client.GetKeyRingAsync(keyRingName3); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateKeyRingAsync(new CreateKeyRingRequest - { - ParentAsLocationName = LocationName.FromProjectLocation(keyRingName3.ProjectId, keyRingName3.LocationId), - KeyRingId = KmsKeyName3.KeyRingId, - KeyRing = new KeyRing(), - }); - } var keyName = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName.ProjectId, KmsKeyName.LocationId, KmsKeyName.KeyRingId, KmsKeyName.CryptoKeyId); try @@ -388,40 +347,6 @@ await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest }, }); } - var keyName2 = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName2.ProjectId, KmsKeyName2.LocationId, KmsKeyName2.KeyRingId, KmsKeyName2.CryptoKeyId); - try - { - await client.GetCryptoKeyAsync(keyName2); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest - { - ParentAsKeyRingName = keyRingName2, - CryptoKeyId = keyName2.CryptoKeyId, - CryptoKey = new CryptoKey - { - Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, - }, - }); - } - var keyName3 = Google.Cloud.Kms.V1.CryptoKeyName.FromProjectLocationKeyRingCryptoKey(KmsKeyName3.ProjectId, KmsKeyName3.LocationId, KmsKeyName3.KeyRingId, KmsKeyName3.CryptoKeyId); - try - { - await client.GetCryptoKeyAsync(keyName3); - } - catch (RpcException e) when (e.StatusCode == StatusCode.NotFound) - { - await client.CreateCryptoKeyAsync(new CreateCryptoKeyRequest - { - ParentAsKeyRingName = keyRingName3, - CryptoKeyId = keyName3.CryptoKeyId, - CryptoKey = new CryptoKey - { - Purpose = CryptoKey.Types.CryptoKeyPurpose.EncryptDecrypt, - }, - }); - } } private async Task InitializeEncryptedBackupAsync() @@ -463,8 +388,8 @@ private async Task InitializeMrCmekBackupAsync() { CreateDatabaseWithMrCmekAsyncSample createDatabaseAsyncSample = new CreateDatabaseWithMrCmekAsyncSample(); InsertDataAsyncSample insertDataAsyncSample = new InsertDataAsyncSample(); - await createDatabaseAsyncSample.CreateDatabaseWithMrCmekAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId, KmsKeyNames); - await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId); + await createDatabaseAsyncSample.CreateDatabaseWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, KmsKeyNames); + await insertDataAsyncSample.InsertDataAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId); } catch (Exception e) when (e.ToString().Contains("Database already exists")) { @@ -477,7 +402,7 @@ private async Task InitializeMrCmekBackupAsync() try { CreateBackupWithMrCmekAsyncSample createBackupSample = new CreateBackupWithMrCmekAsyncSample(); - await createBackupSample.CreateBackupWithMrCmekAsync(ProjectId, InstanceIdWithMultiRegion, FixedMrCmekDatabaseId, FixedMrCmekBackupId, KmsKeyNames); + await createBackupSample.CreateBackupWithMrCmekAsync(ProjectId, InstanceId, FixedMrCmekDatabaseId, FixedMrCmekBackupId, KmsKeyNames); } catch (RpcException e) when (e.StatusCode == StatusCode.AlreadyExists) {