S3 acls are not portable, so let's not make them enums

This commit is contained in:
Adrian Cole 2011-01-31 10:05:23 -08:00
parent 675563c96a
commit c93186ef9d
12 changed files with 162 additions and 126 deletions

View File

@ -19,6 +19,7 @@
package org.jclouds.s3.domain;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -35,8 +36,8 @@ import com.google.common.collect.Collections2;
* An Access Control List (ACL) describes the access control settings for a bucket or object in S3.
*
* ACL settings comprise a set of {@link Grant}s, each of which specifies a {@link Permission} that
* has been granted to a specific {@link Grantee}. If an payload tries to access or modify an item in
* S3, the operation will be denied unless the item has ACL settings that explicitly permit that
* has been granted to a specific {@link Grantee}. If an payload tries to access or modify an item
* in S3, the operation will be denied unless the item has ACL settings that explicitly permit that
* payload to perform that action.
*
*
@ -80,7 +81,7 @@ public class AccessControlList {
* @param grantee
* @param permission
*/
public AccessControlList addPermission(Grantee grantee, Permission permission) {
public AccessControlList addPermission(Grantee grantee, String permission) {
Grant grant = new Grant(grantee, permission);
grants.add(grant);
return this;
@ -92,7 +93,7 @@ public class AccessControlList {
* @param groupGranteeURI
* @param permission
*/
public AccessControlList addPermission(GroupGranteeURI groupGranteeURI, Permission permission) {
public AccessControlList addPermission(URI groupGranteeURI, String permission) {
return addPermission(new GroupGrantee(groupGranteeURI), permission);
}
@ -110,7 +111,7 @@ public class AccessControlList {
* @param grantee
* @param permission
*/
public AccessControlList revokePermission(Grantee grantee, Permission permission) {
public AccessControlList revokePermission(Grantee grantee, String permission) {
Collection<Grant> grantsForGrantee = findGrantsForGrantee(grantee.getIdentifier());
for (Grant grant : grantsForGrantee) {
if (grant.getPermission().equals(permission)) {
@ -134,7 +135,7 @@ public class AccessControlList {
* @param groupGranteeURI
* @param permission
*/
public AccessControlList revokePermission(GroupGranteeURI groupGranteeURI, Permission permission) {
public AccessControlList revokePermission(URI groupGranteeURI, String permission) {
return revokePermission(new GroupGrantee(groupGranteeURI), permission);
}
@ -153,10 +154,10 @@ public class AccessControlList {
* @param granteeId
* @return the permissions assigned to a grantee, as identified by the given ID.
*/
public Collection<Permission> getPermissions(String granteeId) {
public Collection<String> getPermissions(String granteeId) {
Collection<Grant> grantsForGrantee = findGrantsForGrantee(granteeId);
return Collections2.transform(grantsForGrantee, new Function<Grant, Permission>() {
public Permission apply(Grant g) {
return Collections2.transform(grantsForGrantee, new Function<Grant, String>() {
public String apply(Grant g) {
return g.getPermission();
}
});
@ -166,7 +167,7 @@ public class AccessControlList {
* @param grantee
* @return the permissions assigned to a grantee.
*/
public Collection<Permission> getPermissions(Grantee grantee) {
public Collection<String> getPermissions(Grantee grantee) {
return getPermissions(grantee.getIdentifier());
}
@ -174,8 +175,8 @@ public class AccessControlList {
* @param granteeURI
* @return the permissions assigned to a group grantee.
*/
public Collection<Permission> getPermissions(GroupGranteeURI granteeURI) {
return getPermissions(granteeURI.getIdentifier());
public Collection<String> getPermissions(URI granteeURI) {
return getPermissions(granteeURI.toASCIIString());
}
/**
@ -183,7 +184,7 @@ public class AccessControlList {
* @param permission
* @return true if the grantee has the given permission.
*/
public boolean hasPermission(String granteeId, Permission permission) {
public boolean hasPermission(String granteeId, String permission) {
return getPermissions(granteeId).contains(permission);
}
@ -192,7 +193,7 @@ public class AccessControlList {
* @param permission
* @return true if the grantee has the given permission.
*/
public boolean hasPermission(Grantee grantee, Permission permission) {
public boolean hasPermission(Grantee grantee, String permission) {
return hasPermission(grantee.getIdentifier(), permission);
}
@ -201,8 +202,8 @@ public class AccessControlList {
* @param permission
* @return true if the grantee has the given permission.
*/
public boolean hasPermission(GroupGranteeURI granteeURI, Permission permission) {
return getPermissions(granteeURI.getIdentifier()).contains(permission);
public boolean hasPermission(URI granteeURI, String permission) {
return getPermissions(granteeURI).contains(permission);
}
/**
@ -226,8 +227,7 @@ public class AccessControlList {
* @param cannedAP
* @param ownerId
*/
public static AccessControlList fromCannedAccessPolicy(CannedAccessPolicy cannedAP,
String ownerId) {
public static AccessControlList fromCannedAccessPolicy(CannedAccessPolicy cannedAP, String ownerId) {
AccessControlList acl = new AccessControlList();
acl.setOwner(new CanonicalUser(ownerId));
@ -251,16 +251,20 @@ public class AccessControlList {
// Class and Enum declarations to represent Grants, Grantees and Permissions //
// /////////////////////////////////////////////////////////////////////////////
public static enum Permission {
READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL;
public static interface Permission {
public static final String READ = "READ";
public static final String WRITE = "WRITE";
public static final String READ_ACP = "READ_ACP";
public static final String WRITE_ACP = "WRITE_ACP";
public static final String FULL_CONTROL = "FULL_CONTROL";
};
public static class Grant implements Comparable<Grant> {
private Grantee grantee;
private final Permission permission;
private final String permission;
public Grant(Grantee grantee, Permission permission) {
public Grant(Grantee grantee, String permission) {
this.grantee = grantee;
this.permission = permission;
}
@ -274,7 +278,7 @@ public class AccessControlList {
this.grantee = grantee;
}
public Permission getPermission() {
public String getPermission() {
return permission;
}
@ -417,38 +421,17 @@ public class AccessControlList {
}
}
public enum GroupGranteeURI {
ALL_USERS("http://acs.amazonaws.com/groups/global/AllUsers"), AUTHENTICATED_USERS(
"http://acs.amazonaws.com/groups/global/AuthenticatedUsers"), LOG_DELIVERY(
"http://acs.amazonaws.com/groups/LogDelivery");
private final String uri;
GroupGranteeURI(String uri) {
this.uri = uri;
}
public String getIdentifier() {
return this.uri;
}
public static GroupGranteeURI fromURI(String uri) {
if (ALL_USERS.uri.equals(uri)) {
return ALL_USERS;
} else if (AUTHENTICATED_USERS.uri.equals(uri)) {
return AUTHENTICATED_USERS;
} else if (LOG_DELIVERY.uri.equals(uri)) {
return LOG_DELIVERY;
} else {
throw new IllegalArgumentException("No GroupGranteeURI constant matches " + uri);
}
}
public interface GroupGranteeURI {
public static final URI ALL_USERS = URI.create("http://acs.amazonaws.com/groups/global/AllUsers");
public static final URI AUTHENTICATED_USERS = URI
.create("http://acs.amazonaws.com/groups/global/AuthenticatedUsers");
public static final URI LOG_DELIVERY = URI.create("http://acs.amazonaws.com/groups/LogDelivery");
}
public static class GroupGrantee extends Grantee {
public GroupGrantee(GroupGranteeURI groupURI) {
super(groupURI.getIdentifier());
public GroupGrantee(URI groupURI) {
super(groupURI.toASCIIString());
}
}

View File

@ -19,15 +19,15 @@
package org.jclouds.s3.xml;
import java.net.URI;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.s3.domain.AccessControlList;
import org.jclouds.s3.domain.CanonicalUser;
import org.jclouds.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.s3.domain.AccessControlList.Grantee;
import org.jclouds.s3.domain.AccessControlList.GroupGrantee;
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.s3.domain.AccessControlList.Permission;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
/**
@ -72,18 +72,18 @@ public class AccessControlListHandler extends ParseSax.HandlerWithResult<AccessC
} else if ("CanonicalUser".equals(currentGranteeType)) {
currentGrantee = new CanonicalUserGrantee(currentId, currentDisplayName);
} else if ("Group".equals(currentGranteeType)) {
currentGrantee = new GroupGrantee(GroupGranteeURI.fromURI(currentId));
currentGrantee = new GroupGrantee(URI.create(currentId));
}
} else if (qName.equals("Grant")) {
acl.addPermission(currentGrantee, Permission.valueOf(currentPermission));
acl.addPermission(currentGrantee, currentPermission);
}
else if (qName.equals("ID") || qName.equals("EmailAddress") || qName.equals("URI")) {
currentId = currentText.toString();
currentId = currentText.toString().trim();
} else if (qName.equals("DisplayName")) {
currentDisplayName = currentText.toString();
currentDisplayName = currentText.toString().trim();
} else if (qName.equals("Permission")) {
currentPermission = currentText.toString();
currentPermission = currentText.toString().trim();
}
currentText = new StringBuilder();
}

View File

@ -19,17 +19,16 @@
package org.jclouds.s3.xml;
import java.net.URI;
import java.util.Set;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.s3.domain.BucketLogging;
import org.jclouds.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.s3.domain.AccessControlList.Grant;
import org.jclouds.s3.domain.AccessControlList.Grantee;
import org.jclouds.s3.domain.AccessControlList.GroupGrantee;
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.s3.domain.AccessControlList.Permission;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.Attributes;
import com.google.common.collect.Sets;
@ -78,10 +77,10 @@ public class BucketLoggingHandler extends ParseSax.HandlerWithResult<BucketLoggi
} else if ("CanonicalUser".equals(currentGranteeType)) {
currentGrantee = new CanonicalUserGrantee(currentId, currentDisplayName);
} else if ("Group".equals(currentGranteeType)) {
currentGrantee = new GroupGrantee(GroupGranteeURI.fromURI(currentId));
currentGrantee = new GroupGrantee(URI.create(currentId));
}
} else if (qName.equals("Grant")) {
targetGrants.add(new Grant(currentGrantee, Permission.valueOf(currentPermission)));
targetGrants.add(new Grant(currentGrantee, currentPermission));
} else if (qName.equals("ID") || qName.equals("EmailAddress") || qName.equals("URI")) {
currentId = currentText.toString().trim();
} else if (qName.equals("DisplayName")) {

View File

@ -312,7 +312,10 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
}
protected void assertContentEncoding(S3Object newObject, String string) {
assertEquals(newObject.getMetadata().getContentMetadata().getContentEncoding(), string);
assert (newObject.getPayload().getContentMetadata().getContentEncoding().indexOf(string) != -1) : newObject
.getPayload().getContentMetadata().getContentEncoding();
assert (newObject.getMetadata().getContentMetadata().getContentEncoding().indexOf(string) != -1) : newObject
.getMetadata().getContentMetadata().getContentEncoding();
}
@Test(groups = { "integration", "live" })

View File

@ -97,7 +97,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@SuppressWarnings("unchecked")
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
.getResourceAsStream("/const.txt.gz")));
.getResourceAsStream("/const.txt.gz")));
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
@ -120,24 +120,24 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
Map<Integer, Future<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) {
responses.put(i,
Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), new Function<Blob, Void>() {
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key),
new Function<Blob, Void>() {
@Override
public Void apply(Blob from) {
try {
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
checkContentDisposition(from, expectedContentDisposition);
} catch (IOException e) {
Throwables.propagate(e);
@Override
public Void apply(Blob from) {
try {
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
checkContentDisposition(from, expectedContentDisposition);
} catch (IOException e) {
Throwables.propagate(e);
}
return null;
}
return null;
}
}, this.exec));
}, this.exec));
}
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
"get constitution");
"get constitution");
assert exceptions.size() == 0 : exceptions;
} finally {
@ -364,8 +364,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@DataProvider(name = "delete")
public Object[][] createData() {
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
}
@Test(groups = { "integration", "live" }, dataProvider = "delete")
@ -382,19 +382,17 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
private void assertContainerEmptyDeleting(String containerName, String key) {
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
new Predicate<StorageMetadata>() {
new Predicate<StorageMetadata>() {
@Override
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
@Override
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
});
assertEquals(
Iterables.size(listing),
0,
String.format("deleting %s, we still have %s blobs left in container %s, using encoding %s", key,
Iterables.size(listing), containerName, LOCAL_ENCODING));
});
assertEquals(Iterables.size(listing), 0, String.format(
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables
.size(listing), containerName, LOCAL_ENCODING));
}
@Test(groups = { "integration", "live" })
@ -414,13 +412,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
String realObject = Strings2.toStringAndClose(new FileInputStream("pom.xml"));
return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
{ "string", "text/xml", realObject, realObject },
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
}
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException,
IOException {
IOException {
Blob blob = context.getBlobStore().newBlob(key);
blob.setPayload(Payloads.newPayload(content));
blob.getMetadata().getContentMetadata().setContentType(type);
@ -487,32 +485,31 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
protected void checkContentType(Blob blob, String contentType) {
assert blob.getPayload().getContentMetadata().getContentType().startsWith(contentType) : blob.getPayload()
.getContentMetadata().getContentType();
.getContentMetadata().getContentType();
assert blob.getMetadata().getContentMetadata().getContentType().startsWith(contentType) : blob.getMetadata()
.getContentMetadata().getContentType();
.getContentMetadata().getContentType();
}
protected void checkContentDisposition(Blob blob, String contentDisposition) {
assert blob.getPayload().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
.getPayload().getContentMetadata().getContentDisposition();
.getPayload().getContentMetadata().getContentDisposition();
assert blob.getMetadata().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
.getMetadata().getContentMetadata().getContentDisposition();
.getMetadata().getContentMetadata().getContentDisposition();
}
protected void checkContentEncoding(Blob blob, String contentEncoding) {
assert blob.getPayload().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob
.getPayload().getContentMetadata().getContentEncoding();
assert blob.getMetadata().getContentMetadata().getContentEncoding().startsWith(contentEncoding) : blob
.getMetadata().getContentMetadata().getContentEncoding();
assert (blob.getPayload().getContentMetadata().getContentEncoding().indexOf(contentEncoding) != -1) : blob
.getPayload().getContentMetadata().getContentEncoding();
assert (blob.getMetadata().getContentMetadata().getContentEncoding().indexOf(contentEncoding) != -1) : blob
.getMetadata().getContentMetadata().getContentEncoding();
}
protected void checkContentLanguage(Blob blob, String contentLanguage) {
assert blob.getPayload().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
.getPayload().getContentMetadata().getContentLanguage();
.getPayload().getContentMetadata().getContentLanguage();
assert blob.getMetadata().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
.getMetadata().getContentMetadata().getContentLanguage();
.getMetadata().getContentMetadata().getContentLanguage();
}
protected volatile static Crypto crypto;
@ -565,7 +562,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
protected void validateMetadata(BlobMetadata metadata) throws IOException {
assert metadata.getContentMetadata().getContentType().startsWith("text/plain") : metadata.getContentMetadata()
.getContentType();
.getContentType();
assertEquals(metadata.getContentMetadata().getContentLength(), new Long(TEST_STRING.length()));
assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff");
checkMD5(metadata);

View File

@ -20,6 +20,7 @@
package org.jclouds.scaleup.storage;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
import java.util.Properties;
@ -34,6 +35,7 @@ public class ScaleUpStoragePropertiesBuilder extends S3PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_ISO3166_CODES, "DE");
properties.setProperty(PROPERTY_ENDPOINT, "https://scs.scaleupstorage.com");
return properties;
}

View File

@ -20,23 +20,11 @@
package org.jclouds.scaleup.storage.blobstore.config;
import org.jclouds.s3.blobstore.config.S3BlobStoreContextModule;
import org.jclouds.s3.domain.BucketMetadata;
import org.jclouds.domain.Location;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
public class ScaleUpStorageBlobStoreContextModule extends S3BlobStoreContextModule {
// TODO: this is really a scality concern that is coupled to all installations of theirs
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected void bindBucketLocationStrategy() {
bind(new TypeLiteral<Function<BucketMetadata, Location>>() {
}).toInstance((Function) Functions.constant(null));
}
}

View File

@ -19,7 +19,10 @@
package org.jclouds.scaleup.storage;
import static org.testng.Assert.assertEquals;
import org.jclouds.s3.S3ClientLiveTest;
import org.jclouds.s3.domain.S3Object;
import org.testng.annotations.Test;
/**
@ -29,5 +32,16 @@ import org.testng.annotations.Test;
*/
@Test(groups = "live", sequential = true, testName = "ScaleUpStorageClientLiveTest")
public class ScaleUpStorageClientLiveTest extends S3ClientLiveTest {
// no support for content encoding
@Override
protected void assertContentEncoding(S3Object newObject, String string) {
assert (newObject.getPayload().getContentMetadata().getContentEncoding().indexOf(string) != -1);
assert (newObject.getMetadata().getContentMetadata().getContentEncoding().indexOf(string) != -1);
}
// no support for cache control
@Override
protected void assertCacheControl(S3Object newObject, String string) {
assertEquals(newObject.getMetadata().getCacheControl(), null);
}
}

View File

@ -19,13 +19,40 @@
package org.jclouds.scaleup.storage.blobstore;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.s3.blobstore.integration.S3BlobIntegrationLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ScaleUpStorageBlobIntegrationLiveTest")
@Test(groups = "live", testName = "ScaleUpStorageBlobIntegrationLiveTest")
public class ScaleUpStorageBlobIntegrationLiveTest extends S3BlobIntegrationLiveTest {
// no support for content language
@Override
protected void checkContentLanguage(Blob blob, String contentLanguage) {
assert blob.getPayload().getContentMetadata().getContentLanguage() == null;
assert blob.getMetadata().getContentMetadata().getContentLanguage() == null;
}
// double range not supported
@Test(groups = { "integration", "live" })
@Override
public void testGetTwoRanges() throws InterruptedException, IOException {
}
// no md5
@Override
protected void checkMD5(BlobMetadata metadata) throws IOException {
assertEquals(metadata.getContentMetadata().getContentMD5(), null);
}
}

View File

@ -19,13 +19,20 @@
package org.jclouds.scaleup.storage.blobstore;
import static org.testng.Assert.assertEquals;
import org.jclouds.s3.blobstore.integration.S3BlobLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ScaleUpStorageBlobLiveTest")
@Test(groups = "live", testName = "ScaleUpStorageBlobLiveTest")
public class ScaleUpStorageBlobLiveTest extends S3BlobLiveTest {
// no md5
@Override
protected void checkMD5(String container, String name, byte[] md5) {
assertEquals(context.getBlobStore().blobMetadata(container, name).getContentMetadata().getContentMD5(), null);
}
}

View File

@ -19,13 +19,22 @@
package org.jclouds.scaleup.storage.blobstore;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.s3.blobstore.integration.S3ContainerIntegrationLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ScaleUpStorageContainerIntegrationLiveTest")
@Test(groups = "live", testName = "ScaleUpStorageContainerIntegrationLiveTest")
public class ScaleUpStorageContainerIntegrationLiveTest extends S3ContainerIntegrationLiveTest {
// doesn't support MD5
@Override
protected void checkMD5(BlobMetadata metadata) throws IOException {
assertEquals(metadata.getContentMetadata().getContentMD5(), null);
}
}

View File

@ -19,13 +19,20 @@
package org.jclouds.scaleup.storage.blobstore;
import java.util.Set;
import org.jclouds.s3.blobstore.integration.S3ServiceIntegrationLiveTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ScaleUpStorageServiceIntegrationLiveTest")
@Test(groups = "live", testName = "ScaleUpStorageServiceIntegrationLiveTest")
public class ScaleUpStorageServiceIntegrationLiveTest extends S3ServiceIntegrationLiveTest {
@Override
protected Set<String> getIso3166Codes() {
return ImmutableSet.<String> of("DE");
}
}