From 2f291d39cf58070458edb2a0e032a466d0cbb910 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 14 Aug 2018 02:09:53 -0700 Subject: [PATCH 01/13] Add support for defaultEventBasedHold --- .../java/com/google/cloud/storage/Bucket.java | 6 +++++ .../com/google/cloud/storage/BucketInfo.java | 27 +++++++++++++++++++ .../com/google/cloud/storage/Storage.java | 3 ++- .../google/cloud/storage/BucketInfoTest.java | 4 +++ .../com/google/cloud/storage/BucketTest.java | 4 +++ .../cloud/storage/it/ITStorageTest.java | 22 +++++++++++++++ 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 179e8a5cbfef..cd542aaf7b06 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -635,6 +635,12 @@ public Builder setDefaultKmsKeyName(String defaultKmsKeyName) { return this; } + @Override + public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) { + infoBuilder.setDefaultEventBasedHold(defaultEventBasedHold); + return this; + } + @Override public Bucket build() { return new Bucket(storage, infoBuilder); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 6e0b3e2c38e9..01513bfb822a 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -88,6 +88,7 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo) private final StorageClass storageClass; private final Map labels; private final String defaultKmsKeyName; + private final Boolean defaultEventBasedHold; /** * Base class for bucket's delete rules. Allows to configure automatic deletion of blobs and blobs @@ -432,6 +433,11 @@ public abstract static class Builder { @GcpLaunchStage.Beta public abstract Builder setDefaultKmsKeyName(String defaultKmsKeyName); + /** + * Sets the default Event Based Hold for this bucket. + */ + public abstract Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold); + /** * Creates a {@code BucketInfo} object. */ @@ -459,6 +465,7 @@ static final class BuilderImpl extends Builder { private List defaultAcl; private Map labels; private String defaultKmsKeyName; + private Boolean defaultEventBasedHold; BuilderImpl(String name) { this.name = name; @@ -484,6 +491,7 @@ static final class BuilderImpl extends Builder { labels = bucketInfo.labels; requesterPays = bucketInfo.requesterPays; defaultKmsKeyName = bucketInfo.defaultKmsKeyName; + defaultEventBasedHold = bucketInfo.defaultEventBasedHold; } @Override @@ -603,6 +611,12 @@ public Builder setDefaultKmsKeyName(String defaultKmsKeyName) { return this; } + @Override + public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) { + this.defaultEventBasedHold = firstNonNull(defaultEventBasedHold, Data.nullOf(Boolean.class)); + return this; + } + @Override public BucketInfo build() { checkNotNull(name); @@ -630,6 +644,7 @@ public BucketInfo build() { labels = builder.labels; requesterPays = builder.requesterPays; defaultKmsKeyName = builder.defaultKmsKeyName; + defaultEventBasedHold = builder.defaultEventBasedHold; } /** @@ -790,6 +805,11 @@ public String getDefaultKmsKeyName() { return defaultKmsKeyName; } + /** + * Returns the default Event Based Hold to be applied to newly inserted objects in this bucket. + */ + public Boolean getDefaultEventBasedHold() { return defaultEventBasedHold; } + /** * Returns a builder for the current bucket. */ @@ -888,6 +908,10 @@ public Rule apply(DeleteRule deleteRule) { if (defaultKmsKeyName != null) { bucketPb.setEncryption(new Encryption().setDefaultKmsKeyName(defaultKmsKeyName)); } + if (defaultEventBasedHold != null) { + bucketPb.setDefaultEventBasedHold(defaultEventBasedHold); + } + return bucketPb; } @@ -979,6 +1003,9 @@ public DeleteRule apply(Rule rule) { if (encryption != null && encryption.getDefaultKmsKeyName() != null && !encryption.getDefaultKmsKeyName().isEmpty()) { builder.setDefaultKmsKeyName(encryption.getDefaultKmsKeyName()); } + if (bucketPb.getDefaultEventBasedHold() != null) { + builder.setDefaultEventBasedHold(bucketPb.getDefaultEventBasedHold()); + } return builder.build(); } } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index b49d48c70b08..dde1495f2036 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -95,7 +95,8 @@ enum BucketField implements FieldSelector { ETAG("etag"), @GcpLaunchStage.Beta ENCRYPTION("encryption"), - BILLING("billing"); + BILLING("billing"), + DEFAULT_EVENT_BASED_HOLD("defaultEventBasedHold"); static final List REQUIRED_FIELDS = ImmutableList.of(NAME); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java index d31dd0246e0b..22f95276d203 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java @@ -64,6 +64,7 @@ public class BucketInfoTest { private static final Boolean VERSIONING_ENABLED = true; private static final Map BUCKET_LABELS = ImmutableMap.of("label1", "value1"); private static final Boolean REQUESTER_PAYS = true; + private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; private static final BucketInfo BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACL) .setEtag(ETAG) @@ -83,6 +84,7 @@ public class BucketInfoTest { .setLabels(BUCKET_LABELS) .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) + .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) .build(); @Test @@ -128,6 +130,7 @@ public void testBuilder() { assertEquals(VERSIONING_ENABLED, BUCKET_INFO.versioningEnabled()); assertEquals(BUCKET_LABELS, BUCKET_INFO.getLabels()); assertEquals(REQUESTER_PAYS, BUCKET_INFO.requesterPays()); + assertEquals(DEFAULT_EVENT_BASED_HOLD, BUCKET_INFO.getDefaultEventBasedHold()); } @Test @@ -158,6 +161,7 @@ private void compareBuckets(BucketInfo expected, BucketInfo value) { assertEquals(expected.versioningEnabled(), value.versioningEnabled()); assertEquals(expected.getLabels(), value.getLabels()); assertEquals(expected.requesterPays(), value.requesterPays()); + assertEquals(expected.getDefaultEventBasedHold(), value.getDefaultEventBasedHold()); } @Test diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java index 707a9f3c7565..f7317e8ce206 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java @@ -82,6 +82,7 @@ public class BucketTest { private static final Map BUCKET_LABELS = ImmutableMap.of("label1", "value1"); private static final Boolean REQUESTER_PAYS = true; private static final String USER_PROJECT = "test-project"; + private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; private static final BucketInfo FULL_BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACLS) .setEtag(ETAG) @@ -101,6 +102,7 @@ public class BucketTest { .setLabels(BUCKET_LABELS) .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) + .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) .build(); private static final BucketInfo BUCKET_INFO = BucketInfo.newBuilder("b").setMetageneration(42L).build(); @@ -694,6 +696,7 @@ public void testBuilder() { .setLabels(BUCKET_LABELS) .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) + .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) .build(); assertEquals("b", bucket.getName()); assertEquals(ACLS, bucket.getAcl()); @@ -714,6 +717,7 @@ public void testBuilder() { assertEquals(BUCKET_LABELS, bucket.getLabels()); assertEquals(REQUESTER_PAYS, bucket.requesterPays()); assertEquals(DEFAULT_KMS_KEY_NAME, bucket.getDefaultKmsKeyName()); + assertEquals(DEFAULT_EVENT_BASED_HOLD, bucket.getDefaultEventBasedHold()); assertEquals(storage.getOptions(), bucket.getStorage().getOptions()); } } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index ce873f9ea717..c6a36888d4f9 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -209,6 +209,28 @@ public void testUpdateBucketDefaultKmsKeyName() throws ExecutionException, Inter } } + @Test + public void testCreateDefaultEventBasedHoldBucket() throws ExecutionException, InterruptedException { + String bucketName = RemoteStorageHelper.generateBucketName(); + Bucket remoteBucket = storage.create(BucketInfo.newBuilder(bucketName).setDefaultEventBasedHold(true).build()); + + try { + assertTrue(remoteBucket.getDefaultEventBasedHold()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testEnableDisableBucketDefaultEventBasedHold() { + Bucket remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD, BucketField.BILLING)); + assertNull(remoteBucket.getDefaultEventBasedHold()); + Bucket updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(true).build().update(); + assertTrue(updatedBucket.getDefaultEventBasedHold()); + updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update().reload(); + assertFalse(updatedBucket.getDefaultEventBasedHold()); + } + @Test public void testCreateBlob() { String blobName = "test-create-blob"; From 23c27bc1a214cf596f32994683da13397423e6d9 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 14 Aug 2018 13:38:32 -0700 Subject: [PATCH 02/13] Add support for Blob eventBasedHold --- .../java/com/google/cloud/storage/Blob.java | 6 +++++ .../com/google/cloud/storage/BlobInfo.java | 22 +++++++++++++++++++ .../com/google/cloud/storage/Storage.java | 1 + .../google/cloud/storage/BlobInfoTest.java | 5 +++++ .../com/google/cloud/storage/BlobTest.java | 6 +++++ .../cloud/storage/it/ITStorageTest.java | 20 +++++++++++++++++ 6 files changed, 60 insertions(+) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index a5d14126e0f6..3eda92bf9ccd 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -409,6 +409,12 @@ Builder setKmsKeyName(String kmsKeyName) { return this; } + @Override + public Builder setEventBasedHold(Boolean eventBasedHold) { + infoBuilder.setEventBasedHold(eventBasedHold); + return this; + } + @Override public Blob build() { return new Blob(storage, infoBuilder); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index 386daa63390a..154407ae276c 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -85,6 +85,7 @@ public StorageObject apply(BlobInfo blobInfo) { private final boolean isDirectory; private final CustomerEncryption customerEncryption; private final String kmsKeyName; + private final Boolean eventBasedHold; /** * This class is meant for internal use only. Users are discouraged from using this class. @@ -275,6 +276,12 @@ public abstract static class Builder { @GcpLaunchStage.Beta abstract Builder setKmsKeyName(String kmsKeyName); + /** + * Sets the blob's eventBasedHold. + */ + public abstract Builder setEventBasedHold(Boolean eventBasedHold); + + /** * Creates a {@code BlobInfo} object. */ @@ -308,6 +315,7 @@ static final class BuilderImpl extends Builder { private CustomerEncryption customerEncryption; private StorageClass storageClass; private String kmsKeyName; + private Boolean eventBasedHold; BuilderImpl(BlobId blobId) { this.blobId = blobId; @@ -339,6 +347,7 @@ static final class BuilderImpl extends Builder { isDirectory = blobInfo.isDirectory; storageClass = blobInfo.storageClass; kmsKeyName = blobInfo.kmsKeyName; + eventBasedHold = blobInfo.eventBasedHold; } @Override @@ -493,6 +502,12 @@ Builder setKmsKeyName(String kmsKeyName) { return this; } + @Override + public Builder setEventBasedHold(Boolean eventBasedHold) { + this.eventBasedHold = eventBasedHold; + return this; + } + @Override public BlobInfo build() { checkNotNull(blobId); @@ -526,6 +541,7 @@ public BlobInfo build() { isDirectory = firstNonNull(builder.isDirectory, Boolean.FALSE); storageClass = builder.storageClass; kmsKeyName = builder.kmsKeyName; + eventBasedHold = builder.eventBasedHold; } /** @@ -764,6 +780,8 @@ public String getKmsKeyName() { return kmsKeyName; } + public Boolean getEventBasedHold() { return eventBasedHold; } + /** * Returns a builder for the current blob. */ @@ -838,6 +856,7 @@ public ObjectAccessControl apply(Acl acl) { } storageObject.setKmsKeyName(kmsKeyName); + storageObject.setEventBasedHold(eventBasedHold); storageObject.setMetadata(pbMetadata); storageObject.setCacheControl(cacheControl); storageObject.setContentEncoding(contentEncoding); @@ -971,6 +990,9 @@ public Acl apply(ObjectAccessControl objectAccessControl) { if (storageObject.getKmsKeyName() != null) { builder.setKmsKeyName(storageObject.getKmsKeyName()); } + if (storageObject.getEventBasedHold() != null) { + builder.setEventBasedHold(storageObject.getEventBasedHold()); + } return builder.build(); } } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index dde1495f2036..08b0b1b8ebb2 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -139,6 +139,7 @@ enum BlobField implements FieldSelector { TIME_DELETED("timeDeleted"), @GcpLaunchStage.Beta KMS_KEY_NAME("kmsKeyName"), + EVENT_BASED_HOLD("eventBasedHold"), UPDATED("updated"); static final List REQUIRED_FIELDS = ImmutableList.of(BUCKET, NAME); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java index 460bdb1ea811..7b503ae11452 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java @@ -68,6 +68,7 @@ public class BlobInfoTest { new CustomerEncryption(ENCRYPTION_ALGORITHM, KEY_SHA256); private static final String KMS_KEY_NAME = "projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key"; private static final StorageClass STORAGE_CLASS = StorageClass.COLDLINE; + private static final Boolean EVENT_BASED_HOLD = true; private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACL) @@ -93,6 +94,7 @@ public class BlobInfoTest { .setCreateTime(CREATE_TIME) .setStorageClass(STORAGE_CLASS) .setKmsKeyName(KMS_KEY_NAME) + .setEventBasedHold(EVENT_BASED_HOLD) .build(); private static final BlobInfo DIRECTORY_INFO = BlobInfo.newBuilder("b", "n/") .setSize(0L) @@ -156,6 +158,7 @@ public void testBuilder() { assertEquals(CREATE_TIME, BLOB_INFO.getCreateTime()); assertEquals(STORAGE_CLASS, BLOB_INFO.getStorageClass()); assertEquals(KMS_KEY_NAME, BLOB_INFO.getKmsKeyName()); + assertEquals(EVENT_BASED_HOLD, BLOB_INFO.getEventBasedHold()); assertFalse(BLOB_INFO.isDirectory()); assertEquals("b", DIRECTORY_INFO.getBucket()); assertEquals("n/", DIRECTORY_INFO.getName()); @@ -212,6 +215,7 @@ private void compareBlobs(BlobInfo expected, BlobInfo value) { assertEquals(expected.getUpdateTime(), value.getUpdateTime()); assertEquals(expected.getStorageClass(), value.getStorageClass()); assertEquals(expected.getKmsKeyName(), value.getKmsKeyName()); + assertEquals(expected.getEventBasedHold(), value.getEventBasedHold()); } private void compareCustomerEncryptions(CustomerEncryption expected, CustomerEncryption value) { @@ -260,6 +264,7 @@ public void testToPbAndFromPb() { assertNull(blobInfo.getUpdateTime()); assertNull(blobInfo.getStorageClass()); assertNull(blobInfo.getKmsKeyName()); + assertNull(blobInfo.getEventBasedHold()); assertTrue(blobInfo.isDirectory()); } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java index f1b52a526b71..68b95c1dab85 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java @@ -92,6 +92,7 @@ public class BlobTest { private static final BlobInfo.CustomerEncryption CUSTOMER_ENCRYPTION = new BlobInfo.CustomerEncryption(ENCRYPTION_ALGORITHM, KEY_SHA256); private static final String KMS_KEY_NAME = "projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key"; + private static final Boolean EVENT_BASED_HOLD = true; private static final BlobInfo FULL_BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACLS) .setComponentCount(COMPONENT_COUNT) @@ -115,6 +116,7 @@ public class BlobTest { .setCreateTime(CREATE_TIME) .setCustomerEncryption(CUSTOMER_ENCRYPTION) .setKmsKeyName(KMS_KEY_NAME) + .setEventBasedHold(EVENT_BASED_HOLD) .build(); private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n") .setMetageneration(42L) @@ -472,6 +474,7 @@ public void testBuilder() { .setCreateTime(CREATE_TIME) .setCustomerEncryption(CUSTOMER_ENCRYPTION) .setKmsKeyName(KMS_KEY_NAME) + .setEventBasedHold(EVENT_BASED_HOLD) .setDeleteTime(DELETE_TIME) .setEtag(ETAG) .setGeneratedId(GENERATED_ID) @@ -496,6 +499,8 @@ public void testBuilder() { assertEquals(CRC32, blob.getCrc32c()); assertEquals(CREATE_TIME, blob.getCreateTime()); assertEquals(CUSTOMER_ENCRYPTION, blob.getCustomerEncryption()); + assertEquals(KMS_KEY_NAME, blob.getKmsKeyName()); + assertEquals(EVENT_BASED_HOLD, blob.getEventBasedHold()); assertEquals(DELETE_TIME, blob.getDeleteTime()); assertEquals(ETAG, blob.getEtag()); assertEquals(GENERATED_ID, blob.getGeneratedId()); @@ -527,6 +532,7 @@ public void testBuilder() { assertNull(blob.getCreateTime()); assertNull(blob.getCustomerEncryption()); assertNull(blob.getKmsKeyName()); + assertNull(blob.getEventBasedHold()); assertNull(blob.getDeleteTime()); assertNull(blob.getEtag()); assertNull(blob.getGeneratedId()); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index c6a36888d4f9..714d5f5ff20c 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -227,10 +227,30 @@ public void testEnableDisableBucketDefaultEventBasedHold() { assertNull(remoteBucket.getDefaultEventBasedHold()); Bucket updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(true).build().update(); assertTrue(updatedBucket.getDefaultEventBasedHold()); + String blobName = "test-create-with-event-based-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getEventBasedHold()); + remoteBlob = remoteBlob.toBuilder().setEventBasedHold(false).build().update(); + assertFalse(remoteBlob.getEventBasedHold()); updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update().reload(); assertFalse(updatedBucket.getDefaultEventBasedHold()); } + @Test + public void testAttemptDeletionObjectEventBasedHold() { + String blobName = "test-create-with-event-based-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setEventBasedHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getEventBasedHold()); + try { + remoteBlob.delete(); + fail("Expected failure on delete from eventBasedHold"); + } catch (StorageException ex) { + // expected + } + } + @Test public void testCreateBlob() { String blobName = "test-create-blob"; From 65357aa3d15b477c5a7d4b03996cc3bdb382bfb5 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 14 Aug 2018 14:22:32 -0700 Subject: [PATCH 03/13] Add support for blob temporary holds --- .../java/com/google/cloud/storage/Blob.java | 6 +++ .../com/google/cloud/storage/BlobInfo.java | 26 ++++++++++++ .../com/google/cloud/storage/Storage.java | 1 + .../google/cloud/storage/BlobInfoTest.java | 5 +++ .../com/google/cloud/storage/BlobTest.java | 5 +++ .../cloud/storage/it/ITStorageTest.java | 42 ++++++++++++++++--- 6 files changed, 80 insertions(+), 5 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index 3eda92bf9ccd..8733d18964fa 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -415,6 +415,12 @@ public Builder setEventBasedHold(Boolean eventBasedHold) { return this; } + @Override + public Builder setTemporaryHold(Boolean temporaryHold) { + infoBuilder.setTemporaryHold(temporaryHold); + return this; + } + @Override public Blob build() { return new Blob(storage, infoBuilder); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index 154407ae276c..00dc0f116741 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -86,6 +86,7 @@ public StorageObject apply(BlobInfo blobInfo) { private final CustomerEncryption customerEncryption; private final String kmsKeyName; private final Boolean eventBasedHold; + private final Boolean temporaryHold; /** * This class is meant for internal use only. Users are discouraged from using this class. @@ -281,6 +282,10 @@ public abstract static class Builder { */ public abstract Builder setEventBasedHold(Boolean eventBasedHold); + /** + * Sets the blob's temporaryHold. + */ + public abstract Builder setTemporaryHold(Boolean temporaryHold); /** * Creates a {@code BlobInfo} object. @@ -316,6 +321,7 @@ static final class BuilderImpl extends Builder { private StorageClass storageClass; private String kmsKeyName; private Boolean eventBasedHold; + private Boolean temporaryHold; BuilderImpl(BlobId blobId) { this.blobId = blobId; @@ -348,6 +354,7 @@ static final class BuilderImpl extends Builder { storageClass = blobInfo.storageClass; kmsKeyName = blobInfo.kmsKeyName; eventBasedHold = blobInfo.eventBasedHold; + temporaryHold = blobInfo.temporaryHold; } @Override @@ -508,6 +515,12 @@ public Builder setEventBasedHold(Boolean eventBasedHold) { return this; } + @Override + public Builder setTemporaryHold(Boolean temporaryHold) { + this.temporaryHold = temporaryHold; + return this; + } + @Override public BlobInfo build() { checkNotNull(blobId); @@ -542,6 +555,7 @@ public BlobInfo build() { storageClass = builder.storageClass; kmsKeyName = builder.kmsKeyName; eventBasedHold = builder.eventBasedHold; + temporaryHold = builder.temporaryHold; } /** @@ -780,8 +794,16 @@ public String getKmsKeyName() { return kmsKeyName; } + /** + * Returns the Event Based Hold status of the blob, if any. + */ public Boolean getEventBasedHold() { return eventBasedHold; } + /** + * Returns the Temporary Hold status of the blob, if any. + */ + public Boolean getTemporaryHold() { return temporaryHold; } + /** * Returns a builder for the current blob. */ @@ -857,6 +879,7 @@ public ObjectAccessControl apply(Acl acl) { storageObject.setKmsKeyName(kmsKeyName); storageObject.setEventBasedHold(eventBasedHold); + storageObject.setTemporaryHold(temporaryHold); storageObject.setMetadata(pbMetadata); storageObject.setCacheControl(cacheControl); storageObject.setContentEncoding(contentEncoding); @@ -993,6 +1016,9 @@ public Acl apply(ObjectAccessControl objectAccessControl) { if (storageObject.getEventBasedHold() != null) { builder.setEventBasedHold(storageObject.getEventBasedHold()); } + if (storageObject.getTemporaryHold() != null) { + builder.setTemporaryHold(storageObject.getTemporaryHold()); + } return builder.build(); } } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 08b0b1b8ebb2..d8311d3fd266 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -140,6 +140,7 @@ enum BlobField implements FieldSelector { @GcpLaunchStage.Beta KMS_KEY_NAME("kmsKeyName"), EVENT_BASED_HOLD("eventBasedHold"), + TEMPORARY_HOLD("temporaryHold"), UPDATED("updated"); static final List REQUIRED_FIELDS = ImmutableList.of(BUCKET, NAME); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java index 7b503ae11452..43c95aeec5ef 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java @@ -69,6 +69,7 @@ public class BlobInfoTest { private static final String KMS_KEY_NAME = "projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key"; private static final StorageClass STORAGE_CLASS = StorageClass.COLDLINE; private static final Boolean EVENT_BASED_HOLD = true; + private static final Boolean TEMPORARY_HOLD = true; private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACL) @@ -95,6 +96,7 @@ public class BlobInfoTest { .setStorageClass(STORAGE_CLASS) .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) + .setTemporaryHold(TEMPORARY_HOLD) .build(); private static final BlobInfo DIRECTORY_INFO = BlobInfo.newBuilder("b", "n/") .setSize(0L) @@ -159,6 +161,7 @@ public void testBuilder() { assertEquals(STORAGE_CLASS, BLOB_INFO.getStorageClass()); assertEquals(KMS_KEY_NAME, BLOB_INFO.getKmsKeyName()); assertEquals(EVENT_BASED_HOLD, BLOB_INFO.getEventBasedHold()); + assertEquals(TEMPORARY_HOLD, BLOB_INFO.getTemporaryHold()); assertFalse(BLOB_INFO.isDirectory()); assertEquals("b", DIRECTORY_INFO.getBucket()); assertEquals("n/", DIRECTORY_INFO.getName()); @@ -216,6 +219,7 @@ private void compareBlobs(BlobInfo expected, BlobInfo value) { assertEquals(expected.getStorageClass(), value.getStorageClass()); assertEquals(expected.getKmsKeyName(), value.getKmsKeyName()); assertEquals(expected.getEventBasedHold(), value.getEventBasedHold()); + assertEquals(expected.getTemporaryHold(), value.getTemporaryHold()); } private void compareCustomerEncryptions(CustomerEncryption expected, CustomerEncryption value) { @@ -265,6 +269,7 @@ public void testToPbAndFromPb() { assertNull(blobInfo.getStorageClass()); assertNull(blobInfo.getKmsKeyName()); assertNull(blobInfo.getEventBasedHold()); + assertNull(blobInfo.getTemporaryHold()); assertTrue(blobInfo.isDirectory()); } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java index 68b95c1dab85..eac3b36f847d 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java @@ -93,6 +93,7 @@ public class BlobTest { new BlobInfo.CustomerEncryption(ENCRYPTION_ALGORITHM, KEY_SHA256); private static final String KMS_KEY_NAME = "projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key"; private static final Boolean EVENT_BASED_HOLD = true; + private static final Boolean TEMPORARY_HOLD = true; private static final BlobInfo FULL_BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACLS) .setComponentCount(COMPONENT_COUNT) @@ -117,6 +118,7 @@ public class BlobTest { .setCustomerEncryption(CUSTOMER_ENCRYPTION) .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) + .setTemporaryHold(TEMPORARY_HOLD) .build(); private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n") .setMetageneration(42L) @@ -475,6 +477,7 @@ public void testBuilder() { .setCustomerEncryption(CUSTOMER_ENCRYPTION) .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) + .setTemporaryHold(TEMPORARY_HOLD) .setDeleteTime(DELETE_TIME) .setEtag(ETAG) .setGeneratedId(GENERATED_ID) @@ -501,6 +504,7 @@ public void testBuilder() { assertEquals(CUSTOMER_ENCRYPTION, blob.getCustomerEncryption()); assertEquals(KMS_KEY_NAME, blob.getKmsKeyName()); assertEquals(EVENT_BASED_HOLD, blob.getEventBasedHold()); + assertEquals(TEMPORARY_HOLD, blob.getTemporaryHold()); assertEquals(DELETE_TIME, blob.getDeleteTime()); assertEquals(ETAG, blob.getEtag()); assertEquals(GENERATED_ID, blob.getGeneratedId()); @@ -533,6 +537,7 @@ public void testBuilder() { assertNull(blob.getCustomerEncryption()); assertNull(blob.getKmsKeyName()); assertNull(blob.getEventBasedHold()); + assertNull(blob.getTemporaryHold()); assertNull(blob.getDeleteTime()); assertNull(blob.getEtag()); assertNull(blob.getGeneratedId()); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 714d5f5ff20c..15e1225347b0 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -223,18 +223,34 @@ public void testCreateDefaultEventBasedHoldBucket() throws ExecutionException, I @Test public void testEnableDisableBucketDefaultEventBasedHold() { - Bucket remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD, BucketField.BILLING)); + Bucket remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD)); assertNull(remoteBucket.getDefaultEventBasedHold()); - Bucket updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(true).build().update(); - assertTrue(updatedBucket.getDefaultEventBasedHold()); + remoteBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(true).build().update(); + assertTrue(remoteBucket.getDefaultEventBasedHold()); + remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD)); + assertTrue(remoteBucket.getDefaultEventBasedHold()); String blobName = "test-create-with-event-based-hold"; BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).build(); Blob remoteBlob = storage.create(blobInfo); assertTrue(remoteBlob.getEventBasedHold()); + remoteBlob = storage.get(blobInfo.getBlobId(), Storage.BlobGetOption.fields(BlobField.EVENT_BASED_HOLD)); + assertTrue(remoteBlob.getEventBasedHold()); remoteBlob = remoteBlob.toBuilder().setEventBasedHold(false).build().update(); assertFalse(remoteBlob.getEventBasedHold()); - updatedBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update().reload(); - assertFalse(updatedBucket.getDefaultEventBasedHold()); + remoteBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update(); + assertFalse(remoteBucket.getDefaultEventBasedHold()); + } + + @Test + public void testEnableDisableTemporaryHold() { + String blobName = "test-create-with-event-based-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getTemporaryHold()); + remoteBlob = storage.get(remoteBlob.getBlobId(), Storage.BlobGetOption.fields(BlobField.TEMPORARY_HOLD)); + assertTrue(remoteBlob.getTemporaryHold()); + remoteBlob = remoteBlob.toBuilder().setTemporaryHold(false).build().update(); + assertFalse(remoteBlob.getTemporaryHold()); } @Test @@ -251,6 +267,22 @@ public void testAttemptDeletionObjectEventBasedHold() { } } + @Test + public void testAttemptDeletionObjectTemporaryHold() { + String blobName = "test-create-with-temporary-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getTemporaryHold()); + remoteBlob = storage.get(remoteBlob.getBlobId(), Storage.BlobGetOption.fields(BlobField.TEMPORARY_HOLD)); + assertTrue(remoteBlob.getTemporaryHold()); + try { + remoteBlob.delete(); + fail("Expected failure on delete from temporaryHold"); + } catch (StorageException ex) { + // expected + } + } + @Test public void testCreateBlob() { String blobName = "test-create-blob"; From 339e38dfc26e3917073d43ff05c7a6c93f8850ea Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 14 Aug 2018 17:46:30 -0700 Subject: [PATCH 04/13] Add support for lockRetentionPolicy and RetentionPolicy --- .../java/com/google/cloud/storage/Blob.java | 6 + .../com/google/cloud/storage/BlobInfo.java | 27 ++- .../java/com/google/cloud/storage/Bucket.java | 40 ++++ .../com/google/cloud/storage/BucketInfo.java | 80 +++++++ .../com/google/cloud/storage/Storage.java | 24 +- .../com/google/cloud/storage/StorageImpl.java | 17 ++ .../cloud/storage/spi/v1/HttpStorageRpc.java | 17 ++ .../storage/spi/v1/HttpStorageRpcSpans.java | 2 + .../cloud/storage/spi/v1/StorageRpc.java | 7 + .../google/cloud/storage/BlobInfoTest.java | 5 + .../com/google/cloud/storage/BlobTest.java | 5 + .../google/cloud/storage/BucketInfoTest.java | 12 + .../com/google/cloud/storage/BucketTest.java | 29 +++ .../google/cloud/storage/StorageImplTest.java | 25 +- .../cloud/storage/it/ITStorageTest.java | 222 ++++++++++++------ 15 files changed, 438 insertions(+), 80 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index 8733d18964fa..7f0e94af0081 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -421,6 +421,12 @@ public Builder setTemporaryHold(Boolean temporaryHold) { return this; } + @Override + Builder setRetentionExpirationTime(Long retentionExpirationTime) { + infoBuilder.setRetentionExpirationTime(retentionExpirationTime); + return this; + } + @Override public Blob build() { return new Blob(storage, infoBuilder); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index 00dc0f116741..b124bc86e4ad 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -87,6 +87,7 @@ public StorageObject apply(BlobInfo blobInfo) { private final String kmsKeyName; private final Boolean eventBasedHold; private final Boolean temporaryHold; + private final Long retentionExpirationTime; /** * This class is meant for internal use only. Users are discouraged from using this class. @@ -270,10 +271,6 @@ public abstract static class Builder { abstract Builder setCustomerEncryption(CustomerEncryption customerEncryption); - /** - * - * Sets the blob's kmsKeyName. - */ @GcpLaunchStage.Beta abstract Builder setKmsKeyName(String kmsKeyName); @@ -287,6 +284,8 @@ public abstract static class Builder { */ public abstract Builder setTemporaryHold(Boolean temporaryHold); + abstract Builder setRetentionExpirationTime(Long retentionExpirationTime); + /** * Creates a {@code BlobInfo} object. */ @@ -322,6 +321,7 @@ static final class BuilderImpl extends Builder { private String kmsKeyName; private Boolean eventBasedHold; private Boolean temporaryHold; + private Long retentionExpirationTime; BuilderImpl(BlobId blobId) { this.blobId = blobId; @@ -355,6 +355,7 @@ static final class BuilderImpl extends Builder { kmsKeyName = blobInfo.kmsKeyName; eventBasedHold = blobInfo.eventBasedHold; temporaryHold = blobInfo.temporaryHold; + retentionExpirationTime = blobInfo.retentionExpirationTime; } @Override @@ -521,6 +522,12 @@ public Builder setTemporaryHold(Boolean temporaryHold) { return this; } + @Override + Builder setRetentionExpirationTime(Long retentionExpirationTime) { + this.retentionExpirationTime = retentionExpirationTime; + return this; + } + @Override public BlobInfo build() { checkNotNull(blobId); @@ -556,6 +563,7 @@ public BlobInfo build() { kmsKeyName = builder.kmsKeyName; eventBasedHold = builder.eventBasedHold; temporaryHold = builder.temporaryHold; + retentionExpirationTime = builder.retentionExpirationTime; } /** @@ -804,6 +812,11 @@ public String getKmsKeyName() { */ public Boolean getTemporaryHold() { return temporaryHold; } + /** + * Returns the Retention Expiration Time of the blob, if a retention period is defined. + */ + public Long getRetentionExpirationTime() { return retentionExpirationTime; } + /** * Returns a builder for the current blob. */ @@ -876,6 +889,9 @@ public ObjectAccessControl apply(Acl acl) { if (customerEncryption != null) { storageObject.setCustomerEncryption(customerEncryption.toPb()); } + if (retentionExpirationTime != null) { + storageObject.setRetentionExpirationTime(new DateTime(retentionExpirationTime)); + } storageObject.setKmsKeyName(kmsKeyName); storageObject.setEventBasedHold(eventBasedHold); @@ -1019,6 +1035,9 @@ public Acl apply(ObjectAccessControl objectAccessControl) { if (storageObject.getTemporaryHold() != null) { builder.setTemporaryHold(storageObject.getTemporaryHold()); } + if (storageObject.getRetentionExpirationTime() != null) { + builder.setRetentionExpirationTime(storageObject.getRetentionExpirationTime().getValue()); + } return builder.build(); } } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index cd542aaf7b06..761ed0e67650 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -641,6 +641,24 @@ public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) { return this; } + @Override + Builder setRetentionEffectiveTime(Long retentionEffectiveTime) { + infoBuilder.setRetentionEffectiveTime(retentionEffectiveTime); + return this; + } + + @Override + Builder setRetentionPolicyIsLocked(Boolean retentionIsLocked) { + infoBuilder.setRetentionPolicyIsLocked(retentionIsLocked); + return this; + } + + @Override + public Builder setRetentionPeriod(Long retentionPeriod) { + infoBuilder.setRetentionPeriod(retentionPeriod); + return this; + } + @Override public Bucket build() { return new Bucket(storage, infoBuilder); @@ -1117,6 +1135,28 @@ public List listDefaultAcls() { return storage.listDefaultAcls(getName()); } + /** + * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. + * + * Warning: Once a retention policy is locked, it can no longer be unlocked or removed only increased. + * + * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id + * to assign operational costs. + * + *

Example of locking a retention policy on a bucket, only if its metageneration matches the buckets + * metagenerationn otherwise a {@link StorageException} is thrown. + *

 {@code
+   * String bucketName = "my_unique_bucket";
+   * Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
+   * bucket.lockRetentionPolicy(BucketTargetOption.metagenerationMatch());
+   * }
+ * + * @throws StorageException upon failure + */ + public Bucket lockRetentionPolicy(BucketTargetOption... options) { + return storage.lockRetentionPolicy(this, options); + } + /** * Returns the bucket's {@code Storage} object used to issue requests. */ diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 01513bfb822a..5c9c087d3e7a 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -89,6 +89,9 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo) private final Map labels; private final String defaultKmsKeyName; private final Boolean defaultEventBasedHold; + private final Long retentionEffectiveTime; + private final Boolean retentionPolicyIsLocked; + private final Long retentionPeriod; /** * Base class for bucket's delete rules. Allows to configure automatic deletion of blobs and blobs @@ -438,6 +441,16 @@ public abstract static class Builder { */ public abstract Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold); + abstract Builder setRetentionEffectiveTime(Long retentionEffectiveTime); + + abstract Builder setRetentionPolicyIsLocked(Boolean retentionPolicyIsLocked); + + /** + * If policy is not locked this value can be cleared or increased. If policy is locked the retention period can only + * be increased. + */ + public abstract Builder setRetentionPeriod(Long retentionPeriod); + /** * Creates a {@code BucketInfo} object. */ @@ -466,6 +479,9 @@ static final class BuilderImpl extends Builder { private Map labels; private String defaultKmsKeyName; private Boolean defaultEventBasedHold; + private Long retentionEffectiveTime; + private Boolean retentionPolicyIsLocked; + private Long retentionPeriod; BuilderImpl(String name) { this.name = name; @@ -492,6 +508,9 @@ static final class BuilderImpl extends Builder { requesterPays = bucketInfo.requesterPays; defaultKmsKeyName = bucketInfo.defaultKmsKeyName; defaultEventBasedHold = bucketInfo.defaultEventBasedHold; + retentionEffectiveTime = bucketInfo.retentionEffectiveTime; + retentionPolicyIsLocked = bucketInfo.retentionPolicyIsLocked; + retentionPeriod = bucketInfo.retentionPeriod; } @Override @@ -617,6 +636,24 @@ public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) { return this; } + @Override + Builder setRetentionEffectiveTime(Long retentionEffectiveTime) { + this.retentionEffectiveTime = firstNonNull(retentionEffectiveTime, Data.nullOf(Long.class)); + return this; + } + + @Override + Builder setRetentionPolicyIsLocked(Boolean retentionPolicyIsLocked) { + this.retentionPolicyIsLocked = firstNonNull(retentionPolicyIsLocked, Data.nullOf(Boolean.class)); + return this; + } + + @Override + public Builder setRetentionPeriod(Long retentionPeriod) { + this.retentionPeriod = firstNonNull(retentionPeriod, Data.nullOf(Long.class)); + return this; + } + @Override public BucketInfo build() { checkNotNull(name); @@ -645,6 +682,9 @@ public BucketInfo build() { requesterPays = builder.requesterPays; defaultKmsKeyName = builder.defaultKmsKeyName; defaultEventBasedHold = builder.defaultEventBasedHold; + retentionEffectiveTime = builder.retentionEffectiveTime; + retentionPolicyIsLocked = builder.retentionPolicyIsLocked; + retentionPeriod = builder.retentionPeriod; } /** @@ -810,6 +850,21 @@ public String getDefaultKmsKeyName() { */ public Boolean getDefaultEventBasedHold() { return defaultEventBasedHold; } + /** + * Returns the retention effective time a policy took effect if a retention policy is defined. + */ + public Long getRetentionEffectiveTime() { return retentionEffectiveTime; } + + /** + * Returns the lock state of the bucket's retention policy. + */ + public Boolean getRetentionPolicyIsLocked() { return retentionPolicyIsLocked; } + + /** + * Returns the retention period. + */ + public Long getRetentionPeriod() { return retentionPeriod; } + /** * Returns a builder for the current bucket. */ @@ -911,6 +966,19 @@ public Rule apply(DeleteRule deleteRule) { if (defaultEventBasedHold != null) { bucketPb.setDefaultEventBasedHold(defaultEventBasedHold); } + if (retentionPeriod != null || retentionEffectiveTime != null || retentionPolicyIsLocked != null) { + Bucket.RetentionPolicy retentionPolicy = new Bucket.RetentionPolicy(); + if (retentionPeriod != null) { + retentionPolicy.setRetentionPeriod(retentionPeriod); + } + if (retentionEffectiveTime != null) { + retentionPolicy.setEffectiveTime(new DateTime(retentionEffectiveTime)); + } + if (retentionPolicyIsLocked != null) { + retentionPolicy.setIsLocked(retentionPolicyIsLocked); + } + bucketPb.setRetentionPolicy(retentionPolicy); + } return bucketPb; } @@ -1006,6 +1074,18 @@ public DeleteRule apply(Rule rule) { if (bucketPb.getDefaultEventBasedHold() != null) { builder.setDefaultEventBasedHold(bucketPb.getDefaultEventBasedHold()); } + Bucket.RetentionPolicy retentionPolicy = bucketPb.getRetentionPolicy(); + if (retentionPolicy != null) { + if (retentionPolicy.getEffectiveTime() != null) { + builder.setRetentionEffectiveTime(retentionPolicy.getEffectiveTime().getValue()); + } + if (retentionPolicy.getIsLocked() != null) { + builder.setRetentionPolicyIsLocked(retentionPolicy.getIsLocked()); + } + if (retentionPolicy.getRetentionPeriod() != null) { + builder.setRetentionPeriod(retentionPolicy.getRetentionPeriod()); + } + } return builder.build(); } } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index d8311d3fd266..4b0247b277c0 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -96,7 +96,8 @@ enum BucketField implements FieldSelector { @GcpLaunchStage.Beta ENCRYPTION("encryption"), BILLING("billing"), - DEFAULT_EVENT_BASED_HOLD("defaultEventBasedHold"); + DEFAULT_EVENT_BASED_HOLD("defaultEventBasedHold"), + RETENTION_POLICY("retentionPolicy"); static final List REQUIRED_FIELDS = ImmutableList.of(NAME); @@ -141,6 +142,7 @@ enum BlobField implements FieldSelector { KMS_KEY_NAME("kmsKeyName"), EVENT_BASED_HOLD("eventBasedHold"), TEMPORARY_HOLD("temporaryHold"), + RETENTION_EXPIRATION_TIME("retentionExpirationTime"), UPDATED("updated"); static final List REQUIRED_FIELDS = ImmutableList.of(BUCKET, NAME); @@ -1540,6 +1542,26 @@ public static Builder newBuilder() { */ Bucket get(String bucket, BucketGetOption... options); + /** + * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. + * + * Warning: Once a retention policy is locked, it can no longer be unlocked or removed only increased. + * + * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id + * to assign operational costs. + * + *

Example of locking a retention policy on a bucket, only if its local metageneration value matches the buckets + * service metagenerationn otherwise a {@link StorageException} is thrown. + *

 {@code
+   * String bucketName = "my_unique_bucket";
+   * Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
+   * storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch());
+   * }
+ * + * @throws StorageException upon failure + */ + Bucket lockRetentionPolicy(BucketInfo bucket, BucketTargetOption... options); + /** * Returns the requested blob or {@code null} if not found. * diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index e49445d13646..787388006571 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -983,6 +983,23 @@ public Boolean apply(String permission) { } } + @Override + public Bucket lockRetentionPolicy(BucketInfo bucketInfo, BucketTargetOption... options) { + final com.google.api.services.storage.model.Bucket bucketPb = bucketInfo.toPb(); + final Map optionsMap = optionMap(bucketInfo, options); + try { + return Bucket.fromPb(this, runWithRetries( + new Callable() { + @Override + public com.google.api.services.storage.model.Bucket call() { + return storageRpc.lockRetentionPolicy(bucketPb, optionsMap); + } + }, getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } + } + @Override public ServiceAccount getServiceAccount(final String projectId) { try { diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 03db33dae835..39cbc3f99ef2 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -1208,6 +1208,23 @@ public Notification createNotification(String bucket, Notification notification) } } + @Override + public Bucket lockRetentionPolicy(Bucket bucket, Map options) { + Span span = startSpan(HttpStorageRpcSpans.SPAN_LOCK_RETENTION_POLICY); + Scope scope = tracer.withSpan(span); + try { + return storage.buckets().lockRetentionPolicy(bucket.getName(), Option.IF_METAGENERATION_MATCH.getLong(options)) + .setUserProject(Option.USER_PROJECT.getString(options)).execute(); + } catch (IOException ex) { + span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage())); + throw translate(ex); + } finally { + scope.close(); + span.end(); + } + + } + @Override public ServiceAccount getServiceAccount(String projectId) { Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_GET_SERVICE_ACCOUNT); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java index ceb8a3c83e53..41c877f8eefc 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java @@ -90,6 +90,7 @@ class HttpStorageRpcSpans { "listNotifications(String)"); static final String SPAN_NAME_CREATE_NOTIFICATION = getTraceSpanName( "createNotification(String,Notification)"); + static final String SPAN_LOCK_RETENTION_POLICY = getTraceSpanName("lockRetentionPolicy(String,Long)"); static final String SPAN_NAME_GET_SERVICE_ACCOUNT = getTraceSpanName( "getServiceAccount(String)"); static final String SPAN_NAME_BATCH_SUBMIT = getTraceSpanName( @@ -136,6 +137,7 @@ class HttpStorageRpcSpans { SPAN_NAME_LIST_NOTIFICATIONS, SPAN_NAME_CREATE_NOTIFICATION, SPAN_NAME_GET_SERVICE_ACCOUNT, + SPAN_LOCK_RETENTION_POLICY, SPAN_NAME_BATCH_SUBMIT); static String getTraceSpanName(String methodDescriptor) { diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 780d8b864cfd..8bd82bc2e961 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -460,6 +460,13 @@ void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, */ Notification createNotification(String bucket, Notification notification); + /** + * Lock retention policy for the provided bucket. + * @return + * @throws StorageException upon failure + */ + Bucket lockRetentionPolicy(Bucket bucket, Map options); + /** * Returns the service account associated with the given project. * diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java index 43c95aeec5ef..88914f34a4c8 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobInfoTest.java @@ -70,6 +70,7 @@ public class BlobInfoTest { private static final StorageClass STORAGE_CLASS = StorageClass.COLDLINE; private static final Boolean EVENT_BASED_HOLD = true; private static final Boolean TEMPORARY_HOLD = true; + private static final Long RETENTION_EXPIRATION_TIME = 10L; private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACL) @@ -97,6 +98,7 @@ public class BlobInfoTest { .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) .setTemporaryHold(TEMPORARY_HOLD) + .setRetentionExpirationTime(RETENTION_EXPIRATION_TIME) .build(); private static final BlobInfo DIRECTORY_INFO = BlobInfo.newBuilder("b", "n/") .setSize(0L) @@ -162,6 +164,7 @@ public void testBuilder() { assertEquals(KMS_KEY_NAME, BLOB_INFO.getKmsKeyName()); assertEquals(EVENT_BASED_HOLD, BLOB_INFO.getEventBasedHold()); assertEquals(TEMPORARY_HOLD, BLOB_INFO.getTemporaryHold()); + assertEquals(RETENTION_EXPIRATION_TIME, BLOB_INFO.getRetentionExpirationTime()); assertFalse(BLOB_INFO.isDirectory()); assertEquals("b", DIRECTORY_INFO.getBucket()); assertEquals("n/", DIRECTORY_INFO.getName()); @@ -220,6 +223,7 @@ private void compareBlobs(BlobInfo expected, BlobInfo value) { assertEquals(expected.getKmsKeyName(), value.getKmsKeyName()); assertEquals(expected.getEventBasedHold(), value.getEventBasedHold()); assertEquals(expected.getTemporaryHold(), value.getTemporaryHold()); + assertEquals(expected.getRetentionExpirationTime(), value.getRetentionExpirationTime()); } private void compareCustomerEncryptions(CustomerEncryption expected, CustomerEncryption value) { @@ -270,6 +274,7 @@ public void testToPbAndFromPb() { assertNull(blobInfo.getKmsKeyName()); assertNull(blobInfo.getEventBasedHold()); assertNull(blobInfo.getTemporaryHold()); + assertNull(blobInfo.getRetentionExpirationTime()); assertTrue(blobInfo.isDirectory()); } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java index eac3b36f847d..8db0793409a6 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BlobTest.java @@ -94,6 +94,7 @@ public class BlobTest { private static final String KMS_KEY_NAME = "projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key"; private static final Boolean EVENT_BASED_HOLD = true; private static final Boolean TEMPORARY_HOLD = true; + private static final Long RETENTION_EXPIRATION_TIME = 10L; private static final BlobInfo FULL_BLOB_INFO = BlobInfo.newBuilder("b", "n", GENERATION) .setAcl(ACLS) .setComponentCount(COMPONENT_COUNT) @@ -119,6 +120,7 @@ public class BlobTest { .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) .setTemporaryHold(TEMPORARY_HOLD) + .setRetentionExpirationTime(RETENTION_EXPIRATION_TIME) .build(); private static final BlobInfo BLOB_INFO = BlobInfo.newBuilder("b", "n") .setMetageneration(42L) @@ -478,6 +480,7 @@ public void testBuilder() { .setKmsKeyName(KMS_KEY_NAME) .setEventBasedHold(EVENT_BASED_HOLD) .setTemporaryHold(TEMPORARY_HOLD) + .setRetentionExpirationTime(RETENTION_EXPIRATION_TIME) .setDeleteTime(DELETE_TIME) .setEtag(ETAG) .setGeneratedId(GENERATED_ID) @@ -505,6 +508,7 @@ public void testBuilder() { assertEquals(KMS_KEY_NAME, blob.getKmsKeyName()); assertEquals(EVENT_BASED_HOLD, blob.getEventBasedHold()); assertEquals(TEMPORARY_HOLD, blob.getTemporaryHold()); + assertEquals(RETENTION_EXPIRATION_TIME, blob.getRetentionExpirationTime()); assertEquals(DELETE_TIME, blob.getDeleteTime()); assertEquals(ETAG, blob.getEtag()); assertEquals(GENERATED_ID, blob.getGeneratedId()); @@ -538,6 +542,7 @@ public void testBuilder() { assertNull(blob.getKmsKeyName()); assertNull(blob.getEventBasedHold()); assertNull(blob.getTemporaryHold()); + assertNull(blob.getRetentionExpirationTime()); assertNull(blob.getDeleteTime()); assertNull(blob.getEtag()); assertNull(blob.getGeneratedId()); diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java index 22f95276d203..b6c508b0c07b 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java @@ -65,6 +65,9 @@ public class BucketInfoTest { private static final Map BUCKET_LABELS = ImmutableMap.of("label1", "value1"); private static final Boolean REQUESTER_PAYS = true; private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; + private static final Long RETENTION_EFFECTIVE_TIME = 10L; + private static final Long RETENTION_PERIOD = 10L; + private static Boolean RETENTION_POLICY_IS_LOCKED = false; private static final BucketInfo BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACL) .setEtag(ETAG) @@ -85,6 +88,9 @@ public class BucketInfoTest { .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) + .setRetentionEffectiveTime(RETENTION_EFFECTIVE_TIME) + .setRetentionPeriod(RETENTION_PERIOD) + .setRetentionPolicyIsLocked(RETENTION_POLICY_IS_LOCKED) .build(); @Test @@ -131,6 +137,9 @@ public void testBuilder() { assertEquals(BUCKET_LABELS, BUCKET_INFO.getLabels()); assertEquals(REQUESTER_PAYS, BUCKET_INFO.requesterPays()); assertEquals(DEFAULT_EVENT_BASED_HOLD, BUCKET_INFO.getDefaultEventBasedHold()); + assertEquals(RETENTION_EFFECTIVE_TIME, BUCKET_INFO.getRetentionEffectiveTime()); + assertEquals(RETENTION_PERIOD, BUCKET_INFO.getRetentionPeriod()); + assertEquals(RETENTION_POLICY_IS_LOCKED, BUCKET_INFO.getRetentionPolicyIsLocked()); } @Test @@ -162,6 +171,9 @@ private void compareBuckets(BucketInfo expected, BucketInfo value) { assertEquals(expected.getLabels(), value.getLabels()); assertEquals(expected.requesterPays(), value.requesterPays()); assertEquals(expected.getDefaultEventBasedHold(), value.getDefaultEventBasedHold()); + assertEquals(expected.getRetentionEffectiveTime(), value.getRetentionEffectiveTime()); + assertEquals(expected.getRetentionPeriod(), value.getRetentionPeriod()); + assertEquals(expected.getRetentionPolicyIsLocked(), value.getRetentionPolicyIsLocked()); } @Test diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java index f7317e8ce206..c051a77048de 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java @@ -83,6 +83,9 @@ public class BucketTest { private static final Boolean REQUESTER_PAYS = true; private static final String USER_PROJECT = "test-project"; private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; + private static final Long RETENTION_EFFECTIVE_TIME = 10L; + private static final Long RETENTION_PERIOD = 10L; + private static Boolean RETENTION_POLICY_IS_LOCKED = false; private static final BucketInfo FULL_BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACLS) .setEtag(ETAG) @@ -103,6 +106,9 @@ public class BucketTest { .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) + .setRetentionEffectiveTime(RETENTION_EFFECTIVE_TIME) + .setRetentionPeriod(RETENTION_PERIOD) + .setRetentionPolicyIsLocked(RETENTION_POLICY_IS_LOCKED) .build(); private static final BucketInfo BUCKET_INFO = BucketInfo.newBuilder("b").setMetageneration(42L).build(); @@ -661,6 +667,23 @@ public void testListDefaultAcls() throws Exception { assertEquals(ACLS, bucket.listDefaultAcls()); } + @Test + public void testLockRetention() throws Exception { + initializeExpectedBucket(5); + Bucket expectedRetentionLockedBucket = expectedBucket.toBuilder().setRetentionPeriod(RETENTION_PERIOD) + .setRetentionPolicyIsLocked(true).build(); + expect(storage.getOptions()).andReturn(mockOptions).times(2); + expect(storage.lockRetentionPolicy(expectedRetentionLockedBucket, Storage.BucketTargetOption.metagenerationMatch(), + Storage.BucketTargetOption.userProject(USER_PROJECT))).andReturn(expectedRetentionLockedBucket); + replay(storage); + initializeBucket(); + Bucket lockedRetentionPolicyBucket = new Bucket(storage, new BucketInfo.BuilderImpl(expectedRetentionLockedBucket)); + Bucket actualRetentionLockedBucket = lockedRetentionPolicyBucket + .lockRetentionPolicy(Storage.BucketTargetOption.metagenerationMatch(), + Storage.BucketTargetOption.userProject(USER_PROJECT)); + assertEquals(expectedRetentionLockedBucket, actualRetentionLockedBucket); + } + @Test public void testToBuilder() { expect(storage.getOptions()).andReturn(mockOptions).times(4); @@ -697,6 +720,9 @@ public void testBuilder() { .setRequesterPays(REQUESTER_PAYS) .setDefaultKmsKeyName(DEFAULT_KMS_KEY_NAME) .setDefaultEventBasedHold(DEFAULT_EVENT_BASED_HOLD) + .setRetentionEffectiveTime(RETENTION_EFFECTIVE_TIME) + .setRetentionPeriod(RETENTION_PERIOD) + .setRetentionPolicyIsLocked(RETENTION_POLICY_IS_LOCKED) .build(); assertEquals("b", bucket.getName()); assertEquals(ACLS, bucket.getAcl()); @@ -718,6 +744,9 @@ public void testBuilder() { assertEquals(REQUESTER_PAYS, bucket.requesterPays()); assertEquals(DEFAULT_KMS_KEY_NAME, bucket.getDefaultKmsKeyName()); assertEquals(DEFAULT_EVENT_BASED_HOLD, bucket.getDefaultEventBasedHold()); + assertEquals(RETENTION_EFFECTIVE_TIME, bucket.getRetentionEffectiveTime()); + assertEquals(RETENTION_PERIOD, bucket.getRetentionPeriod()); + assertEquals(RETENTION_POLICY_IS_LOCKED, bucket.getRetentionPolicyIsLocked()); assertEquals(storage.getOptions(), bucket.getStorage().getOptions()); } } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java index 9fea3887c464..574c02ea001f 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplTest.java @@ -92,6 +92,7 @@ public class StorageImplTest { private static final String BUCKET_NAME1 = "b1"; private static final String BUCKET_NAME2 = "b2"; + private static final String BUCKET_NAME3 = "b3"; private static final String BLOB_NAME1 = "n1"; private static final String BLOB_NAME2 = "n2"; private static final String BLOB_NAME3 = "n3"; @@ -104,11 +105,15 @@ public class StorageImplTest { new SecretKeySpec(BaseEncoding.base64().decode(BASE64_KEY), "AES256"); private static final String KMS_KEY_NAME = "projects/gcloud-devel/locations/us/keyRings/gcs_kms_key_ring_us/cryptoKeys/key"; + private static final Long RETENTION_PERIOD = 10L; + private static final String USER_PROJECT = "test-project"; // BucketInfo objects private static final BucketInfo BUCKET_INFO1 = BucketInfo.newBuilder(BUCKET_NAME1).setMetageneration(42L).build(); private static final BucketInfo BUCKET_INFO2 = BucketInfo.newBuilder(BUCKET_NAME2).build(); + private static final BucketInfo BUCKET_INFO3 = BucketInfo.newBuilder(BUCKET_NAME3) + .setRetentionPeriod(RETENTION_PERIOD).setRetentionPolicyIsLocked(true).setMetageneration(42L).build(); // BlobInfo objects private static final BlobInfo BLOB_INFO1 = @@ -128,10 +133,16 @@ public class StorageImplTest { Storage.BucketTargetOption.metagenerationMatch(); private static final Storage.BucketTargetOption BUCKET_TARGET_PREDEFINED_ACL = Storage.BucketTargetOption.predefinedAcl(Storage.PredefinedAcl.PRIVATE); + private static final Storage.BucketTargetOption BUCKET_TARGET_USER_PROJECT = + Storage.BucketTargetOption.userProject(USER_PROJECT); private static final Map BUCKET_TARGET_OPTIONS = ImmutableMap.of( StorageRpc.Option.IF_METAGENERATION_MATCH, BUCKET_INFO1.getMetageneration(), StorageRpc.Option.PREDEFINED_ACL, BUCKET_TARGET_PREDEFINED_ACL.getValue()); + private static final Map BUCKET_TARGET_OPTIONS_LOCK_RETENTION_POLICY = + ImmutableMap.of( + StorageRpc.Option.IF_METAGENERATION_MATCH, BUCKET_INFO3.getMetageneration(), + StorageRpc.Option.USER_PROJECT, USER_PROJECT); // Blob target options (create, update, compose) private static final BlobTargetOption BLOB_TARGET_GENERATION = BlobTargetOption.generationMatch(); @@ -320,7 +331,7 @@ public long millisTime() { private Storage storage; private Blob expectedBlob1, expectedBlob2, expectedBlob3; - private Bucket expectedBucket1, expectedBucket2; + private Bucket expectedBucket1, expectedBucket2, expectedBucket3; @Rule public ExpectedException thrown = ExpectedException.none(); @@ -367,6 +378,7 @@ private void initializeServiceDependentObjects() { expectedBlob3 = new Blob(storage, new BlobInfo.BuilderImpl(BLOB_INFO3)); expectedBucket1 = new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO1)); expectedBucket2 = new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO2)); + expectedBucket3 = new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO3)); } @Test @@ -2325,6 +2337,17 @@ public void testTestIamPermissionsNonNull() { assertEquals(expectedPermissions, storage.testIamPermissions(BUCKET_NAME1, checkedPermissions)); } + @Test + public void testLockRetentionPolicy() { + EasyMock.expect(storageRpcMock + .lockRetentionPolicy(BUCKET_INFO3.toPb(), BUCKET_TARGET_OPTIONS_LOCK_RETENTION_POLICY)) + .andReturn(BUCKET_INFO3.toPb()); + EasyMock.replay(storageRpcMock); + initializeService(); + Bucket bucket = storage.lockRetentionPolicy(BUCKET_INFO3, BUCKET_TARGET_METAGENERATION, BUCKET_TARGET_USER_PROJECT); + assertEquals(expectedBucket3, bucket); + } + @Test public void testGetServiceAccount() { EasyMock.expect(storageRpcMock.getServiceAccount("projectId")) diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 15e1225347b0..df7475cc7eef 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -110,6 +110,8 @@ public class ITStorageTest { private static final String SERVICE_ACCOUNT_EMAIL = "gcloud-devel@gs-project-accounts.iam.gserviceaccount.com"; private static final String KMS_KEY_NAME_1 = "projects/gcloud-devel/locations/us/keyRings/gcs_kms_key_ring_us/cryptoKeys/key"; private static final String KMS_KEY_NAME_2 = "projects/gcloud-devel/locations/us/keyRings/gcs_kms_key_ring_us/cryptoKeys/key2"; + private static final Long RETENTION_PERIOD = 5L; + private static final Long RETENTION_PERIOD_IN_MILLISECONDS = RETENTION_PERIOD * 1000; @BeforeClass public static void beforeClass() throws NoSuchAlgorithmException, InvalidKeySpecException { @@ -209,80 +211,6 @@ public void testUpdateBucketDefaultKmsKeyName() throws ExecutionException, Inter } } - @Test - public void testCreateDefaultEventBasedHoldBucket() throws ExecutionException, InterruptedException { - String bucketName = RemoteStorageHelper.generateBucketName(); - Bucket remoteBucket = storage.create(BucketInfo.newBuilder(bucketName).setDefaultEventBasedHold(true).build()); - - try { - assertTrue(remoteBucket.getDefaultEventBasedHold()); - } finally { - RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); - } - } - - @Test - public void testEnableDisableBucketDefaultEventBasedHold() { - Bucket remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD)); - assertNull(remoteBucket.getDefaultEventBasedHold()); - remoteBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(true).build().update(); - assertTrue(remoteBucket.getDefaultEventBasedHold()); - remoteBucket = storage.get(BUCKET, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD)); - assertTrue(remoteBucket.getDefaultEventBasedHold()); - String blobName = "test-create-with-event-based-hold"; - BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).build(); - Blob remoteBlob = storage.create(blobInfo); - assertTrue(remoteBlob.getEventBasedHold()); - remoteBlob = storage.get(blobInfo.getBlobId(), Storage.BlobGetOption.fields(BlobField.EVENT_BASED_HOLD)); - assertTrue(remoteBlob.getEventBasedHold()); - remoteBlob = remoteBlob.toBuilder().setEventBasedHold(false).build().update(); - assertFalse(remoteBlob.getEventBasedHold()); - remoteBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update(); - assertFalse(remoteBucket.getDefaultEventBasedHold()); - } - - @Test - public void testEnableDisableTemporaryHold() { - String blobName = "test-create-with-event-based-hold"; - BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); - Blob remoteBlob = storage.create(blobInfo); - assertTrue(remoteBlob.getTemporaryHold()); - remoteBlob = storage.get(remoteBlob.getBlobId(), Storage.BlobGetOption.fields(BlobField.TEMPORARY_HOLD)); - assertTrue(remoteBlob.getTemporaryHold()); - remoteBlob = remoteBlob.toBuilder().setTemporaryHold(false).build().update(); - assertFalse(remoteBlob.getTemporaryHold()); - } - - @Test - public void testAttemptDeletionObjectEventBasedHold() { - String blobName = "test-create-with-event-based-hold"; - BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setEventBasedHold(true).build(); - Blob remoteBlob = storage.create(blobInfo); - assertTrue(remoteBlob.getEventBasedHold()); - try { - remoteBlob.delete(); - fail("Expected failure on delete from eventBasedHold"); - } catch (StorageException ex) { - // expected - } - } - - @Test - public void testAttemptDeletionObjectTemporaryHold() { - String blobName = "test-create-with-temporary-hold"; - BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); - Blob remoteBlob = storage.create(blobInfo); - assertTrue(remoteBlob.getTemporaryHold()); - remoteBlob = storage.get(remoteBlob.getBlobId(), Storage.BlobGetOption.fields(BlobField.TEMPORARY_HOLD)); - assertTrue(remoteBlob.getTemporaryHold()); - try { - remoteBlob.delete(); - fail("Expected failure on delete from temporaryHold"); - } catch (StorageException ex) { - // expected - } - } - @Test public void testCreateBlob() { String blobName = "test-create-blob"; @@ -1989,6 +1917,152 @@ public void testListBucketDefaultKmsKeyName() throws ExecutionException, Interru } } + @Test + public void testRetentionPolicyNoLock() throws ExecutionException, InterruptedException { + String bucketName = RemoteStorageHelper.generateBucketName(); + Bucket remoteBucket = storage.create(BucketInfo.newBuilder(bucketName) + .setRetentionPeriod(RETENTION_PERIOD).build()); + try { + assertEquals(RETENTION_PERIOD, remoteBucket.getRetentionPeriod()); + assertNotNull(remoteBucket.getRetentionEffectiveTime()); + assertNull(remoteBucket.getRetentionPolicyIsLocked()); + remoteBucket = storage.get(bucketName, Storage.BucketGetOption.fields(BucketField.RETENTION_POLICY)); + assertEquals(RETENTION_PERIOD, remoteBucket.getRetentionPeriod()); + assertNotNull(remoteBucket.getRetentionEffectiveTime()); + assertNull(remoteBucket.getRetentionPolicyIsLocked()); + String blobName = "test-create-with-retention-policy-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, blobName).build(); + Blob remoteBlob = storage.create(blobInfo); + assertNotNull(remoteBlob.getRetentionExpirationTime()); + remoteBucket = remoteBucket.toBuilder().setRetentionPeriod(null).build().update(); + assertNull(remoteBucket.getRetentionPeriod()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testRetentionPolicyLock() throws ExecutionException, InterruptedException { + retentionPolicyLockRequesterPays(true); + retentionPolicyLockRequesterPays(false); + } + + private void retentionPolicyLockRequesterPays(boolean requesterPays) throws ExecutionException, InterruptedException { + String projectId = remoteStorageHelper.getOptions().getProjectId(); + String bucketName = RemoteStorageHelper.generateBucketName(); + BucketInfo bucketInfo; + if (requesterPays) { + bucketInfo = BucketInfo.newBuilder(bucketName).setRetentionPeriod(RETENTION_PERIOD) + .setRequesterPays(true).build(); + } else { + bucketInfo = BucketInfo.newBuilder(bucketName).setRetentionPeriod(RETENTION_PERIOD).build(); + } + Bucket remoteBucket = storage.create(bucketInfo); + try { + assertNull(remoteBucket.getRetentionPolicyIsLocked()); + assertNotNull(remoteBucket.getRetentionEffectiveTime()); + assertNotNull(remoteBucket.getMetageneration()); + if (requesterPays) { + remoteBucket = storage.lockRetentionPolicy(remoteBucket, Storage.BucketTargetOption.metagenerationMatch(), + Storage.BucketTargetOption.userProject(projectId)); + } else { + remoteBucket = storage.lockRetentionPolicy(remoteBucket, Storage.BucketTargetOption.metagenerationMatch()); + } + assertTrue(remoteBucket.getRetentionPolicyIsLocked()); + assertNotNull(remoteBucket.getRetentionEffectiveTime()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testAttemptObjectDeleteWithRetentionPolicy() throws ExecutionException, InterruptedException { + String bucketName = RemoteStorageHelper.generateBucketName(); + Bucket remoteBucket = storage.create(BucketInfo.newBuilder(bucketName) + .setRetentionPeriod(RETENTION_PERIOD).build()); + assertEquals(RETENTION_PERIOD, remoteBucket.getRetentionPeriod()); + String blobName = "test-create-with-retention-policy"; + BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, blobName).build(); + Blob remoteBlob = storage.create(blobInfo); + assertNotNull(remoteBlob.getRetentionExpirationTime()); + try { + remoteBlob.delete(); + fail("Expected failure on delete from retentionPolicy"); + } catch (StorageException ex) { + // expected + } finally { + Thread.sleep(RETENTION_PERIOD_IN_MILLISECONDS); + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testEnableDisableBucketDefaultEventBasedHold() throws ExecutionException, InterruptedException { + String bucketName = RemoteStorageHelper.generateBucketName(); + Bucket remoteBucket = storage.create(BucketInfo.newBuilder(bucketName).setDefaultEventBasedHold(true).build()); + try { + assertTrue(remoteBucket.getDefaultEventBasedHold()); + remoteBucket = storage.get(bucketName, Storage.BucketGetOption.fields(BucketField.DEFAULT_EVENT_BASED_HOLD)); + assertTrue(remoteBucket.getDefaultEventBasedHold()); + String blobName = "test-create-with-event-based-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, blobName).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getEventBasedHold()); + remoteBlob = storage.get(blobInfo.getBlobId(), Storage.BlobGetOption.fields(BlobField.EVENT_BASED_HOLD)); + assertTrue(remoteBlob.getEventBasedHold()); + remoteBlob = remoteBlob.toBuilder().setEventBasedHold(false).build().update(); + assertFalse(remoteBlob.getEventBasedHold()); + remoteBucket = remoteBucket.toBuilder().setDefaultEventBasedHold(false).build().update(); + assertFalse(remoteBucket.getDefaultEventBasedHold()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testEnableDisableTemporaryHold() { + String blobName = "test-create-with-temporary-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getTemporaryHold()); + remoteBlob = storage.get(remoteBlob.getBlobId(), Storage.BlobGetOption.fields(BlobField.TEMPORARY_HOLD)); + assertTrue(remoteBlob.getTemporaryHold()); + remoteBlob = remoteBlob.toBuilder().setTemporaryHold(false).build().update(); + assertFalse(remoteBlob.getTemporaryHold()); + } + + @Test + public void testAttemptObjectDeleteWithEventBasedHold() { + String blobName = "test-create-with-event-based-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setEventBasedHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getEventBasedHold()); + try { + remoteBlob.delete(); + fail("Expected failure on delete from eventBasedHold"); + } catch (StorageException ex) { + // expected + } finally { + remoteBlob.toBuilder().setEventBasedHold(false).build().update(); + } + } + + @Test + public void testAttemptDeletionObjectTemporaryHold() { + String blobName = "test-create-with-temporary-hold"; + BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).setTemporaryHold(true).build(); + Blob remoteBlob = storage.create(blobInfo); + assertTrue(remoteBlob.getTemporaryHold()); + try { + remoteBlob.delete(); + fail("Expected failure on delete from temporaryHold"); + } catch (StorageException ex) { + // expected + } finally { + remoteBlob.toBuilder().setEventBasedHold(false).build().update(); + } + } + @Test public void testGetServiceAccount() throws InterruptedException { String projectId = remoteStorageHelper.getOptions().getProjectId(); From 7078d02f89c6f10eb9989876091545dbf21f1d79 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Fri, 17 Aug 2018 01:16:06 -0700 Subject: [PATCH 05/13] Remove Beta launch annotations for CMEK --- .../src/main/java/com/google/cloud/storage/Blob.java | 1 - .../src/main/java/com/google/cloud/storage/BlobInfo.java | 3 --- .../src/main/java/com/google/cloud/storage/Bucket.java | 1 - .../src/main/java/com/google/cloud/storage/BucketInfo.java | 6 ------ .../src/main/java/com/google/cloud/storage/Storage.java | 4 ---- .../java/com/google/cloud/storage/spi/v1/StorageRpc.java | 1 - 6 files changed, 16 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index 7f0e94af0081..b29ce5455040 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -402,7 +402,6 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) { return this; } - @GcpLaunchStage.Beta @Override Builder setKmsKeyName(String kmsKeyName) { infoBuilder.setKmsKeyName(kmsKeyName); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index b124bc86e4ad..eb2297b86bc7 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -271,7 +271,6 @@ public abstract static class Builder { abstract Builder setCustomerEncryption(CustomerEncryption customerEncryption); - @GcpLaunchStage.Beta abstract Builder setKmsKeyName(String kmsKeyName); /** @@ -503,7 +502,6 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) { return this; } - @GcpLaunchStage.Beta @Override Builder setKmsKeyName(String kmsKeyName) { this.kmsKeyName = kmsKeyName; @@ -797,7 +795,6 @@ public StorageClass getStorageClass() { /** * Returns the Cloud KMS key used to encrypt the blob, if any. */ - @GcpLaunchStage.Beta public String getKmsKeyName() { return kmsKeyName; } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 761ed0e67650..363c40de76fa 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -628,7 +628,6 @@ public Builder setLabels(Map labels) { return this; } - @GcpLaunchStage.Beta @Override public Builder setDefaultKmsKeyName(String defaultKmsKeyName) { infoBuilder.setDefaultKmsKeyName(defaultKmsKeyName); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 5c9c087d3e7a..16f1691f0156 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -350,7 +350,6 @@ public abstract static class Builder { * Sets whether a user accessing the bucket or an object it contains should assume the transit costs * related to the access. * - * GcpLaunchStage.Alpha */ public abstract Builder setRequesterPays(Boolean requesterPays); @@ -433,7 +432,6 @@ public abstract static class Builder { /** * Sets the default Cloud KMS key name for this bucket. */ - @GcpLaunchStage.Beta public abstract Builder setDefaultKmsKeyName(String defaultKmsKeyName); /** @@ -543,7 +541,6 @@ public Builder setVersioningEnabled(Boolean enable) { return this; } - /** GcpLaunchStage.Alpha */ @Override public Builder setRequesterPays(Boolean enable) { this.requesterPays = firstNonNull(enable, Data.nullOf(Boolean.class)); @@ -622,7 +619,6 @@ public Builder setLabels(Map labels) { return this; } - @GcpLaunchStage.Beta @Override public Builder setDefaultKmsKeyName(String defaultKmsKeyName) { this.defaultKmsKeyName = defaultKmsKeyName != null @@ -727,7 +723,6 @@ public Boolean versioningEnabled() { * Returns {@code true} if a user accessing the bucket or an object it contains should assume the transit costs * related to the access, {@code false} otherwise. * - * GcpLaunchStage.Alpha */ public Boolean requesterPays() { return Data.isNull(requesterPays) ? null : requesterPays; @@ -840,7 +835,6 @@ public Map getLabels() { /** * Returns the default Cloud KMS key to be applied to newly inserted objects in this bucket. */ - @GcpLaunchStage.Beta public String getDefaultKmsKeyName() { return defaultKmsKeyName; } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 4b0247b277c0..2ecf9066fbee 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -93,7 +93,6 @@ enum BucketField implements FieldSelector { CORS("cors"), STORAGE_CLASS("storageClass"), ETAG("etag"), - @GcpLaunchStage.Beta ENCRYPTION("encryption"), BILLING("billing"), DEFAULT_EVENT_BASED_HOLD("defaultEventBasedHold"), @@ -138,7 +137,6 @@ enum BlobField implements FieldSelector { SIZE("size"), STORAGE_CLASS("storageClass"), TIME_DELETED("timeDeleted"), - @GcpLaunchStage.Beta KMS_KEY_NAME("kmsKeyName"), EVENT_BASED_HOLD("eventBasedHold"), TEMPORARY_HOLD("temporaryHold"), @@ -393,7 +391,6 @@ public static BlobTargetOption encryptionKey(String key) { /** * Returns an option to set a customer-managed key for server-side encryption of the blob. */ - @GcpLaunchStage.Beta public static BlobTargetOption kmsKeyName(String kmsKeyName) { return new BlobTargetOption(StorageRpc.Option.KMS_KEY_NAME, kmsKeyName); } @@ -555,7 +552,6 @@ public static BlobWriteOption encryptionKey(String key) { * * @param kmsKeyName the KMS key resource id */ - @GcpLaunchStage.Beta public static BlobWriteOption kmsKeyName(String kmsKeyName) { return new BlobWriteOption(Option.KMS_KEY_NAME, kmsKeyName); } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 8bd82bc2e961..39de5ca15033 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -57,7 +57,6 @@ enum Option { FIELDS("fields"), CUSTOMER_SUPPLIED_KEY("customerSuppliedKey"), USER_PROJECT("userProject"), - @GcpLaunchStage.Beta KMS_KEY_NAME("kmsKeyName"); private final String value; From 154fef1933b8de78d55e7f04bf5e999a78b6ffc6 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Fri, 17 Aug 2018 07:58:39 -0700 Subject: [PATCH 06/13] Update FakeStorageRPC --- .../cloud/storage/contrib/nio/testing/FakeStorageRpc.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/google-cloud-clients/google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java b/google-cloud-clients/google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java index f8c4125b8557..d27664683db8 100644 --- a/google-cloud-clients/google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java +++ b/google-cloud-clients/google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java @@ -65,6 +65,7 @@ *
  • createBatch *
  • checksums, etags *
  • IAM operations
  • + *
  • BucketLock operations
  • * * */ @@ -520,6 +521,11 @@ public Notification createNotification(String bucket, Notification notification) throw new UnsupportedOperationException(); } + @Override + public Bucket lockRetentionPolicy(Bucket bucket, Map options) { + throw new UnsupportedOperationException(); + } + @Override public ServiceAccount getServiceAccount(String projectId) { return null; From 7a109589d7d1c5852961bcd7303936e664ef5091 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Fri, 17 Aug 2018 08:42:20 -0700 Subject: [PATCH 07/13] codacy-bot review fix (final only) --- .../src/test/java/com/google/cloud/storage/BucketInfoTest.java | 2 +- .../src/test/java/com/google/cloud/storage/BucketTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java index b6c508b0c07b..be4262c25b7b 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java @@ -67,7 +67,7 @@ public class BucketInfoTest { private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; private static final Long RETENTION_EFFECTIVE_TIME = 10L; private static final Long RETENTION_PERIOD = 10L; - private static Boolean RETENTION_POLICY_IS_LOCKED = false; + private static final Boolean RETENTION_POLICY_IS_LOCKED = false; private static final BucketInfo BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACL) .setEtag(ETAG) diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java index c051a77048de..0839adc4391c 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java @@ -85,7 +85,7 @@ public class BucketTest { private static final Boolean DEFAULT_EVENT_BASED_HOLD = true; private static final Long RETENTION_EFFECTIVE_TIME = 10L; private static final Long RETENTION_PERIOD = 10L; - private static Boolean RETENTION_POLICY_IS_LOCKED = false; + private static final Boolean RETENTION_POLICY_IS_LOCKED = false; private static final BucketInfo FULL_BUCKET_INFO = BucketInfo.newBuilder("b") .setAcl(ACLS) .setEtag(ETAG) From 5190137d91eaab95a279911ff989c2d16b1678d9 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 28 Aug 2018 22:10:41 -0700 Subject: [PATCH 08/13] Update getRetentionPolicyIsLocked() -> retentionPolicyIsLocked() and misc. --- .../main/java/com/google/cloud/storage/BucketInfo.java | 7 ++++--- .../java/com/google/cloud/storage/BucketInfoTest.java | 4 ++-- .../test/java/com/google/cloud/storage/BucketTest.java | 2 +- .../java/com/google/cloud/storage/it/ITStorageTest.java | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 16f1691f0156..45ab3850c4ee 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -718,7 +718,6 @@ public Boolean versioningEnabled() { return Data.isNull(versioningEnabled) ? null : versioningEnabled; } - /** * Returns {@code true} if a user accessing the bucket or an object it contains should assume the transit costs * related to the access, {@code false} otherwise. @@ -850,9 +849,11 @@ public String getDefaultKmsKeyName() { public Long getRetentionEffectiveTime() { return retentionEffectiveTime; } /** - * Returns the lock state of the bucket's retention policy. + * Returns {@code true} if the bucket retention policy is locked, {@code false} otherwise. */ - public Boolean getRetentionPolicyIsLocked() { return retentionPolicyIsLocked; } + public Boolean retentionPolicyIsLocked() { + return Data.isNull(retentionPolicyIsLocked) ? null : retentionPolicyIsLocked; + } /** * Returns the retention period. diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java index be4262c25b7b..f371af93bc0a 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java @@ -139,7 +139,7 @@ public void testBuilder() { assertEquals(DEFAULT_EVENT_BASED_HOLD, BUCKET_INFO.getDefaultEventBasedHold()); assertEquals(RETENTION_EFFECTIVE_TIME, BUCKET_INFO.getRetentionEffectiveTime()); assertEquals(RETENTION_PERIOD, BUCKET_INFO.getRetentionPeriod()); - assertEquals(RETENTION_POLICY_IS_LOCKED, BUCKET_INFO.getRetentionPolicyIsLocked()); + assertEquals(RETENTION_POLICY_IS_LOCKED, BUCKET_INFO.retentionPolicyIsLocked()); } @Test @@ -173,7 +173,7 @@ private void compareBuckets(BucketInfo expected, BucketInfo value) { assertEquals(expected.getDefaultEventBasedHold(), value.getDefaultEventBasedHold()); assertEquals(expected.getRetentionEffectiveTime(), value.getRetentionEffectiveTime()); assertEquals(expected.getRetentionPeriod(), value.getRetentionPeriod()); - assertEquals(expected.getRetentionPolicyIsLocked(), value.getRetentionPolicyIsLocked()); + assertEquals(expected.retentionPolicyIsLocked(), value.retentionPolicyIsLocked()); } @Test diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java index 0839adc4391c..9f0324b205b3 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java @@ -746,7 +746,7 @@ public void testBuilder() { assertEquals(DEFAULT_EVENT_BASED_HOLD, bucket.getDefaultEventBasedHold()); assertEquals(RETENTION_EFFECTIVE_TIME, bucket.getRetentionEffectiveTime()); assertEquals(RETENTION_PERIOD, bucket.getRetentionPeriod()); - assertEquals(RETENTION_POLICY_IS_LOCKED, bucket.getRetentionPolicyIsLocked()); + assertEquals(RETENTION_POLICY_IS_LOCKED, bucket.retentionPolicyIsLocked()); assertEquals(storage.getOptions(), bucket.getStorage().getOptions()); } } diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index df7475cc7eef..e8a233354b74 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -1925,11 +1925,11 @@ public void testRetentionPolicyNoLock() throws ExecutionException, InterruptedEx try { assertEquals(RETENTION_PERIOD, remoteBucket.getRetentionPeriod()); assertNotNull(remoteBucket.getRetentionEffectiveTime()); - assertNull(remoteBucket.getRetentionPolicyIsLocked()); + assertNull(remoteBucket.retentionPolicyIsLocked()); remoteBucket = storage.get(bucketName, Storage.BucketGetOption.fields(BucketField.RETENTION_POLICY)); assertEquals(RETENTION_PERIOD, remoteBucket.getRetentionPeriod()); assertNotNull(remoteBucket.getRetentionEffectiveTime()); - assertNull(remoteBucket.getRetentionPolicyIsLocked()); + assertNull(remoteBucket.retentionPolicyIsLocked()); String blobName = "test-create-with-retention-policy-hold"; BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, blobName).build(); Blob remoteBlob = storage.create(blobInfo); @@ -1959,7 +1959,7 @@ private void retentionPolicyLockRequesterPays(boolean requesterPays) throws Exec } Bucket remoteBucket = storage.create(bucketInfo); try { - assertNull(remoteBucket.getRetentionPolicyIsLocked()); + assertFalse(remoteBucket.retentionPolicyIsLocked()); assertNotNull(remoteBucket.getRetentionEffectiveTime()); assertNotNull(remoteBucket.getMetageneration()); if (requesterPays) { @@ -1968,7 +1968,7 @@ private void retentionPolicyLockRequesterPays(boolean requesterPays) throws Exec } else { remoteBucket = storage.lockRetentionPolicy(remoteBucket, Storage.BucketTargetOption.metagenerationMatch()); } - assertTrue(remoteBucket.getRetentionPolicyIsLocked()); + assertTrue(remoteBucket.retentionPolicyIsLocked()); assertNotNull(remoteBucket.getRetentionEffectiveTime()); } finally { RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); From 2943c4241d3258945c3ff23050ddb3b793557a0d Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Wed, 29 Aug 2018 21:41:00 -0700 Subject: [PATCH 09/13] Address comments --- .../com/google/cloud/storage/BlobInfo.java | 18 ++++++++++++------ .../java/com/google/cloud/storage/Bucket.java | 11 ++++++----- .../com/google/cloud/storage/BucketInfo.java | 10 +++++----- .../java/com/google/cloud/storage/Storage.java | 9 +++++---- .../cloud/storage/spi/v1/StorageRpc.java | 2 +- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index eb2297b86bc7..94bb8e2e18aa 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -800,19 +800,25 @@ public String getKmsKeyName() { } /** - * Returns the Event Based Hold status of the blob, if any. + * Returns the event based hold status of the blob, if any. */ - public Boolean getEventBasedHold() { return eventBasedHold; } + public Boolean getEventBasedHold() { + return eventBasedHold; + } /** - * Returns the Temporary Hold status of the blob, if any. + * Returns the temporary hold status of the blob, if any. */ - public Boolean getTemporaryHold() { return temporaryHold; } + public Boolean getTemporaryHold() { + return temporaryHold; + } /** - * Returns the Retention Expiration Time of the blob, if a retention period is defined. + * Returns the retention expiration time of the blob, if a retention period is defined. */ - public Long getRetentionExpirationTime() { return retentionExpirationTime; } + public Long getRetentionExpirationTime() { + return retentionExpirationTime; + } /** * Returns a builder for the current blob. diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 363c40de76fa..2fede4761cf9 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -1137,19 +1137,20 @@ public List listDefaultAcls() { /** * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. * - * Warning: Once a retention policy is locked, it can no longer be unlocked or removed only increased. - * * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id * to assign operational costs. * - *

    Example of locking a retention policy on a bucket, only if its metageneration matches the buckets - * metagenerationn otherwise a {@link StorageException} is thrown. + *

    Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened. + * + *

    Example of locking a retention policy on a bucket, only if its local metageneration value matches the bucket's + * service metageneration otherwise a {@link StorageException} is thrown. *

     {@code
        * String bucketName = "my_unique_bucket";
        * Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
    -   * bucket.lockRetentionPolicy(BucketTargetOption.metagenerationMatch());
    +   * storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch());
        * }
    * + * @return locked bucket * @throws StorageException upon failure */ public Bucket lockRetentionPolicy(BucketTargetOption... options) { diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 45ab3850c4ee..157cb32a7d67 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -435,7 +435,7 @@ public abstract static class Builder { public abstract Builder setDefaultKmsKeyName(String defaultKmsKeyName); /** - * Sets the default Event Based Hold for this bucket. + * Sets the default event based hold for this bucket. */ public abstract Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold); @@ -444,8 +444,8 @@ public abstract static class Builder { abstract Builder setRetentionPolicyIsLocked(Boolean retentionPolicyIsLocked); /** - * If policy is not locked this value can be cleared or increased. If policy is locked the retention period can only - * be increased. + * If policy is not locked this value can be cleared, increased, and decreased. If policy is locked the retention + * period can only be increased. */ public abstract Builder setRetentionPeriod(Long retentionPeriod); @@ -839,7 +839,7 @@ public String getDefaultKmsKeyName() { } /** - * Returns the default Event Based Hold to be applied to newly inserted objects in this bucket. + * Returns the default event based hold value used for inserted objects in this bucket. */ public Boolean getDefaultEventBasedHold() { return defaultEventBasedHold; } @@ -856,7 +856,7 @@ public Boolean retentionPolicyIsLocked() { } /** - * Returns the retention period. + * Returns the Retention Period. */ public Long getRetentionPeriod() { return retentionPeriod; } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 2ecf9066fbee..3b6e33d7b667 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1541,19 +1541,20 @@ public static Builder newBuilder() { /** * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. * - * Warning: Once a retention policy is locked, it can no longer be unlocked or removed only increased. - * * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id * to assign operational costs. * - *

    Example of locking a retention policy on a bucket, only if its local metageneration value matches the buckets - * service metagenerationn otherwise a {@link StorageException} is thrown. + *

    Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened. + * + *

    Example of locking a retention policy on a bucket, only if its local metageneration value matches the bucket's + * service metageneration otherwise a {@link StorageException} is thrown. *

     {@code
        * String bucketName = "my_unique_bucket";
        * Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
        * storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch());
        * }
    * + * @return locked bucket * @throws StorageException upon failure */ Bucket lockRetentionPolicy(BucketInfo bucket, BucketTargetOption... options); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 39de5ca15033..0ed6325b5b20 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -461,7 +461,7 @@ void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, /** * Lock retention policy for the provided bucket. - * @return + * @return locked bucket * @throws StorageException upon failure */ Bucket lockRetentionPolicy(Bucket bucket, Map options); From 3bd389c05c557d3c409adbdd92610d2a23936422 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Wed, 29 Aug 2018 21:45:49 -0700 Subject: [PATCH 10/13] Address comments --- .../src/main/java/com/google/cloud/storage/BucketInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 157cb32a7d67..f569ccdf04da 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -444,8 +444,8 @@ public abstract static class Builder { abstract Builder setRetentionPolicyIsLocked(Boolean retentionPolicyIsLocked); /** - * If policy is not locked this value can be cleared, increased, and decreased. If policy is locked the retention - * period can only be increased. + * If policy is not locked this value can be cleared, increased, and decreased. + * If policy is locked the retention period can only be increased. */ public abstract Builder setRetentionPeriod(Long retentionPeriod); From b12413197b81460ef627eb8eac8077a6bf3c156f Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 4 Sep 2018 12:04:19 -0700 Subject: [PATCH 11/13] Address comments. --- .../src/main/java/com/google/cloud/storage/Bucket.java | 2 +- .../src/main/java/com/google/cloud/storage/BucketInfo.java | 2 +- .../src/main/java/com/google/cloud/storage/Storage.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 2fede4761cf9..4a53882091b7 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -1137,7 +1137,7 @@ public List listDefaultAcls() { /** * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. * - * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id + *

    Accepts an optional userProject {@link BucketTargetOption} option which defines the project id * to assign operational costs. * *

    Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened. diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index f569ccdf04da..e24a5a7a89eb 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -856,7 +856,7 @@ public Boolean retentionPolicyIsLocked() { } /** - * Returns the Retention Period. + * Returns the retention policy retention period. */ public Long getRetentionPeriod() { return retentionPeriod; } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 3b6e33d7b667..0a8a778c6eeb 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1541,7 +1541,7 @@ public static Builder newBuilder() { /** * Locks bucket retention policy. Requires a local metageneration value in the request. Review example below. * - * Accepts an optional userProject {@link BucketTargetOption} option which defines the project id + *

    Accepts an optional userProject {@link BucketTargetOption} option which defines the project id * to assign operational costs. * *

    Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened. From 50b0cf7d2cf43ae97ccaffe054a58c9b9e8999bd Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 4 Sep 2018 12:07:20 -0700 Subject: [PATCH 12/13] Small nits --- .../src/main/java/com/google/cloud/storage/BlobInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index 94bb8e2e18aa..b130b880ce55 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -274,12 +274,12 @@ public abstract static class Builder { abstract Builder setKmsKeyName(String kmsKeyName); /** - * Sets the blob's eventBasedHold. + * Sets the blob's event based hold. */ public abstract Builder setEventBasedHold(Boolean eventBasedHold); /** - * Sets the blob's temporaryHold. + * Sets the blob's temporary hold. */ public abstract Builder setTemporaryHold(Boolean temporaryHold); From db07b0cb49e5c8b8fb663db3f64fc61eb950e440 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Tue, 4 Sep 2018 12:12:05 -0700 Subject: [PATCH 13/13] Fix additional comments --- .../src/main/java/com/google/cloud/storage/Bucket.java | 2 +- .../src/main/java/com/google/cloud/storage/Storage.java | 2 +- .../main/java/com/google/cloud/storage/spi/v1/StorageRpc.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 4a53882091b7..c06ed6f6958a 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -1150,7 +1150,7 @@ public List listDefaultAcls() { * storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch()); * } * - * @return locked bucket + * @return a {@code Bucket} object of the locked bucket * @throws StorageException upon failure */ public Bucket lockRetentionPolicy(BucketTargetOption... options) { diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 0a8a778c6eeb..aacff7c460e5 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1554,7 +1554,7 @@ public static Builder newBuilder() { * storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch()); * } * - * @return locked bucket + * @return a {@code Bucket} object of the locked bucket * @throws StorageException upon failure */ Bucket lockRetentionPolicy(BucketInfo bucket, BucketTargetOption... options); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 0ed6325b5b20..2a62a66a9967 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -461,7 +461,8 @@ void write(String uploadId, byte[] toWrite, int toWriteOffset, long destOffset, /** * Lock retention policy for the provided bucket. - * @return locked bucket + * + * @return a {@code Bucket} object of the locked bucket * @throws StorageException upon failure */ Bucket lockRetentionPolicy(Bucket bucket, Map options);