Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(storage): support bucket restore in soft delete phase 2 #13894

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

mahendra-google
Copy link

Feature request includes the following:-

  1. Get Bucket Generation
  2. Get a Soft Deleted Bucket (Also soft-delete time and hard-delete time)
  3. List Soft Deleted Buckets
  4. Restore a Soft Deleted Bucket

@mahendra-google mahendra-google requested review from a team as code owners November 28, 2024 12:39
@product-auto-label product-auto-label bot added the api: storage Issues related to the Cloud Storage API. label Nov 28, 2024
Copy link
Collaborator

@jskeet jskeet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a full code review by any means, but I'm hoping that this little bit will reduce the number of iterations required after Amanda is back from Thanksgiving.

Directory.Packages.props Outdated Show resolved Hide resolved
@mahendra-google
Copy link
Author

This is not a full code review by any means, but I'm hoping that this little bit will reduce the number of iterations required after Amanda is back from Thanksgiving.

Ok

…version for Google.Cloud.Storage.V1 in apis.json
@jskeet
Copy link
Collaborator

jskeet commented Nov 29, 2024

Unassigning myself from review - I'm on vacation until Tuesday. (I expect Amanda will review before then.)

@amanda-tarafa amanda-tarafa self-assigned this Dec 3, 2024
@amanda-tarafa
Copy link
Contributor

I'll review today. @mahendra-google if you can rebase on main to remove conflicts, that'd be great, thanks.

@mahendra-google
Copy link
Author

I'll review today. @mahendra-google if you can rebase on main to remove conflicts, that'd be great, thanks.

@amanda-tarafa I have removed conflict for Directory.Packages.props file.

@mahendra-google
Copy link
Author

I'll review today. @mahendra-google if you can rebase on main to remove conflicts, that'd be great, thanks.

@amanda-tarafa I have removed conflict for Directory.Packages.props file.

@amanda-tarafa I have removed project file conflict.

@mahendra-google
Copy link
Author

mahendra-google commented Dec 6, 2024

@amanda-tarafa Storage Samples requires latest package of Google.Cloud.Storage.V1 having properties of GetBucketOptions , ListBucketOptions, RestoreBucketOptions to work sample as expected. So for samples can I proceed with lastest dlls?

public long? Generation { get; set; }

/// <summary>
/// (Optional) Set to true to retrieve a soft-deleted bucket .It will return the bucket metadata only if the bucket exists and is in a soft-deleted state.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit while I spot it: the period after the first sentence is in the wrong place.

Copy link
Contributor

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add unit tests for all the option classes that you modified. See #12060 for examples.

@@ -4967,7 +4967,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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is now on the generator-input folder

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment hasn't been addressed. This file is now in a different location to when you started this PR. That's the source of the conflict that github is signaling.

You need to rebase this PR on the repo's HEAD, and while you are at it, please squash all the commits. We are very keen on keeping a clean history on the repo and commits like "fixing this" or "addressing that" don't help.

@@ -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" VersionOverride="[4.9.0, 5.0.0)" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment hasn't been addressed.


foreach (var bucket in actualBuckets)
{
// Check if list contains only soft deleted buckets created in storage fixture
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what you are checking here. You are only saying to tests assertions on buckets whose names en with soft-delete.

Ain't there a metadata field indicating that the bucket has been softdeleted?

Copy link
Author

@mahendra-google mahendra-google Dec 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before further filtering soft deleted buckets with soft-delete, I have added SoftDeletedOnly metatdata for ListBucketsOptions to check if bucket has been softdeleted or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several things wrong with this test

  • When this test executes there's absolutely no guaratee that you have run a test that has created a soft delete bucket.
  • You want to test that setting the SoftDeleteOnly option works, so you cannot rely on it working to test it works (as per your comment: "I have added SoftDeletedOnly metatdata for ListBucketsOptions to check if bucket has been softdeleted or not.")
  • You are not testing that only soft-deleted buckets were returned, you are testing that if a bucket whose name ends in "soft-delete" is returned, then: its name is not null, its generation is not null, it has a soft delete time, and a hard delete time. If this test is passing anywhere it's because there's no "soft-deleted" bucket that has been created.

}
catch (Exception)
{
// If bucket is not empty, we delete on a best effort basis.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as in the other test. You won't need this one you create the bucket in the test.

(And also there's an option that can be passed to indicate "delete the bucket and all its contents", so you really wouldn't even need this).

}
await _fixture.Client.DeleteBucketAsync(_fixture.SoftDeleteBucketOne);
}
// We get softDeleted object using get bucket async method for soft deleted bucket.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not getting an object.

