Skip to content

Commit 2fda901

Browse files
frankynFrank Natividad
authored andcommitted
[Storage] Replay GCS Bucket Lock (#3645)
* Add support for defaultEventBasedHold * Add support for Blob eventBasedHold * Add support for blob temporary holds * Remove Beta launch annotations for CMEK * Add support for lockRetentionPolicy and RetentionPolicy * Update FakeStorageRPC * codacy-bot review fix (final only) * Update getRetentionPolicyIsLocked() -> retentionPolicyIsLocked() and misc. * Address comments * Address comments * Address comments. * Small nits * Fix additional comments
1 parent 739d519 commit 2fda901

File tree

16 files changed

+579
-22
lines changed

16 files changed

+579
-22
lines changed

google-cloud-clients/google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
* <li>createBatch
6666
* <li>checksums, etags
6767
* <li>IAM operations</li>
68+
* <li>BucketLock operations</li>
6869
* </ul>
6970
* </ul>
7071
*/
@@ -520,6 +521,11 @@ public Notification createNotification(String bucket, Notification notification)
520521
throw new UnsupportedOperationException();
521522
}
522523

524+
@Override
525+
public Bucket lockRetentionPolicy(Bucket bucket, Map<Option, ?> options) {
526+
throw new UnsupportedOperationException();
527+
}
528+
523529
@Override
524530
public ServiceAccount getServiceAccount(String projectId) {
525531
return null;

google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,13 +402,30 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) {
402402
return this;
403403
}
404404

405-
@GcpLaunchStage.Beta
406405
@Override
407406
Builder setKmsKeyName(String kmsKeyName) {
408407
infoBuilder.setKmsKeyName(kmsKeyName);
409408
return this;
410409
}
411410

