-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Storage: Deprecate DeleteRules and add LifecycleRules to accommodate SetStorageClass actions #3795
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
Conversation
…etStorageClass actions
chingor13
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you set delete rules and lifecycle rules, won't the lifecycle rules overwrite the delete ones?
Should we merge the underlying representation of all the rules to be lifecycle rules?
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left one request in comment for now and have three follow-up requests.
-
Could you add an integration test that exercises this against the service?
-
Also the code should keep the existing unit tests for the Deprecated method until it's removed entirely. At the moment the new feature removes support for the Deprecated
setDeleteRules(). -
Could you format your code using this tool https://github.com/google/google-java-format?
...le-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
Show resolved
Hide resolved
| })); | ||
| builder.setDeleteRules( | ||
| transform( | ||
| bucketPb.getLifecycle().getRule(), |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
|
||
| @Test | ||
| public void testGetBucketLifecycleRules() { | ||
| Bucket remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.values())); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| storage = remoteStorageHelper.getOptions().getService(); | ||
| storage.create( | ||
| BucketInfo.newBuilder(BUCKET) | ||
| .setDeleteRules(Collections.singleton(new BucketInfo.AgeDeleteRule(1))) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| Rule rule = new Rule(); | ||
|
|
||
| Rule.Action action = new Rule.Action().setType(lifecycleAction.getActionType()); | ||
| if (lifecycleAction instanceof SetStorageClassLifecycleAction) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
|
||
| switch (action.getType()) { | ||
| case DeleteLifecycleAction.TYPE: | ||
| { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| return createdBefore; | ||
| } | ||
|
|
||
| public LifecycleCondition setCreatedBefore(DateTime createdBefore) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Builder feedback and a few other nits. Thanks @JesseLovelace!
| @Test | ||
| public void testLifecycleRules() { | ||
| Rule deleteLifecycleRule = new LifecycleRule(new LifecycleRule.DeleteLifecycleAction(), | ||
| new LifecycleRule.LifecycleCondition.Builder().setAge(10).build()).toPb(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| .setCreatedBefore(new DateTime(System.currentTimeMillis())) | ||
| .setMatchesStorageClass(ImmutableList.of(StorageClass.COLDLINE)) | ||
| .build()))) | ||
| .build()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| .setNumberOfNewerVersions(3) | ||
| .setIsLive(false) | ||
| .setCreatedBefore(new DateTime(System.currentTimeMillis())) | ||
| .setMatchesStorageClass(ImmutableList.of(StorageClass.COLDLINE)) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| private static final String KMS_KEY_ONE_NAME = "gcs_kms_key_one"; | ||
| private static final String KMS_KEY_TWO_NAME = "gcs_kms_key_two"; | ||
| private static final boolean IS_VPC_TEST = System.getenv("GOOGLE_CLOUD_TESTS_IN_VPCSC") != null | ||
| && System.getenv("GOOGLE_CLOUD_TESTS_IN_VPCSC").equalsIgnoreCase("true"); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| } | ||
| } | ||
|
|
||
| public static class SetStorageClassLifecycleAction extends LifecycleAction { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| new LifecycleRule.SetStorageClassLifecycleAction(StorageClass.COLDLINE), | ||
| new LifecycleRule.LifecycleCondition.Builder().setIsLive(true).setNumberOfNewerVersions(10).build()).toPb(); | ||
|
|
||
| assertEquals("COLDLINE", setStorageClassLifecycleRule.getAction().getStorageClass()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| Rule deleteLifecycleRule = new LifecycleRule(new LifecycleRule.DeleteLifecycleAction(), | ||
| new LifecycleRule.LifecycleCondition.Builder().setAge(10).build()).toPb(); | ||
|
|
||
| assertEquals("Delete", deleteLifecycleRule.getAction().getType()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these are my last nits.
| switch (action.getType()) { | ||
| case DeleteLifecycleAction.TYPE: | ||
| lifecycleAction = new DeleteLifecycleAction(); | ||
| lifecycleAction = LifecycleAction.newDeleteLifecycleAction(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| case SetStorageClassLifecycleAction.TYPE: | ||
| lifecycleAction = | ||
| new SetStorageClassLifecycleAction(StorageClass.valueOf(action.getStorageClass())); | ||
| LifecycleAction.newSetStorageClassLifecycleAction(StorageClass.valueOf(action.getStorageClass())); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| assertEquals("COLDLINE", setStorageClassLifecycleRule.getAction().getStorageClass()); | ||
| assertEquals(StorageClass.COLDLINE, setStorageClassLifecycleRule.getAction().getStorageClass()); | ||
| assertTrue(setStorageClassLifecycleRule.getCondition().getIsLive()); | ||
| assertEquals(10, (long)setStorageClassLifecycleRule.getCondition().getNumNewerVersions()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| .toPb(); | ||
|
|
||
| assertEquals(LifecycleRule.DeleteLifecycleAction.TYPE, deleteLifecycleRule.getAction().getType()); | ||
| assertEquals(10, (long)deleteLifecycleRule.getCondition().getAge()); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary comments:
- Reduce length of class names for Actions by removing Lifecycle.
- Try to use more of cloud.google.com/storage/docs documentation on this feature with your method javadocs.
- Add short snippets of how to use the new feature in the javadoc sparingly. We will have samples, but in the mean time it will help provide direction.
- One question about a possible breaking change.
Looks good! Minor requests.
| /** | ||
| * Condition for a Lifecycle rule, specifies under what criteria an Action should be executed | ||
| * | ||
| * @see <a href="https://cloud.google.com/storage/docs/lifecycle">Object Lifecycle Management</a> |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * Lifecycle rule for a bucket. Allows supported Actions, such as deleting and changing storage class, | ||
| * to be executed when certain Conditions are met | ||
| * | ||
| * @see <a href="https://cloud.google.com/storage/docs/lifecycle">Object Lifecycle Management</a> |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * @see <a href="https://cloud.google.com/storage/docs/lifecycle">Object Lifecycle Management</a> | ||
| * | ||
| * @deprecated Use a {@code LifecycleRule} with a {@code DeleteLifecycleAction} and use | ||
| * {@code LifecycleCondition.Builder.setAge} instead |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| @Override | ||
| void populateCondition(Rule.Condition condition) { | ||
| condition.setCreatedBefore(new DateTime(timeMillis)); | ||
| condition.setCreatedBefore(new DateTime(true, timeMillis, 0)); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * Sets the bucket's lifecycle configuration as a number of lifecycle rules, consisting of an action and a | ||
| * condition. | ||
| * | ||
| * @see <a href="https://cloud.google.com/storage/docs/lifecycle">Lifecycle Management</a> |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
|
||
| /** Sets whether a Live Blob meets the Condition for an Action to be executed. If this is set to {@code false}, | ||
| * the condition is met by Archived Blobs. | ||
| */ |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| return this; | ||
| } | ||
|
|
||
| /** Sets a list of Storage Classes ({@code StorageClass} objects) for a Blob to match for an Action to be executed **/ |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
|
||
| /** | ||
| * Base class for the Action to take when a Lifecycle Condition is met. Specific Actions are expressed as subclasses | ||
| * of this class, accessed by static factory methods |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * | ||
| * @param storageclass The {@code StorageClass} to set Blobs that meet the condition to | ||
| */ | ||
| public static SetStorageClassLifecycleAction newSetStorageClassAction(StorageClass storageclass) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| /** Creates a new {@code SetStorageClassLifecycleAction}. Blobs that meet the Condition associated with this | ||
| * action will have their Storage Class changed to the one specified | ||
| * | ||
| * @param storageclass The {@code StorageClass} to set Blobs that meet the condition to |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * | ||
| * @deprecated Use a {@code LifecycleRule} with a {@code DeleteLifecycleAction} and use | ||
| * {@code LifecycleCondition.Builder.setAge} instead | ||
| * @deprecated Use a {@code LifecycleRule} with a {@code DeleteLifecycleAction} and use {@code |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last nit, mainly spacing and then I'll approve.
Thanks @JesseLovelace
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add a new line between deprecation message and the example.
- Found another missing period I missed on the last review.
| } | ||
|
|
||
| /** | ||
| * Condition for a Lifecycle rule, specifies under what criteria an Action should be executed |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One missed period. I think that's the last of my comments. Double checking on the generated javadocs. What do you think about the @deprecation section rendered?
|
|
||
| /** | ||
| * Lifecycle rule for a bucket. Allows supported Actions, such as deleting and changing storage class, | ||
| * to be executed when certain Conditions are met |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, One additional AI discussed offline is to format the code with the java formatter.
frankyn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments are now within column limits. LGTM Thanks @JesseLovelace!
(Note: I'm holding on off Javadoc until the general class structure is approved)
This deprecates DeleteRules and establishes LifecycleRules as the standard to support object lifecycle management. The DeleteRules approach had the following problems:
Instead of following this pattern I've established a new pattern that more closely mirrors the API spec. Now rules are described by LifecycleRules, which have a LifecycleAction (currently Delete or SetStorageClass) and a LifecycleCondition(At least one of age, created before, num newer versions, etc). This way if a new action is created we only have to add one new subclass of LifecycleAction (instead of an amount equal to the number of conditions) and if a new condition is created we just add one new field to LifecycleCondition.
In addition to the new approach, this PR adds support for SetStorageClass lifecycle actions and MatchesStorageClass lifecycle conditions.