Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit 8b69f61

Browse files
committed
Added soft-delete feature for blob
1 parent 43a0619 commit 8b69f61

21 files changed

+1207
-27
lines changed

ChangeLog.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
XXXX.XX.XX Version X.X.X
2+
* Added support for soft delete feature. If a delete retention policy is enabled through the set service properties API, then blobs or snapshots can be deleted softly and retained for a specified number of days, before being permanently removed by garbage collection.
3+
* Support for 2017-07-29 REST version. Please see our REST API documentation and blogs for information about the related added features.
4+
15
2017.11.01 Version 6.1.0
26
* Added support for the last time the tier was modified.
37

microsoft-azure-storage-test/src/com/microsoft/azure/storage/ServicePropertiesTests.java

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,169 @@ private void testAnalyticsRetentionPolicies(ServiceClient client, ServicePropert
397397
assertServicePropertiesAreEqual(props, callDownloadServiceProperties(client));
398398
}
399399

400+
/**
401+
* Test delete retention policy for blobs
402+
*
403+
* @throws StorageException
404+
* @throws InterruptedException
405+
*/
406+
@Test
407+
public void testValidDeleteRetentionPolicy() throws StorageException, InterruptedException {
408+
ServiceClient client = TestHelper.createCloudBlobClient();
409+
410+
// average setting
411+
testValidDeleteRetentionPolicy(client, true, 5, 3);
412+
413+
// minimum setting
414+
testValidDeleteRetentionPolicy(client, true, 1, 1);
415+
416+
// maximum setting
417+
testValidDeleteRetentionPolicy(client, true, 365, 10);
418+
419+
// disable setting
420+
testValidDeleteRetentionPolicy(client, false, 5, 3);
421+
}
422+
423+
private void testValidDeleteRetentionPolicy(ServiceClient client, boolean enabled,
424+
Integer interval, Integer retainedVersionsPerBlob)
425+
throws StorageException, InterruptedException {
426+
427+
try {
428+
ServiceProperties expectedServiceProperties = new ServiceProperties();
429+
expectedServiceProperties.setDefaultServiceVersion(Constants.HeaderConstants.TARGET_STORAGE_VERSION);
430+
431+
if (enabled) {
432+
expectedServiceProperties.getDeleteRetentionPolicy().setEnabled(true);
433+
expectedServiceProperties.getDeleteRetentionPolicy().setRetentionIntervalInDays(interval);
434+
expectedServiceProperties.getDeleteRetentionPolicy().setRetainedVersionsPerBlob(retainedVersionsPerBlob);
435+
callUploadServiceProps(client, expectedServiceProperties, null);
436+
} else {
437+
// interval and retained versions per blob would both be ignored by the service in case the policy is not enabled
438+
ServiceProperties propertiesToUpload = new ServiceProperties();
439+
propertiesToUpload.getDeleteRetentionPolicy().setEnabled(false);
440+
propertiesToUpload.getDeleteRetentionPolicy().setRetentionIntervalInDays(interval);
441+
propertiesToUpload.getDeleteRetentionPolicy().setRetainedVersionsPerBlob(retainedVersionsPerBlob);
442+
443+
expectedServiceProperties.getDeleteRetentionPolicy().setEnabled(false);
444+
callUploadServiceProps(client, propertiesToUpload, null);
445+
}
446+
447+
// verify
448+
assertServicePropertiesAreEqual(expectedServiceProperties, callDownloadServiceProperties(client));
449+
}
450+
finally {
451+
// reset the delete retention policy
452+
ServiceProperties disabledDeleteRetentionPolicy = new ServiceProperties();
453+
disabledDeleteRetentionPolicy.getDeleteRetentionPolicy().setEnabled(false);
454+
callUploadServiceProps(client, disabledDeleteRetentionPolicy, null);
455+
}
456+
}
457+
458+
/**
459+
* Test invalid delete retention policy for blobs
460+
*
461+
* @throws StorageException
462+
* @throws InterruptedException
463+
*/
464+
@Test
465+
public void testInvalidDeleteRetentionPolicy() throws StorageException, InterruptedException {
466+
ServiceClient client = TestHelper.createCloudBlobClient();
467+
468+
// Should not work with 0 days
469+
testInvalidDeleteRetentionPolicy(client, true, 0, 1);
470+
471+
// Should not work with <0 days
472+
testInvalidDeleteRetentionPolicy(client, true, 0, -1);
473+
474+
// Should not work with 0 retained versions per blob
475+
testInvalidDeleteRetentionPolicy(client, true, 1, 0);
476+
477+
// Should not work with <0 retained versions per blob
478+
testInvalidDeleteRetentionPolicy(client, true, -1, 0);
479+
480+
// Should not work with 366 days
481+
testInvalidDeleteRetentionPolicy(client, true, 366, 1);
482+
483+
// Should not work with 11 retained_versions_per_blob
484+
testInvalidDeleteRetentionPolicy(client, true, 1, 11);
485+
486+
// Should not work with interval as null
487+
testInvalidDeleteRetentionPolicy(client, true, null, 1);
488+
489+
// Should not work with retained versions per blob as null
490+
testInvalidDeleteRetentionPolicy(client, true, 1, null);
491+
}
492+
493+
private void testInvalidDeleteRetentionPolicy(ServiceClient client, boolean enabled,
494+
Integer interval, Integer retainedVersionsPerBlob)
495+
throws StorageException, InterruptedException {
496+
497+
// Arrange
498+
ServiceProperties serviceProperties = new ServiceProperties();
499+
serviceProperties.setDefaultServiceVersion(Constants.HeaderConstants.TARGET_STORAGE_VERSION);
500+
501+
if (enabled) {
502+
serviceProperties.getDeleteRetentionPolicy().setEnabled(true);
503+
}
504+
else {
505+
serviceProperties.getDeleteRetentionPolicy().setEnabled(false);
506+
}
507+
serviceProperties.getDeleteRetentionPolicy().setRetentionIntervalInDays(interval);
508+
serviceProperties.getDeleteRetentionPolicy().setRetainedVersionsPerBlob(retainedVersionsPerBlob);
509+
510+
// Failure is expected since the retention policy is invalid
511+
try {
512+
callUploadServiceProps(client, serviceProperties, null);
513+
fail("No exception received. An invalid delete retention policy should have raised an exception.");
514+
}
515+
catch (StorageException e) {
516+
assertEquals(e.errorCode, "InvalidXmlDocument");
517+
}
518+
catch (IllegalArgumentException e) {
519+
assertTrue(e.getMessage().contains("argument must not be null"));
520+
}
521+
catch (Exception e) {
522+
fail("Invalid exception " + e.getClass() + " received when expecting StorageException");
523+
}
524+
}
525+
526+
/**
527+
* Test empty delete retention policy for blobs
528+
*
529+
* @throws StorageException
530+
* @throws InterruptedException
531+
*/
532+
@Test
533+
public void testEmptyDeleteRetentionPolicy() throws StorageException, InterruptedException {
534+
ServiceClient client = TestHelper.createCloudBlobClient();
535+
536+
try {
537+
// set up initial delete retention policy
538+
ServiceProperties currentServiceProperties = new ServiceProperties();
539+
currentServiceProperties.setDefaultServiceVersion(Constants.HeaderConstants.TARGET_STORAGE_VERSION);
540+
currentServiceProperties.getDeleteRetentionPolicy().setEnabled(true);
541+
currentServiceProperties.getDeleteRetentionPolicy().setRetentionIntervalInDays(5);
542+
currentServiceProperties.getDeleteRetentionPolicy().setRetainedVersionsPerBlob(3);
543+
callUploadServiceProps(client, currentServiceProperties, null);
544+
545+
// verify
546+
assertServicePropertiesAreEqual(currentServiceProperties, callDownloadServiceProperties(client));
547+
548+
// try to upload empty retention policy
549+
ServiceProperties emptyServiceProperties = new ServiceProperties();
550+
callUploadServiceProps(client, emptyServiceProperties, null);
551+
552+
// verify
553+
assertServicePropertiesAreEqual(currentServiceProperties, callDownloadServiceProperties(client));
554+
}
555+
finally {
556+
// reset the delete retention policy
557+
ServiceProperties disabledDeleteRetentionPolicy = new ServiceProperties();
558+
disabledDeleteRetentionPolicy.getDeleteRetentionPolicy().setEnabled(false);
559+
callUploadServiceProps(client, disabledDeleteRetentionPolicy, null);
560+
}
561+
}
562+
400563
/**
401564
* Test CORS with different rules.
402565
*
@@ -974,6 +1137,16 @@ private static void assertServicePropertiesAreEqual(ServiceProperties propsA, Se
9741137
assertNull(propsA.getCors());
9751138
assertNull(propsB.getCors());
9761139
}
1140+
1141+
if (propsA.getDeleteRetentionPolicy() != null && propsB.getDeleteRetentionPolicy() != null) {
1142+
assertEquals(propsA.getDeleteRetentionPolicy().getEnabled(), propsB.getDeleteRetentionPolicy().getEnabled());
1143+
assertEquals(propsA.getDeleteRetentionPolicy().getRetentionIntervalInDays(), propsB.getDeleteRetentionPolicy().getRetentionIntervalInDays());
1144+
assertEquals(propsA.getDeleteRetentionPolicy().getRetainedVersionsPerBlob(), propsB.getDeleteRetentionPolicy().getRetainedVersionsPerBlob());
1145+
}
1146+
else {
1147+
assertNull(propsA.getDeleteRetentionPolicy());
1148+
assertNull(propsB.getDeleteRetentionPolicy());
1149+
}
9771150
}
9781151

9791152
/**

microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/BlobTestHelper.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.microsoft.azure.storage.StorageCredentials;
1919
import com.microsoft.azure.storage.StorageException;
2020
import com.microsoft.azure.storage.TestHelper;
21+
import com.microsoft.azure.storage.ServiceProperties;
2122

2223
import java.io.ByteArrayInputStream;
2324
import java.io.IOException;
@@ -436,4 +437,24 @@ public static void assertAreEqual(CopyState copy1, CopyState copy2) {
436437
assertEquals(copy1.getTotalBytes(), copy2.getTotalBytes());
437438
}
438439
}
440+
441+
public static void enableSoftDelete() throws StorageException, URISyntaxException, InterruptedException {
442+
ServiceProperties serviceProperties = new ServiceProperties();
443+
serviceProperties.getDeleteRetentionPolicy().setEnabled(true);
444+
serviceProperties.getDeleteRetentionPolicy().setRetentionIntervalInDays(3);
445+
serviceProperties.getDeleteRetentionPolicy().setRetainedVersionsPerBlob(3);
446+
447+
CloudBlobClient bClient = TestHelper.createCloudBlobClient();
448+
bClient.uploadServiceProperties(serviceProperties);
449+
Thread.sleep(30000);
450+
}
451+
452+
public static void disableSoftDelete() throws StorageException, URISyntaxException, InterruptedException {
453+
ServiceProperties serviceProperties = new ServiceProperties();
454+
serviceProperties.getDeleteRetentionPolicy().setEnabled(false);
455+
456+
CloudBlobClient bClient = TestHelper.createCloudBlobClient();
457+
bClient.uploadServiceProperties(serviceProperties);
458+
Thread.sleep(30000);
459+
}
439460
}

0 commit comments

Comments
 (0)