411+
@Override
412+
public Builder setEventBasedHold(Boolean eventBasedHold) {
413+
infoBuilder.setEventBasedHold(eventBasedHold);
414+
return this;
415+
}
416+
417+
@Override
418+
public Builder setTemporaryHold(Boolean temporaryHold) {
419+
infoBuilder.setTemporaryHold(temporaryHold);
420+
return this;
421+
}
422+
423+
@Override
424+
Builder setRetentionExpirationTime(Long retentionExpirationTime) {
425+
infoBuilder.setRetentionExpirationTime(retentionExpirationTime);
426+
return this;
427+
}
428+
412429
@Override
413430
public Blob build() {
414431
return new Blob(storage, infoBuilder);

google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ public StorageObject apply(BlobInfo blobInfo) {
8585
private final boolean isDirectory;
8686
private final CustomerEncryption customerEncryption;
8787
private final String kmsKeyName;
88+
private final Boolean eventBasedHold;
89+
private final Boolean temporaryHold;
90+
private final Long retentionExpirationTime;
8891

8992
/**
9093
* This class is meant for internal use only. Users are discouraged from using this class.
@@ -268,12 +271,19 @@ public abstract static class Builder {
268271

269272
abstract Builder setCustomerEncryption(CustomerEncryption customerEncryption);
270273

274+
abstract Builder setKmsKeyName(String kmsKeyName);
275+
271276
/**
272-
*
273-
* Sets the blob's kmsKeyName.
277+
* Sets the blob's event based hold.
274278
*/
275-
@GcpLaunchStage.Beta
276-
abstract Builder setKmsKeyName(String kmsKeyName);
279+
public abstract Builder setEventBasedHold(Boolean eventBasedHold);
280+
281+
/**
282+
* Sets the blob's temporary hold.
283+
*/
284+
public abstract Builder setTemporaryHold(Boolean temporaryHold);
285+
286+
abstract Builder setRetentionExpirationTime(Long retentionExpirationTime);
277287

278288
/**
279289
* Creates a {@code BlobInfo} object.
@@ -308,6 +318,9 @@ static final class BuilderImpl extends Builder {
308318
private CustomerEncryption customerEncryption;
309319
private StorageClass storageClass;
310320
private String kmsKeyName;
321+
private Boolean eventBasedHold;
322+
private Boolean temporaryHold;
323+
private Long retentionExpirationTime;
311324

312325
BuilderImpl(BlobId blobId) {
313326
this.blobId = blobId;
@@ -339,6 +352,9 @@ static final class BuilderImpl extends Builder {
339352
isDirectory = blobInfo.isDirectory;
340353
storageClass = blobInfo.storageClass;
341354
kmsKeyName = blobInfo.kmsKeyName;
355+
eventBasedHold = blobInfo.eventBasedHold;
356+
temporaryHold = blobInfo.temporaryHold;
357+
retentionExpirationTime = blobInfo.retentionExpirationTime;
342358
}
343359

344360
@Override
@@ -486,13 +502,30 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) {
486502
return this;
487503
}
488504

489-
@GcpLaunchStage.Beta
490505
@Override
491506
Builder setKmsKeyName(String kmsKeyName) {
492507
this.kmsKeyName = kmsKeyName;
493508
return this;
494509
}
495510

511+
@Override
512+
public Builder setEventBasedHold(Boolean eventBasedHold) {
513+
this.eventBasedHold = eventBasedHold;
514+
return this;
515+
}
516+
517+
@Override
518+
public Builder setTemporaryHold(Boolean temporaryHold) {
519+
this.temporaryHold = temporaryHold;
520+
return this;
521+
}
522+
523+
@Override
524+
Builder setRetentionExpirationTime(Long retentionExpirationTime) {
525+
this.retentionExpirationTime = retentionExpirationTime;
526+
return this;
527+
}
528+
496529
@Override
497530
public BlobInfo build() {
498531
checkNotNull(blobId);
@@ -526,6 +559,9 @@ public BlobInfo build() {
526559
isDirectory = firstNonNull(builder.isDirectory, Boolean.FALSE);
527560
storageClass = builder.storageClass;
528561
kmsKeyName = builder.kmsKeyName;
562+
eventBasedHold = builder.eventBasedHold;
563+
temporaryHold = builder.temporaryHold;
564+
retentionExpirationTime = builder.retentionExpirationTime;
529565
}
530566

531567
/**
@@ -759,11 +795,31 @@ public StorageClass getStorageClass() {
759795
/**
760796
* Returns the Cloud KMS key used to encrypt the blob, if any.
761797
*/
762-
@GcpLaunchStage.Beta
763798
public String getKmsKeyName() {
764799
return kmsKeyName;
765800
}
766801

802+
/**
803+
* Returns the event based hold status of the blob, if any.
804+
*/
805+
public Boolean getEventBasedHold() {
806+
return eventBasedHold;
807+
}
808+
809+
/**
810+
* Returns the temporary hold status of the blob, if any.
811+
*/
812+
public Boolean getTemporaryHold() {
813+
return temporaryHold;
814+
}
815+
816+
/**
817+
* Returns the retention expiration time of the blob, if a retention period is defined.
818+
*/
819+
public Long getRetentionExpirationTime() {
820+
return retentionExpirationTime;
821+
}
822+
767823
/**
768824
* Returns a builder for the current blob.
769825
*/
@@ -836,8 +892,13 @@ public ObjectAccessControl apply(Acl acl) {
836892
if (customerEncryption != null) {
837893
storageObject.setCustomerEncryption(customerEncryption.toPb());
838894
}
895+
if (retentionExpirationTime != null) {
896+
storageObject.setRetentionExpirationTime(new DateTime(retentionExpirationTime));
897+
}
839898

840899
storageObject.setKmsKeyName(kmsKeyName);
900+
storageObject.setEventBasedHold(eventBasedHold);
901+
storageObject.setTemporaryHold(temporaryHold);
841902
storageObject.setMetadata(pbMetadata);
842903
storageObject.setCacheControl(cacheControl);
843904
storageObject.setContentEncoding(contentEncoding);
@@ -971,6 +1032,15 @@ public Acl apply(ObjectAccessControl objectAccessControl) {
9711032
if (storageObject.getKmsKeyName() != null) {
9721033
builder.setKmsKeyName(storageObject.getKmsKeyName());
9731034
}
1035+
if (storageObject.getEventBasedHold() != null) {
1036+
builder.setEventBasedHold(storageObject.getEventBasedHold());
1037+
}
1038+
if (storageObject.getTemporaryHold() != null) {
1039+
builder.setTemporaryHold(storageObject.getTemporaryHold());
1040+
}
1041+
if (storageObject.getRetentionExpirationTime() != null) {
1042+
builder.setRetentionExpirationTime(storageObject.getRetentionExpirationTime().getValue());
1043+
}
9741044
return builder.build();
9751045
}
9761046
}

google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,13 +628,36 @@ public Builder setLabels(Map<String, String> labels) {
628628
return this;
629629
}
630630

631-
@GcpLaunchStage.Beta
632631
@Override
633632
public Builder setDefaultKmsKeyName(String defaultKmsKeyName) {
634633
infoBuilder.setDefaultKmsKeyName(defaultKmsKeyName);
635634
return this;
636635
}
637636

637+
@Override
638+
public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) {
639+
infoBuilder.setDefaultEventBasedHold(defaultEventBasedHold);
640+
return this;
641+
}
642+
643+
@Override
644+
Builder setRetentionEffectiveTime(Long retentionEffectiveTime) {
645+
infoBuilder.setRetentionEffectiveTime(retentionEffectiveTime);
646+
return this;
647+
}
648+
649+
@Override
650+
Builder setRetentionPolicyIsLocked(Boolean retentionIsLocked) {
651+
infoBuilder.setRetentionPolicyIsLocked(retentionIsLocked);
652+
return this;
653+
}
654+
655+
@Override
656+
public Builder setRetentionPeriod(Long retentionPeriod) {
657+
infoBuilder.setRetentionPeriod(retentionPeriod);
658+
return this;
659+
}
660+
638661
@Override
639662
public Bucket build() {
640663
return new Bucket(storage, infoBuilder);
@@ -1111,6 +1134,29 @@ public List<Acl> listDefaultAcls() {
11111134
return storage.listDefaultAcls(getName());
11121135
}
11131136

1137+
/**
1138+
* Locks bucket retention policy. Requires a local metageneration value in the request. Review example below.
1139+
*
1140+
* <p>Accepts an optional userProject {@link BucketTargetOption} option which defines the project id
1141+
* to assign operational costs.
1142+
*
1143+
* <p>Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened.
1144+
*
1145+
* <p>Example of locking a retention policy on a bucket, only if its local metageneration value matches the bucket's
1146+
* service metageneration otherwise a {@link StorageException} is thrown.
1147+
* <pre> {@code
1148+
* String bucketName = "my_unique_bucket";
1149+
* Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
1150+
* storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch());
1151+
* }</pre>
1152+
*
1153+
* @return a {@code Bucket} object of the locked bucket
1154+
* @throws StorageException upon failure
1155+
*/
1156+
public Bucket lockRetentionPolicy(BucketTargetOption... options) {
1157+
return storage.lockRetentionPolicy(this, options);
1158+
}
1159+
11141160
/**
11151161
* Returns the bucket's {@code Storage} object used to issue requests.
11161162
*/

0 commit comments

Comments
 (0)