Skip to content

Commit

Permalink
[Storage] Replay GCS Bucket Lock (#3645)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
frankyn committed Sep 15, 2018
1 parent 739d519 commit 2fda901
Show file tree
Hide file tree
Showing 16 changed files with 579 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
* <li>createBatch
* <li>checksums, etags
* <li>IAM operations</li>
* <li>BucketLock operations</li>
* </ul>
* </ul>
*/
Expand Down Expand Up @@ -520,6 +521,11 @@ public Notification createNotification(String bucket, Notification notification)
throw new UnsupportedOperationException();
}

@Override
public Bucket lockRetentionPolicy(Bucket bucket, Map<Option, ?> options) {
throw new UnsupportedOperationException();
}

@Override
public ServiceAccount getServiceAccount(String projectId) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,30 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) {
return this;
}

@GcpLaunchStage.Beta
@Override
Builder setKmsKeyName(String kmsKeyName) {
infoBuilder.setKmsKeyName(kmsKeyName);
return this;
}

@Override
public Builder setEventBasedHold(Boolean eventBasedHold) {
infoBuilder.setEventBasedHold(eventBasedHold);
return this;
}

@Override
public Builder setTemporaryHold(Boolean temporaryHold) {
infoBuilder.setTemporaryHold(temporaryHold);
return this;
}

@Override
Builder setRetentionExpirationTime(Long retentionExpirationTime) {
infoBuilder.setRetentionExpirationTime(retentionExpirationTime);
return this;
}

@Override
public Blob build() {
return new Blob(storage, infoBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ public StorageObject apply(BlobInfo blobInfo) {
private final boolean isDirectory;
private final CustomerEncryption customerEncryption;
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.
Expand Down Expand Up @@ -268,12 +271,19 @@ public abstract static class Builder {

abstract Builder setCustomerEncryption(CustomerEncryption customerEncryption);

abstract Builder setKmsKeyName(String kmsKeyName);

/**
*
* Sets the blob's kmsKeyName.
* Sets the blob's event based hold.
*/
@GcpLaunchStage.Beta
abstract Builder setKmsKeyName(String kmsKeyName);
public abstract Builder setEventBasedHold(Boolean eventBasedHold);

/**
* Sets the blob's temporary hold.
*/
public abstract Builder setTemporaryHold(Boolean temporaryHold);

abstract Builder setRetentionExpirationTime(Long retentionExpirationTime);

/**
* Creates a {@code BlobInfo} object.
Expand Down Expand Up @@ -308,6 +318,9 @@ static final class BuilderImpl extends Builder {
private CustomerEncryption customerEncryption;
private StorageClass storageClass;
private String kmsKeyName;
private Boolean eventBasedHold;
private Boolean temporaryHold;
private Long retentionExpirationTime;

BuilderImpl(BlobId blobId) {
this.blobId = blobId;
Expand Down Expand Up @@ -339,6 +352,9 @@ static final class BuilderImpl extends Builder {
isDirectory = blobInfo.isDirectory;
storageClass = blobInfo.storageClass;
kmsKeyName = blobInfo.kmsKeyName;
eventBasedHold = blobInfo.eventBasedHold;
temporaryHold = blobInfo.temporaryHold;
retentionExpirationTime = blobInfo.retentionExpirationTime;
}

@Override
Expand Down Expand Up @@ -486,13 +502,30 @@ Builder setCustomerEncryption(CustomerEncryption customerEncryption) {
return this;
}

@GcpLaunchStage.Beta
@Override
Builder setKmsKeyName(String kmsKeyName) {
this.kmsKeyName = kmsKeyName;
return this;
}

@Override
public Builder setEventBasedHold(Boolean eventBasedHold) {
this.eventBasedHold = eventBasedHold;
return this;
}

@Override
public Builder setTemporaryHold(Boolean temporaryHold) {
this.temporaryHold = temporaryHold;
return this;
}

@Override
Builder setRetentionExpirationTime(Long retentionExpirationTime) {
this.retentionExpirationTime = retentionExpirationTime;
return this;
}

@Override
public BlobInfo build() {
checkNotNull(blobId);
Expand Down Expand Up @@ -526,6 +559,9 @@ public BlobInfo build() {
isDirectory = firstNonNull(builder.isDirectory, Boolean.FALSE);
storageClass = builder.storageClass;
kmsKeyName = builder.kmsKeyName;
eventBasedHold = builder.eventBasedHold;
temporaryHold = builder.temporaryHold;
retentionExpirationTime = builder.retentionExpirationTime;
}

/**
Expand Down Expand Up @@ -759,11 +795,31 @@ public StorageClass getStorageClass() {
/**
* Returns the Cloud KMS key used to encrypt the blob, if any.
*/
@GcpLaunchStage.Beta
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 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.
*/
Expand Down Expand Up @@ -836,8 +892,13 @@ 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);
storageObject.setTemporaryHold(temporaryHold);
storageObject.setMetadata(pbMetadata);
storageObject.setCacheControl(cacheControl);
storageObject.setContentEncoding(contentEncoding);
Expand Down Expand Up @@ -971,6 +1032,15 @@ public Acl apply(ObjectAccessControl objectAccessControl) {
if (storageObject.getKmsKeyName() != null) {
builder.setKmsKeyName(storageObject.getKmsKeyName());
}
if (storageObject.getEventBasedHold() != null) {
builder.setEventBasedHold(storageObject.getEventBasedHold());
}
if (storageObject.getTemporaryHold() != null) {
builder.setTemporaryHold(storageObject.getTemporaryHold());
}
if (storageObject.getRetentionExpirationTime() != null) {
builder.setRetentionExpirationTime(storageObject.getRetentionExpirationTime().getValue());
}
return builder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -628,13 +628,36 @@ public Builder setLabels(Map<String, String> labels) {
return this;
}

@GcpLaunchStage.Beta
@Override
public Builder setDefaultKmsKeyName(String defaultKmsKeyName) {
infoBuilder.setDefaultKmsKeyName(defaultKmsKeyName);
return this;
}

@Override
public Builder setDefaultEventBasedHold(Boolean defaultEventBasedHold) {
infoBuilder.setDefaultEventBasedHold(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);
Expand Down Expand Up @@ -1111,6 +1134,29 @@ public List<Acl> listDefaultAcls() {
return storage.listDefaultAcls(getName());
}

/**
* Locks bucket retention policy. Requires a local metageneration value in the request. Review example below.
*
* <p>Accepts an optional userProject {@link BucketTargetOption} option which defines the project id
* to assign operational costs.
*
* <p>Warning: Once a retention policy is locked, it can't be unlocked, removed, or shortened.
*
* <p>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.
* <pre> {@code
* String bucketName = "my_unique_bucket";
* Bucket bucket = storage.get(bucketName, BucketGetOption.fields(BucketField.METAGENERATION));
* storage.lockRetentionPolicy(bucket, BucketTargetOption.metagenerationMatch());
* }</pre>
*
* @return a {@code Bucket} object of the locked bucket
* @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.
*/
Expand Down
Loading

0 comments on commit 2fda901

Please sign in to comment.