From f3c40da368d2e825bbd337c554f6f9bd33a00bdb Mon Sep 17 00:00:00 2001
From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com>
Date: Wed, 13 Oct 2021 13:52:59 -0700
Subject: [PATCH 1/6] (feat) Add RPO metadata settings
---
.../clirr-ignored-differences.xml | 5 ++
.../java/com/google/cloud/storage/Bucket.java | 6 +++
.../com/google/cloud/storage/BucketInfo.java | 22 ++++++++
.../java/com/google/cloud/storage/Rpo.java | 53 +++++++++++++++++++
.../cloud/storage/it/ITStorageTest.java | 39 +++++++-------
5 files changed, 106 insertions(+), 19 deletions(-)
create mode 100644 google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml
index 85c4887d6..14d4e43e2 100644
--- a/google-cloud-storage/clirr-ignored-differences.xml
+++ b/google-cloud-storage/clirr-ignored-differences.xml
@@ -21,6 +21,11 @@
com.google.cloud.storage.BucketInfo$Builder deleteLifecycleRules()
7013
+
+ com/google/cloud/storage/BucketInfo$Builder
+ com.google.cloud.storage.BucketInfo$Builder setRpo(com.google.cloud.storage.Rpo)
+ 7013
+
com/google/cloud/storage/BucketInfo$Builder
com.google.cloud.storage.BucketInfo$Builder setUpdateTime(java.lang.Long)
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
index 3714e6e94..95acd19d6 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
@@ -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);
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
index 83a836f78..d5d87f443 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
@@ -92,6 +92,7 @@ public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo)
private final List acl;
private final List defaultAcl;
private final String location;
+ private final Rpo rpo;
private final StorageClass storageClass;
private final Map labels;
private final String defaultKmsKeyName;
@@ -1185,6 +1186,8 @@ public abstract static class Builder {
/** Deletes the lifecycle rules of this bucket. */
public abstract Builder deleteLifecycleRules();
+ 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 deleteRules;
private List lifecycleRules;
+ private Rpo rpo;
private StorageClass storageClass;
private String location;
private String etag;
@@ -1317,6 +1321,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;
@@ -1410,6 +1415,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;
@@ -1548,6 +1559,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;
@@ -1709,6 +1721,10 @@ public String getLocationType() {
return locationType;
}
+ 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.
@@ -1879,6 +1895,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());
}
@@ -2042,6 +2061,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()));
}
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
new file mode 100644
index 000000000..6454d8662
--- /dev/null
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+public class Rpo extends StringEnumValue {
+
+ private Rpo(String constant) {
+ super(constant);
+ }
+
+ private static final ApiFunction CONSTRUCTOR = Rpo::new;
+
+ private static final StringEnumType type = new StringEnumType(Rpo.class, CONSTRUCTOR);
+
+ public static final Rpo DEFAULT = type.createAndRegister("DEFAULT");
+
+ 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();
+ }
+}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
index 73ef7e9b8..52510562c 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
@@ -54,34 +54,16 @@
import com.google.cloud.kms.v1.KeyManagementServiceGrpc.KeyManagementServiceBlockingStub;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.cloud.kms.v1.LocationName;
-import com.google.cloud.storage.Acl;
+import com.google.cloud.storage.*;
import com.google.cloud.storage.Acl.Role;
import com.google.cloud.storage.Acl.User;
-import com.google.cloud.storage.Blob;
-import com.google.cloud.storage.BlobId;
-import com.google.cloud.storage.BlobInfo;
-import com.google.cloud.storage.Bucket;
-import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.BucketInfo.LifecycleRule;
import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleAction;
import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleCondition;
-import com.google.cloud.storage.CopyWriter;
-import com.google.cloud.storage.Cors;
-import com.google.cloud.storage.HmacKey;
-import com.google.cloud.storage.HttpMethod;
-import com.google.cloud.storage.PostPolicyV4;
import com.google.cloud.storage.PostPolicyV4.PostFieldsV4;
-import com.google.cloud.storage.ServiceAccount;
-import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.BlobField;
import com.google.cloud.storage.Storage.BlobWriteOption;
import com.google.cloud.storage.Storage.BucketField;
-import com.google.cloud.storage.StorageBatch;
-import com.google.cloud.storage.StorageBatchResult;
-import com.google.cloud.storage.StorageClass;
-import com.google.cloud.storage.StorageException;
-import com.google.cloud.storage.StorageOptions;
-import com.google.cloud.storage.StorageRoles;
import com.google.cloud.storage.spi.StorageRpcFactory;
import com.google.cloud.storage.spi.v1.StorageRpc;
import com.google.cloud.storage.spi.v1.StorageRpc.Option;
@@ -3940,6 +3922,25 @@ protected Object handleInvocation(
assertArrayEquals(randStringBytes, 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) {
From 682736279c7f166dd4df010053a66c43f9bd0983 Mon Sep 17 00:00:00 2001
From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com>
Date: Thu, 14 Oct 2021 14:06:52 -0700
Subject: [PATCH 2/6] Add javadoc
---
.../com/google/cloud/storage/BucketInfo.java | 13 +++++++++
.../java/com/google/cloud/storage/Rpo.java | 17 +++++++++++
.../cloud/storage/it/ITStorageTest.java | 29 +++++++++++++++----
3 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
index d5d87f443..b7f915908 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
@@ -1186,6 +1186,13 @@ 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 here for additional
+ * details.
+ */
public abstract Builder setRpo(Rpo rpo);
/**
@@ -1721,6 +1728,12 @@ 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
+ */
public Rpo getRpo() {
return rpo;
}
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
index 6454d8662..b99c7cec0 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
@@ -19,8 +19,17 @@
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 betweens regions.
+ *
+ * @see https://cloud.google.com/storage/docs/turbo-replication
+ */
public class Rpo extends StringEnumValue {
+ private static final long serialVersionUID = -3954216195295821508L;
+
private Rpo(String constant) {
super(constant);
}
@@ -29,8 +38,16 @@ private Rpo(String constant) {
private static final StringEnumType 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");
/**
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
index 52510562c..4b4865f79 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
@@ -54,16 +54,35 @@
import com.google.cloud.kms.v1.KeyManagementServiceGrpc.KeyManagementServiceBlockingStub;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.cloud.kms.v1.LocationName;
-import com.google.cloud.storage.*;
+import com.google.cloud.storage.Acl;
import com.google.cloud.storage.Acl.Role;
import com.google.cloud.storage.Acl.User;
+import com.google.cloud.storage.Blob;
+import com.google.cloud.storage.BlobId;
+import com.google.cloud.storage.BlobInfo;
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.BucketInfo.LifecycleRule;
import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleAction;
import com.google.cloud.storage.BucketInfo.LifecycleRule.LifecycleCondition;
+import com.google.cloud.storage.CopyWriter;
+import com.google.cloud.storage.Cors;
+import com.google.cloud.storage.HmacKey;
+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;
import com.google.cloud.storage.Storage.BlobWriteOption;
import com.google.cloud.storage.Storage.BucketField;
+import com.google.cloud.storage.StorageBatch;
+import com.google.cloud.storage.StorageBatchResult;
+import com.google.cloud.storage.StorageClass;
+import com.google.cloud.storage.StorageException;
+import com.google.cloud.storage.StorageOptions;
+import com.google.cloud.storage.StorageRoles;
import com.google.cloud.storage.spi.StorageRpcFactory;
import com.google.cloud.storage.spi.v1.StorageRpc;
import com.google.cloud.storage.spi.v1.StorageRpc.Option;
@@ -3926,11 +3945,9 @@ protected Object handleInvocation(
public void testRpoConfig() {
String rpoBucket = RemoteStorageHelper.generateBucketName();
try {
- Bucket bucket = storage.create(
- BucketInfo.newBuilder(rpoBucket)
- .setLocation("NAM4")
- .setRpo(Rpo.ASYNC_TURBO)
- .build());
+ 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();
From 1edd21687690e0423593dccbff1d07f630cb7da8 Mon Sep 17 00:00:00 2001
From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com>
Date: Mon, 25 Oct 2021 14:41:58 -0700
Subject: [PATCH 3/6] Apply suggestions from code review
Co-authored-by: BenWhitehead
---
.../src/main/java/com/google/cloud/storage/Rpo.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
index b99c7cec0..b4c8e4104 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
@@ -26,7 +26,7 @@
* @see https://cloud.google.com/storage/docs/turbo-replication
*/
-public class Rpo extends StringEnumValue {
+public final class Rpo extends StringEnumValue {
private static final long serialVersionUID = -3954216195295821508L;
@@ -36,7 +36,7 @@ private Rpo(String constant) {
private static final ApiFunction CONSTRUCTOR = Rpo::new;
- private static final StringEnumType type = new StringEnumType(Rpo.class, CONSTRUCTOR);
+ private static final StringEnumType type = new StringEnumType<>(Rpo.class, CONSTRUCTOR);
/**
* Default recovery point objective. With this setting, there is no guarantee on the amount of
From 3861b3764c410d9a454c8295221945ee55dc6c4e Mon Sep 17 00:00:00 2001
From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com>
Date: Fri, 19 Nov 2021 14:57:05 -0800
Subject: [PATCH 4/6] typo
---
.../src/main/java/com/google/cloud/storage/Rpo.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
index b99c7cec0..1e155abb5 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Rpo.java
@@ -21,7 +21,7 @@
/**
* Enums for the Recovery Point Objective (RPO) of dual-region buckets, which determines how fast
- * data is replicated betweens regions.
+ * data is replicated between regions.
*
* @see https://cloud.google.com/storage/docs/turbo-replication
From ce47c976088d1916b6800e2ae9929ebbb5e5dedc Mon Sep 17 00:00:00 2001
From: Owl Bot
Date: Mon, 10 Jan 2022 21:12:40 +0000
Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 42a0678cd..9c0c0ab4a 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ If you are using Maven without BOM, add this to your dependencies:
If you are using Gradle 5.x or later, add this to your dependencies
```Groovy
-implementation platform('com.google.cloud:libraries-bom:24.1.2')
+implementation platform('com.google.cloud:libraries-bom:24.2.0')
implementation 'com.google.cloud:google-cloud-storage'
```
From 38d38e8afc7327e64637e0bd3f109fdbdc53b548 Mon Sep 17 00:00:00 2001
From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com>
Date: Wed, 12 Jan 2022 11:30:49 -0800
Subject: [PATCH 6/6] fix clirr
---
google-cloud-storage/clirr-ignored-differences.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml
index 44f6eb201..c45b439cc 100644
--- a/google-cloud-storage/clirr-ignored-differences.xml
+++ b/google-cloud-storage/clirr-ignored-differences.xml
@@ -5,6 +5,7 @@
com/google/cloud/storage/BucketInfo$Builder
com.google.cloud.storage.BucketInfo$Builder setRpo(com.google.cloud.storage.Rpo)
7013
+
com/google/cloud/storage/BucketInfo$LifecycleRule$LifecycleAction
BucketInfo$LifecycleRule$LifecycleAction()