Skip to content

Commit

Permalink
feat: add Autoclass v2.1 support (#2258)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenWhitehead committed Oct 18, 2023
1 parent eff00fb commit a134994
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 13 deletions.
Expand Up @@ -484,13 +484,23 @@ private Bucket.Autoclass autoclassEncode(Autoclass from) {
Bucket.Autoclass to = new Bucket.Autoclass();
ifNonNull(from.getEnabled(), to::setEnabled);
ifNonNull(from.getToggleTime(), dateTimeCodec::encode, to::setToggleTime);
ifNonNull(from.getTerminalStorageClass(), StorageClass::toString, to::setTerminalStorageClass);
ifNonNull(
from.getTerminalStorageClassUpdateTime(),
dateTimeCodec::encode,
to::setTerminalStorageClassUpdateTime);
return to;
}

private Autoclass autoclassDecode(Bucket.Autoclass from) {
Autoclass.Builder to = Autoclass.newBuilder();
to.setEnabled(from.getEnabled());
ifNonNull(from.getToggleTime(), dateTimeCodec::decode, to::setToggleTime);
ifNonNull(from.getTerminalStorageClass(), StorageClass::valueOf, to::setTerminalStorageClass);
ifNonNull(
from.getTerminalStorageClassUpdateTime(),
dateTimeCodec::decode,
to::setTerminalStorageClassUpdateTime);
return to.build();
}

Expand Down
Expand Up @@ -344,11 +344,26 @@ public String toString() {
}
}

/**
* Configuration for the Autoclass settings of a bucket.
*
* @see <a
* href="https://cloud.google.com/storage/docs/autoclass">https://cloud.google.com/storage/docs/autoclass</a>
*/
public static final class Autoclass implements Serializable {

private static final long serialVersionUID = -2378172222188072439L;
private Boolean enabled;
private OffsetDateTime toggleTime;
private final Boolean enabled;
private final OffsetDateTime toggleTime;
private final StorageClass terminalStorageClass;
private final OffsetDateTime terminalStorageClassUpdateTime;

private Autoclass(Builder builder) {
this.enabled = builder.enabled;
this.toggleTime = builder.toggleTime;
this.terminalStorageClass = builder.terminalStorageClass;
this.terminalStorageClassUpdateTime = builder.terminalStorageClassUpdateTime;
}

public Boolean getEnabled() {
return enabled;
Expand All @@ -358,6 +373,14 @@ public OffsetDateTime getToggleTime() {
return toggleTime;
}

public StorageClass getTerminalStorageClass() {
return terminalStorageClass;
}

public OffsetDateTime getTerminalStorageClassUpdateTime() {
return terminalStorageClassUpdateTime;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -366,41 +389,47 @@ public boolean equals(Object o) {
if (!(o instanceof Autoclass)) {
return false;
}
Autoclass that = (Autoclass) o;
return Objects.equals(enabled, that.enabled) && Objects.equals(toggleTime, that.toggleTime);
Autoclass autoclass = (Autoclass) o;
return Objects.equals(enabled, autoclass.enabled)
&& Objects.equals(toggleTime, autoclass.toggleTime)
&& Objects.equals(terminalStorageClass, autoclass.terminalStorageClass)
&& Objects.equals(
terminalStorageClassUpdateTime, autoclass.terminalStorageClassUpdateTime);
}

@Override
public int hashCode() {
return Objects.hash(enabled, toggleTime);
return Objects.hash(
enabled, toggleTime, terminalStorageClass, terminalStorageClassUpdateTime);
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("enabled", enabled)
.add("toggleTime", toggleTime)
.add("terminalStorageClass", terminalStorageClass)
.add("terminalStorageClassUpdateTime", terminalStorageClassUpdateTime)
.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);
return newBuilder()
.setEnabled(enabled)
.setToggleTime(toggleTime)
.setTerminalStorageClass(terminalStorageClass)
.setTerminalStorageClassUpdateTime(terminalStorageClassUpdateTime);
}

public static final class Builder {
private Boolean enabled;
private OffsetDateTime toggleTime;
private StorageClass terminalStorageClass;
private OffsetDateTime terminalStorageClassUpdateTime;

/**
* Sets whether Autoclass is enabled for this bucket. Currently, autoclass can only be enabled
Expand All @@ -421,6 +450,30 @@ Builder setToggleTime(OffsetDateTime toggleTime) {
return this;
}

/**
* When set to {@link StorageClass#NEARLINE}, Autoclass restricts transitions between Standard
* and Nearline storage classes only.
*
* <p>When set to {@link StorageClass#ARCHIVE}, Autoclass allows transitions to Coldline and
* Archive as well.
*
* <p>Only valid values are {@code NEARLINE} and {@code ARCHIVE}.
*/
public Builder setTerminalStorageClass(StorageClass terminalStorageClass) {
this.terminalStorageClass = terminalStorageClass;
return this;
}

/**
* The time at which Autoclass terminal storage class was last updated for this bucket.
*
* <p>This is auto populated when the feature is enabled.
*/
Builder setTerminalStorageClassUpdateTime(OffsetDateTime terminalStorageClassUpdateTime) {
this.terminalStorageClassUpdateTime = terminalStorageClassUpdateTime;
return this;
}

public Autoclass build() {
return new Autoclass(this);
}
Expand Down
Expand Up @@ -565,13 +565,27 @@ 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);

String terminalStorageClass = from.getTerminalStorageClass();
if (!terminalStorageClass.isEmpty()) {
to.setTerminalStorageClass(StorageClass.valueOf(terminalStorageClass));
}
ifNonNull(
from.getTerminalStorageClassUpdateTime(),
timestampCodec::decode,
to::setTerminalStorageClassUpdateTime);
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);
ifNonNull(from.getTerminalStorageClass(), StorageClass::toString, to::setTerminalStorageClass);
ifNonNull(
from.getTerminalStorageClassUpdateTime(),
timestampCodec::encode,
to::setTerminalStorageClassUpdateTime);
return to.build();
}

Expand Down
Expand Up @@ -42,6 +42,7 @@
import com.google.cloud.storage.Storage.BucketGetOption;
import com.google.cloud.storage.Storage.BucketListOption;
import com.google.cloud.storage.Storage.BucketTargetOption;
import com.google.cloud.storage.StorageClass;
import com.google.cloud.storage.TransportCompatibility.Transport;
import com.google.cloud.storage.it.runner.StorageITRunner;
import com.google.cloud.storage.it.runner.annotations.Backend;
Expand All @@ -58,6 +59,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.junit.Ignore;
import org.junit.Test;
Expand Down Expand Up @@ -417,6 +419,51 @@ public void testCreateBucketWithAutoclass() {
}
}

@Test
public void testCreateBucketWithAutoclass_ARCHIVE() throws Exception {
String bucketName = generator.randomBucketName();
Autoclass autoclass =
Autoclass.newBuilder()
.setEnabled(true)
.setTerminalStorageClass(StorageClass.ARCHIVE)
.build();
BucketInfo info = BucketInfo.newBuilder(bucketName).setAutoclass(autoclass).build();
try (TemporaryBucket tmpb =
TemporaryBucket.newBuilder().setStorage(storage).setBucketInfo(info).build()) {
BucketInfo remoteBucket = tmpb.getBucket();

Autoclass remoteBucketAutoclass = remoteBucket.getAutoclass();
assertThat(remoteBucketAutoclass).isNotNull();
assertThat(remoteBucketAutoclass.getEnabled()).isTrue();
assertThat(remoteBucketAutoclass.getToggleTime()).isNotNull();
assertThat(remoteBucketAutoclass.getTerminalStorageClassUpdateTime()).isNotNull();
assertThat(remoteBucketAutoclass.getTerminalStorageClass()).isEqualTo(StorageClass.ARCHIVE);

Page<Bucket> bucketPage = storage.list(BucketListOption.prefix(bucketName));
ImmutableList<Bucket> buckets = ImmutableList.copyOf(bucketPage.iterateAll());

Optional<Bucket> first =
buckets.stream().filter(b -> bucketName.equals(b.getName())).findFirst();

assertThat(first.isPresent()).isTrue();
assertThat(first.get().getAutoclass().getTerminalStorageClass())
.isEqualTo(StorageClass.ARCHIVE);

BucketInfo disabled =
remoteBucket
.toBuilder()
.setAutoclass(Autoclass.newBuilder().setEnabled(false).build())
.build();
Bucket updated = storage.update(disabled, BucketTargetOption.metagenerationMatch());

Autoclass updatedAutoclass = updated.getAutoclass();
assertThat(updatedAutoclass.getEnabled()).isFalse();
assertThat(updatedAutoclass.getTerminalStorageClass()).isNull();

assertThat(updatedAutoclass).isNotEqualTo(remoteBucketAutoclass);
}
}

@Test
public void testUpdateBucket_noModification() throws Exception {
String bucketName = generator.randomBucketName();
Expand Down

0 comments on commit a134994

Please sign in to comment.