Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: delete bucket OLM rules #352

Merged
merged 11 commits into from Jun 16, 2020
2 changes: 1 addition & 1 deletion google-cloud-storage/clirr-ignored-differences.xml
Expand Up @@ -21,4 +21,4 @@
<method>com.google.cloud.storage.PostPolicyV4 generateSignedPostPolicyV4(com.google.cloud.storage.BlobInfo, long, java.util.concurrent.TimeUnit, com.google.cloud.storage.Storage$PostPolicyV4Option[])</method>
<differenceType>7012</differenceType>
</difference>
</differences>
</differences>
Expand Up @@ -24,25 +24,30 @@
import com.google.api.client.util.Data;
import com.google.api.client.util.DateTime;
import com.google.api.core.BetaApi;
import com.google.api.services.storage.model.*;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.Bucket.Encryption;
import com.google.api.services.storage.model.Bucket.Lifecycle;
import com.google.api.services.storage.model.Bucket.Lifecycle.Rule;
import com.google.api.services.storage.model.Bucket.Owner;
import com.google.api.services.storage.model.Bucket.Versioning;
import com.google.api.services.storage.model.Bucket.Website;
import com.google.api.services.storage.model.BucketAccessControl;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.cloud.storage.Acl.Entity;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -1181,13 +1186,15 @@ public Builder setNotFoundPage(String notFoundPage) {
@Override
@Deprecated
public Builder setDeleteRules(Iterable<? extends DeleteRule> rules) {
this.deleteRules = rules != null ? ImmutableList.copyOf(rules) : null;
this.deleteRules =
rules != null ? ImmutableList.copyOf(rules) : ImmutableList.<DeleteRule>of();
athakor marked this conversation as resolved.
Show resolved Hide resolved
return this;
}

@Override
public Builder setLifecycleRules(Iterable<? extends LifecycleRule> rules) {
this.lifecycleRules = rules != null ? ImmutableList.copyOf(rules) : null;
this.lifecycleRules =
rules != null ? ImmutableList.copyOf(rules) : ImmutableList.<LifecycleRule>of();
athakor marked this conversation as resolved.
Show resolved Hide resolved
return this;
}

Expand Down Expand Up @@ -1316,6 +1323,7 @@ public BucketInfo build() {
}

BucketInfo(BuilderImpl builder) {
// super(StorageOptions.newBuilder().build());
athakor marked this conversation as resolved.
Show resolved Hide resolved
generatedId = builder.generatedId;
name = builder.name;
etag = builder.etag;
Expand Down Expand Up @@ -1430,11 +1438,78 @@ public String getNotFoundPage() {
*/
@Deprecated
public List<? extends DeleteRule> getDeleteRules() {
return deleteRules;
return deleteRules != null ? deleteRules : ImmutableList.<DeleteRule>of();
athakor marked this conversation as resolved.
Show resolved Hide resolved
}

public List<? extends LifecycleRule> getLifecycleRules() {
return lifecycleRules;
return lifecycleRules != null ? lifecycleRules : ImmutableList.<LifecycleRule>of();
}

/**
* Deletes the lifecycle rules of this bucket.
*
athakor marked this conversation as resolved.
Show resolved Hide resolved
* <p>Example of deleting the lifecycle rules of this bucket:
*
* <pre>{@code
* String bucketName = "my-unique-bucket";
* LifecycleRule lifecycleRule_1 =
* new LifecycleRule(
* LifecycleAction.newSetStorageClassAction(StorageClass.COLDLINE),
* LifecycleCondition.newBuilder()
* .setAge(1)
* .setNumberOfNewerVersions(3)
* .setIsLive(false)
* .setMatchesStorageClass(ImmutableList.of(StorageClass.COLDLINE))
* .build());
* LifecycleRule lifecycleRule_2 =
* new LifecycleRule(
* LifecycleAction.newDeleteAction(), LifecycleCondition.newBuilder().setAge(1).build());
* ImmutableList<LifecycleRule> lifecycleRules =
* ImmutableList.of(lifecycleRule_1, lifecycleRule_2);
* Bucket bucket =
* storage.create(
* BucketInfo.newBuilder(bucketName)
* .setLocation("us")
* .setLifecycleRules(lifecycleRules)
* .build());
* List<LifecycleRule> results = bucket.deleteLifecycleRules(storage, lifecycleRule_1);
* }</pre>
*
athakor marked this conversation as resolved.
Show resolved Hide resolved
* @param rulesToDelete the set of lifecycle rules to delete
* @param storage an object of storage
* @return the lists of deleted lifecycle rules of bucket, an empty list if the requested
* lifecycle rules was not found
* @throws StorageException upon failure
*/
public List<LifecycleRule> deleteLifecycleRules(Storage storage, LifecycleRule... rulesToDelete) {
athakor marked this conversation as resolved.
Show resolved Hide resolved
athakor marked this conversation as resolved.
Show resolved Hide resolved

final String bucket = getName();
final List<LifecycleRule> results = Lists.newArrayList();
try {
com.google.cloud.storage.Bucket remoteBucket =
storage.get(bucket, Storage.BucketGetOption.fields(Storage.BucketField.LIFECYCLE));
List<LifecycleRule> lifecycleRules = new ArrayList(remoteBucket.getLifecycleRules());
for (Iterator<LifecycleRule> iterator = lifecycleRules.iterator(); iterator.hasNext(); ) {
LifecycleRule lifecycleRule = iterator.next();
for (LifecycleRule ruleToDelete : rulesToDelete) {
if (lifecycleRule.equals(ruleToDelete)) {
iterator.remove();
results.add(ruleToDelete);
}
}
}
if (results.size() > 0) {
storage
.get(bucket, Storage.BucketGetOption.fields())
.toBuilder()
.setLifecycleRules(lifecycleRules)
.build()
.update();
}
return Collections.unmodifiableList(results);
} catch (StorageException ex) {
throw ex;
}
athakor marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -1711,7 +1786,7 @@ public Rule apply(LifecycleRule lifecycleRule) {
}
}));
}
if (!rules.isEmpty()) {
if (rules != null) {
Lifecycle lifecycle = new Lifecycle();
lifecycle.setRule(ImmutableList.copyOf(rules));
bucketPb.setLifecycle(lifecycle);
Expand Down
Expand Up @@ -1999,7 +1999,6 @@ Blob create(
* only if supplied Decrpytion Key decrypts the blob successfully, otherwise a {@link
* StorageException} is thrown. For more information review
*
* @throws StorageException upon failure
athakor marked this conversation as resolved.
Show resolved Hide resolved
* @see <a
* href="https://cloud.google.com/storage/docs/encryption/customer-supplied-keys#encrypted-elements">Encrypted
* Elements</a>
Expand Down
Expand Up @@ -17,6 +17,9 @@
package com.google.cloud.storage;

import static com.google.cloud.storage.Acl.Project.ProjectRole.VIEWERS;
import static com.google.common.truth.Truth.assertThat;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
Expand All @@ -42,6 +45,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.easymock.EasyMock;
import org.junit.Test;

public class BucketInfoTest {
Expand Down Expand Up @@ -333,4 +337,34 @@ public void testLogging() {
assertEquals("test-bucket", logging.getLogBucket());
assertEquals("test-", logging.getLogObjectPrefix());
}

@Test
public void testDeleteLifecycleRules() {
Storage storage = EasyMock.createStrictMock(Storage.class);
BucketInfo bucketInfo = EasyMock.createStrictMock(BUCKET_INFO.getClass());
expect(bucketInfo.deleteLifecycleRules(storage, LIFECYCLE_RULES.get(0)))
.andReturn(ImmutableList.of(LIFECYCLE_RULES.get(0)));
replay(bucketInfo);
List<LifecycleRule> actualResults =
bucketInfo.deleteLifecycleRules(storage, LIFECYCLE_RULES.get(0));
assertThat(actualResults).hasSize(1);
assertThat(actualResults.get(0)).isEqualTo(LIFECYCLE_RULES.get(0));
}

@Test
public void testDeleteNonExistingLifecycleRule() {
Storage storage = EasyMock.createStrictMock(Storage.class);
BucketInfo bucketInfo = EasyMock.createStrictMock(BucketInfo.class);
LifecycleRule nonExistingLifecycleRule =
new LifecycleRule(
LifecycleAction.newSetStorageClassAction(StorageClass.ARCHIVE),
LifecycleCondition.newBuilder().setAge(10).build());
List<LifecycleRule> expectedResults = ImmutableList.of();
expect(bucketInfo.deleteLifecycleRules(storage, nonExistingLifecycleRule))
.andReturn(expectedResults);
replay(bucketInfo);
List<LifecycleRule> actualResults =
bucketInfo.deleteLifecycleRules(storage, nonExistingLifecycleRule);
assertThat(actualResults).isEmpty();
}
}
athakor marked this conversation as resolved.
Show resolved Hide resolved
Expand Up @@ -181,6 +181,20 @@ public class ITStorageTest {
&& System.getenv("GOOGLE_CLOUD_TESTS_IN_VPCSC").equalsIgnoreCase("true");
private static final List<String> LOCATION_TYPES =
ImmutableList.of("multi-region", "region", "dual-region");
private static final LifecycleRule LIFECYCLE_RULE_1 =
new LifecycleRule(
LifecycleAction.newSetStorageClassAction(StorageClass.COLDLINE),
LifecycleCondition.newBuilder()
.setAge(1)
.setNumberOfNewerVersions(3)
.setIsLive(false)
.setMatchesStorageClass(ImmutableList.of(StorageClass.COLDLINE))
.build());
private static final LifecycleRule LIFECYCLE_RULE_2 =
new LifecycleRule(
LifecycleAction.newDeleteAction(), LifecycleCondition.newBuilder().setAge(1).build());
private static final ImmutableList<LifecycleRule> LIFECYCLE_RULES =
ImmutableList.of(LIFECYCLE_RULE_1, LIFECYCLE_RULE_2);

@BeforeClass
public static void beforeClass() throws IOException {
Expand Down Expand Up @@ -3273,4 +3287,69 @@ public void testBlobReload() throws Exception {
updated.delete();
assertNull(updated.reload());
}

@Test
public void testDeleteIndividualLifecycleRules() throws ExecutionException, InterruptedException {
String bucketName = RemoteStorageHelper.generateBucketName();
Bucket bucket =
storage.create(
BucketInfo.newBuilder(bucketName)
.setLocation("us")
.setLifecycleRules(LIFECYCLE_RULES)
.build());
assertThat(bucket.getName()).isEqualTo(bucketName);
assertThat(bucket.getLifecycleRules()).hasSize(2);
try {
List<LifecycleRule> results = bucket.deleteLifecycleRules(storage, LIFECYCLE_RULE_1);
assertThat(results).hasSize(1);
assertThat(results.get(0)).isEqualTo(LIFECYCLE_RULE_1);
} finally {
RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
}
}

@Test
public void testDeleteAllLifecycleRules() throws ExecutionException, InterruptedException {
String bucketName = RemoteStorageHelper.generateBucketName();
Bucket bucket =
storage.create(
BucketInfo.newBuilder(bucketName)
.setLocation("us")
.setLifecycleRules(LIFECYCLE_RULES)
.build());
assertThat(bucket.getName()).isEqualTo(bucketName);
assertThat(bucket.getLifecycleRules()).hasSize(2);
try {
List<LifecycleRule> results =
bucket.deleteLifecycleRules(storage, LIFECYCLE_RULE_1, LIFECYCLE_RULE_2);
assertThat(results).hasSize(2);
assertThat(results).contains(LIFECYCLE_RULE_1);
assertThat(results).contains(LIFECYCLE_RULE_2);
} finally {
RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
}
}

@Test
public void testDeleteNonExistingLifecycleRule() throws ExecutionException, InterruptedException {
String bucketName = RemoteStorageHelper.generateBucketName();
LifecycleRule nonExistingLifecycleRule =
new LifecycleRule(
LifecycleAction.newSetStorageClassAction(StorageClass.ARCHIVE),
LifecycleCondition.newBuilder().setAge(10).build());
Bucket bucket =
storage.create(
BucketInfo.newBuilder(bucketName)
.setLocation("us")
.setLifecycleRules(LIFECYCLE_RULES)
.build());
assertThat(bucket.getName()).isEqualTo(bucketName);
assertThat(bucket.getLifecycleRules()).hasSize(2);
try {
List<LifecycleRule> results = bucket.deleteLifecycleRules(storage, nonExistingLifecycleRule);
assertThat(results).isEmpty();
} finally {
RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
}
}
athakor marked this conversation as resolved.
Show resolved Hide resolved
}