diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml
index e45beaea0..1afd91a66 100644
--- a/google-cloud-storage/clirr-ignored-differences.xml
+++ b/google-cloud-storage/clirr-ignored-differences.xml
@@ -7,6 +7,12 @@
* setCustomPlacementConfig(com.google.cloud.storage.BucketInfo$CustomPlacementConfig)
+
+ com/google/cloud/storage/BucketInfo*
+ 7013
+ * setAutoclass(com.google.cloud.storage.BucketInfo$Autoclass)
+
+
7002
com/google/cloud/storage/HmacKey$HmacKeyMetadata
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/ApiaryConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/ApiaryConversions.java
index d876be88e..d5ca3b594 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/ApiaryConversions.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/ApiaryConversions.java
@@ -53,6 +53,7 @@
import com.google.cloud.storage.Acl.Role;
import com.google.cloud.storage.Acl.User;
import com.google.cloud.storage.BlobInfo.CustomerEncryption;
+import com.google.cloud.storage.BucketInfo.Autoclass;
import com.google.cloud.storage.BucketInfo.CustomPlacementConfig;
import com.google.cloud.storage.BucketInfo.IamConfiguration;
import com.google.cloud.storage.BucketInfo.LifecycleRule;
@@ -101,6 +102,8 @@ final class ApiaryConversions {
Codec.of(this::loggingEncode, this::loggingDecode);
private final Codec iamConfigurationCodec =
Codec.of(this::iamConfigEncode, this::iamConfigDecode);
+ private final Codec autoclassCodec =
+ Codec.of(this::autoclassEncode, this::autoclassDecode);
private final Codec lifecycleRuleCodec =
Codec.of(this::lifecycleRuleEncode, this::lifecycleRuleDecode);
private final Codec lifecycleConditionCodec =
@@ -386,6 +389,7 @@ private Bucket bucketInfoEncode(BucketInfo from) {
to.setRetentionPolicy(retentionPolicy);
}
ifNonNull(from.getIamConfiguration(), this::iamConfigEncode, to::setIamConfiguration);
+ ifNonNull(from.getAutoclass(), this::autoclassEncode, to::setAutoclass);
ifNonNull(from.getLogging(), this::loggingEncode, to::setLogging);
ifNonNull(
from.getCustomPlacementConfig(),
@@ -438,6 +442,7 @@ private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket
ifNonNull(retentionPolicy, RetentionPolicy::getIsLocked, to::setRetentionPolicyIsLocked);
ifNonNull(retentionPolicy, RetentionPolicy::getRetentionPeriod, to::setRetentionPeriod);
ifNonNull(from.getIamConfiguration(), this::iamConfigDecode, to::setIamConfiguration);
+ ifNonNull(from.getAutoclass(), this::autoclassDecode, to::setAutoclass);
ifNonNull(from.getLogging(), this::loggingDecode, to::setLogging);
ifNonNull(
from.getCustomPlacementConfig(),
@@ -473,6 +478,20 @@ private IamConfiguration iamConfigDecode(Bucket.IamConfiguration from) {
return to.build();
}
+ private Bucket.Autoclass autoclassEncode(Autoclass from) {
+ Bucket.Autoclass to = new Bucket.Autoclass();
+ ifNonNull(from.getEnabled(), to::setEnabled);
+ ifNonNull(from.getToggleTime(), dateTimeCodec::encode, to::setToggleTime);
+ return to;
+ }
+
+ private Autoclass autoclassDecode(Bucket.Autoclass from) {
+ Autoclass.Builder to = Autoclass.newBuilder();
+ to.setEnabled(from.getEnabled());
+ ifNonNull(from.getToggleTime(), dateTimeCodec::decode, to::setToggleTime);
+ return to.build();
+ }
+
private UniformBucketLevelAccess ublaEncode(IamConfiguration from) {
UniformBucketLevelAccess to = new UniformBucketLevelAccess();
to.setEnabled(from.isUniformBucketLevelAccessEnabled());
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 c74e784d3..cbfbf5251 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
@@ -603,6 +603,12 @@ public Builder setIamConfiguration(IamConfiguration iamConfiguration) {
return this;
}
+ @Override
+ public Builder setAutoclass(Autoclass autoclass) {
+ infoBuilder.setAutoclass(autoclass);
+ return this;
+ }
+
@Override
public Builder setLogging(Logging logging) {
infoBuilder.setLogging(logging);
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 60a330453..8857f55d3 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
@@ -107,6 +107,7 @@ public class BucketInfo implements Serializable {
private final Boolean retentionPolicyIsLocked;
private final Duration retentionPeriod;
private final IamConfiguration iamConfiguration;
+ private final Autoclass autoclass;
private final String locationType;
private final Logging logging;
private final CustomPlacementConfig customPlacementConfig;
@@ -340,6 +341,89 @@ public String toString() {
}
}
+ public static final class Autoclass implements Serializable {
+
+ private static final long serialVersionUID = -2378172222188072439L;
+ private Boolean enabled;
+ private OffsetDateTime toggleTime;
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public OffsetDateTime getToggleTime() {
+ return toggleTime;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Autoclass)) {
+ return false;
+ }
+ Autoclass that = (Autoclass) o;
+ return Objects.equals(enabled, that.enabled) && Objects.equals(toggleTime, that.toggleTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(enabled, toggleTime);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("enabled", enabled)
+ .add("toggleTime", toggleTime)
+ .toString();
+ }
+
+ private Autoclass() {}
+
+ private Autoclass(Builder builder) {
+ this.enabled = builder.enabled;
+ this.toggleTime = builder.toggleTime;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return newBuilder().setEnabled(enabled).setToggleTime(toggleTime);
+ }
+
+ public static final class Builder {
+ private Boolean enabled;
+ private OffsetDateTime toggleTime;
+
+ /**
+ * Sets whether Autoclass is enabled for this bucket. Currently, autoclass can only be enabled
+ * at bucket create time. Any calls to update an existing Autoclass configuration must be to
+ * disable it, calls to enable Autoclass on an existing bucket will fail.
+ */
+ public Builder setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ return this;
+ }
+
+ /**
+ * Sets the last time autoclass was toggled on or off. Set to package private because this
+ * should only be set by the backend.
+ */
+ Builder setToggleTime(OffsetDateTime toggleTime) {
+ this.toggleTime = toggleTime;
+ return this;
+ }
+
+ public Autoclass build() {
+ return new Autoclass(this);
+ }
+ }
+ }
+
/**
* The bucket's custom placement configuration for Custom Dual Regions. If using `location` is
* also required.
@@ -1443,6 +1527,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) {
@BetaApi
public abstract Builder setIamConfiguration(IamConfiguration iamConfiguration);
+ public abstract Builder setAutoclass(Autoclass autoclass);
+
public abstract Builder setLogging(Logging logging);
public abstract Builder setCustomPlacementConfig(CustomPlacementConfig customPlacementConfig);
@@ -1540,6 +1626,7 @@ static final class BuilderImpl extends Builder {
private Boolean retentionPolicyIsLocked;
private Duration retentionPeriod;
private IamConfiguration iamConfiguration;
+ private Autoclass autoclass;
private String locationType;
private Logging logging;
private CustomPlacementConfig customPlacementConfig;
@@ -1577,6 +1664,7 @@ static final class BuilderImpl extends Builder {
retentionPolicyIsLocked = bucketInfo.retentionPolicyIsLocked;
retentionPeriod = bucketInfo.retentionPeriod;
iamConfiguration = bucketInfo.iamConfiguration;
+ autoclass = bucketInfo.autoclass;
locationType = bucketInfo.locationType;
logging = bucketInfo.logging;
customPlacementConfig = bucketInfo.customPlacementConfig;
@@ -1910,6 +1998,15 @@ public Builder setIamConfiguration(IamConfiguration iamConfiguration) {
return this;
}
+ @Override
+ public Builder setAutoclass(Autoclass autoclass) {
+ if (!Objects.equals(this.autoclass, autoclass)) {
+ modifiedFields.add(BucketField.AUTOCLASS);
+ }
+ this.autoclass = autoclass;
+ return this;
+ }
+
@Override
public Builder setLogging(Logging logging) {
Logging tmp = logging != null ? logging : Logging.newBuilder().build();
@@ -2165,6 +2262,7 @@ private Builder clearDeleteLifecycleRules() {
retentionPolicyIsLocked = builder.retentionPolicyIsLocked;
retentionPeriod = builder.retentionPeriod;
iamConfiguration = builder.iamConfiguration;
+ autoclass = builder.autoclass;
locationType = builder.locationType;
logging = builder.logging;
customPlacementConfig = builder.customPlacementConfig;
@@ -2487,6 +2585,11 @@ public IamConfiguration getIamConfiguration() {
return iamConfiguration;
}
+ /** Returns the Autoclass configuration */
+ public Autoclass getAutoclass() {
+ return autoclass;
+ }
+
/** Returns the Logging */
public Logging getLogging() {
return logging;
@@ -2531,6 +2634,7 @@ public int hashCode() {
retentionPolicyIsLocked,
retentionPeriod,
iamConfiguration,
+ autoclass,
locationType,
logging);
}
@@ -2570,6 +2674,7 @@ public boolean equals(Object o) {
&& Objects.equals(retentionPolicyIsLocked, that.retentionPolicyIsLocked)
&& Objects.equals(retentionPeriod, that.retentionPeriod)
&& Objects.equals(iamConfiguration, that.iamConfiguration)
+ && Objects.equals(autoclass, that.autoclass)
&& Objects.equals(locationType, that.locationType)
&& Objects.equals(logging, that.logging);
}
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
index dab56a647..a6e02608e 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java
@@ -82,6 +82,8 @@ final class GrpcConversions {
Codec.of(this::loggingEncode, this::loggingDecode);
private final Codec iamConfigurationCodec =
Codec.of(this::iamConfigEncode, this::iamConfigDecode);
+ private final Codec autoclassCodec =
+ Codec.of(this::autoclassEncode, this::autoclassDecode);
private final Codec lifecycleRuleCodec =
Codec.of(this::lifecycleRuleEncode, this::lifecycleRuleDecode);
private final Codec bucketInfoCodec =
@@ -276,6 +278,9 @@ private BucketInfo bucketInfoDecode(Bucket from) {
if (from.hasIamConfig()) {
to.setIamConfiguration(iamConfigurationCodec.decode(from.getIamConfig()));
}
+ if (from.hasAutoclass()) {
+ to.setAutoclass(autoclassCodec.decode(from.getAutoclass()));
+ }
if (from.hasCustomPlacementConfig()) {
Bucket.CustomPlacementConfig customPlacementConfig = from.getCustomPlacementConfig();
to.setCustomPlacementConfig(
@@ -364,6 +369,7 @@ private Bucket bucketInfoEncode(BucketInfo from) {
to::addAllDefaultObjectAcl);
ifNonNull(from.getAcl(), toImmutableListOf(bucketAclCodec::encode), to::addAllAcl);
ifNonNull(from.getIamConfiguration(), iamConfigurationCodec::encode, to::setIamConfig);
+ ifNonNull(from.getAutoclass(), autoclassCodec::encode, to::setAutoclass);
CustomPlacementConfig customPlacementConfig = from.getCustomPlacementConfig();
if (customPlacementConfig != null && customPlacementConfig.getDataLocations() != null) {
to.setCustomPlacementConfig(
@@ -516,6 +522,20 @@ private Bucket.IamConfig.UniformBucketLevelAccess ublaEncode(BucketInfo.IamConfi
return to.build();
}
+ private BucketInfo.Autoclass autoclassDecode(Bucket.Autoclass from) {
+ BucketInfo.Autoclass.Builder to = BucketInfo.Autoclass.newBuilder();
+ to.setEnabled(from.getEnabled());
+ ifNonNull(from.getToggleTime(), timestampCodec::decode, to::setToggleTime);
+ return to.build();
+ }
+
+ private Bucket.Autoclass autoclassEncode(BucketInfo.Autoclass from) {
+ Bucket.Autoclass.Builder to = Bucket.Autoclass.newBuilder();
+ ifNonNull(from.getEnabled(), to::setEnabled);
+ ifNonNull(from.getToggleTime(), timestampCodec::encode, to::setToggleTime);
+ return to.build();
+ }
+
private Bucket.IamConfig iamConfigEncode(BucketInfo.IamConfiguration from) {
Bucket.IamConfig.Builder to = Bucket.IamConfig.newBuilder();
to.setUniformBucketLevelAccess(ublaEncode(from));
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java
index 658a8f4c0..faa1f7fb7 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -31,6 +32,7 @@
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketFixture;
import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.BucketInfo.Autoclass;
import com.google.cloud.storage.BucketInfo.CustomPlacementConfig;
import com.google.cloud.storage.Cors;
import com.google.cloud.storage.HttpMethod;
@@ -44,6 +46,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.time.Duration;
+import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -495,6 +498,40 @@ public void testEnableDisableBucketDefaultEventBasedHold()
}
}
+ @Test
+ public void testCreateBucketWithAutoclass() throws ExecutionException, InterruptedException {
+ String bucketName = bucketFixture.newBucketName();
+ storageFixtureHttp
+ .getInstance()
+ .create(
+ BucketInfo.newBuilder(bucketName)
+ .setAutoclass(Autoclass.newBuilder().setEnabled(true).build())
+ .build());
+ try {
+ Bucket remoteBucket = storageFixture.getInstance().get(bucketName);
+
+ assertNotNull(remoteBucket.getAutoclass());
+ assertTrue(remoteBucket.getAutoclass().getEnabled());
+ OffsetDateTime time = remoteBucket.getAutoclass().getToggleTime();
+ assertNotNull(time);
+
+ remoteBucket
+ .toBuilder()
+ .setAutoclass(Autoclass.newBuilder().setEnabled(false).build())
+ .build()
+ .update();
+
+ remoteBucket = storageFixture.getInstance().get(bucketName);
+ assertNotNull(remoteBucket.getAutoclass());
+ assertFalse(remoteBucket.getAutoclass().getEnabled());
+ assertNotNull(remoteBucket.getAutoclass().getToggleTime());
+ assertNotEquals(time, remoteBucket.getAutoclass().getToggleTime());
+ } finally {
+ RemoteStorageHelper.forceDelete(
+ storageFixtureHttp.getInstance(), bucketName, 5, TimeUnit.SECONDS);
+ }
+ }
+
private void unsetRequesterPays() {
Bucket remoteBucket =
storageFixture
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketAutoclass.java b/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketAutoclass.java
new file mode 100644
index 000000000..b413541c8
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/GetBucketAutoclass.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 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.example.storage.bucket;
+
+// [START storage_get_autoclass]
+
+import com.google.cloud.storage.BucketInfo.Autoclass;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class GetBucketAutoclass {
+ public static void getBucketAutoclass(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Autoclass autoclass = storage.get(bucketName).getAutoclass();
+ String status = autoclass.getEnabled() ? "enabled" : "disabled";
+ String toggleTime = autoclass.getToggleTime().toString();
+
+ System.out.println("Autoclass is currently " + status + " for bucket " + bucketName
+ + " and was last changed at " + toggleTime);
+ }
+}
+// [END storage_get_autoclass]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/SetBucketAutoclass.java b/samples/snippets/src/main/java/com/example/storage/bucket/SetBucketAutoclass.java
new file mode 100644
index 000000000..ec6ea4204
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/SetBucketAutoclass.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022 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.example.storage.bucket;
+
+// [START storage_set_autoclass]
+
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo.Autoclass;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class SetBucketAutoclass {
+ public static void setBucketAutoclass(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // Whether to set Autoclass to on or off.
+ // Note: Only update requests that disable qutoclass are currently supported.
+ // To enable autoclass, you must enable it at bucket creation time.
+ boolean enabled = false;
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Bucket bucket = storage.get(bucketName);
+
+ bucket.toBuilder()
+ .setAutoclass(Autoclass.newBuilder()
+ .setEnabled(enabled)
+ .build())
+ .build()
+ .update();
+
+ System.out.println("Autoclass for bucket " + bucketName + " was "
+ + (enabled ? "enabled." : "disabled."));
+ }
+}
+// [END storage_set_autoclass]
diff --git a/samples/snippets/src/test/java/com/example/storage/bucket/AutoclassTest.java b/samples/snippets/src/test/java/com/example/storage/bucket/AutoclassTest.java
new file mode 100644
index 000000000..9ccda14dd
--- /dev/null
+++ b/samples/snippets/src/test/java/com/example/storage/bucket/AutoclassTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 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.example.storage.bucket;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.example.storage.TestBase;
+import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.BucketInfo.Autoclass;
+import com.google.cloud.storage.testing.RemoteStorageHelper;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AutoclassTest extends TestBase {
+
+ private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+
+ @Test
+ public void testSetGetBucketAutoclass() {
+ String autoclassBucket = RemoteStorageHelper.generateBucketName();
+ storage.create(BucketInfo.newBuilder(autoclassBucket)
+ .setAutoclass(Autoclass.newBuilder().setEnabled(true).build())
+ .build());
+ try {
+ SetBucketAutoclass.setBucketAutoclass(PROJECT_ID, autoclassBucket);
+ Autoclass autoclass = storage.get(autoclassBucket).getAutoclass();
+ Assert.assertFalse(autoclass.getEnabled());
+
+ GetBucketAutoclass.getBucketAutoclass(PROJECT_ID, autoclassBucket);
+ assertThat(stdOut.getCapturedOutputAsUtf8String())
+ .contains(autoclass.getToggleTime().toString());
+ } finally {
+ RemoteStorageHelper.forceDelete(storage, autoclassBucket);
+ }
+ }
+}