Comment on lines +50 to +51
Assert.NotNull(bucket.Generation);
Assert.NotNull(softDeleted.Generation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what these are meant to be testing, shouldn't you test they are the same value?

Copy link
Author

@mahendra-google mahendra-google Dec 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I added that here (I was checking that in the second test) also checking that bucket generations before and after delete are not null.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the null check then.

}

[Fact]
public async Task GetSoftDeletedBucket()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between this test and the one above? What are the different cases they are testing?

Copy link
Author

@mahendra-google mahendra-google Dec 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above test is for checking generation explicitly and this test is for checking bucket name along with soft delete and hard delete time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need two tests for that.

Copy link
Author

@mahendra-google mahendra-google Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will share design doc let me know so that I will add everything in single test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, everything in a single test please.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I will add in single test

@@ -4967,7 +4967,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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment hasn't been addressed. This file is now in a different location to when you started this PR. That's the source of the conflict that github is signaling.

You need to rebase this PR on the repo's HEAD, and while you are at it, please squash all the commits. We are very keen on keeping a clean history on the repo and commits like "fixing this" or "addressing that" don't help.

@@ -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" VersionOverride="[4.9.0, 5.0.0)" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment hasn't been addressed.

{
ValidateBucketName(bucket);
var request = Service.Buckets.Restore(bucket, generation);
ApplyEncryptionKey(options?.EncryptionKey, kmsNameFromOptions: null, request);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JesseLovelace Can you confirm that RestoreBucket supports encryption? I seem to remember this was just for object related operations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Buckets can have a default encryption key, but that wouldn't be relevant to the restore bucket request. No need to support it as a RestoreBucketOption

var request = Service.Buckets.Restore(bucket, generation);
ApplyEncryptionKey(options?.EncryptionKey, kmsNameFromOptions: null, request);
options?.ModifyRequest(request);
RetryOptions retryOptions = options?.RetryOptions ?? RetryOptions.IdempotentRetryOptions;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JesseLovelace can you confirm that RestoreBucket is idempotent and retryable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restore Bucket doesn't support the common idempotency params (ifGenerationMatch etc) but it is safely retryable, so it can probably use the same retry handler

/// except for the bucket's access controls. This only affects
/// what information is returned when restoration is successful.
/// </summary>
public Projection? Projection { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave a blank line between one property and the next.

Comment on lines +50 to +51
Assert.NotNull(bucket.Generation);
Assert.NotNull(softDeleted.Generation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove the null check then.

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also check that the soft delete timespan is set, that is the real confirmation that this is a soft deleted bucket.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per design doc I have added soft delete timespan in GetSoftDeletedBucket test. I will share design doc

}

[Fact]
public async Task GetSoftDeletedBucket()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need two tests for that.

[Fact]
public async Task GetBucketGeneration()
{
var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you still need to create the bucket using CreateBucket, but you should generate de bucket name using GenerateBucketName. (here and everywhere)

public async Task GetBucketGeneration()
{
var softDeleteBucket = _fixture.CreateBucket(Guid.NewGuid().ToString() + "-soft-delete", false, true);
var bucket = await _fixture.Client.GetBucketAsync(softDeleteBucket.Name, new GetBucketOptions { SoftDeleted = false });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure you have the generation already in softDeleteBucket. The metadata returned on bucket creation should be the same as the one you are obtaining here, as the bucket shouldn't have changed because it's owned by this test.

}

[Fact]
public async Task GetSoftDeletedBucket()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, everything in a single test please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the Cloud Storage API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants