Skip to content

Commit

Permalink
feat: expose timeStorageClassUpdated field of blob
Browse files Browse the repository at this point in the history
  • Loading branch information
athakor committed Aug 6, 2020
1 parent f0e945e commit 5657f74
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 4 deletions.
5 changes: 5 additions & 0 deletions google-cloud-storage/clirr-ignored-differences.xml
Expand Up @@ -26,4 +26,9 @@
<method>com.google.cloud.storage.BucketInfo$Builder setUpdateTime(java.lang.Long)</method>
<differenceType>7013</differenceType>
</difference>
<difference>
<className>com/google/cloud/storage/BlobInfo$Builder</className>
<method>com.google.cloud.storage.BlobInfo$Builder setTimeStorageClassUpdated(java.lang.Long)</method>
<differenceType>7013</differenceType>
</difference>
</differences>
Expand Up @@ -410,6 +410,12 @@ public Builder setStorageClass(StorageClass storageClass) {
return this;
}

@Override
Builder setTimeStorageClassUpdated(Long timeStorageClassUpdated) {
infoBuilder.setTimeStorageClassUpdated(timeStorageClassUpdated);
return this;
}

@Override
Builder setMetageneration(Long metageneration) {
infoBuilder.setMetageneration(metageneration);
Expand Down
Expand Up @@ -95,6 +95,7 @@ public StorageObject apply(BlobInfo blobInfo) {
private final String contentDisposition;
private final String contentLanguage;
private final StorageClass storageClass;
private final Long timeStorageClassUpdated;
private final Integer componentCount;
private final boolean isDirectory;
private final CustomerEncryption customerEncryption;
Expand Down Expand Up @@ -276,6 +277,8 @@ public abstract static class Builder {
/** Sets the blob's storage class. */
public abstract Builder setStorageClass(StorageClass storageClass);

abstract Builder setTimeStorageClassUpdated(Long timeStorageClassUpdated);

/** Sets the blob's user provided metadata. */
public abstract Builder setMetadata(Map<String, String> metadata);

Expand Down Expand Up @@ -334,6 +337,7 @@ static final class BuilderImpl extends Builder {
private Boolean isDirectory;
private CustomerEncryption customerEncryption;
private StorageClass storageClass;
private Long timeStorageClassUpdated;
private String kmsKeyName;
private Boolean eventBasedHold;
private Boolean temporaryHold;
Expand Down Expand Up @@ -368,6 +372,7 @@ static final class BuilderImpl extends Builder {
createTime = blobInfo.createTime;
isDirectory = blobInfo.isDirectory;
storageClass = blobInfo.storageClass;
timeStorageClassUpdated = blobInfo.timeStorageClassUpdated;
kmsKeyName = blobInfo.kmsKeyName;
eventBasedHold = blobInfo.eventBasedHold;
temporaryHold = blobInfo.temporaryHold;
Expand Down Expand Up @@ -535,6 +540,12 @@ public Builder setStorageClass(StorageClass storageClass) {
return this;
}

@Override
Builder setTimeStorageClassUpdated(Long timeStorageClassUpdated) {
this.timeStorageClassUpdated = timeStorageClassUpdated;
return this;
}

@Override
Builder setMetageneration(Long metageneration) {
this.metageneration = metageneration;
Expand Down Expand Up @@ -627,6 +638,7 @@ public BlobInfo build() {
createTime = builder.createTime;
isDirectory = firstNonNull(builder.isDirectory, Boolean.FALSE);
storageClass = builder.storageClass;
timeStorageClassUpdated = builder.timeStorageClassUpdated;
kmsKeyName = builder.kmsKeyName;
eventBasedHold = builder.eventBasedHold;
temporaryHold = builder.temporaryHold;
Expand Down Expand Up @@ -882,6 +894,14 @@ public StorageClass getStorageClass() {
return storageClass;
}

/**
* Returns the time at which the object's storage class was last changed. When the object is
* initially created, it will be set to timeCreated.
*/
public Long getTimeStorageClassUpdated() {
return timeStorageClassUpdated;
}

/** Returns the Cloud KMS key used to encrypt the blob, if any. */
public String getKmsKeyName() {
return kmsKeyName;
Expand Down Expand Up @@ -1011,6 +1031,9 @@ public ObjectAccessControl apply(Acl acl) {
if (storageClass != null) {
storageObject.setStorageClass(storageClass.toString());
}
if (timeStorageClassUpdated != null) {
storageObject.setTimeStorageClassUpdated(new DateTime(timeStorageClassUpdated));
}

Map<String, String> pbMetadata = metadata;
if (metadata != null && !Data.isNull(metadata)) {
Expand Down Expand Up @@ -1152,6 +1175,9 @@ public Acl apply(ObjectAccessControl objectAccessControl) {
if (storageObject.getStorageClass() != null) {
builder.setStorageClass(StorageClass.valueOf(storageObject.getStorageClass()));
}
if (storageObject.getTimeStorageClassUpdated() != null) {
builder.setTimeStorageClassUpdated(storageObject.getTimeStorageClassUpdated().getValue());
}
if (storageObject.getKmsKeyName() != null) {
builder.setKmsKeyName(storageObject.getKmsKeyName());
}
Expand Down
Expand Up @@ -19,10 +19,7 @@
import static com.google.cloud.storage.Acl.Project.ProjectRole.VIEWERS;
import static com.google.cloud.storage.Acl.Role.READER;
import static com.google.cloud.storage.Acl.Role.WRITER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;

import com.google.api.services.storage.model.StorageObject;
import com.google.cloud.storage.Acl.Project;
Expand Down Expand Up @@ -74,6 +71,7 @@ public class BlobInfoTest {
private static final String KMS_KEY_NAME =
"projects/p/locations/kr-loc/keyRings/kr/cryptoKeys/key";
private static final StorageClass STORAGE_CLASS = StorageClass.COLDLINE;
private static final Long TIME_STORAGE_CLASS_UPDATED = CREATE_TIME;
private static final Boolean EVENT_BASED_HOLD = true;
private static final Boolean TEMPORARY_HOLD = true;
private static final Long RETENTION_EXPIRATION_TIME = 10L;
Expand Down Expand Up @@ -102,6 +100,7 @@ public class BlobInfoTest {
.setUpdateTime(UPDATE_TIME)
.setCreateTime(CREATE_TIME)
.setStorageClass(STORAGE_CLASS)
.setTimeStorageClassUpdated(TIME_STORAGE_CLASS_UPDATED)
.setKmsKeyName(KMS_KEY_NAME)
.setEventBasedHold(EVENT_BASED_HOLD)
.setTemporaryHold(TEMPORARY_HOLD)
Expand Down Expand Up @@ -196,6 +195,7 @@ public void testBuilder() {
assertEquals(UPDATE_TIME, BLOB_INFO.getUpdateTime());
assertEquals(CREATE_TIME, BLOB_INFO.getCreateTime());
assertEquals(STORAGE_CLASS, BLOB_INFO.getStorageClass());
assertEquals(TIME_STORAGE_CLASS_UPDATED, BLOB_INFO.getTimeStorageClassUpdated());
assertEquals(KMS_KEY_NAME, BLOB_INFO.getKmsKeyName());
assertEquals(EVENT_BASED_HOLD, BLOB_INFO.getEventBasedHold());
assertEquals(TEMPORARY_HOLD, BLOB_INFO.getTemporaryHold());
Expand Down Expand Up @@ -259,6 +259,7 @@ private void compareBlobs(BlobInfo expected, BlobInfo value) {
assertEquals(expected.getSize(), value.getSize());
assertEquals(expected.getUpdateTime(), value.getUpdateTime());
assertEquals(expected.getStorageClass(), value.getStorageClass());
assertEquals(expected.getTimeStorageClassUpdated(), value.getTimeStorageClassUpdated());
assertEquals(expected.getKmsKeyName(), value.getKmsKeyName());
assertEquals(expected.getEventBasedHold(), value.getEventBasedHold());
assertEquals(expected.getTemporaryHold(), value.getTemporaryHold());
Expand Down Expand Up @@ -313,6 +314,7 @@ public void testToPbAndFromPb() {
assertEquals(0L, (long) blobInfo.getSize());
assertNull(blobInfo.getUpdateTime());
assertNull(blobInfo.getStorageClass());
assertNull(blobInfo.getTimeStorageClassUpdated());
assertNull(blobInfo.getKmsKeyName());
assertNull(blobInfo.getEventBasedHold());
assertNull(blobInfo.getTemporaryHold());
Expand Down
Expand Up @@ -91,6 +91,8 @@ public class BlobTest {
private static final Long SIZE = 1024L;
private static final Long UPDATE_TIME = DELETE_TIME - 1L;
private static final Long CREATE_TIME = UPDATE_TIME - 1L;
private static final StorageClass STORAGE_CLASS = StorageClass.COLDLINE;
private static final Long TIME_STORAGE_CLASS_UPDATED = CREATE_TIME;
private static final String ENCRYPTION_ALGORITHM = "AES256";
private static final String KEY_SHA256 = "keySha";
private static final BlobInfo.CustomerEncryption CUSTOMER_ENCRYPTION =
Expand Down Expand Up @@ -122,6 +124,8 @@ public class BlobTest {
.setSize(SIZE)
.setUpdateTime(UPDATE_TIME)
.setCreateTime(CREATE_TIME)
.setStorageClass(STORAGE_CLASS)
.setTimeStorageClassUpdated(TIME_STORAGE_CLASS_UPDATED)
.setCustomerEncryption(CUSTOMER_ENCRYPTION)
.setKmsKeyName(KMS_KEY_NAME)
.setEventBasedHold(EVENT_BASED_HOLD)
Expand Down Expand Up @@ -510,6 +514,8 @@ public void testBuilder() {
.setContentLanguage(CONTENT_LANGUAGE)
.setCrc32c(CRC32)
.setCreateTime(CREATE_TIME)
.setStorageClass(STORAGE_CLASS)
.setTimeStorageClassUpdated(TIME_STORAGE_CLASS_UPDATED)
.setCustomerEncryption(CUSTOMER_ENCRYPTION)
.setKmsKeyName(KMS_KEY_NAME)
.setEventBasedHold(EVENT_BASED_HOLD)
Expand Down Expand Up @@ -539,6 +545,8 @@ public void testBuilder() {
assertEquals(CRC32, blob.getCrc32c());
assertEquals(CRC32_HEX_STRING, blob.getCrc32cToHexString());
assertEquals(CREATE_TIME, blob.getCreateTime());
assertEquals(STORAGE_CLASS, blob.getStorageClass());
assertEquals(TIME_STORAGE_CLASS_UPDATED, blob.getTimeStorageClassUpdated());
assertEquals(CUSTOMER_ENCRYPTION, blob.getCustomerEncryption());
assertEquals(KMS_KEY_NAME, blob.getKmsKeyName());
assertEquals(EVENT_BASED_HOLD, blob.getEventBasedHold());
Expand Down Expand Up @@ -572,6 +580,8 @@ public void testBuilder() {
assertNull(blob.getCrc32c());
assertNull(blob.getCrc32cToHexString());
assertNull(blob.getCreateTime());
assertNull(blob.getStorageClass());
assertNull(blob.getTimeStorageClassUpdated());
assertNull(blob.getCustomerEncryption());
assertNull(blob.getKmsKeyName());
assertNull(blob.getEventBasedHold());
Expand Down
Expand Up @@ -3557,4 +3557,42 @@ public void testBucketUpdateTime() throws ExecutionException, InterruptedExcepti
RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
}
}

@Test
public void testBlobTimeStorageClassUpdated() {
String blobName = "test-blob-with-storage-class";
StorageClass storageClass = StorageClass.COLDLINE;
BlobInfo blob = BlobInfo.newBuilder(BUCKET, blobName).setStorageClass(storageClass).build();
Blob remoteBlob = storage.create(blob);
assertThat(remoteBlob).isNotNull();
assertThat(remoteBlob.getBucket()).isEqualTo(blob.getBucket());
assertThat(remoteBlob.getName()).isEqualTo(blob.getName());
assertThat(remoteBlob.getCreateTime()).isNotNull();
assertThat(remoteBlob.getUpdateTime()).isEqualTo(remoteBlob.getCreateTime());
assertThat(remoteBlob.getTimeStorageClassUpdated()).isEqualTo(remoteBlob.getCreateTime());

// You can't change an object's storage class directly, the only way is to rewrite the object
// with the desired storage class.
BlobId blobId = BlobId.of(BUCKET, blobName);
Storage.CopyRequest request =
Storage.CopyRequest.newBuilder()
.setSource(blobId)
.setTarget(BlobInfo.newBuilder(blobId).setStorageClass(StorageClass.STANDARD).build())
.build();
Blob updatedBlob1 = storage.copy(request).getResult();
assertThat(updatedBlob1.getTimeStorageClassUpdated()).isNotNull();
assertThat(updatedBlob1.getCreateTime()).isGreaterThan(remoteBlob.getCreateTime());
assertThat(updatedBlob1.getUpdateTime()).isGreaterThan(remoteBlob.getCreateTime());
assertThat(updatedBlob1.getTimeStorageClassUpdated())
.isGreaterThan(remoteBlob.getTimeStorageClassUpdated());

// Updates the other properties of the blob's to check the difference between blob updateTime
// and timeStorageClassUpdated.
Blob updatedBlob2 = updatedBlob1.toBuilder().setContentType(CONTENT_TYPE).build().update();
assertThat(updatedBlob2.getUpdateTime())
.isGreaterThan(updatedBlob2.getTimeStorageClassUpdated());
assertThat(updatedBlob2.getTimeStorageClassUpdated())
.isEqualTo(updatedBlob1.getTimeStorageClassUpdated());
assertThat(updatedBlob2.delete()).isTrue();
}
}

0 comments on commit 5657f74

Please sign in to comment.