From 7c3aba2f0a26ac550e4f37f9287ed6b041d75919 Mon Sep 17 00:00:00 2001 From: Sydney Munro <97561403+sydney-munro@users.noreply.github.com> Date: Tue, 7 Jun 2022 13:28:12 -0700 Subject: [PATCH] feat: Support AbortIncompleteMultipartUpload LifecycleAction (#1347) * Support AbortIncompleteMultipartUpload LifecycleAction --- .../com/google/cloud/storage/BucketInfo.java | 21 ++++++++++++++++ .../google/cloud/storage/BucketInfoTest.java | 21 ++++++++++++++++ .../cloud/storage/it/ITStorageTest.java | 24 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index e03110ff2..16d802476 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -548,6 +548,9 @@ static LifecycleRule fromPb(Rule rule) { LifecycleAction.newSetStorageClassAction( StorageClass.valueOf(action.getStorageClass())); break; + case AbortIncompleteMPUAction.TYPE: + lifecycleAction = LifecycleAction.newAbortIncompleteMPUploadAction(); + break; default: log.warning( "The lifecycle action " @@ -845,6 +848,15 @@ public static SetStorageClassLifecycleAction newSetStorageClassAction( return new SetStorageClassLifecycleAction(storageClass); } + /** + * Create a new {@code AbortIncompleteMPUAction}. An incomplete multipart upload will be + * aborted when the multipart upload meets the specified condition. Age is the only condition + * supported for this action. See: https://cloud.google.com/storage/docs/lifecycle##abort-mpu + */ + public static LifecycleAction newAbortIncompleteMPUploadAction() { + return new AbortIncompleteMPUAction(); + } + /** * Creates a new {@code LifecycleAction , with no specific supported action associated with it. This * is only intended as a "backup" for when the library doesn't recognize the type, and should @@ -888,6 +900,15 @@ public StorageClass getStorageClass() { return storageClass; } } + + public static class AbortIncompleteMPUAction extends LifecycleAction { + public static final String TYPE = "AbortIncompleteMultipartUpload"; + private static final long serialVersionUID = -1072182310389348060L; + + private AbortIncompleteMPUAction() { + super(TYPE); + } + } } /** diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java index 2041de556..96eeb38e0 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java @@ -39,8 +39,11 @@ import com.google.cloud.storage.BucketInfo.IamConfiguration; import com.google.cloud.storage.BucketInfo.IsLiveDeleteRule; import com.google.cloud.storage.BucketInfo.LifecycleRule; +import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction; +import com.google.cloud.storage.BucketInfo.LifecycleRule.DeleteLifecycleAction; import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleAction; import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleCondition; +import com.google.cloud.storage.BucketInfo.LifecycleRule.SetStorageClassLifecycleAction; import com.google.cloud.storage.BucketInfo.NumNewerVersionsDeleteRule; import com.google.cloud.storage.BucketInfo.PublicAccessPrevention; import com.google.cloud.storage.BucketInfo.RawDeleteRule; @@ -331,6 +334,8 @@ public void testLifecycleRules() { assertEquals( LifecycleRule.DeleteLifecycleAction.TYPE, deleteLifecycleRule.getAction().getType()); assertEquals(10, deleteLifecycleRule.getCondition().getAge().intValue()); + assertTrue( + LifecycleRule.fromPb(deleteLifecycleRule).getAction() instanceof DeleteLifecycleAction); Rule setStorageClassLifecycleRule = new LifecycleRule( @@ -346,6 +351,9 @@ public void testLifecycleRules() { setStorageClassLifecycleRule.getAction().getStorageClass()); assertTrue(setStorageClassLifecycleRule.getCondition().getIsLive()); assertEquals(10, setStorageClassLifecycleRule.getCondition().getNumNewerVersions().intValue()); + assertTrue( + LifecycleRule.fromPb(setStorageClassLifecycleRule).getAction() + instanceof SetStorageClassLifecycleAction); Rule lifecycleRule = new LifecycleRule( @@ -367,6 +375,19 @@ public void testLifecycleRules() { assertEquals(StorageClass.COLDLINE.toString(), lifecycleRule.getAction().getStorageClass()); assertEquals(30, lifecycleRule.getCondition().getDaysSinceCustomTime().intValue()); assertNotNull(lifecycleRule.getCondition().getCustomTimeBefore()); + assertTrue( + LifecycleRule.fromPb(lifecycleRule).getAction() instanceof SetStorageClassLifecycleAction); + + Rule abortMpuLifecycleRule = + new LifecycleRule( + LifecycleAction.newAbortIncompleteMPUploadAction(), + LifecycleCondition.newBuilder().setAge(10).build()) + .toPb(); + assertEquals(AbortIncompleteMPUAction.TYPE, abortMpuLifecycleRule.getAction().getType()); + assertEquals(10, abortMpuLifecycleRule.getCondition().getAge().intValue()); + assertTrue( + LifecycleRule.fromPb(abortMpuLifecycleRule).getAction() + instanceof AbortIncompleteMPUAction); Rule unsupportedRule = new LifecycleRule( diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index e5ecf1f04..b1863b38e 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -66,6 +66,7 @@ import com.google.cloud.storage.Bucket; import com.google.cloud.storage.BucketInfo; import com.google.cloud.storage.BucketInfo.LifecycleRule; +import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction; import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleAction; import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleCondition; import com.google.cloud.storage.CopyWriter; @@ -565,6 +566,29 @@ public void testGetBucketLifecycleRules() { } } + @Test + public void testGetBucketAbortMPULifecycle() { + String lifecycleTestBucketName = RemoteStorageHelper.generateBucketName(); + storage.create( + BucketInfo.newBuilder(lifecycleTestBucketName) + .setLocation("us") + .setLifecycleRules( + ImmutableList.of( + new LifecycleRule( + LifecycleAction.newAbortIncompleteMPUploadAction(), + LifecycleCondition.newBuilder().setAge(1).build()))) + .build()); + Bucket remoteBucket = + storage.get(lifecycleTestBucketName, Storage.BucketGetOption.fields(BucketField.LIFECYCLE)); + LifecycleRule lifecycleRule = remoteBucket.getLifecycleRules().get(0); + try { + assertEquals(AbortIncompleteMPUAction.TYPE, lifecycleRule.getAction().getActionType()); + assertEquals(1, lifecycleRule.getCondition().getAge().intValue()); + } finally { + storage.delete(lifecycleTestBucketName); + } + } + @Test public void testClearBucketDefaultKmsKeyName() throws ExecutionException, InterruptedException { String bucketName = RemoteStorageHelper.generateBucketName();