From 7d099f83b457783fb2669746fc25e2e3db55cd4d Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Tue, 26 Nov 2024 04:50:10 -0800 Subject: [PATCH 1/7] feat(storage): add getbucket generation , get soft deleted bucket and related test cases Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> Co-authored-by: Amanda Tarafa Mas <14878252+amanda-tarafa@users.noreply.github.com> --- .../GetBucketTest.cs | 58 +++++++++++++++++++ .../ListBucketsTest.cs | 21 +++++++ .../RestoreBucketTest.cs | 43 ++++++++++++++ .../GetBucketOptionsTest.cs | 10 +++- .../ListBucketsOptionsTest.cs | 5 +- .../RestoreBucketOptionsTest.cs | 45 ++++++++++++++ .../GetBucketOptions.cs | 20 +++++++ .../Google.Cloud.Storage.V1.csproj | 4 +- .../ListBucketsOptions.cs | 9 +++ .../RestoreBucketOptions.cs | 58 +++++++++++++++++++ .../StorageClient.RestoreBucket.cs | 49 ++++++++++++++++ .../StorageClientImpl.RestoreBucket.cs | 45 ++++++++++++++ generator-input/apis.json | 2 +- 13 files changed, 364 insertions(+), 5 deletions(-) create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/RestoreBucketOptionsTest.cs create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClient.RestoreBucket.cs create mode 100644 apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs new file mode 100644 index 000000000000..17945192b327 --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs @@ -0,0 +1,58 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"): +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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; + +namespace Google.Cloud.Storage.V1.IntegrationTests; +[Collection(nameof(StorageFixture))] +public class GetBucketTest +{ + private readonly StorageFixture _fixture; + + public GetBucketTest(StorageFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task SoftDeleted() + { + var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); + var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); + + await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); + var softDeleted = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = true, Generation = bucket.Generation }); + Assert.NotNull(bucket.Generation); + Assert.NotNull(softDeleted.Generation); + Assert.Equal(bucket.Generation, softDeleted.Generation); + } + + [Fact] + public async Task GetSoftDeletedBucket() + { + var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); + var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); + await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); + + var softDeleted = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = true, Generation = bucket.Generation }); + + Assert.NotNull(bucket.Name); + Assert.NotNull(softDeleted.Name); + Assert.Equal(bucket.Name, softDeleted.Name); + Assert.NotNull(softDeleted.SoftDeleteTimeDateTimeOffset); + Assert.NotNull(softDeleted.HardDeleteTimeDateTimeOffset); + } +} diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs index c4f6f04799a1..46c9956ade9b 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs @@ -75,6 +75,25 @@ public void PartialResponses() } } + [Fact] + public async Task SoftDeletedOnly() + { + var actualBuckets = await _fixture.Client.ListBucketsAsync(_fixture.ProjectId, new ListBucketsOptions { SoftDeletedOnly = true }).ToListAsync(); + + foreach (var bucket in actualBuckets) + { + // Check if list contains only soft deleted buckets created in storage fixture + if (bucket.Name.EndsWith("soft-delete")) + { + Assert.NotNull(bucket.Name); + Assert.NotNull(bucket.Generation); + Assert.NotNull(bucket.SoftDeleteTimeDateTimeOffset); + Assert.NotNull(bucket.HardDeleteTimeDateTimeOffset); + } + + } + } + // Fetches buckets using the given options in each possible way, validating that the expected bucket names are returned. private async Task AssertBuckets(ListBucketsOptions options, params string[] expectedBucketNames) { @@ -90,5 +109,7 @@ private void AssertBucketNames(IEnumerable actualBuckets, string[] expec var actualNames = actualBuckets.Select(b => b.Name).Where(name => name.StartsWith(_fixture.BucketPrefix)).OrderBy(x => x).ToList(); Assert.Equal(expectedNames.OrderBy(x => x), actualNames); } + + } } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs new file mode 100644 index 000000000000..08ae55dd0e1d --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs @@ -0,0 +1,43 @@ +// Copyright 2024 Google Inc. All Rights Reserved. +// +// 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; + +namespace Google.Cloud.Storage.V1.IntegrationTests +{ + [Collection(nameof(StorageFixture))] + public class RestoreBucketTest + { + private readonly StorageFixture _fixture; + + public RestoreBucketTest(StorageFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task RestoreSoftDeletedBucket() + { + var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); + var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); + await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); + + var restored = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, bucket.Generation.Value); + Assert.Equal(bucket.Name, restored.Name); + Assert.Equal(bucket.Generation, restored.Generation); + } + } +} diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/GetBucketOptionsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/GetBucketOptionsTest.cs index abdb68f17624..73df3f10fda2 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/GetBucketOptionsTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/GetBucketOptionsTest.cs @@ -31,6 +31,8 @@ public void ModifyRequest_DefaultOptions() Assert.Null(request.IfMetagenerationNotMatch); Assert.Null(request.Projection); Assert.Null(request.UserProject); + Assert.Null(request.SoftDeleted); + Assert.Null(request.Generation); } [Fact] @@ -41,13 +43,17 @@ public void ModifyRequest_PositiveMatchOptions() { IfMetagenerationMatch = 1L, Projection = Projection.Full, - UserProject = "proj" + UserProject = "proj", + SoftDeleted = true, + Generation = long.MaxValue }; options.ModifyRequest(request); Assert.Equal(1L, request.IfMetagenerationMatch); Assert.Null(request.IfMetagenerationNotMatch); Assert.Equal(ProjectionEnum.Full, request.Projection); Assert.Equal("proj", request.UserProject); + Assert.Equal(true, request.SoftDeleted); + Assert.Equal(long.MaxValue,request.Generation); } [Fact] @@ -61,6 +67,8 @@ public void ModifyRequest_NegativeMatchOptions() }; options.ModifyRequest(request); Assert.Null(request.IfMetagenerationMatch); + Assert.Null(request.SoftDeleted); + Assert.Null(request.Generation); Assert.Equal(1L, request.IfMetagenerationNotMatch); Assert.Equal(ProjectionEnum.Full, request.Projection); } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/ListBucketsOptionsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/ListBucketsOptionsTest.cs index f4868acd6c0a..2d21162d4248 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/ListBucketsOptionsTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/ListBucketsOptionsTest.cs @@ -30,6 +30,7 @@ public void ModifyRequest_DefaultOptions() Assert.Null(request.Prefix); Assert.Null(request.MaxResults); Assert.Null(request.PageToken); + Assert.Null(request.SoftDeleted); } [Fact] @@ -42,7 +43,8 @@ public void ModifyRequest_AllOptions() Prefix = "prefix", Projection = Projection.Full, PageToken = "nextpage", - Fields = "items(name),nextPageToken" + Fields = "items(name),nextPageToken", + SoftDeletedOnly = true, }; options.ModifyRequest(request); Assert.Equal(10, request.MaxResults); @@ -50,6 +52,7 @@ public void ModifyRequest_AllOptions() Assert.Equal(ProjectionEnum.Full, request.Projection); Assert.Equal("nextpage", request.PageToken); Assert.Equal("items(name),nextPageToken", request.Fields); + Assert.Equal(true, request.SoftDeleted); } } } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/RestoreBucketOptionsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/RestoreBucketOptionsTest.cs new file mode 100644 index 000000000000..8a5fe2503c69 --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.Tests/RestoreBucketOptionsTest.cs @@ -0,0 +1,45 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"): +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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 Xunit; +using static Google.Apis.Storage.v1.BucketsResource; +using static Google.Apis.Storage.v1.BucketsResource.RestoreRequest; + +namespace Google.Cloud.Storage.V1.Tests; +public class RestoreBucketOptionsTest +{ + [Fact] + public void ModifyRequest_DefaultOptions() + { + var request = new RestoreRequest(null, "bucket", 2L); + var options = new RestoreBucketOptions(); + options.ModifyRequest(request); + Assert.Null(request.Projection); + Assert.Null(request.UserProject); + } + + [Fact] + public void ModifyRequest_AllOptions() + { + var request = new RestoreRequest(null, "bucket", 2L); + var options = new RestoreBucketOptions + { + Projection = Projection.Full, + UserProject = "proj" + }; + options.ModifyRequest(request); + Assert.Equal(ProjectionEnum.Full, request.Projection); + Assert.Equal("proj", request.UserProject); + } +} diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/GetBucketOptions.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/GetBucketOptions.cs index 266dab4389f6..c79ce8762512 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/GetBucketOptions.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/GetBucketOptions.cs @@ -52,6 +52,17 @@ public sealed class GetBucketOptions /// public RetryOptions RetryOptions { get; set; } + /// + /// The bucket generation to be retrieved. It must be set if is true. + /// + public long? Generation { get; set; } + + /// + /// If true, the soft-deleted version of the bucket will be retrieved. + /// If true, must be set. + /// + public bool? SoftDeleted { get; set; } + internal void ModifyRequest(GetRequest request) { if (IfMetagenerationMatch != null && IfMetagenerationNotMatch != null) @@ -75,6 +86,15 @@ internal void ModifyRequest(GetRequest request) { request.UserProject = UserProject; } + if (Generation != null) + { + request.Generation = Generation; + } + if (SoftDeleted != null) + { + request.SoftDeleted = SoftDeleted; + } + } } } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj index 9cfae17c9fd9..d2092038012c 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/ListBucketsOptions.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/ListBucketsOptions.cs index 3fe2fccd2110..13881e8bce8f 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/ListBucketsOptions.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/ListBucketsOptions.cs @@ -62,6 +62,11 @@ public sealed class ListBucketsOptions /// public RetryOptions RetryOptions { get; set; } + /// + /// If true, only soft-deleted buckets will be listed. The default is false. + /// + public bool? SoftDeletedOnly { get; set; } + /// /// Modifies the specified request for all non-null properties of this options object. /// @@ -88,6 +93,10 @@ internal void ModifyRequest(ListRequest request) { request.Fields = Fields; } + if (SoftDeletedOnly != null) + { + request.SoftDeleted = SoftDeletedOnly; + } } } } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs new file mode 100644 index 000000000000..a52f168b7f66 --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs @@ -0,0 +1,58 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"): +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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; +using static Google.Apis.Storage.v1.BucketsResource; +using static Google.Apis.Storage.v1.BucketsResource.RestoreRequest; + +namespace Google.Cloud.Storage.V1; + +/// +/// Options for RestoreBucket operations. +/// +public sealed class RestoreBucketOptions +{ + /// + /// The projection of the restored bucket to return. Note the whole bucket will be restored, + /// except for the bucket's access controls. This only affects + /// what information is returned when restoration is successful. + /// + public Projection? Projection { get; set; } + /// + /// The encryption key to use for this operation. If this property is null, the + /// will be used instead. Use to remove encryption headers from this request. + /// + public EncryptionKey EncryptionKey { get; set; } + /// + /// If set, this is the ID of the project which will be billed for the request. + /// The caller must have suitable permissions for the project being billed. + /// + public string UserProject { get; set; } + /// + /// Options to pass custom retry configuration for each API request. + /// + public RetryOptions RetryOptions { get; set; } + + internal void ModifyRequest(RestoreRequest request) + { + if (Projection != null) + { + request.Projection = GaxPreconditions.CheckEnumValue((ProjectionEnum) Projection, nameof(Projection)); + } + if (UserProject != null) + { + request.UserProject = UserProject; + } + } +} diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClient.RestoreBucket.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClient.RestoreBucket.cs new file mode 100644 index 000000000000..37f7b707120f --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClient.RestoreBucket.cs @@ -0,0 +1,49 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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; +using System.Threading.Tasks; +using Bucket = Google.Apis.Storage.v1.Data.Bucket; + +namespace Google.Cloud.Storage.V1; +public abstract partial class StorageClient +{ + /// + /// Restores a soft-deleted bucket. + /// + /// The name of the bucket. Must not be null. + /// The specific revision of the bucket to restore. + /// Additional options for the restore operation. May be null, in which case appropriate + /// defaults will be used. + /// The representation of the restored Storage bucket. + public virtual Bucket RestoreBucket(string bucket, long generation, RestoreBucketOptions options = null) => + throw new NotImplementedException(); + + /// + /// Restores a soft-deleted bucket. + /// + /// The name of the bucket. Must not be null. + /// The specific revision of the bucket to restore. + /// Additional options for the restore operation. May be null, in which case appropriate + /// defaults will be used. + /// The token to monitor for cancellation requests. + /// A task representing the asynchronous operation, with a result returning the + /// representation of the restored Storage bucket. + public virtual Task RestoreBucketAsync( + string bucket, + long generation, + RestoreBucketOptions options = null, + CancellationToken cancellationToken = default) => throw new NotImplementedException(); +} diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs new file mode 100644 index 000000000000..cf1601e15416 --- /dev/null +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs @@ -0,0 +1,45 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"): +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://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 System.Threading; +using Google.Apis.Storage.v1; +using Bucket = Google.Apis.Storage.v1.Data.Bucket; + +namespace Google.Cloud.Storage.V1; +public sealed partial class StorageClientImpl : StorageClient +{ + /// + public override Bucket RestoreBucket(string bucket, long generation, RestoreBucketOptions options = null) => + CreateRestoreBucketRequest(bucket, generation, options).Execute(); + + /// + public override Task RestoreBucketAsync( + string bucket, + long generation, + RestoreBucketOptions options = null, + CancellationToken cancellationToken = default) => + CreateRestoreBucketRequest(bucket, generation, options).ExecuteAsync(cancellationToken); + + private BucketsResource.RestoreRequest CreateRestoreBucketRequest(string bucket, long generation, RestoreBucketOptions options) + { + ValidateBucketName(bucket); + var request = Service.Buckets.Restore(bucket, generation); + ApplyEncryptionKey(options?.EncryptionKey, kmsNameFromOptions: null, request); + options?.ModifyRequest(request); + RetryOptions retryOptions = options?.RetryOptions ?? RetryOptions.IdempotentRetryOptions; + MarkAsRetriable(request, retryOptions); + return request; + } +} diff --git a/generator-input/apis.json b/generator-input/apis.json index 364541b497fb..ab03c7130f91 100644 --- a/generator-input/apis.json +++ b/generator-input/apis.json @@ -5152,7 +5152,7 @@ "description": "Recommended Google client library to access the Google Cloud Storage API. It wraps the Google.Apis.Storage.v1 client library, making common operations simpler in client code. Google Cloud Storage stores and retrieves potentially large, immutable data objects.", "dependencies": { "Google.Api.Gax.Rest": "default", - "Google.Apis.Storage.v1": "1.68.0.3431" + "Google.Apis.Storage.v1": "1.68.0.3604" }, "testDependencies": { "Google.Api.Gax.Testing": "default", From 8849e6b72920518f4dd2d4f389f4146931df06fe Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Thu, 23 Jan 2025 23:06:24 -0800 Subject: [PATCH 2/7] file-scoped namespace and generate bucket name method added --- .../RestoreBucketTest.cs | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs index 08ae55dd0e1d..c092e0cdeca8 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs @@ -16,28 +16,27 @@ using System.Threading.Tasks; using Xunit; -namespace Google.Cloud.Storage.V1.IntegrationTests +namespace Google.Cloud.Storage.V1.IntegrationTests; + +[Collection(nameof(StorageFixture))] +public class RestoreBucketTest { - [Collection(nameof(StorageFixture))] - public class RestoreBucketTest - { - private readonly StorageFixture _fixture; + private readonly StorageFixture _fixture; - public RestoreBucketTest(StorageFixture fixture) - { - _fixture = fixture; - } + public RestoreBucketTest(StorageFixture fixture) + { + _fixture = fixture; + } - [Fact] - public async Task RestoreSoftDeletedBucket() - { - var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); - var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); - await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); + [Fact] + public async Task RestoreSoftDeletedBucket() + { + var bucketName = _fixture.GenerateBucketName(); + var softDeleteBucket = _fixture.CreateBucket(bucketName, false, true); + await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); - var restored = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, bucket.Generation.Value); - Assert.Equal(bucket.Name, restored.Name); - Assert.Equal(bucket.Generation, restored.Generation); - } + var restored = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, softDeleteBucket.Generation.Value); + Assert.Equal(softDeleteBucket.Name, restored.Name); + Assert.Equal(softDeleteBucket.Generation, restored.Generation); } } From b3439a96e459bf99d37a241dac892abd27cf0d6b Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Fri, 24 Jan 2025 01:57:41 -0800 Subject: [PATCH 3/7] Adding all tests in single test , addition of generatebucket name method --- .../GetBucketTest.cs | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs index 17945192b327..f97b21c0b207 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/GetBucketTest.cs @@ -30,28 +30,13 @@ public GetBucketTest(StorageFixture fixture) [Fact] public async Task SoftDeleted() { - var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); - var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); - - await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); - var softDeleted = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = true, Generation = bucket.Generation }); - Assert.NotNull(bucket.Generation); - Assert.NotNull(softDeleted.Generation); - Assert.Equal(bucket.Generation, softDeleted.Generation); - } - - [Fact] - public async Task GetSoftDeletedBucket() - { - var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true); - var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false }); + var bucketName = _fixture.GenerateBucketName(); + var softDeleteBucket = _fixture.CreateBucket(bucketName, false, true); await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); - var softDeleted = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = true, Generation = bucket.Generation }); - - Assert.NotNull(bucket.Name); - Assert.NotNull(softDeleted.Name); - Assert.Equal(bucket.Name, softDeleted.Name); + var softDeleted = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = true, Generation = softDeleteBucket.Generation }); + Assert.Equal(softDeleteBucket.Name, softDeleted.Name); + Assert.Equal(softDeleteBucket.Generation, softDeleted.Generation); Assert.NotNull(softDeleted.SoftDeleteTimeDateTimeOffset); Assert.NotNull(softDeleted.HardDeleteTimeDateTimeOffset); } From bcac735f07acc79f00c3b77ba25cbf0207d015ff Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Fri, 24 Jan 2025 02:03:00 -0800 Subject: [PATCH 4/7] adding a blank line between one property and the next --- .../Google.Cloud.Storage.V1/RestoreBucketOptions.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs index a52f168b7f66..200dc17dc759 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/RestoreBucketOptions.cs @@ -29,16 +29,19 @@ public sealed class RestoreBucketOptions /// what information is returned when restoration is successful. /// public Projection? Projection { get; set; } + /// /// The encryption key to use for this operation. If this property is null, the /// will be used instead. Use to remove encryption headers from this request. /// public EncryptionKey EncryptionKey { get; set; } + /// /// If set, this is the ID of the project which will be billed for the request. /// The caller must have suitable permissions for the project being billed. /// public string UserProject { get; set; } + /// /// Options to pass custom retry configuration for each API request. /// From 8b75ae05923e70372be854cd512488b582035148 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Fri, 24 Jan 2025 02:45:49 -0800 Subject: [PATCH 5/7] List Soft Deleted Bucket test case changes --- .../ListBucketsTest.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs index 46c9956ade9b..863d36c79e6a 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs @@ -78,19 +78,19 @@ public void PartialResponses() [Fact] public async Task SoftDeletedOnly() { + var bucketName = _fixture.GenerateBucketName(); + var softDeleteBucket = _fixture.CreateBucket(bucketName, false, true); + await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); var actualBuckets = await _fixture.Client.ListBucketsAsync(_fixture.ProjectId, new ListBucketsOptions { SoftDeletedOnly = true }).ToListAsync(); foreach (var bucket in actualBuckets) { - // Check if list contains only soft deleted buckets created in storage fixture - if (bucket.Name.EndsWith("soft-delete")) + if (bucket.Name == softDeleteBucket.Name) { - Assert.NotNull(bucket.Name); Assert.NotNull(bucket.Generation); Assert.NotNull(bucket.SoftDeleteTimeDateTimeOffset); Assert.NotNull(bucket.HardDeleteTimeDateTimeOffset); } - } } @@ -109,7 +109,5 @@ private void AssertBucketNames(IEnumerable actualBuckets, string[] expec var actualNames = actualBuckets.Select(b => b.Name).Where(name => name.StartsWith(_fixture.BucketPrefix)).OrderBy(x => x).ToList(); Assert.Equal(expectedNames.OrderBy(x => x), actualNames); } - - } } From 11b58d26f7d9dbe3f64b193a32b395faaf737fe1 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Sun, 26 Jan 2025 22:02:24 -0800 Subject: [PATCH 6/7] Removal of encryption key support for restore bucket request and removal of package version override --- .../Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj | 2 +- .../Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj index d2092038012c..d0fb5ece91fe 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.csproj @@ -9,7 +9,7 @@ - + diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs index cf1601e15416..ad3be96a5c46 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1/StorageClientImpl.RestoreBucket.cs @@ -36,7 +36,6 @@ private BucketsResource.RestoreRequest CreateRestoreBucketRequest(string bucket, { ValidateBucketName(bucket); var request = Service.Buckets.Restore(bucket, generation); - ApplyEncryptionKey(options?.EncryptionKey, kmsNameFromOptions: null, request); options?.ModifyRequest(request); RetryOptions retryOptions = options?.RetryOptions ?? RetryOptions.IdempotentRetryOptions; MarkAsRetriable(request, retryOptions); From fcc31670583babb51d4fc859a3b7dbaa347cae07 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Tue, 28 Jan 2025 02:51:21 -0800 Subject: [PATCH 7/7] Recommended changes as per internal PR review --- .../ListBucketsTest.cs | 12 +++++++----- .../RestoreBucketTest.cs | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs index 863d36c79e6a..563b3cabcdca 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/ListBucketsTest.cs @@ -84,12 +84,14 @@ public async Task SoftDeletedOnly() var actualBuckets = await _fixture.Client.ListBucketsAsync(_fixture.ProjectId, new ListBucketsOptions { SoftDeletedOnly = true }).ToListAsync(); foreach (var bucket in actualBuckets) - { + { // Verify if the bucket is soft-deleted only + Assert.NotNull(bucket.Generation); + Assert.NotNull(bucket.SoftDeleteTimeDateTimeOffset); + Assert.NotNull(bucket.HardDeleteTimeDateTimeOffset); + if (bucket.Name == softDeleteBucket.Name) - { - Assert.NotNull(bucket.Generation); - Assert.NotNull(bucket.SoftDeleteTimeDateTimeOffset); - Assert.NotNull(bucket.HardDeleteTimeDateTimeOffset); + { // Compare the generation number + Assert.Equal(bucket.Generation, softDeleteBucket.Generation); } } } diff --git a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs index c092e0cdeca8..888f2afd29bf 100644 --- a/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs +++ b/apis/Google.Cloud.Storage.V1/Google.Cloud.Storage.V1.IntegrationTests/RestoreBucketTest.cs @@ -35,8 +35,8 @@ public async Task RestoreSoftDeletedBucket() var softDeleteBucket = _fixture.CreateBucket(bucketName, false, true); await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true }); - var restored = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, softDeleteBucket.Generation.Value); - Assert.Equal(softDeleteBucket.Name, restored.Name); - Assert.Equal(softDeleteBucket.Generation, restored.Generation); + var restoredBucket = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, softDeleteBucket.Generation.Value); + Assert.Equal(softDeleteBucket.Name, restoredBucket.Name); + Assert.Equal(softDeleteBucket.Generation, restoredBucket.Generation); } }