Skip to content
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 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 = softDeleteBucket.Generation });
Assert.Equal(softDeleteBucket.Name, softDeleted.Name);
Assert.Equal(softDeleteBucket.Generation, softDeleted.Generation);
Assert.NotNull(softDeleted.SoftDeleteTimeDateTimeOffset);
Assert.NotNull(softDeleted.HardDeleteTimeDateTimeOffset);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@ 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)
{ // 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)
{ // Compare the generation number
Assert.Equal(bucket.Generation, softDeleteBucket.Generation);
}
}
}

// 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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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 bucketName = _fixture.GenerateBucketName();
var softDeleteBucket = _fixture.CreateBucket(bucketName, false, true);
await _fixture.Client.DeleteBucketAsync(softDeleteBucket.Name, new DeleteBucketOptions { DeleteObjects = true });

var restoredBucket = await _fixture.Client.RestoreBucketAsync(softDeleteBucket.Name, softDeleteBucket.Generation.Value);
Assert.Equal(softDeleteBucket.Name, restoredBucket.Name);
Assert.Equal(softDeleteBucket.Generation, restoredBucket.Generation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -42,14 +43,16 @@ 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);
Assert.Equal("prefix", request.Prefix);
Assert.Equal(ProjectionEnum.Full, request.Projection);
Assert.Equal("nextpage", request.PageToken);
Assert.Equal("items(name),nextPageToken", request.Fields);
Assert.Equal(true, request.SoftDeleted);
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ public sealed class GetBucketOptions
/// </summary>
public RetryOptions RetryOptions { get; set; }

/// <summary>
/// The bucket generation to be retrieved. It must be set if <see ref="SoftDelete" /> is true.
/// </summary>
public long? Generation { get; set; }

/// <summary>
/// If true, the soft-deleted version of the bucket will be retrieved.
/// If true, <see ref="Generation" /> must be set.
/// </summary>
public bool? SoftDeleted { get; set; }

internal void ModifyRequest(GetRequest request)
{
if (IfMetagenerationMatch != null && IfMetagenerationNotMatch != null)
Expand All @@ -75,6 +86,15 @@ internal void ModifyRequest(GetRequest request)
{
request.UserProject = UserProject;
}
if (Generation != null)
{
request.Generation = Generation;
}
if (SoftDeleted != null)
{
request.SoftDeleted = SoftDeleted;
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ConfigureAwaitChecker.Analyzer" PrivateAssets="All" />
<PackageReference Include="Google.Api.Gax.Rest" />
<PackageReference Include="Google.Apis.Storage.v1" VersionOverride="[1.68.0.3431, 2.0.0.0)" />
<PackageReference Include="Google.Api.Gax.Rest"/>
<PackageReference Include="Google.Apis.Storage.v1" VersionOverride="[1.68.0.3604, 2.0.0.0)" />
</ItemGroup>
<ItemGroup>
<Compile Update="StorageClient.*.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public sealed class ListBucketsOptions
/// </summary>
public RetryOptions RetryOptions { get; set; }

/// <summary>
/// If true, only soft-deleted buckets will be listed. The default is false.
/// </summary>
public bool? SoftDeletedOnly { get; set; }

/// <summary>
/// Modifies the specified request for all non-null properties of this options object.
/// </summary>
Expand All @@ -88,6 +93,10 @@ internal void ModifyRequest(ListRequest request)
{
request.Fields = Fields;
}
if (SoftDeletedOnly != null)
{
request.SoftDeleted = SoftDeletedOnly;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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;

/// <summary>
/// Options for RestoreBucket operations.
/// </summary>
public sealed class RestoreBucketOptions
{
/// <summary>
/// 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.
/// </summary>
public Projection? Projection { get; set; }

/// <summary>
/// The encryption key to use for this operation. If this property is null, the <see cref="StorageClient.EncryptionKey"/>
/// will be used instead. Use <see cref="EncryptionKey.None"/> to remove encryption headers from this request.
/// </summary>
public EncryptionKey EncryptionKey { get; set; }

/// <summary>
/// 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.
/// </summary>
public string UserProject { get; set; }

/// <summary>
/// Options to pass custom retry configuration for each API request.
/// </summary>
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;
}
}
}
Loading