Skip to content

Commit

Permalink
feat: Add RPO metadata settings (#1105)
Browse files Browse the repository at this point in the history
* (feat) Add RPO metadata settings

* Add javadoc

* Apply suggestions from code review

Co-authored-by: BenWhitehead <BenWhitehead@users.noreply.github.com>

* typo

* 🦉 Updates from OwlBot

See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md

* fix clirr

Co-authored-by: BenWhitehead <BenWhitehead@users.noreply.github.com>
Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 12, 2022
1 parent ece0fe5 commit 6f9dfdf
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 0 deletions.
5 changes: 5 additions & 0 deletions google-cloud-storage/clirr-ignored-differences.xml
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- see https://www.mojohaus.org/clirr-maven-plugin/examples/ignored-differences.html -->
<differences>
<difference>
<className>com/google/cloud/storage/BucketInfo$Builder</className>
<method>com.google.cloud.storage.BucketInfo$Builder setRpo(com.google.cloud.storage.Rpo)</method>
<differenceType>7013</differenceType>
</difference>
<difference>
<className>com/google/cloud/storage/BucketInfo$LifecycleRule$LifecycleAction</className>
<method>BucketInfo$LifecycleRule$LifecycleAction()</method>
Expand Down
Expand Up @@ -577,6 +577,12 @@ public Builder deleteLifecycleRules() {
return this;
}

@Override
public Builder setRpo(Rpo rpo) {
infoBuilder.setRpo(rpo);
return this;
}

@Override
public Builder setStorageClass(StorageClass storageClass) {
infoBuilder.setStorageClass(storageClass);
Expand Down
Expand Up @@ -92,6 +92,7 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo)
private final List<Acl> acl;
private final List<Acl> defaultAcl;
private final String location;
private final Rpo rpo;
private final StorageClass storageClass;
private final Map<String, String> labels;
private final String defaultKmsKeyName;
Expand Down Expand Up @@ -1205,6 +1206,15 @@ public abstract static class Builder {
/** Deletes the lifecycle rules of this bucket. */
public abstract Builder deleteLifecycleRules();

/**
* Sets the bucket's Recovery Point Objective (RPO). This can only be set for a dual-region
* bucket, and determines the speed at which data will be replicated between regions. See the
* {@code Rpo} class for supported values, and <a
* href="https://cloud.google.com/storage/docs/turbo-replication">here</a> for additional
* details.
*/
public abstract Builder setRpo(Rpo rpo);

/**
* Sets the bucket's storage class. This defines how blobs in the bucket are stored and
* determines the SLA and the cost of storage. A list of supported values is available <a
Expand Down Expand Up @@ -1306,6 +1316,7 @@ static final class BuilderImpl extends Builder {
private String notFoundPage;
private List<DeleteRule> deleteRules;
private List<LifecycleRule> lifecycleRules;
private Rpo rpo;
private StorageClass storageClass;
private String location;
private String etag;
Expand Down Expand Up @@ -1337,6 +1348,7 @@ static final class BuilderImpl extends Builder {
updateTime = bucketInfo.updateTime;
metageneration = bucketInfo.metageneration;
location = bucketInfo.location;
rpo = bucketInfo.rpo;
storageClass = bucketInfo.storageClass;
cors = bucketInfo.cors;
acl = bucketInfo.acl;
Expand Down Expand Up @@ -1430,6 +1442,12 @@ public Builder deleteLifecycleRules() {
return this;
}

@Override
public Builder setRpo(Rpo rpo) {
this.rpo = rpo;
return this;
}

@Override
public Builder setStorageClass(StorageClass storageClass) {
this.storageClass = storageClass;
Expand Down Expand Up @@ -1568,6 +1586,7 @@ public BucketInfo build() {
updateTime = builder.updateTime;
metageneration = builder.metageneration;
location = builder.location;
rpo = builder.rpo;
storageClass = builder.storageClass;
cors = builder.cors;
acl = builder.acl;
Expand Down Expand Up @@ -1729,6 +1748,16 @@ public String getLocationType() {
return locationType;
}

/**
* Returns the bucket's recovery point objective (RPO). This defines how quickly data is
* replicated between regions in a dual-region bucket. Not defined for single-region buckets.
*
* @see <a href="https://cloud.google.com/storage/docs/turbo-replication"Turbo Replication"</a>
*/
public Rpo getRpo() {
return rpo;
}

/**
* Returns the bucket's storage class. This defines how blobs in the bucket are stored and
* determines the SLA and the cost of storage.
Expand Down Expand Up @@ -1899,6 +1928,9 @@ com.google.api.services.storage.model.Bucket toPb() {
if (locationType != null) {
bucketPb.setLocationType(locationType);
}
if (rpo != null) {
bucketPb.setRpo(rpo.toString());
}
if (storageClass != null) {
bucketPb.setStorageClass(storageClass.toString());
}
Expand Down Expand Up @@ -2062,6 +2094,9 @@ static BucketInfo fromPb(com.google.api.services.storage.model.Bucket bucketPb)
if (bucketPb.getLocation() != null) {
builder.setLocation(bucketPb.getLocation());
}
if (bucketPb.getRpo() != null) {
builder.setRpo(Rpo.valueOf(bucketPb.getRpo()));
}
if (bucketPb.getStorageClass() != null) {
builder.setStorageClass(StorageClass.valueOf(bucketPb.getStorageClass()));
}
Expand Down
@@ -0,0 +1,70 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.storage;

import com.google.api.core.ApiFunction;
import com.google.cloud.StringEnumType;
import com.google.cloud.StringEnumValue;

/**
* Enums for the Recovery Point Objective (RPO) of dual-region buckets, which determines how fast
* data is replicated between regions.
*
* @see <a
* href="https://cloud.google.com/storage/docs/turbo-replication">https://cloud.google.com/storage/docs/turbo-replication</a>
*/
public final class Rpo extends StringEnumValue {

private static final long serialVersionUID = -3954216195295821508L;

private Rpo(String constant) {
super(constant);
}

private static final ApiFunction<String, Rpo> CONSTRUCTOR = Rpo::new;

private static final StringEnumType<Rpo> type = new StringEnumType<>(Rpo.class, CONSTRUCTOR);

/**
* Default recovery point objective. With this setting, there is no guarantee on the amount of
* time it takes for data to replicate between regions.
*/
public static final Rpo DEFAULT = type.createAndRegister("DEFAULT");

/**
* Turbo recovery point objective. With this setting, data in a dual-region bucket will replicate
* between regions within 15 minutes.
*/
public static final Rpo ASYNC_TURBO = type.createAndRegister("ASYNC_TURBO");

/**
* Get the Rpo for the given String constant, and throw an exception if the constant is not
* recognized.
*/
public static Rpo valueOfStrict(String constant) {
return type.valueOfStrict(constant);
}

/** Get the Rpo for the given String constant, and allow unrecognized values. */
public static Rpo valueOf(String constant) {
return type.valueOf(constant);
}

/** Return the known values for Rpo. */
public static Rpo[] values() {
return type.values();
}
}
Expand Up @@ -73,6 +73,7 @@
import com.google.cloud.storage.HttpMethod;
import com.google.cloud.storage.PostPolicyV4;
import com.google.cloud.storage.PostPolicyV4.PostFieldsV4;
import com.google.cloud.storage.Rpo;
import com.google.cloud.storage.ServiceAccount;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.BlobField;
Expand Down Expand Up @@ -3951,4 +3952,33 @@ protected Object handleInvocation(
blobGen2.downloadTo(actualData);
assertEquals(contentGen2Expected, ByteBuffer.wrap(actualData.toByteArray()));
}

@Test
public void testRpoConfig() {
String rpoBucket = RemoteStorageHelper.generateBucketName();
try {
Bucket bucket =
storage.create(
BucketInfo.newBuilder(rpoBucket).setLocation("NAM4").setRpo(Rpo.ASYNC_TURBO).build());
assertEquals("ASYNC_TURBO", bucket.getRpo().toString());

bucket.toBuilder().setRpo(Rpo.DEFAULT).build().update();

assertEquals("DEFAULT", storage.get(rpoBucket).getRpo().toString());
} finally {
storage.delete(rpoBucket);
}
}

private static String randString(Random rand, int length) {
final StringBuilder sb = new StringBuilder();
while (sb.length() < length) {
int i = rand.nextInt('z');
char c = (char) i;
if (Character.isLetter(c) || Character.isDigit(c)) {
sb.append(c);
}
}
return sb.toString();
}
}

0 comments on commit 6f9dfdf

Please sign in to comment.