diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/AdvancedNetworkOptionsConverter.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/AdvancedNetworkOptionsConverter.java index 524aeb7f48..45eb4d2d2d 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/AdvancedNetworkOptionsConverter.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/strategy/AdvancedNetworkOptionsConverter.java @@ -48,7 +48,7 @@ public class AdvancedNetworkOptionsConverter implements OptionsConverter { checkArgument(templateOptions.getSecurityGroupIds().isEmpty(), "security groups cannot be specified for locations (zones) that use advanced networking"); if (templateOptions.getNetworkIds().size() > 0) { options.networkIds(templateOptions.getNetworkIds()); - } else { + } else if (templateOptions.getIpsToNetworks().isEmpty()) { checkArgument(!networks.isEmpty(), "please setup a network for zone: " + zoneId); Network defaultNetworkInZone = Iterables.getFirst(filter(networks.values(), and(defaultNetworkInZone(zoneId), supportsStaticNAT())), null); if(defaultNetworkInZone == null) { diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeployVirtualMachineOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeployVirtualMachineOptions.java index f992bf7502..c8b13d435d 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeployVirtualMachineOptions.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeployVirtualMachineOptions.java @@ -129,8 +129,8 @@ public class DeployVirtualMachineOptions extends AccountInDomainOptions { public DeployVirtualMachineOptions ipsToNetworks(Map ipsToNetworks) { int count = 0; for (String ip : ipsToNetworks.keySet()) { - this.queryParameters.replaceValues(String.format("ipnetworklist[%d].ip", count), ImmutableSet.of(ip)); - this.queryParameters.replaceValues(String.format("ipnetworklist[%d].networkid", count), + this.queryParameters.replaceValues(String.format("iptonetworklist[%d].ip", count), ImmutableSet.of(ip)); + this.queryParameters.replaceValues(String.format("iptonetworklist[%d].networkid", count), ImmutableSet.of("" + ipsToNetworks.get(ip))); count += 1; } diff --git a/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java b/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java index 321910f564..465b8c245a 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java +++ b/apis/s3/src/main/java/org/jclouds/s3/binders/BindAsHostPrefixIfConfigured.java @@ -63,7 +63,14 @@ public class BindAsHostPrefixIfConfigured implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object payload) { - if (isVhostStyle) { + // If we have a payload/bucket/container that is not all lowercase, vhost-style URLs are not an option and must be + // automatically converted to their path-based equivalent. This should only be possible for AWS-S3 since it is + // the only S3 implementation configured to allow uppercase payload/bucket/container names. + // + // http://code.google.com/p/jclouds/issues/detail?id=992 + String payloadAsString = payload.toString(); + + if (isVhostStyle && payloadAsString.equals(payloadAsString.toLowerCase())) { request = bindAsHostPrefix.bindToRequest(request, payload); String host = request.getEndpoint().getHost(); if (request.getEndpoint().getPort() != -1) { @@ -80,7 +87,7 @@ public class BindAsHostPrefixIfConfigured implements Binder { indexToInsert = indexToInsert == -1 ? 0 : indexToInsert; indexToInsert += servicePath.length(); } - path.insert(indexToInsert, "/" + payload.toString()); + path.insert(indexToInsert, "/" + payloadAsString); builder.replacePath(path.toString()); return (R) request.toBuilder().endpoint(builder.buildFromEncodedMap(ImmutableMap. of())) .build(); diff --git a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java index 74876d10e6..f6a2d20a0d 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java +++ b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java @@ -33,8 +33,8 @@ import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collection; import java.util.Locale; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import javax.annotation.Resource; import javax.inject.Inject; @@ -161,8 +161,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign } appendAmzHeaders(canonicalizedHeaders, buffer); - if (isVhostStyle) - appendBucketName(request, buffer); + appendBucketName(request, buffer); appendUriPath(request, buffer); if (signatureWire.enabled()) signatureWire.output(buffer.toString()); @@ -232,19 +231,14 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign @VisibleForTesting void appendBucketName(HttpRequest req, StringBuilder toSign) { - checkArgument(req instanceof GeneratedHttpRequest, "this should be a generated http request"); - GeneratedHttpRequest request = GeneratedHttpRequest.class.cast(req); + String bucketName = getBucketName(req); - String bucketName = null; - - for (int i = 0; i < request.getJavaMethod().getParameterAnnotations().length; i++) { - if (any(Arrays.asList(request.getJavaMethod().getParameterAnnotations()[i]), ANNOTATIONTYPE_BUCKET)) { - bucketName = (String) request.getArgs().get(i); - break; - } - } - - if (bucketName != null) + // If we have a payload/bucket/container that is not all lowercase, vhost-style URLs are not an option and must be + // automatically converted to their path-based equivalent. This should only be possible for AWS-S3 since it is + // the only S3 implementation configured to allow uppercase payload/bucket/container names. + // + // http://code.google.com/p/jclouds/issues/detail?id=992 + if (isVhostStyle && bucketName!= null && bucketName.equals(bucketName.toLowerCase())) toSign.append(servicePath).append(bucketName); } @@ -271,4 +265,21 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign } } } + + private String getBucketName(HttpRequest req) { + checkArgument(req instanceof GeneratedHttpRequest, "this should be a generated http request"); + GeneratedHttpRequest request = GeneratedHttpRequest.class.cast(req); + + String bucketName = null; + + for (int i = 0; i < request.getJavaMethod().getParameterAnnotations().length; i++) { + if (any(Arrays.asList(request.getJavaMethod().getParameterAnnotations()[i]), ANNOTATIONTYPE_BUCKET)) { + bucketName = (String) request.getArgs().get(i); + break; + } + } + + return bucketName; + } + } diff --git a/apis/s3/src/main/java/org/jclouds/s3/handlers/ParseS3ErrorFromXmlContent.java b/apis/s3/src/main/java/org/jclouds/s3/handlers/ParseS3ErrorFromXmlContent.java index ecf1c3fb72..62c9fc426a 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/handlers/ParseS3ErrorFromXmlContent.java +++ b/apis/s3/src/main/java/org/jclouds/s3/handlers/ParseS3ErrorFromXmlContent.java @@ -25,12 +25,14 @@ import static com.google.common.collect.Lists.newArrayList; import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH; import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS; +import java.net.URI; import java.util.List; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; import org.jclouds.aws.domain.AWSError; import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent; import org.jclouds.aws.util.AWSUtils; @@ -39,9 +41,7 @@ import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.jclouds.rest.ResourceNotFoundException; - -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; +import org.jclouds.s3.S3ApiMetadata; /** * @author Adrian Cole @@ -54,7 +54,7 @@ public class ParseS3ErrorFromXmlContent extends ParseAWSErrorFromXmlContent { private final boolean isVhostStyle; @Inject - ParseS3ErrorFromXmlContent(AWSUtils utils, @Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle, + public ParseS3ErrorFromXmlContent(AWSUtils utils, @Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle, @Named(PROPERTY_S3_SERVICE_PATH) String servicePath) { super(utils); this.servicePath = servicePath; @@ -66,8 +66,19 @@ public class ParseS3ErrorFromXmlContent extends ParseAWSErrorFromXmlContent { switch (response.getStatusCode()) { case 404: if (!command.getCurrentRequest().getMethod().equals("DELETE")) { + // If we have a payload/bucket/container that is not all lowercase, vhost-style URLs are not an option + // and must be automatically converted to their path-based equivalent. This should only be possible for + // AWS-S3 since it is the only S3 implementation configured to allow uppercase payload/bucket/container + // names. + // + // http://code.google.com/p/jclouds/issues/detail?id=992 + URI defaultS3Endpoint = URI.create(new S3ApiMetadata().getDefaultEndpoint().get()); + URI requestEndpoint = command.getCurrentRequest().getEndpoint(); + boolean wasPathBasedRequest = requestEndpoint.getHost().contains(defaultS3Endpoint.getHost()) && + requestEndpoint.getHost().equals(defaultS3Endpoint.getHost()); + exception = new ResourceNotFoundException(message, exception); - if (isVhostStyle) { + if (isVhostStyle && !wasPathBasedRequest) { String container = command.getCurrentRequest().getEndpoint().getHost(); String key = command.getCurrentRequest().getEndpoint().getPath(); if (key == null || key.equals("/")) diff --git a/apis/s3/src/main/java/org/jclouds/s3/predicates/validators/BucketNameValidator.java b/apis/s3/src/main/java/org/jclouds/s3/predicates/validators/BucketNameValidator.java index acf473fe45..ed441fe62c 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/predicates/validators/BucketNameValidator.java +++ b/apis/s3/src/main/java/org/jclouds/s3/predicates/validators/BucketNameValidator.java @@ -40,7 +40,7 @@ import com.google.inject.Singleton; public class BucketNameValidator extends DnsNameValidator { @Inject - BucketNameValidator() { + public BucketNameValidator() { super(3, 63); } diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java index 1b1e25bf9b..34fa5479de 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftApiMetadata.java @@ -20,17 +20,12 @@ package org.jclouds.openstack.swift; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; -import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; -import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; -import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule.StorageEndpointModule; @@ -69,12 +64,8 @@ public class SwiftApiMetadata extends BaseRestApiMetadata { public static Properties defaultProperties() { Properties properties = BaseRestApiMetadata.defaultProperties(); - properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE); - // TODO: this doesn't actually do anything yet. - properties.setProperty(KeystoneProperties.VERSION, "2.0"); - properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.API_ACCESS_KEY_CREDENTIALS); - properties.setProperty(PROPERTY_REGIONS, "DEFAULT"); properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-"); + properties.setProperty(PROPERTY_REGIONS, "DEFAULT"); return properties; } @@ -82,8 +73,8 @@ public class SwiftApiMetadata extends BaseRestApiMetadata { protected Builder(Class syncClient, Class asyncClient){ super(syncClient, asyncClient); id("swift") - .name("OpenStack Swift Pre-Diablo API") - .identityName("tenantName:user or user") + .name("OpenStack Swift with SwiftAuth") + .identityName("tenantId:user") .credentialName("password") .documentation(URI.create("http://api.openstack.org/")) .version("1.0") diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java index 520ae80918..803054168e 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java @@ -19,10 +19,15 @@ package org.jclouds.openstack.swift; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import java.util.Properties; import org.jclouds.apis.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule; import org.jclouds.openstack.swift.config.SwiftKeystoneRestClientModule; import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; @@ -64,6 +69,10 @@ public class SwiftKeystoneApiMetadata extends SwiftApiMetadata { public static Properties defaultProperties() { Properties properties = SwiftApiMetadata.defaultProperties(); + properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE); + // TODO: this doesn't actually do anything yet. + properties.setProperty(KeystoneProperties.VERSION, "2.0"); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.API_ACCESS_KEY_CREDENTIALS); properties.remove(PROPERTY_REGIONS); return properties; } @@ -72,6 +81,9 @@ public class SwiftKeystoneApiMetadata extends SwiftApiMetadata { protected Builder(){ super(SwiftKeystoneClient.class, SwiftKeystoneAsyncClient.class); id("swift-keystone") + .name("OpenStack Swift with Keystone authentication") + .identityName("tenantName:user or user") + .credentialName("password") .context(CONTEXT_TOKEN) .defaultModules(ImmutableSet.>of(KeystoneStorageEndpointModule.class, SwiftKeystoneRestClientModule.class, SwiftBlobStoreContextModule.class)); } diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java new file mode 100644 index 0000000000..7070455160 --- /dev/null +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java @@ -0,0 +1,73 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.swift; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.swift.internal.BaseSwiftExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(testName = "SwiftClientExpectTest") +public class SwiftClientExpectTest extends BaseSwiftExpectTest { + + public void testContainerExistsWhenResponseIs2xxReturnsTrue() throws Exception { + HttpRequest headContainer = HttpRequest.builder() + .method("HEAD") + .endpoint(URI.create(swiftEndpointWithHostReplaced + "/foo")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse headContainerResponse = HttpResponse.builder().statusCode(200).build(); + + SwiftClient clientWhenContainerExists = requestsSendResponses(authRequest, + authResponse, headContainer, headContainerResponse); + + assertTrue(clientWhenContainerExists.containerExists("foo")); + } + + public void testContainerExistsWhenResponseIs404ReturnsFalse() throws Exception { + HttpRequest headContainer = HttpRequest.builder() + .method("HEAD") + .endpoint(URI.create(swiftEndpointWithHostReplaced + "/foo")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse headContainerResponse = HttpResponse.builder().statusCode(404).build(); + + SwiftClient clientWhenContainerDoesntExist = requestsSendResponses(authRequest, + authResponse, headContainer, headContainerResponse); + + assertFalse(clientWhenContainerDoesntExist.containerExists("foo")); + + } + +} diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/BaseSwiftExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/BaseSwiftExpectTest.java new file mode 100644 index 0000000000..ff15a6c741 --- /dev/null +++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/BaseSwiftExpectTest.java @@ -0,0 +1,75 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.swift.internal; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +import com.google.common.collect.ImmutableMultimap; + +/** + * Base class for writing Swift Expect tests + * + * @author Adrian Cole + */ +public class BaseSwiftExpectTest extends BaseRestClientExpectTest { + + protected String endpoint = "http://myhost:8080/auth"; + protected HttpRequest authRequest; + public BaseSwiftExpectTest() { + provider = "swift"; + identity = "test:tester"; + credential = "testing"; + authRequest = HttpRequest.builder() + .method("GET") + .endpoint(URI.create(endpoint+ "/v1.0")) + .headers(ImmutableMultimap.builder() + .put("X-Auth-User", identity) + .put("X-Auth-Key", credential) + .put("Accept", "*/*") + .put("Host", "myhost:8080").build()).build(); + } + + protected String authToken = "AUTH_tk36dabe83ca744cc296a98ec46089ec35"; + + protected String swiftEndpoint = "http://127.0.0.1:8080/v1/AUTH_test"; + + /** + * often swift returns the localhost url when requested via a dns name. this + * test ensures that replacement works. + */ + protected String swiftEndpointWithHostReplaced = swiftEndpoint.replace("127.0.0.1", "myhost"); + + protected HttpResponse authResponse = HttpResponse.builder() + .statusCode(200) + .message("HTTP/1.1 200 OK") + .headers(ImmutableMultimap.builder() + .put("X-Storage-Url", swiftEndpoint) + .put("X-Auth-Token", authToken).build()).build(); + + protected Properties setupProperties() { + Properties props = super.setupProperties(); + props.put(provider+".endpoint", endpoint); + return props; + } +} \ No newline at end of file diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java index cb508a3acd..7b779f5c59 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapter.java @@ -36,6 +36,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Location; import org.jclouds.logging.Logger; import org.jclouds.ovf.Envelope; +import org.jclouds.util.Throwables2; import org.jclouds.vcloud.TaskInErrorStateException; import org.jclouds.vcloud.TaskStillRunningException; import org.jclouds.vcloud.VCloudClient; @@ -109,6 +110,14 @@ public class VCloudComputeServiceAdapter implements ComputeServiceAdapter { @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = SaxUtils.cleanseAttributes(attrs); - if (qName.equals("Catalog")) { + if (SaxUtils.equalsOrSuffix(qName, "Catalog")) { catalog = newReferenceType(attributes, VCloudMediaType.CATALOG_XML); - } else if (qName.equals("CatalogItem")) { + } else if (SaxUtils.equalsOrSuffix(qName, "CatalogItem")) { putReferenceType(contents, attributes); - } else if (qName.equals("Link") && "up".equals(attributes.get("rel"))) { + } else if (SaxUtils.equalsOrSuffix(qName, "Link") && "up".equals(attributes.get("rel"))) { org = newReferenceType(attributes); - } else if (qName.equals("Link") && "add".equals(attributes.get("rel"))) { + } else if (SaxUtils.equalsOrSuffix(qName, "Link") && "add".equals(attributes.get("rel"))) { readOnly = false; } else { taskHandler.startElement(uri, localName, qName, attrs); @@ -85,11 +85,11 @@ public class CatalogHandler extends ParseSax.HandlerWithResult { public void endElement(String uri, String name, String qName) { taskHandler.endElement(uri, name, qName); - if (qName.equals("Task")) { + if (SaxUtils.equalsOrSuffix(qName, "Task")) { this.tasks.add(taskHandler.getResult()); - } else if (qName.equals("Description")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Description")) { description = currentOrNull(); - } else if (qName.equals("IsPublished")) { + } else if (SaxUtils.equalsOrSuffix(qName, "IsPublished")) { published = Boolean.parseBoolean(currentOrNull()); } currentText = new StringBuilder(); diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogItemHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogItemHandler.java index 6f544d7fd8..ee4c6067c9 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogItemHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogItemHandler.java @@ -53,19 +53,19 @@ public class CatalogItemHandler extends ParseSax.HandlerWithResult @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = SaxUtils.cleanseAttributes(attrs); - if (qName.equals("CatalogItem")) { + if (SaxUtils.equalsOrSuffix(qName, "CatalogItem")) { catalogItem = newReferenceType(attributes); - } else if (qName.equals("Entity")) { + } else if (SaxUtils.equalsOrSuffix(qName, ("Entity"))) { entity = newReferenceType(attributes); - } else if (qName.equals("Property")) { + } else if (SaxUtils.equalsOrSuffix(qName, ("Property"))) { key = attributes.get("key"); } } public void endElement(String uri, String name, String qName) { - if (qName.equals("Description")) { + if (SaxUtils.equalsOrSuffix(qName, ("Description"))) { description = currentOrNull(); - } else if (qName.equals("Property")) { + } else if (SaxUtils.equalsOrSuffix(qName, ("Property"))) { properties.put(key, currentOrNull()); key = null; } diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java index 2122c6aed3..2ad6a9bbe3 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/ErrorHandler.java @@ -40,7 +40,7 @@ public class ErrorHandler extends ParseSax.HandlerWithResult { @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = SaxUtils.cleanseAttributes(attrs); - if (qName.equals("Error")) { + if (SaxUtils.equalsOrSuffix(qName, "Error")) { error = Utils.newError(attributes); } } diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/OrgNetworkHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/OrgNetworkHandler.java index 539dc8fd78..3cf072302d 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/OrgNetworkHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/OrgNetworkHandler.java @@ -145,13 +145,13 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = SaxUtils.cleanseAttributes(attrs); - if (qName.equals("OrgNetwork")) { + if (SaxUtils.equalsOrSuffix(qName, "OrgNetwork")) { network = newReferenceType(attributes); - } else if (qName.equals("FirewallRule")) { + } else if (SaxUtils.equalsOrSuffix(qName, "FirewallRule")) { this.inFirewallRule = true; - } else if (qName.equals("ParentNetwork")) { + } else if (SaxUtils.equalsOrSuffix(qName, "ParentNetwork")) { parentNetwork = newReferenceType(attributes); - } else if (qName.equals("Link") && "up".equals(attributes.get("rel"))) { + } else if (SaxUtils.equalsOrSuffix(qName, "Link") && "up".equals(attributes.get("rel"))) { org = newReferenceType(attributes); } else { taskHandler.startElement(uri, localName, qName, attrs); @@ -166,38 +166,38 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { public void endElement(String uri, String name, String qName) { taskHandler.endElement(uri, name, qName); - if (qName.equals("Task")) { + if (SaxUtils.equalsOrSuffix(qName, "Task")) { this.tasks.add(taskHandler.getResult()); - } else if (qName.equals("Description")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Description")) { if (inFirewallRule) firewallRuleDescription = currentOrNull(); else orgDescription = currentOrNull(); - } else if (qName.equals("FenceMode")) { + } else if (SaxUtils.equalsOrSuffix(qName, "FenceMode")) { fenceMode = FenceMode.fromValue(currentOrNull()); - } else if (qName.equals("StartAddress")) { + } else if (SaxUtils.equalsOrSuffix(qName, "StartAddress")) { startAddress = currentOrNull(); - } else if (qName.equals("EndAddress")) { + } else if (SaxUtils.equalsOrSuffix(qName, "EndAddress")) { endAddress = currentOrNull(); - } else if (qName.equals("AllocatedIpAddress")) { + } else if (SaxUtils.equalsOrSuffix(qName, "AllocatedIpAddress")) { allocatedIpAddresses.add(currentOrNull()); - } else if (qName.equals("IpRange")) { + } else if (SaxUtils.equalsOrSuffix(qName, "IpRange")) { ipRanges.add(new IpRange(startAddress, endAddress)); this.startAddress = null; this.endAddress = null; - } else if (qName.equals("IsInherited")) { + } else if (SaxUtils.equalsOrSuffix(qName, "IsInherited")) { inherited = Boolean.parseBoolean(currentOrNull()); - } else if (qName.equals("Gateway")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Gateway")) { gateway = currentOrNull(); - } else if (qName.equals("Netmask")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Netmask")) { netmask = currentOrNull(); - } else if (qName.equals("Dns1")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Dns1")) { dns1 = currentOrNull(); - } else if (qName.equals("Dns2")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Dns2")) { dns2 = currentOrNull(); - } else if (qName.equals("DnsSuffix")) { + } else if (SaxUtils.equalsOrSuffix(qName, "DnsSuffix")) { dnsSuffix = currentOrNull(); - } else if (qName.equals("IpScope")) { + } else if (SaxUtils.equalsOrSuffix(qName, "IpScope")) { ipScope = new IpScope(inherited, gateway, netmask, dns1, dns2, dnsSuffix, ipRanges, allocatedIpAddresses); this.inherited = false; this.gateway = null; @@ -207,38 +207,38 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { this.dnsSuffix = null; this.ipRanges = Sets.newLinkedHashSet(); this.allocatedIpAddresses = Sets.newLinkedHashSet(); - } else if (qName.equals("IsEnabled")) { + } else if (SaxUtils.equalsOrSuffix(qName, "IsEnabled")) { if (inFirewallRule) firewallRuleEnabled = Boolean.parseBoolean(currentOrNull()); else serviceEnabled = Boolean.parseBoolean(currentOrNull()); - } else if (qName.equals("DefaultLeaseTime")) { + } else if (SaxUtils.equalsOrSuffix(qName, "DefaultLeaseTime")) { defaultLeaseTime = Integer.parseInt(currentOrNull()); - } else if (qName.equals("MaxLeaseTime")) { + } else if (SaxUtils.equalsOrSuffix(qName, "MaxLeaseTime")) { maxLeaseTime = Integer.parseInt(currentOrNull()); - } else if (qName.equals("DhcpService")) { + } else if (SaxUtils.equalsOrSuffix(qName, "DhcpService")) { this.dhcpService = new DhcpService(serviceEnabled, defaultLeaseTime, maxLeaseTime, Iterables .getOnlyElement(ipRanges)); this.serviceEnabled = false; this.defaultLeaseTime = null; this.maxLeaseTime = null; this.ipRanges = Sets.newLinkedHashSet(); - } else if (qName.equals("Policy")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Policy")) { if (inFirewallRule) firewallPolicy = FirewallPolicy.fromValue(currentOrNull()); else natPolicy = NatPolicy.fromValue(currentOrNull()); - } else if (qName.equals("Tcp")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Tcp")) { tcp = Boolean.parseBoolean(currentOrNull()); - } else if (qName.equals("Udp")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Udp")) { udp = Boolean.parseBoolean(currentOrNull()); - } else if (qName.equals("Protocols")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Protocols")) { this.protocols = new FirewallProtocols(tcp, udp); this.tcp = false; this.udp = false; - } else if (qName.equals("DestinationIp")) { + } else if (SaxUtils.equalsOrSuffix(qName, "DestinationIp")) { this.destinationIp = currentOrNull(); - } else if (qName.equals("FirewallRule")) { + } else if (SaxUtils.equalsOrSuffix(qName, "FirewallRule")) { this.inFirewallRule = false; this.firewallRules.add(new FirewallRule(firewallRuleEnabled, firewallRuleDescription, firewallPolicy, protocols, port, destinationIp)); @@ -248,13 +248,13 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { this.protocols = null; this.port = -1; this.destinationIp = null; - } else if (qName.equals("FirewallService")) { + } else if (SaxUtils.equalsOrSuffix(qName, "FirewallService")) { firewallService = new FirewallService(serviceEnabled, firewallRules); this.serviceEnabled = false; this.firewallRules = Lists.newArrayList(); - } else if (qName.equals("NatType")) { + } else if (SaxUtils.equalsOrSuffix(qName, "NatType")) { natType = NatType.fromValue(currentOrNull()); - } else if (qName.equals("MappingMode")) { + } else if (SaxUtils.equalsOrSuffix(qName, "MappingMode")) { mappingMode = MappingMode.fromValue(currentOrNull()); } else if (qName.equalsIgnoreCase("ExternalIP")) { externalIP = currentOrNull(); @@ -264,7 +264,7 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { vAppScopedLocalId = currentOrNull(); } else if (qName.equalsIgnoreCase("vmNicId")) { vmNicId = Integer.parseInt(currentOrNull()); - } else if (qName.equals("OneToOneVmRule")) { + } else if (SaxUtils.equalsOrSuffix(qName, "OneToOneVmRule")) { natRules.add(new OneToOneVmRule(mappingMode, externalIP, vAppScopedVmId, vmNicId)); this.mappingMode = null; this.externalIP = null; @@ -278,14 +278,14 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { internalPort = Integer.parseInt(currentOrNull()); } else if (equalsOrSuffix(qName, "Protocol")) { natProtocol = NatProtocol.valueOf(currentOrNull()); - } else if (qName.equals("PortForwardingRule")) { + } else if (SaxUtils.equalsOrSuffix(qName, "PortForwardingRule")) { natRules.add(new PortForwardingRule(externalIP, externalPort, internalIP, internalPort, natProtocol)); this.externalIP = null; this.externalPort = -1; this.internalIP = null; this.internalPort = -1; this.natProtocol = null; - } else if (qName.equals("VmRule")) { + } else if (SaxUtils.equalsOrSuffix(qName, "VmRule")) { natRules.add(new VmRule(externalIP, externalPort, vAppScopedLocalId, vmNicId, internalPort, natProtocol)); this.externalIP = null; this.externalPort = -1; @@ -293,24 +293,24 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult { this.vmNicId = -1; this.internalPort = -1; this.natProtocol = null; - } else if (qName.equals("NatService")) { + } else if (SaxUtils.equalsOrSuffix(qName, "NatService")) { this.natService = new NatService(serviceEnabled, natType, natPolicy, natRules); this.serviceEnabled = false; this.natType = null; this.natPolicy = null; this.natRules = Lists.newArrayList(); - } else if (qName.equals("Features")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Features")) { this.features = new Features(dhcpService, firewallService, natService); this.dhcpService = null; this.firewallService = null; this.natService = null; - } else if (qName.equals("Configuration")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Configuration")) { configuration = new OrgNetworkImpl.ConfigurationImpl(ipScope, parentNetwork, fenceMode, features); this.ipScope = null; this.parentNetwork = null; this.fenceMode = null; this.features = null; - } else if (qName.equals("AllowedExternalIpAddress")) { + } else if (SaxUtils.equalsOrSuffix(qName, "AllowedExternalIpAddress")) { allowedExternalIpAddresses.add(currentOrNull()); } currentText = new StringBuilder(); diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/SupportedVersionsHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/SupportedVersionsHandler.java index 7d131e6229..8a9ef79be4 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/SupportedVersionsHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/SupportedVersionsHandler.java @@ -22,6 +22,7 @@ import java.net.URI; import java.util.SortedMap; import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; import com.google.common.collect.Maps; @@ -40,11 +41,11 @@ public class SupportedVersionsHandler extends ParseSax.HandlerWithResult { @Override public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = SaxUtils.cleanseAttributes(attrs); - if (qName.equals("TasksList")) { + if (SaxUtils.equalsOrSuffix(qName, "TasksList")) { resource = Utils.newReferenceType(attributes); - } else if (qName.equals("Link") && "self".equals(attributes.get("rel"))) { + } else if (SaxUtils.equalsOrSuffix(qName, "Link") && "self".equals(attributes.get("rel"))) { resource = Utils.newReferenceType(attributes); } else { taskHandler.startElement(uri, localName, qName, attrs); @@ -68,7 +68,7 @@ public class TasksListHandler extends ParseSax.HandlerWithResult { @Override public void endElement(String uri, String localName, String qName) throws SAXException { taskHandler.endElement(uri, localName, qName); - if (qName.equals("Task")) { + if (SaxUtils.equalsOrSuffix(qName, "Task")) { this.tasks.add(taskHandler.getResult()); } } diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VmHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VmHandler.java index 04dd74f567..dcf12367af 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VmHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VmHandler.java @@ -113,12 +113,12 @@ public class VmHandler extends ParseSax.HandlerWithResult { guestCustomizationHandler.startElement(uri, localName, qName, attrs); } else if (inTasks) { taskHandler.startElement(uri, localName, qName, attrs); - } else if (qName.equals("Vm")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Vm")) { vm = newReferenceType(attributes); String status = attributes.get("status"); if (status != null) this.status = Status.fromValue(Integer.parseInt(status)); - } else if (qName.equals("Link") && "up".equals(attributes.get("rel"))) { + } else if (SaxUtils.equalsOrSuffix(qName, "Link") && "up".equals(attributes.get("rel"))) { vdc = newReferenceType(attributes); } } @@ -150,9 +150,9 @@ public class VmHandler extends ParseSax.HandlerWithResult { networkConnectionSectionHandler.endElement(uri, name, qName); } else if (inTasks) { taskHandler.endElement(uri, name, qName); - } else if (qName.equals("Description")) { + } else if (SaxUtils.equalsOrSuffix(qName, "Description")) { description = currentOrNull(); - } else if (qName.equals("VAppScopedLocalId")) { + } else if (SaxUtils.equalsOrSuffix(qName, "VAppScopedLocalId")) { vAppScopedLocalId = currentOrNull(); } currentText = new StringBuilder(); diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/BaseVCloudComputeServiceExpectTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/BaseVCloudComputeServiceExpectTest.java index 3dca2658d4..73ac7b9060 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/BaseVCloudComputeServiceExpectTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/BaseVCloudComputeServiceExpectTest.java @@ -131,6 +131,10 @@ public abstract class BaseVCloudComputeServiceExpectTest extends BaseRestClientE .message("HTTP/1.1 200 OK").payload(payloadFromResourceWithContentType("/template1.0-vcd15.xml", VCloudMediaType.VAPPTEMPLATE_XML +";version=1.0")) .build(); + protected HttpResponse successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithMultipleVMsAndVDCParent = HttpResponse.builder().statusCode(200) + .message("HTTP/1.1 200 OK").payload(payloadFromResourceWithContentType("/template1.0-vcd15-multi-vm.xml", VCloudMediaType.VAPPTEMPLATE_XML +";version=1.0")) + .build(); + protected HttpRequest version1_0GetOVFForVAppTemplateRequest = HttpRequest.builder().method("GET").endpoint( URI.create(ENDPOINT + "/v1.0/vAppTemplate/" + templateId + "/ovf")) .headers(ImmutableMultimap. builder() @@ -141,6 +145,10 @@ public abstract class BaseVCloudComputeServiceExpectTest extends BaseRestClientE .message("HTTP/1.1 200 OK").payload(payloadFromResourceWithContentType("/ovf-ubuntu64.xml", MediaType.TEXT_XML +";version=1.0")) .build(); + protected HttpResponse successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithMultipleVMs = HttpResponse.builder().statusCode(200) + .message("HTTP/1.1 200 OK").payload(payloadFromResourceWithContentType("/ovf-multi-vm.xml", MediaType.TEXT_XML +";version=1.0")) + .build(); + public BaseVCloudComputeServiceExpectTest() { provider = "vcloud"; } diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapterTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapterTest.java new file mode 100644 index 0000000000..8bf2bc9fdb --- /dev/null +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapterTest.java @@ -0,0 +1,74 @@ +package org.jclouds.vcloud.compute.strategy; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Collections; + +import org.jclouds.compute.ComputeService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.vcloud.compute.BaseVCloudComputeServiceExpectTest; +import org.jclouds.vcloud.domain.VAppTemplate; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +public class VCloudComputeServiceAdapterTest extends BaseVCloudComputeServiceExpectTest { + + @Test + public void testListHardwareProfiles() throws Exception { + ComputeService compute = requestsSendResponses(ImmutableMap. builder() + .put(versionsRequest, versionsResponseFromVCD1_5) + .put(version1_0LoginRequest, successfulVersion1_0LoginResponseFromVCD1_5WithSingleOrg) + .put(version1_0GetOrgRequest, successfulVersion1_0GetOrgResponseFromVCD1_5WithSingleTasksListVDCAndNetwork) + .put(version1_0GetCatalogRequest, successfulVersion1_0GetCatalogResponseFromVCD1_5WithSingleTemplate) + .put(version1_0GetCatalogItemRequest, successfulVersion1_0GetCatalogItemResponseFromVCD1_5ForTemplate) + .put(version1_0GetVDCRequest, successfulVersion1_0GetVDCResponseFromVCD1_5WithSingleTemplateAndNetwork) + .put(version1_0GetVAppTemplateRequest, successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithSingleVMAndVDCParent) + .put(version1_0GetOVFForVAppTemplateRequest, successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithSingleVM) + .build()); + + VCloudComputeServiceAdapter adapter = compute.getContext() + .utils().injector().getInstance(VCloudComputeServiceAdapter.class); + + Iterable hardwareProfiles = adapter.listHardwareProfiles(); + + Iterable hardwareProfileRefs = Iterables.transform(ImmutableList.copyOf(hardwareProfiles), new Function() { + @Override public URI apply(VAppTemplate input) { + return input.getHref(); + } + }); + assertEquals(ImmutableSet.copyOf(hardwareProfileRefs), ImmutableSet.of(URI.create("https://zone.myvcloud.com/api/v1.0/vAppTemplate/vappTemplate-51891b97-c5dd-47dc-a687-aabae354f728"))); + } + + /** + * For issue 994. In BaseEnvelopeHandler when it encounters VirtualSystemCollection, it throws IllegalArgumentException + * (cannot currently create envelopes with multiple virtual systems). + * Thus we do not include the VM in the supported set, but we do return without propagating the exception. + */ + @Test + public void testListHardwareProfilesWithUnsupportedTemplate() throws Exception { + ComputeService compute = requestsSendResponses(ImmutableMap. builder() + .put(versionsRequest, versionsResponseFromVCD1_5) + .put(version1_0LoginRequest, successfulVersion1_0LoginResponseFromVCD1_5WithSingleOrg) + .put(version1_0GetOrgRequest, successfulVersion1_0GetOrgResponseFromVCD1_5WithSingleTasksListVDCAndNetwork) + .put(version1_0GetCatalogRequest, successfulVersion1_0GetCatalogResponseFromVCD1_5WithSingleTemplate) + .put(version1_0GetCatalogItemRequest, successfulVersion1_0GetCatalogItemResponseFromVCD1_5ForTemplate) + .put(version1_0GetVDCRequest, successfulVersion1_0GetVDCResponseFromVCD1_5WithSingleTemplateAndNetwork) + .put(version1_0GetVAppTemplateRequest, successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithMultipleVMsAndVDCParent) + .put(version1_0GetOVFForVAppTemplateRequest, successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithMultipleVMs) + .build()); + + VCloudComputeServiceAdapter adapter = compute.getContext() + .utils().injector().getInstance(VCloudComputeServiceAdapter.class); + + Iterable hardwareProfiles = adapter.listHardwareProfiles(); + + assertEquals(ImmutableSet.copyOf(hardwareProfiles), Collections.emptySet()); + } +} diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/xml/CatalogItemHandlerTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/xml/CatalogItemHandlerTest.java index 17c2b8a0ee..b5050e5945 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/xml/CatalogItemHandlerTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/xml/CatalogItemHandlerTest.java @@ -59,4 +59,30 @@ public class CatalogItemHandlerTest { ))); } + + public void testApplyInputStreamWithNamespaceUsingVcloud() { + InputStream is = getClass().getResourceAsStream("/catalogItem-carrenza-with-vcloud-namespace.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + CatalogItem result = factory.create(injector.getInstance(CatalogItemHandler.class)).parse(is); + + assertEquals(result, new CatalogItemImpl("ubuntu10.10x64", + URI.create("https://myvdc.carrenza.net/api/v1.0/catalogItem/ecd4d3a0-0d12-4195-a6d2-14cdf9f925a3"), + null, new ReferenceTypeImpl("ubuntu10.10x64", "application/vnd.vmware.vcloud.vAppTemplate+xml", + URI.create("https://myvdc.carrenza.net/api/v1.0/vAppTemplate/vappTemplate-123766ea-2b55-482c-8adf-735ab1952834")), + ImmutableSortedMap.of())); + } + + public void testApplyInputStreamWithNamespaceUsingDefault() { + InputStream is = getClass().getResourceAsStream("/catalogItem-carrenza-with-default-namespace.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + CatalogItem result = factory.create(injector.getInstance(CatalogItemHandler.class)).parse(is); + + assertEquals(result, new CatalogItemImpl("ubuntu10.10x64", + URI.create("https://myvdc.carrenza.net/api/v1.0/catalogItem/ecd4d3a0-0d12-4195-a6d2-14cdf9f925a3"), + null, new ReferenceTypeImpl("ubuntu10.10x64", "application/vnd.vmware.vcloud.vAppTemplate+xml", + URI.create("https://myvdc.carrenza.net/api/v1.0/vAppTemplate/vappTemplate-123766ea-2b55-482c-8adf-735ab1952834")), + ImmutableSortedMap.of())); + } } diff --git a/apis/vcloud/src/test/resources/catalogItem-carrenza-with-default-namespace.xml b/apis/vcloud/src/test/resources/catalogItem-carrenza-with-default-namespace.xml new file mode 100644 index 0000000000..88fec20ef4 --- /dev/null +++ b/apis/vcloud/src/test/resources/catalogItem-carrenza-with-default-namespace.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apis/vcloud/src/test/resources/catalogItem-carrenza-with-vcloud-namespace.xml b/apis/vcloud/src/test/resources/catalogItem-carrenza-with-vcloud-namespace.xml new file mode 100644 index 0000000000..917c143b95 --- /dev/null +++ b/apis/vcloud/src/test/resources/catalogItem-carrenza-with-vcloud-namespace.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apis/vcloud/src/test/resources/ovf-multi-vm.xml b/apis/vcloud/src/test/resources/ovf-multi-vm.xml new file mode 100644 index 0000000000..fa4bb37236 --- /dev/null +++ b/apis/vcloud/src/test/resources/ovf-multi-vm.xml @@ -0,0 +1,285 @@ + + + + + The list of logical networks + + + + + + The configuration parameters for logical networks + + + + + false + 192.168.2.1 + 255.255.255.0 + 195.225.219.131 + + + 192.168.2.100 + 192.168.2.199 + + + + isolated + + + false + 7200 + 7200 + + + + + false + + + + Lease settings section + 0 + 0 + + + VApp template customization section + true + + + A collection of virtual machines: + centos-web/db-5.5 + + VApp startup section + + + + + A virtual machine: + centos-db + + Specifies the operating system installed + Other 2.6x Linux (64-bit) + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + centos-db + vmx-07 + + + 00:50:56:01:06:81 + 0 + true + vapp net + + PCNet32 ethernet adapter + Network adapter 0 + 1 + PCNet32 + 10 + + + 0 + SCSI Controller + SCSI Controller 0 + 2 + lsilogic + 6 + + + 0 + Hard disk + Hard disk 1 + + 2000 + 2 + 17 + + + 0 + IDE Controller + IDE Controller 0 + 3 + 5 + + + 0 + false + CD/DVD Drive + CD/DVD Drive 1 + + 3000 + 3 + 15 + + + 0 + false + Floppy Drive + Floppy Drive 1 + + 8000 + 14 + + + hertz * 10^6 + Number of Virtual CPUs + 1 virtual CPU(s) + 4 + 0 + 3 + 1 + 0 + + + byte * 2^20 + Memory Size + 2048 MB of memory + 5 + 0 + 4 + 2048 + 0 + + + + Specifies the available VM network connections + 0 + + 0 + 192.168.2.100 + true + 00:50:56:01:06:81 + POOL + + + + Specifies Guest OS Customization Settings + true + false + false + false + false + true + false + centos-db + + + + A virtual machine: + centos-web + + Specifies the operating system installed + Other 2.6x Linux (64-bit) + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + centos-web + vmx-07 + + + 00:50:56:01:06:82 0 + true + vapp net + + PCNet32 ethernet adapter + Network adapter 0 + 1 + PCNet32 + 10 + + + 0 + SCSI Controller + SCSI Controller 0 + 2 + lsilogic + 6 + + + 0 + Hard disk + Hard disk 1 + + 2000 + 2 + 17 + + + 0 + IDE Controller + IDE Controller 0 + 3 + 5 + + + 0 + false + CD/DVD Drive + CD/DVD Drive 1 + + 3000 + 3 + 15 + + + 0 + false + Floppy Drive + Floppy Drive 1 + + 8000 + 14 + + + hertz * 10^6 + Number of Virtual CPUs + 1 virtual CPU(s) + 4 + 0 + 3 + 1 + 0 + + + byte * 2^20 + Memory Size + 2048 MB of memory + 5 + 0 + 4 + 2048 + 0 + + + + Specifies the available VM network connections + 0 + + 0 + 192.168.2.101 + true + 00:50:56:01:06:82 + POOL + + + + Specifies Guest OS Customization Settings + true + false + false + false + false + true + false + centos-web + + + + diff --git a/apis/vcloud/src/test/resources/template1.0-vcd15-multi-vm.xml b/apis/vcloud/src/test/resources/template1.0-vcd15-multi-vm.xml new file mode 100644 index 0000000000..46b3c83011 --- /dev/null +++ b/apis/vcloud/src/test/resources/template1.0-vcd15-multi-vm.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + Specifies the available VM network connections + 0 + + 0 + false + 00:50:56:b5:09:dc + NONE + + + + Specifies Guest OS Customization Settings + true + false + false + false + true + true + true WindowsServ-001 + + Windows Server 2008 R2 + + + The list of logical networks + + This is a special place-holder used for disconnected network interfaces. + + + The configuration parameters for logical networks + + This is a special place-holder used for disconnected network interfaces. + + + false + 196.254.254.254 + 255.255.0.0 + 196.254.254.254 + + isolated + + false + + + + Lease settings section + 0 + + + VApp template customization section + true + + + diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java index 1c011141f7..611e93ba25 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientStorageStrategy.java @@ -79,8 +79,9 @@ public class TransientStorageStrategy { } public void removeBlob(final String containerName, final String blobName) { - if (containerToBlobs.containsKey(containerName)) - containerToBlobs.get(containerName).remove(blobName); + Map map = containerToBlobs.get(containerName); + if (map != null) + map.remove(blobName); } public Iterable getBlobKeysInsideContainer(final String containerName) { diff --git a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java index 8061c41553..9b68139a8d 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java @@ -90,9 +90,6 @@ public class ParseAuthenticationResponseFromHeaders implements Function that) { if (that instanceof Hardware) { Hardware thatHardware = Hardware.class.cast(that); - return ComparisonChain.start().compare(getCoresAndSpeed(this), getCoresAndSpeed(thatHardware)).compare( - this.getRam(), thatHardware.getRam()).compare(getSpace(this), getSpace(thatHardware)).compare( - getHypervisor(), thatHardware.getHypervisor()).result(); + return ComparisonChain.start().compare(getCores(this), getCores(thatHardware)).compare(this.getRam(), thatHardware.getRam()) + .compare(getSpace(this), getSpace(thatHardware)).result(); } else { return super.compareTo(that); } diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java index 63adb96371..e75fc7d58f 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/TemplateBuilderImpl.java @@ -437,6 +437,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { predicates.add(hypervisorPredicate); predicates.add(hardwareCoresPredicate); predicates.add(hardwareRamPredicate); + predicates.add(hardwareDiskPredicate); // looks verbose, but explicit type needed for this to compile // properly diff --git a/core/src/main/java/org/jclouds/collect/PaginatedSet.java b/core/src/main/java/org/jclouds/collect/PaginatedSet.java new file mode 100644 index 0000000000..fd23d63c4b --- /dev/null +++ b/core/src/main/java/org/jclouds/collect/PaginatedSet.java @@ -0,0 +1,103 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.collect; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableSet; + +/** + * An {@code Set} that can be continued + * + * @author Adrian Cole + */ +@Beta +public class PaginatedSet extends ForwardingSet { + + public static PaginatedSet copyOf(Iterable contents) { + return new PaginatedSet(contents, null); + } + + public static PaginatedSet copyOfWithMarker(Iterable contents, String marker) { + return new PaginatedSet(contents, marker); + } + + private final Set contents; + private final String marker; + + protected PaginatedSet(Iterable contents, @Nullable String marker) { + this.contents = ImmutableSet. copyOf(checkNotNull(contents, "contents")); + this.marker = marker; + } + + /** + * If there is a next marker, then the set is incomplete and you should issue another command to + * retrieve the rest, setting the option {@code marker} to this value + * + * @return next marker, or null if list is complete + */ + @Nullable + public String getNextMarker() { + return marker; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(contents, marker); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PaginatedSet other = PaginatedSet.class.cast(obj); + return Objects.equal(this.contents, other.contents) && Objects.equal(this.marker, other.marker); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this).add("contents", contents).add("marker", marker).toString(); + } + + @Override + protected Set delegate() { + return contents; + } + +} diff --git a/core/src/main/java/org/jclouds/collect/PaginatedSets.java b/core/src/main/java/org/jclouds/collect/PaginatedSets.java new file mode 100644 index 0000000000..293b1a8886 --- /dev/null +++ b/core/src/main/java/org/jclouds/collect/PaginatedSets.java @@ -0,0 +1,86 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.collect; + +import java.util.Iterator; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.collect.AbstractIterator; + +/** + * Utilities for using {@link PaginatedSet}s. + * + * @author Adrian Cole, Jeremy Whitlock + */ +@Beta +public class PaginatedSets { + + /** + * + * @param initial + * the initial set of data + * @param markerToNext + * produces the next set based on the marker + * + * @return iterable of users fitting the criteria + */ + public static Iterable lazyContinue(final PaginatedSet initial, + final Function> markerToNext) { + if (initial.getNextMarker() == null) + return initial; + return new Iterable() { + @Override + public Iterator iterator() { + return new AbstractIterator() { + + private PaginatedSet response = initial; + private Iterator iterator = response.iterator(); + + /** + * {@inheritDoc} + */ + @Override + protected T computeNext() { + while (true) { + if (iterator == null) { + response = markerToNext.apply(response.getNextMarker()); + iterator = response.iterator(); + } + if (iterator.hasNext()) { + return iterator.next(); + } + if (response.getNextMarker() == null) { + return endOfData(); + } + iterator = null; + } + } + + }; + } + + @Override + public String toString() { + return "lazyContinue(" + markerToNext.toString() + ")"; + } + }; + } + +} diff --git a/core/src/main/java/org/jclouds/json/config/GsonModule.java b/core/src/main/java/org/jclouds/json/config/GsonModule.java index 937f518fc4..e5a3011b19 100644 --- a/core/src/main/java/org/jclouds/json/config/GsonModule.java +++ b/core/src/main/java/org/jclouds/json/config/GsonModule.java @@ -18,6 +18,7 @@ */ package org.jclouds.json.config; +import java.beans.ConstructorProperties; import java.io.IOException; import java.lang.reflect.Type; import java.util.Date; @@ -35,20 +36,29 @@ import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.DateService; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; +import org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory; import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue; import org.jclouds.json.internal.GsonWrapper; +import org.jclouds.json.internal.NamingStrategies.AnnotationConstructorNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.AnnotationOrNameFieldNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.ExtractNamed; +import org.jclouds.json.internal.NamingStrategies.ExtractSerializedName; import org.jclouds.json.internal.NullHackJsonLiteralAdapter; import org.jclouds.json.internal.OptionalTypeAdapterFactory; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.primitives.Bytes; +import com.google.gson.FieldNamingStrategy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; import com.google.gson.internal.JsonReaderInternalAccess; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; @@ -69,8 +79,12 @@ public class GsonModule extends AbstractModule { @Singleton Gson provideGson(TypeAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter, ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings) - throws ClassNotFoundException, Exception { - GsonBuilder builder = new GsonBuilder(); + throws Exception { + + FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(new ExtractSerializedName(), + new ExtractNamed()); + + GsonBuilder builder = new GsonBuilder().setFieldNamingStrategy(serializationPolicy); // simple (type adapters) builder.registerTypeAdapter(Properties.class, propertiesAdapter.nullSafe()); @@ -81,6 +95,14 @@ public class GsonModule extends AbstractModule { builder.registerTypeAdapter(JsonBall.class, jsonAdapter.nullSafe()); builder.registerTypeAdapterFactory(new OptionalTypeAdapterFactory()); + AnnotationConstructorNamingStrategy deserializationPolicy = + new AnnotationConstructorNamingStrategy( + ImmutableSet.of(ConstructorProperties.class, Inject.class), ImmutableSet.of(new ExtractNamed())); + + builder.registerTypeAdapterFactory( + new DeserializationConstructorAndReflectiveTypeAdapterFactory(new ConstructorConstructor(), + serializationPolicy, Excluder.DEFAULT, deserializationPolicy)); + // complicated (serializers/deserializers as they need context to operate) builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue()); diff --git a/core/src/main/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactory.java b/core/src/main/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactory.java new file mode 100644 index 0000000000..14ce076ce0 --- /dev/null +++ b/core/src/main/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactory.java @@ -0,0 +1,256 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.json.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.jclouds.json.internal.NamingStrategies.ConstructorFieldNamingStrategy; + +import com.google.gson.FieldNamingStrategy; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.$Gson$Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +/** + * Creates type adapters for types handled in the following ways: + *

+ *

    + *
  • Deserialization
  • + * If there's an annotation designating a parameterized constructor, invoke that for fields + * correlating to named parameter annotations. Otherwise, use {@link ConstructorConstructor}, and + * set fields via reflection. + *
  • Serialization
  • + * Serialize based on reflective access to fields, delegating to ReflectiveTypeAdaptor. + *
+ *

Example: Using javax inject to select a constructor and corresponding named parameters

+ *

+ *

+ *    
+ * import NamingStrategies.*;
+ *
+ * serializationStrategy = new AnnotationOrNameFieldNamingStrategy(
+ *    new ExtractSerializedName(), new ExtractNamed());
+ * 
+ * deserializationStrategy = new AnnotationConstructorNamingStrategy(
+ *    Collections.singleton(javax.inject.Inject.class),
+ *    Collections.singleton(new ExtractNamed()));
+ *    
+ * factory = new DeserializationConstructorAndReflectiveTypeAdapterFactory(new ConstructorConstructor(),
+ *      serializationStrategy, Excluder.DEFAULT, deserializationStrategy);
+ *
+ * gson = new GsonBuilder(serializationStrategy).registerTypeAdapterFactory(factory).create();
+ *
+ * 
+ *

+ * The above would work fine on the following class, which has no gson-specific annotations: + *

+ *

+ * private static class ImmutableAndVerifiedInCtor {
+ *    final int foo;
+ *    @Named("_bar")
+ *    final int bar;
+ *
+ *    @Inject
+ *    ImmutableAndVerifiedInCtor(@Named("foo") int foo, @Named("_bar") int bar) {
+ *       if (foo < 0)
+ *          throw new IllegalArgumentException("negative!");
+ *       this.foo = foo;
+ *       this.bar = bar;
+ *    }
+ * }
+ * 
+ *

+ *
+ * + * @author Adrian Cole + * @author Adam Lowe + */ +public final class DeserializationConstructorAndReflectiveTypeAdapterFactory implements TypeAdapterFactory { + private final ConstructorFieldNamingStrategy constructorFieldNamingPolicy; + private final ReflectiveTypeAdapterFactory delegateFactory; + + /** + * @param constructorConstructor passed through to delegate ReflectiveTypeAdapterFactory for serialization + * @param serializationFieldNamingPolicy passed through to delegate ReflectiveTypeAdapterFactory for serialization + * @param excluder passed through to delegate ReflectiveTypeAdapterFactory for serialization + * @param deserializationFieldNamingPolicy + * determines which constructor to use and how to determine field names for + * deserialization + * @see ReflectiveTypeAdapterFactory + */ + public DeserializationConstructorAndReflectiveTypeAdapterFactory( + ConstructorConstructor constructorConstructor, + FieldNamingStrategy serializationFieldNamingPolicy, + Excluder excluder, + ConstructorFieldNamingStrategy deserializationFieldNamingPolicy) { + this.constructorFieldNamingPolicy = checkNotNull(deserializationFieldNamingPolicy, "deserializationFieldNamingPolicy"); + this.delegateFactory = new ReflectiveTypeAdapterFactory(constructorConstructor, checkNotNull(serializationFieldNamingPolicy, "fieldNamingPolicy"), checkNotNull(excluder, "excluder")); + } + + @SuppressWarnings("unchecked") + public TypeAdapter create(Gson gson, final TypeToken type) { + Class raw = type.getRawType(); + Constructor deserializationCtor = constructorFieldNamingPolicy.getDeserializationConstructor(raw); + + if (deserializationCtor == null) { + return null; // allow GSON to choose the correct Adapter (can't simply return delegateFactory.create()) + } else { + deserializationCtor.setAccessible(true); + return new DeserializeWithParameterizedConstructorSerializeWithDelegate(delegateFactory.create(gson, type), deserializationCtor, + getParameterReaders(gson, type, deserializationCtor)); + } + } + + private final class DeserializeWithParameterizedConstructorSerializeWithDelegate extends TypeAdapter { + private final Constructor parameterizedCtor; + private final Map parameterReaders; + private final TypeAdapter delegate; + + private DeserializeWithParameterizedConstructorSerializeWithDelegate(TypeAdapter delegate, + Constructor parameterizedCtor, Map parameterReaders) { + this.delegate = delegate; + this.parameterizedCtor = parameterizedCtor; + this.parameterReaders = parameterReaders; + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Class[] paramTypes = parameterizedCtor.getParameterTypes(); + Object[] ctorParams = new Object[paramTypes.length]; + + // TODO determine if we can drop this + for (int i = 0; i < paramTypes.length; i++) { + if (paramTypes[i] == boolean.class) { + ctorParams[i] = Boolean.FALSE; + } else if (paramTypes[i].isPrimitive()) { + ctorParams[i] = 0; + } + } + + try { + in.beginObject(); + while (in.hasNext()) { + String name = in.nextName(); + ParameterReader parameter = parameterReaders.get(name); + if (parameter == null) { + in.skipValue(); + } else { + Object value = parameter.read(in); + if (value != null) ctorParams[parameter.index] = value; + } + } + } catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } + + for (int i = 0; i < paramTypes.length; i++) { + if (paramTypes[i].isPrimitive()) { + checkArgument(ctorParams[i] != null, "Primative param[" + i + "] in constructor " + parameterizedCtor + + " cannot be absent!"); + } + } + in.endObject(); + return newInstance(ctorParams); + } + + /** + * pass to delegate + */ + @Override + public void write(JsonWriter out, T value) throws IOException { + delegate.write(out, value); + } + + @SuppressWarnings("unchecked") + private T newInstance(Object[] ctorParams) throws AssertionError { + try { + return (T) parameterizedCtor.newInstance(ctorParams); + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) + throw RuntimeException.class.cast(e.getCause()); + throw new AssertionError(e); + } + } + } + + // logic borrowed from ReflectiveTypeAdapterFactory + static class ParameterReader { + final String name; + final int index; + final TypeAdapter typeAdapter; + + ParameterReader(String name, int index, TypeAdapter typeAdapter) { + this.name = name; + this.index = index; + this.typeAdapter = typeAdapter; + } + + public Object read(JsonReader reader) throws IOException { + return typeAdapter.read(reader); + } + } + + @SuppressWarnings("unchecked") + private Map getParameterReaders(Gson context, TypeToken declaring, Constructor constructor) { + Map result = new LinkedHashMap(); + + for (int index = 0; index < constructor.getGenericParameterTypes().length; index++) { + Type parameterType = getTypeOfConstructorParameter(declaring, constructor, index); + TypeAdapter adapter = context.getAdapter(TypeToken.get(parameterType)); + String parameterName = constructorFieldNamingPolicy.translateName(constructor, index); + checkArgument(parameterName != null, constructor + " parameter " + 0 + " failed to be named by " + constructorFieldNamingPolicy); + ParameterReader parameterReader = new ParameterReader(parameterName, index, adapter); + ParameterReader previous = result.put(parameterReader.name, parameterReader); + checkArgument(previous == null, constructor + " declares multiple JSON parameters named " + parameterReader.name); + } + + return result; + } + + private Type getTypeOfConstructorParameter(TypeToken declaring, Constructor constructor, int index) { + Type genericParameter = constructor.getGenericParameterTypes()[index]; + return $Gson$Types.resolve(declaring.getType(), declaring.getRawType(), genericParameter); + } +} diff --git a/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java b/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java new file mode 100644 index 0000000000..e3a3c3d55d --- /dev/null +++ b/core/src/main/java/org/jclouds/json/internal/NamingStrategies.java @@ -0,0 +1,226 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.json.internal; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; + +import javax.inject.Named; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.gson.FieldNamingStrategy; +import com.google.gson.annotations.SerializedName; + +/** + * NamingStrategies used for JSON deserialization using GSON + * + * @author Adrian Cole + * @author Adam Lowe + */ +public class NamingStrategies { + /** + * Specifies how to extract the name from an annotation for use in determining the serialized + * name. + * + * @see com.google.gson.annotations.SerializedName + * @see ExtractSerializedName + */ + public abstract static class NameExtractor { + protected final Class annotationType; + + protected NameExtractor(Class annotationType) { + this.annotationType = checkNotNull(annotationType, "annotationType"); + } + + public abstract String extractName(A in); + + public Class annotationType() { + return annotationType; + } + + @Override + public String toString() { + return "nameExtractor(" + annotationType.getSimpleName() + ")"; + } + + @Override + public int hashCode() { + return annotationType.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + return annotationType.equals(NameExtractor.class.cast(obj).annotationType); + } + } + + public static class ExtractSerializedName extends NameExtractor { + public ExtractSerializedName() { + super(SerializedName.class); + } + + @Override + public String extractName(SerializedName in) { + return checkNotNull(in, "input annotation").value(); + } + } + + public static class ExtractNamed extends NameExtractor { + public ExtractNamed() { + super(Named.class); + } + + @Override + public String extractName(Named in) { + return checkNotNull(in, "input annotation").value(); + } + } + + public static abstract class AnnotationBasedNamingStrategy { + protected final Map, ? extends NameExtractor> annotationToNameExtractor; + private String forToString; + + @SuppressWarnings("unchecked") + public AnnotationBasedNamingStrategy(Iterable extractors) { + checkNotNull(extractors, "means to extract names by annotations"); + + this.annotationToNameExtractor = Maps.uniqueIndex(extractors, new Function>() { + @Override + public Class apply(NameExtractor input) { + return input.annotationType(); + } + }); + this.forToString = Joiner.on(",").join(Iterables.transform(extractors, new Function() { + @Override + public String apply(NameExtractor input) { + return input.annotationType().getName(); + } + })); + } + + @Override + public String toString() { + return "AnnotationBasedNamingStrategy requiring one of " + forToString; + } + } + + /** + * Definition of field naming policy for annotation-based field + */ + public static class AnnotationFieldNamingStrategy extends AnnotationBasedNamingStrategy implements FieldNamingStrategy { + + public AnnotationFieldNamingStrategy(Iterable extractors) { + super(extractors); + checkArgument(extractors.iterator().hasNext(), "you must supply at least one name extractor, for example: " + + ExtractSerializedName.class.getSimpleName()); + } + + @SuppressWarnings("unchecked") + @Override + public String translateName(Field f) { + for (Annotation annotation : f.getAnnotations()) { + if (annotationToNameExtractor.containsKey(annotation.annotationType())) { + return annotationToNameExtractor.get(annotation.annotationType()).extractName(annotation); + } + } + return null; + } + } + + public static class AnnotationOrNameFieldNamingStrategy extends AnnotationFieldNamingStrategy implements FieldNamingStrategy { + public AnnotationOrNameFieldNamingStrategy(NameExtractor... extractors) { + this(ImmutableSet.copyOf(extractors)); + } + + public AnnotationOrNameFieldNamingStrategy(Iterable extractors) { + super(extractors); + } + + @Override + public String translateName(Field f) { + String result = super.translateName(f); + return result == null ? f.getName() : result; + } + } + + public static interface ConstructorFieldNamingStrategy { + public String translateName(Constructor c, int index); + + public Constructor getDeserializationConstructor(Class raw); + + } + + /** + * Determines field naming from constructor annotations + */ + public static class AnnotationConstructorNamingStrategy extends AnnotationBasedNamingStrategy implements ConstructorFieldNamingStrategy { + private final Set> markers; + + public AnnotationConstructorNamingStrategy(Iterable> markers, Iterable extractors) { + super(extractors); + this.markers = ImmutableSet.copyOf(checkNotNull(markers, "you must supply at least one annotation to mark deserialization constructors")); + } + + @SuppressWarnings("unchecked") + public Constructor getDeserializationConstructor(Class raw) { + for (Constructor ctor : raw.getDeclaredConstructors()) + for (Class deserializationCtorAnnotation : markers) + if (ctor.isAnnotationPresent(deserializationCtorAnnotation)) + return (Constructor) ctor; + + return null; + } + + @SuppressWarnings("unchecked") + @Override + public String translateName(Constructor c, int index) { + String name = null; + + if (markers.contains(ConstructorProperties.class) && c.getAnnotation(ConstructorProperties.class) != null) { + String[] names = c.getAnnotation(ConstructorProperties.class).value(); + if (names != null && names.length > index) { + name = names[index]; + } + } + + for (Annotation annotation : c.getParameterAnnotations()[index]) { + if (annotationToNameExtractor.containsKey(annotation.annotationType())) { + name = annotationToNameExtractor.get(annotation.annotationType()).extractName(annotation); + break; + } + } + return name; + } + } +} diff --git a/core/src/test/java/org/jclouds/collect/PaginatedSetsTest.java b/core/src/test/java/org/jclouds/collect/PaginatedSetsTest.java new file mode 100644 index 0000000000..e260c1f2c2 --- /dev/null +++ b/core/src/test/java/org/jclouds/collect/PaginatedSetsTest.java @@ -0,0 +1,76 @@ +package org.jclouds.collect; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; + +import org.easymock.EasyMock; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * Tests behavior of {@code PaginatedSets}. + * + * @author Adrian Cole + */ +@Test(testName = "PaginatedSetsTest") +public class PaginatedSetsTest { + + @SuppressWarnings("unchecked") + @Test + public void testSinglePageResultReturnsSame() { + + PaginatedSet initial = PaginatedSet.copyOf(ImmutableSet.of("foo", "bar")); + Function> markerToNext = createMock(Function.class); + + EasyMock.replay(markerToNext); + + Assert.assertSame(PaginatedSets.lazyContinue(initial, markerToNext), initial); + + EasyMock.verify(markerToNext); + } + + @SuppressWarnings("unchecked") + @Test + public void testMultiPage2Pages() { + + PaginatedSet initial = PaginatedSet.copyOfWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1"); + Function> markerToNext = createMock(Function.class); + + expect(markerToNext.apply("MARKER1")).andReturn( + PaginatedSet.copyOfWithMarker(ImmutableSet.of("boo", "baz"), null)); + + EasyMock.replay(markerToNext); + + Assert.assertEquals(ImmutableSet.copyOf(PaginatedSets.lazyContinue(initial, markerToNext)), ImmutableSet.of( + "foo", "bar", "boo", "baz")); + + EasyMock.verify(markerToNext); + + } + + @SuppressWarnings("unchecked") + @Test + public void testMultiPage3Pages() { + + PaginatedSet initial = PaginatedSet.copyOfWithMarker(ImmutableSet.of("foo", "bar"), "MARKER1"); + Function> markerToNext = createMock(Function.class); + + expect(markerToNext.apply("MARKER1")).andReturn( + PaginatedSet.copyOfWithMarker(ImmutableSet.of("boo", "baz"), "MARKER2")); + + expect(markerToNext.apply("MARKER2")).andReturn( + PaginatedSet.copyOfWithMarker(ImmutableSet.of("ham", "cheeze"), null)); + + EasyMock.replay(markerToNext); + + Assert.assertEquals(ImmutableSet.copyOf(PaginatedSets.lazyContinue(initial, markerToNext)), ImmutableSet.of( + "foo", "bar", "boo", "baz", "ham", "cheeze")); + + EasyMock.verify(markerToNext); + + } + +} diff --git a/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java b/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java new file mode 100644 index 0000000000..995474fe0f --- /dev/null +++ b/core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java @@ -0,0 +1,245 @@ +package org.jclouds.json.internal; +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; + +import java.beans.ConstructorProperties; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.json.internal.NamingStrategies.AnnotationOrNameFieldNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.ExtractNamed; +import org.jclouds.json.internal.NamingStrategies.ExtractSerializedName; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.gson.FieldNamingStrategy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.reflect.TypeToken; + +/** + * @author Adrian Cole + * @author Adam Lowe + */ +@Test(testName = "DeserializationConstructorTypeAdapterFactoryTest") +public final class DeserializationConstructorAndReflectiveTypeAdapterFactoryTest { + + Gson gson = new Gson(); + + DeserializationConstructorAndReflectiveTypeAdapterFactory parameterizedCtorFactory = parameterizedCtorFactory(); + + static DeserializationConstructorAndReflectiveTypeAdapterFactory parameterizedCtorFactory() { + FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy( + ImmutableSet.of(new ExtractSerializedName(), new ExtractNamed()) + ); + NamingStrategies.AnnotationConstructorNamingStrategy deserializationPolicy = + new NamingStrategies.AnnotationConstructorNamingStrategy( + ImmutableSet.of(ConstructorProperties.class, Inject.class), + ImmutableSet.of(new ExtractNamed())); + + return new DeserializationConstructorAndReflectiveTypeAdapterFactory(new ConstructorConstructor(), + serializationPolicy, Excluder.DEFAULT, deserializationPolicy); + } + + public void testNullWhenPrimitive() { + assertNull(parameterizedCtorFactory.create(gson, TypeToken.get(int.class))); + } + + private static class DefaultConstructor { + int foo; + int bar; + + private DefaultConstructor() { + } + + @Override + public boolean equals(Object obj) { + DefaultConstructor other = DefaultConstructor.class.cast(obj); + if (bar != other.bar) + return false; + if (foo != other.foo) + return false; + return true; + } + + } + + public void testRejectsIfNoConstuctorMarked() throws IOException { + TypeAdapter adapter = parameterizedCtorFactory.create(gson, TypeToken.get(DefaultConstructor.class)); + assertNull(adapter); + } + + private static class WithDeserializationConstructorButWithoutSerializedName { + final int foo; + + @Inject + WithDeserializationConstructorButWithoutSerializedName(int foo) { + this.foo = foo; + } + } + + public void testSerializedNameRequiredOnAllParameters() { + try { + parameterizedCtorFactory.create(gson, TypeToken + .get(WithDeserializationConstructorButWithoutSerializedName.class)); + fail(); + } catch (IllegalArgumentException actual) { + assertEquals(actual.getMessage(), + "org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactoryTest$WithDeserializationConstructorButWithoutSerializedName(int)" + + " parameter 0 failed to be named by AnnotationBasedNamingStrategy requiring one of javax.inject.Named"); + } + } + + private static class DuplicateSerializedNames { + final int foo; + final int bar; + + @Inject + DuplicateSerializedNames(@Named("foo") int foo, @Named("foo") int bar) { + this.foo = foo; + this.bar = bar; + } + } + + public void testNoDuplicateSerializedNamesRequiredOnAllParameters() { + try { + parameterizedCtorFactory.create(gson, TypeToken.get(DuplicateSerializedNames.class)); + fail(); + } catch (IllegalArgumentException actual) { + assertEquals(actual.getMessage(), + "org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactoryTest$DuplicateSerializedNames(int,int)" + + " declares multiple JSON parameters named foo"); + } + } + + private static class ValidatedConstructor { + final int foo; + final int bar; + + @Inject + ValidatedConstructor(@Named("foo") int foo, @Named("bar") int bar) { + if (foo < 0) + throw new IllegalArgumentException("negative!"); + this.foo = foo; + this.bar = bar; + } + + @Override + public boolean equals(Object obj) { + ValidatedConstructor other = ValidatedConstructor.class.cast(obj); + if (bar != other.bar) + return false; + if (foo != other.foo) + return false; + return true; + } + + } + + public void testValidatedConstructor() throws IOException { + TypeAdapter adapter = parameterizedCtorFactory.create(gson, TypeToken + .get(ValidatedConstructor.class)); + assertEquals(new ValidatedConstructor(0, 1), adapter.fromJson("{\"foo\":0,\"bar\":1}")); + try { + adapter.fromJson("{\"foo\":-1,\"bar\":1}"); + fail(); + } catch (IllegalArgumentException expected) { + assertEquals("negative!", expected.getMessage()); + } + } + + private static class GenericParamsCopiedIn { + final List foo; + final Map bar; + + @Inject + GenericParamsCopiedIn(@Named("foo") List foo, @Named("bar") Map bar) { + this.foo = new ArrayList(foo); + this.bar = new HashMap(bar); + } + + } + + public void testGenericParamsCopiedIn() throws IOException { + TypeAdapter adapter = parameterizedCtorFactory.create(gson, TypeToken + .get(GenericParamsCopiedIn.class)); + List inputFoo = new ArrayList(); + inputFoo.add("one"); + HashMap inputBar = new HashMap(); + inputBar.put("2", "two"); + + GenericParamsCopiedIn toTest = adapter.fromJson("{ \"foo\":[\"one\"], \"bar\":{ \"2\":\"two\"}}"); + assertEquals(inputFoo, toTest.foo); + assertNotSame(inputFoo, toTest.foo); + assertEquals(inputBar, toTest.bar); + + } + + private static class RenamedFields { + final int foo; + @Named("_bar") + final int bar; + + @ConstructorProperties({"foo", "_bar"}) + RenamedFields(int foo, int bar) { + if (foo < 0) + throw new IllegalArgumentException("negative!"); + this.foo = foo; + this.bar = bar; + } + + @Override + public boolean equals(Object obj) { + RenamedFields other = RenamedFields.class.cast(obj); + if (bar != other.bar) + return false; + if (foo != other.foo) + return false; + return true; + } + + } + + public void testRenamedFields() throws IOException { + TypeAdapter adapter = parameterizedCtorFactory.create(gson, TypeToken.get(RenamedFields.class)); + assertEquals(new RenamedFields(0, 1), adapter.fromJson("{\"foo\":0,\"_bar\":1}")); + assertEquals(adapter.toJson(new RenamedFields(0, 1)), "{\"foo\":0,\"_bar\":1}"); + } + + public void testCanOverrideDefault() throws IOException { + Gson gson = new GsonBuilder().registerTypeAdapterFactory(parameterizedCtorFactory).create(); + + assertEquals(new RenamedFields(0, 1), gson.fromJson("{\"foo\":0,\"_bar\":1}", RenamedFields.class)); + assertEquals(gson.toJson(new RenamedFields(0, 1)), "{\"foo\":0,\"_bar\":1}"); + } +} diff --git a/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java b/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java new file mode 100644 index 0000000000..1397775bef --- /dev/null +++ b/core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java @@ -0,0 +1,203 @@ +package org.jclouds.json.internal; +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.fail; + +import java.beans.ConstructorProperties; +import java.lang.reflect.Constructor; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.json.internal.NamingStrategies.AnnotationConstructorNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.AnnotationFieldNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.AnnotationOrNameFieldNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.ConstructorFieldNamingStrategy; +import org.jclouds.json.internal.NamingStrategies.ExtractNamed; +import org.jclouds.json.internal.NamingStrategies.ExtractSerializedName; +import org.jclouds.json.internal.NamingStrategies.NameExtractor; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.gson.FieldNamingStrategy; +import com.google.gson.annotations.SerializedName; + +/** + * @author Adam Lowe + */ +@Test(testName = "NamingStrategiesTest") +public final class NamingStrategiesTest { + + private static class SimpleTest { + @SerializedName("aardvark") + private String a; + private String b; + @Named("cat") + private String c; + @Named("dog") + private String d; + + @ConstructorProperties({"aardvark", "bat", "coyote", "dog"}) + private SimpleTest(String aa, String bb, String cc, @Named("dingo") String dd) { + } + + @Inject + private SimpleTest(@Named("aa") String aa, @Named("bb") String bb, @Named("cc") String cc, @Named("dd") String dd, boolean nothing) { + } + } + + private static class MixedConstructorTest { + @Inject + @ConstructorProperties("thiscanbeoverriddenbyNamed") + private MixedConstructorTest(@Named("aardvark") String aa, @Named("bat") String bb, @Named("cat") String cc, @Named("dog") String dd) { + } + } + + + public void testExtractSerializedName() throws Exception { + NameExtractor extractor = new ExtractSerializedName(); + assertEquals(extractor.extractName(SimpleTest.class.getDeclaredField("a").getAnnotation(SerializedName.class)), + "aardvark"); + try { + extractor.extractName(SimpleTest.class.getDeclaredField("b").getAnnotation(SerializedName.class)); + fail(); + } catch (NullPointerException e) { + } + try { + extractor.extractName(SimpleTest.class.getDeclaredField("c").getAnnotation(SerializedName.class)); + fail(); + } catch (NullPointerException e) { + } + try { + extractor.extractName(SimpleTest.class.getDeclaredField("d").getAnnotation(SerializedName.class)); + fail(); + } catch (NullPointerException e) { + } + } + + public void testExtractNamed() throws Exception { + NameExtractor extractor = new ExtractNamed(); + try { + extractor.extractName(SimpleTest.class.getDeclaredField("a").getAnnotation(Named.class)); + } catch (NullPointerException e) { + } + try { + extractor.extractName(SimpleTest.class.getDeclaredField("b").getAnnotation(Named.class)); + fail(); + } catch (NullPointerException e) { + } + assertEquals(extractor.extractName(SimpleTest.class.getDeclaredField("c").getAnnotation(Named.class)), + "cat"); + assertEquals(extractor.extractName(SimpleTest.class.getDeclaredField("d").getAnnotation(Named.class)), + "dog"); + } + + public void testAnnotationFieldNamingStrategy() throws Exception { + FieldNamingStrategy strategy = new AnnotationFieldNamingStrategy(ImmutableSet.of(new ExtractNamed())); + + assertNull(strategy.translateName(SimpleTest.class.getDeclaredField("a"))); + assertNull(strategy.translateName(SimpleTest.class.getDeclaredField("b"))); + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("c")), "cat"); + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("d")), "dog"); + } + + public void testAnnotationOrNameFieldNamingStrategy() throws Exception { + FieldNamingStrategy strategy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(new ExtractNamed())); + + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("a")), "a"); + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("b")), "b"); + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("c")), "cat"); + assertEquals(strategy.translateName(SimpleTest.class.getDeclaredField("d")), "dog"); + } + + public void testAnnotationConstructorFieldNamingStrategyCPAndNamed() throws Exception { + ConstructorFieldNamingStrategy strategy = new AnnotationConstructorNamingStrategy( + ImmutableSet.of(ConstructorProperties.class), ImmutableSet.of(new ExtractNamed())); + + Constructor constructor = strategy.getDeserializationConstructor(SimpleTest.class); + assertNotNull(constructor); + assertEquals(constructor.getParameterTypes().length, 4); + + assertEquals(strategy.translateName(constructor, 0), "aardvark"); + assertEquals(strategy.translateName(constructor, 1), "bat"); + assertEquals(strategy.translateName(constructor, 2), "coyote"); + // Note: @Named overrides the ConstructorProperties setting + assertEquals(strategy.translateName(constructor, 3), "dingo"); + + Constructor mixedCtor = strategy.getDeserializationConstructor(MixedConstructorTest.class); + assertNotNull(mixedCtor); + assertEquals(mixedCtor.getParameterTypes().length, 4); + + assertEquals(strategy.translateName(mixedCtor, 0), "aardvark"); + assertEquals(strategy.translateName(mixedCtor, 1), "bat"); + assertEquals(strategy.translateName(mixedCtor, 2), "cat"); + assertEquals(strategy.translateName(mixedCtor, 3), "dog"); + } + + public void testAnnotationConstructorFieldNamingStrategyCP() throws Exception { + ConstructorFieldNamingStrategy strategy = new AnnotationConstructorNamingStrategy( + ImmutableSet.of(ConstructorProperties.class), ImmutableSet.of()); + + Constructor constructor = strategy.getDeserializationConstructor(SimpleTest.class); + assertNotNull(constructor); + assertEquals(constructor.getParameterTypes().length, 4); + + assertEquals(strategy.translateName(constructor, 0), "aardvark"); + assertEquals(strategy.translateName(constructor, 1), "bat"); + assertEquals(strategy.translateName(constructor, 2), "coyote"); + assertEquals(strategy.translateName(constructor, 3), "dog"); + + Constructor mixedCtor = strategy.getDeserializationConstructor(MixedConstructorTest.class); + assertNotNull(mixedCtor); + assertEquals(mixedCtor.getParameterTypes().length, 4); + + assertEquals(strategy.translateName(mixedCtor, 0), "thiscanbeoverriddenbyNamed"); + assertNull(strategy.translateName(mixedCtor, 1)); + assertNull(strategy.translateName(mixedCtor, 2)); + assertNull(strategy.translateName(mixedCtor, 3)); + } + + public void testAnnotationConstructorFieldNamingStrategyInject() throws Exception { + ConstructorFieldNamingStrategy strategy = new AnnotationConstructorNamingStrategy( + ImmutableSet.of(Inject.class), ImmutableSet.of(new ExtractNamed())); + + Constructor constructor = strategy.getDeserializationConstructor(SimpleTest.class); + assertNotNull(constructor); + assertEquals(constructor.getParameterTypes().length, 5); + + assertEquals(strategy.translateName(constructor, 0), "aa"); + assertEquals(strategy.translateName(constructor, 1), "bb"); + assertEquals(strategy.translateName(constructor, 2), "cc"); + assertEquals(strategy.translateName(constructor, 3), "dd"); + + Constructor mixedCtor = strategy.getDeserializationConstructor(MixedConstructorTest.class); + assertNotNull(mixedCtor); + assertEquals(mixedCtor.getParameterTypes().length, 4); + + assertEquals(strategy.translateName(mixedCtor, 0), "aardvark"); + assertEquals(strategy.translateName(mixedCtor, 1), "bat"); + assertEquals(strategy.translateName(mixedCtor, 2), "cat"); + assertEquals(strategy.translateName(mixedCtor, 3), "dog"); + } + +} diff --git a/drivers/sshj/pom.xml b/drivers/sshj/pom.xml index e76230570f..46faacc3df 100644 --- a/drivers/sshj/pom.xml +++ b/drivers/sshj/pom.xml @@ -52,7 +52,7 @@ org.jclouds.sshj*;version="${project.version}" - org.jclouds*;version="${project.version}",* + org.jclouds*;version="${project.version}",org.apache.commons.io.input;version="[1.4,3)",* @@ -97,7 +97,7 @@ commons-io commons-io - 1.4 + 2.0 diff --git a/labs/aws-iam/pom.xml b/labs/aws-iam/pom.xml new file mode 100644 index 0000000000..fc9f282bc5 --- /dev/null +++ b/labs/aws-iam/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + aws-iam + jclouds Amazon Identity and Access Management (IAM) provider + Identity and Access Management (IAM) to Amazon Web Services + bundle + + + https://iam.amazonaws.com + 2010-05-08 + + ${test.aws.identity} + ${test.aws.credential} + + org.jclouds.aws.iam*;version="${project.version}" + org.jclouds*;version="${project.version}",* + + + + + org.jclouds.labs + iam + ${project.version} + jar + + + org.jclouds.labs + iam + ${project.version} + test-jar + test + + + org.jclouds + jclouds-core + ${project.version} + test-jar + test + + + org.jclouds.driver + jclouds-log4j + ${project.version} + test + + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + ${test.aws-iam.endpoint} + ${test.aws-iam.api-version} + ${test.aws-iam.build-version} + ${test.aws-iam.identity} + ${test.aws-iam.credential} + + + + + + + + + + + diff --git a/labs/aws-iam/src/main/java/org/jclouds/aws/iam/AWSIAMProviderMetadata.java b/labs/aws-iam/src/main/java/org/jclouds/aws/iam/AWSIAMProviderMetadata.java new file mode 100644 index 0000000000..8ed144436e --- /dev/null +++ b/labs/aws-iam/src/main/java/org/jclouds/aws/iam/AWSIAMProviderMetadata.java @@ -0,0 +1,87 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.aws.iam; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.iam.IAMApiMetadata; +import org.jclouds.providers.ProviderMetadata; +import org.jclouds.providers.internal.BaseProviderMetadata; + +/** + * Implementation of @ link org.jclouds.types.ProviderMetadata} for Amazon's IAM + * provider. +* +* @author Adrian Cole +*/ +public class AWSIAMProviderMetadata extends BaseProviderMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 2394954723306943404L; + + public static Builder builder() { + return new Builder(); + } + + @Override + public Builder toBuilder() { + return builder().fromProviderMetadata(this); + } + + public AWSIAMProviderMetadata() { + super(builder()); + } + + public AWSIAMProviderMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = new Properties(); + return properties; + } + + public static class Builder extends BaseProviderMetadata.Builder { + + protected Builder(){ + id("aws-iam") + .name("Amazon IAM") + .endpoint("https://iam.amazonaws.com") + .homepage(URI.create("http://aws.amazon.com/iam")) + .console(URI.create("https://console.aws.amazon.com/iam/home")) + .linkedServices("aws-ec2","aws-elb", "aws-cloudwatch", "aws-s3", "aws-simpledb") + .iso3166Codes("US-VA", "US-CA", "BR-SP", "US-OR", "IE", "SG", "JP-13") + .apiMetadata(new IAMApiMetadata()) + .defaultProperties(AWSIAMProviderMetadata.defaultProperties()); + } + + @Override + public AWSIAMProviderMetadata build() { + return new AWSIAMProviderMetadata(this); + } + + @Override + public Builder fromProviderMetadata(ProviderMetadata in) { + super.fromProviderMetadata(in); + return this; + } + + } +} \ No newline at end of file diff --git a/labs/aws-iam/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/aws-iam/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata new file mode 100644 index 0000000000..9f5ac036a9 --- /dev/null +++ b/labs/aws-iam/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata @@ -0,0 +1 @@ +org.jclouds.aws.iam.AWSIAMProviderMetadata diff --git a/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMClientLiveTest.java b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMClientLiveTest.java new file mode 100644 index 0000000000..c31f58f6e5 --- /dev/null +++ b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMClientLiveTest.java @@ -0,0 +1,35 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.aws.iam; + +import org.jclouds.iam.IAMClientLiveTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code IAMClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", singleThreaded = true, testName = "AWSIAMClientLiveTest") +public class AWSIAMClientLiveTest extends IAMClientLiveTest { + public AWSIAMClientLiveTest() { + provider = "aws-iam"; + } + +} diff --git a/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMProviderTest.java b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMProviderTest.java new file mode 100644 index 0000000000..577a23e9d5 --- /dev/null +++ b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMProviderTest.java @@ -0,0 +1,37 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.aws.iam; + +import org.jclouds.aws.iam.AWSIAMProviderMetadata; +import org.jclouds.iam.IAMApiMetadata; +import org.jclouds.providers.internal.BaseProviderMetadataTest; +import org.testng.annotations.Test; + +/** + * The AWSIAMProviderTest tests the org.jclouds.providers.AWSIAMProvider class. + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "AWSIAMProviderTest") +public class AWSIAMProviderTest extends BaseProviderMetadataTest { + + public AWSIAMProviderTest() { + super(new AWSIAMProviderMetadata(), new IAMApiMetadata()); + } +} diff --git a/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSUserClientLiveTest.java b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSUserClientLiveTest.java new file mode 100644 index 0000000000..d298f7b012 --- /dev/null +++ b/labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSUserClientLiveTest.java @@ -0,0 +1,32 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.aws.iam.features; + +import org.jclouds.iam.features.UserClientLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "AWSUserClientLiveTest") +public class AWSUserClientLiveTest extends UserClientLiveTest { + public AWSUserClientLiveTest() { + provider = "aws-iam"; + } +} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/config/GleSYSParserModule.java b/labs/glesys/src/main/java/org/jclouds/glesys/config/GleSYSParserModule.java index ea77989090..e429296ef5 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/config/GleSYSParserModule.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/config/GleSYSParserModule.java @@ -23,9 +23,10 @@ import java.util.Map; import javax.inject.Singleton; +import org.jclouds.glesys.domain.GleSYSBoolean; import org.jclouds.glesys.domain.Server; import org.jclouds.glesys.functions.internal.GleSYSTypeAdapters; -import org.jclouds.glesys.functions.internal.GlesysDateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.json.config.GsonModule.DateAdapter; import com.google.common.collect.ImmutableMap; @@ -34,18 +35,20 @@ import com.google.inject.Provides; /** * @author Adrian Cole + * @author Adam Lowe */ public class GleSYSParserModule extends AbstractModule { @Provides @Singleton public Map provideCustomAdapterBindings() { - return ImmutableMap. of(Server.State.class, new GleSYSTypeAdapters.ServerStateAdapter()); + return ImmutableMap.of(Server.State.class, new GleSYSTypeAdapters.ServerStateAdapter(), + GleSYSBoolean.class, new GleSYSTypeAdapters.GleSYSBooleanAdapter()); } @Override protected void configure() { - bind(DateAdapter.class).to(GlesysDateAdapter.class); + bind(DateAdapter.class).to(Iso8601DateAdapter.class); } } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/AllowedArgumentsForCreateServer.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/AllowedArgumentsForCreateServer.java index 8769902833..8c17e9babc 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/AllowedArgumentsForCreateServer.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/AllowedArgumentsForCreateServer.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,12 +20,12 @@ package org.jclouds.glesys.domain; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; import java.util.Set; -import com.google.common.base.Joiner; import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; import com.google.common.collect.ImmutableSet; -import com.google.gson.annotations.SerializedName; /** * Sets the allowed arguments for some of the functions in this module such as disksize, cpucores etc. @@ -34,79 +34,104 @@ import com.google.gson.annotations.SerializedName; * @see */ public class AllowedArgumentsForCreateServer { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private Set diskSizes; - private Set memorySizes; - private Set cpuCores; - private Set templates; - private Set transfers; - private Set dataCenters; + public Builder toBuilder() { + return new ConcreteBuilder().fromAllowedArgumentsForCreateServer(this); + } - public Builder diskSizes(Integer... sizes) { - return diskSizes(ImmutableSet.copyOf(sizes)); + public static abstract class Builder> { + protected abstract T self(); + + protected Set diskSizes = ImmutableSet.of(); + protected Set memorySizes = ImmutableSet.of(); + protected Set cpuCores = ImmutableSet.of(); + protected Set templates = ImmutableSet.of(); + protected Set transfers = ImmutableSet.of(); + protected Set dataCenters = ImmutableSet.of(); + + /** + * @see AllowedArgumentsForCreateServer#getDiskSizesInGB() + */ + public T diskSizes(Set diskSizes) { + this.diskSizes = ImmutableSet.copyOf(checkNotNull(diskSizes, "diskSizesInGB")); + return self(); } - public Builder diskSizes(Set sizes) { - this.diskSizes = sizes; - return this; + public T diskSizes(Integer... in) { + return diskSizes(ImmutableSet.copyOf(in)); } - public Builder memorySizes(Integer... sizes) { - return memorySizes(ImmutableSet.copyOf(sizes)); + /** + * @see AllowedArgumentsForCreateServer#getMemorySizesInMB() + */ + public T memorySizes(Set memorySizes) { + this.memorySizes = ImmutableSet.copyOf(checkNotNull(memorySizes, "memorySizesInMB")); + return self(); } - public Builder memorySizes(Set sizes) { - this.memorySizes = sizes; - return this; + public T memorySizes(Integer... in) { + return memorySizes(ImmutableSet.copyOf(in)); } - public Builder cpuCores(Integer... cpuCores) { - this.cpuCores = ImmutableSet.copyOf(cpuCores); - return this; + /** + * @see AllowedArgumentsForCreateServer#getCpuCoreOptions() + */ + public T cpuCores(Set cpuCores) { + this.cpuCores = ImmutableSet.copyOf(checkNotNull(cpuCores, "cpuCoreOptions")); + return self(); } - public Builder cpuCores(Set cpuCores) { - this.cpuCores = cpuCores; - return this; + public T cpuCores(Integer... in) { + return cpuCores(ImmutableSet.copyOf(in)); } - public Builder templates(String... templates) { - return templates(ImmutableSet.copyOf(templates)); + /** + * @see AllowedArgumentsForCreateServer#getTemplateNames() + */ + public T templates(Set templates) { + this.templates = ImmutableSet.copyOf(checkNotNull(templates, "templateNames")); + return self(); } - public Builder templates(Set templates) { - this.templates = templates; - return this; + public T templates(String... in) { + return templates(ImmutableSet.copyOf(in)); } - public Builder transfers(Integer... transfers) { - return transfers(ImmutableSet.copyOf(transfers)); + /** + * @see AllowedArgumentsForCreateServer#getTransfersInGB() + */ + public T transfers(Set transfers) { + this.transfers = ImmutableSet.copyOf(checkNotNull(transfers, "transfersInGB")); + return self(); } - public Builder transfers(Set transfers) { - this.transfers = transfers; - return this; + public T transfers(Integer... in) { + return transfers(ImmutableSet.copyOf(in)); } - public Builder dataCenters(String... dataCenters) { - return dataCenters(ImmutableSet.copyOf(dataCenters)); + /** + * @see AllowedArgumentsForCreateServer#getDataCenters() + */ + public T dataCenters(Set dataCenters) { + this.dataCenters = ImmutableSet.copyOf(checkNotNull(dataCenters, "dataCenters")); + return self(); } - public Builder dataCenters(Set dataCenters) { - this.dataCenters = dataCenters; - return this; + public T dataCenters(String... in) { + return dataCenters(ImmutableSet.copyOf(in)); } public AllowedArgumentsForCreateServer build() { return new AllowedArgumentsForCreateServer(diskSizes, memorySizes, cpuCores, templates, transfers, dataCenters); } - public Builder fromAllowedArguments(AllowedArgumentsForCreateServer in) { - return diskSizes(in.getDiskSizesInGB()) + public T fromAllowedArgumentsForCreateServer(AllowedArgumentsForCreateServer in) { + return this + .diskSizes(in.getDiskSizesInGB()) .memorySizes(in.getMemorySizesInMB()) .cpuCores(in.getCpuCoreOptions()) .templates(in.getTemplateNames()) @@ -115,34 +140,30 @@ public class AllowedArgumentsForCreateServer { } } - @SerializedName("disksize") - private final Set diskSizes; - @SerializedName("memorysize") - private final Set memorySizes; - @SerializedName("cpucores") - private final Set cpuCores; - @SerializedName("template") - private final Set templates; - @SerializedName("transfer") - private final Set transfers; - @SerializedName("datacenter") + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final Set diskSizesInGB; + private final Set memorySizesInMB; + private final Set cpuCoreOptions; + private final Set templateNames; + private final Set transfersInGB; private final Set dataCenters; - public AllowedArgumentsForCreateServer(Set diskSizes, Set memorySizes, Set cpuCores, - Set templates, Set transfers, Set dataCenters) { - checkNotNull(diskSizes, "diskSizes"); - checkNotNull(memorySizes, "memorySizes"); - checkNotNull(cpuCores, "cpuCores"); - checkNotNull(templates, "templates"); - checkNotNull(transfers, "transfers"); - checkNotNull(dataCenters, "dataCenters"); - - this.diskSizes = diskSizes; - this.memorySizes = memorySizes; - this.cpuCores = cpuCores; - this.templates = templates; - this.transfers = transfers; - this.dataCenters = dataCenters; + @ConstructorProperties({ + "disksize", "memorysize", "cpucores", "template", "transfer", "datacenter" + }) + protected AllowedArgumentsForCreateServer(Set diskSizesInGB, Set memorySizesInMB, Set cpuCoreOptions, Set templateNames, Set transfersInGB, Set dataCenters) { + this.diskSizesInGB = ImmutableSet.copyOf(checkNotNull(diskSizesInGB, "diskSizesInGB")); + this.memorySizesInMB = ImmutableSet.copyOf(checkNotNull(memorySizesInMB, "memorySizesInMB")); + this.cpuCoreOptions = ImmutableSet.copyOf(checkNotNull(cpuCoreOptions, "cpuCoreOptions")); + this.templateNames = ImmutableSet.copyOf(checkNotNull(templateNames, "templateNames")); + this.transfersInGB = ImmutableSet.copyOf(checkNotNull(transfersInGB, "transfersInGB")); + this.dataCenters = ImmutableSet.copyOf(checkNotNull(dataCenters, "dataCenters")); } /** @@ -150,82 +171,73 @@ public class AllowedArgumentsForCreateServer { * @see org.jclouds.glesys.domain.OSTemplate#getMinDiskSize() */ public Set getDiskSizesInGB() { - return diskSizes; + return this.diskSizesInGB; } /** * @return a list of memory sizes, in MB, that can be used for creating servers on this platform - * @see org.jclouds.glesys.domain.OSTemplate#getMinMemSize() + * @see org.jclouds.glesys.domain.OSTemplate#getMinMemSize() */ public Set getMemorySizesInMB() { - return memorySizes; + return this.memorySizesInMB; } /** * @return a list of which core counts can be used for creating servers on this platform */ public Set getCpuCoreOptions() { - return cpuCores; + return this.cpuCoreOptions; } /** * @return a list of template names available for creating servers on this platform - * @see org.jclouds.glesys.domain.OSTemplate#getName() + * @see org.jclouds.glesys.domain.OSTemplate#getName() */ public Set getTemplateNames() { - return templates; + return this.templateNames; } /** * @return the list of transfer settings available for creating servers on this platform */ public Set getTransfersInGB() { - return transfers; + return this.transfersInGB; } /** * @return the list of datacenters available that support creating servers on this platform */ public Set getDataCenters() { - return dataCenters; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof AllowedArgumentsForCreateServer) { - final AllowedArgumentsForCreateServer other = (AllowedArgumentsForCreateServer) object; - return Objects.equal(diskSizes, other.diskSizes) - && Objects.equal(memorySizes, other.memorySizes) - && Objects.equal(cpuCores, other.cpuCores) - && Objects.equal(templates, other.templates) - && Objects.equal(transfers, other.transfers) - && Objects.equal(dataCenters, other.dataCenters); - } else { - return false; - } + return this.dataCenters; } @Override public int hashCode() { - return Objects.hashCode(diskSizes, memorySizes, cpuCores, templates, transfers, dataCenters); + return Objects.hashCode(diskSizesInGB, memorySizesInMB, cpuCoreOptions, templateNames, transfersInGB, dataCenters); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + AllowedArgumentsForCreateServer that = AllowedArgumentsForCreateServer.class.cast(obj); + return Objects.equal(this.diskSizesInGB, that.diskSizesInGB) + && Objects.equal(this.memorySizesInMB, that.memorySizesInMB) + && Objects.equal(this.cpuCoreOptions, that.cpuCoreOptions) + && Objects.equal(this.templateNames, that.templateNames) + && Objects.equal(this.transfersInGB, that.transfersInGB) + && Objects.equal(this.dataCenters, that.dataCenters); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("diskSizesInGB", diskSizesInGB).add("memorySizesInMB", memorySizesInMB) + .add("cpuCoreOptions", cpuCoreOptions).add("templateNames", templateNames) + .add("transfersInGB", transfersInGB).add("dataCenters", dataCenters); } @Override public String toString() { - checkNotNull(diskSizes, "diskSizes"); - checkNotNull(memorySizes, "memorySizes"); - checkNotNull(cpuCores, "cpuCores"); - checkNotNull(templates, "templates"); - checkNotNull(transfers, "transfers"); - checkNotNull(dataCenters, "dataCenters"); - - Joiner commaJoiner = Joiner.on(", "); - return String.format("[disksize=[%s], memorysize=[%s], cpuCores=[%s], templates=[%s], transfers=[%s], datacenters=[%s]]", - commaJoiner.join(diskSizes), commaJoiner.join(memorySizes), commaJoiner.join(cpuCores), commaJoiner.join(templates), - commaJoiner.join(transfers), commaJoiner.join(dataCenters)); + return string().toString(); } -} +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Archive.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Archive.java index cfbb059b87..a3cf7ed83d 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Archive.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Archive.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,8 +18,12 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Information about an archive @@ -27,102 +31,143 @@ import com.google.gson.annotations.SerializedName; * @author Adam Lowe * @see */ -public class Archive implements Comparable { - public static Builder builder() { - return new Builder(); +public class Archive { + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { + public Builder toBuilder() { + return new ConcreteBuilder().fromArchive(this); + } + + public static abstract class Builder> { + protected abstract T self(); + protected String username; protected String totalSize; protected String freeSize; protected boolean locked; - public Builder username(String username) { - this.username = username; - return this; + /** + * @see Archive#getUsername() + */ + public T username(String username) { + this.username = checkNotNull(username, "username"); + return self(); } - public Builder totalSize(String totalSize) { - this.totalSize = totalSize; - return this; + /** + * @see Archive#getTotalSize() + */ + public T totalSize(String totalSize) { + this.totalSize = checkNotNull(totalSize, "totalSize"); + return self(); } - public Builder freeSize(String freeSize) { - this.freeSize = freeSize; - return this; + /** + * @see Archive#getFreeSize() + */ + public T freeSize(String freeSize) { + this.freeSize = checkNotNull(freeSize, "freeSize"); + return self(); } - public Builder locked(boolean locked) { + /** + * @see Archive#isLocked() + */ + public T locked(boolean locked) { this.locked = locked; - return this; + return self(); } public Archive build() { - return new Archive(username, totalSize, freeSize, locked); + return new Archive(username, totalSize, freeSize, new GleSYSBoolean(locked)); } - public Builder fromArchive(Archive in) { - return username(in.getUsername()).totalSize(in.getTotalSize()).freeSize(in.getFreeSize()).locked(in.isLocked()); + public T fromArchive(Archive in) { + return this + .username(in.getUsername()) + .totalSize(in.getTotalSize()) + .freeSize(in.getFreeSize()) + .locked(in.isLocked()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } private final String username; - @SerializedName("size_total") private final String totalSize; - @SerializedName("size_free") private final String freeSize; private final boolean locked; - /** @return the name (username) of the archive */ + @ConstructorProperties({ + "username", "sizetotal", "sizefree", "locked" + }) + protected Archive(String username, String totalSize, String freeSize, GleSYSBoolean locked) { + this.username = checkNotNull(username, "username"); + this.totalSize = checkNotNull(totalSize, "totalSize"); + this.freeSize = checkNotNull(freeSize, "freeSize"); + this.locked = checkNotNull(locked, "locked").getValue(); + } + + /** + * @return the name (username) of the archive + */ public String getUsername() { - return username; + return this.username; } - /** @return the total size of the archive, ex. "10 GB" */ + /** + * @return the total size of the archive, ex. "10 GB" + */ public String getTotalSize() { - return totalSize; + return this.totalSize; } - /** @return the free space left of the archive */ + /** + * @return the free space left of the archive + */ public String getFreeSize() { - return freeSize; + return this.freeSize; } - /** @return true if the archive is locked */ + /** + * @return true if the archive is locked + */ public boolean isLocked() { - return locked; - } - - public Archive(String username, String totalSize, String freeSize, boolean locked) { - this.username = username; - this.totalSize = totalSize; - this.freeSize = freeSize; - this.locked = locked; + return this.locked; } @Override public int hashCode() { - return Objects.hashCode(username); + return Objects.hashCode(username, totalSize, freeSize, locked); } - @Override - public int compareTo(Archive other) { - return username.compareTo(other.getUsername()); - } - @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - return obj instanceof Archive - && Objects.equal(username, ((Archive) obj).username); + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Archive that = Archive.class.cast(obj); + return Objects.equal(this.username, that.username) + && Objects.equal(this.totalSize, that.totalSize) + && Objects.equal(this.freeSize, that.freeSize) + && Objects.equal(this.locked, that.locked); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("username", username).add("totalSize", totalSize).add("freeSize", freeSize).add("locked", locked); } @Override public String toString() { - return String.format("[username=%s, totalSize=%s, freeSize=%s, locked=%b]", username, totalSize, freeSize, locked); + return string().toString(); } -} +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveAllowedArguments.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveAllowedArguments.java index 8cdb47bdde..15a0150484 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveAllowedArguments.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveAllowedArguments.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,14 +18,14 @@ */ package org.jclouds.glesys.domain; -import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; -import java.util.Arrays; +import java.beans.ConstructorProperties; import java.util.List; -import com.google.common.base.Joiner; import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableList; /** * The allowed arguments for archive manipulation, such as archivesize @@ -34,53 +34,62 @@ import com.google.gson.annotations.SerializedName; * @see */ public class ArchiveAllowedArguments { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private List archiveSizes; + public Builder toBuilder() { + return new ConcreteBuilder().fromArchiveAllowedArguments(this); + } - public Builder archiveSizes(List archiveSizes) { - this.archiveSizes = archiveSizes; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected List archiveSizes = ImmutableList.of(); + + /** + * @see ArchiveAllowedArguments#getArchiveSizes() + */ + public T archiveSizes(List archiveSizes) { + this.archiveSizes = ImmutableList.copyOf(checkNotNull(archiveSizes, "archiveSizes")); + return self(); } - public Builder archiveSizes(Integer... archiveSizes) { - return archiveSizes(Arrays.asList(archiveSizes)); + public T archiveSizes(Integer... in) { + return archiveSizes(ImmutableList.copyOf(in)); } public ArchiveAllowedArguments build() { return new ArchiveAllowedArguments(archiveSizes); } - - public Builder fromArchiveAllowedArguments(ArchiveAllowedArguments in) { - return archiveSizes(in.getArchiveSizes()); + + public T fromArchiveAllowedArguments(ArchiveAllowedArguments in) { + return this.archiveSizes(in.getArchiveSizes()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } - @SerializedName("archivesize") private final List archiveSizes; - public ArchiveAllowedArguments(List archiveSizes) { - checkArgument(archiveSizes != null, "archiveSizes"); - this.archiveSizes = archiveSizes; + @ConstructorProperties({ + "archivesize" + }) + protected ArchiveAllowedArguments(List archiveSizes) { + this.archiveSizes = ImmutableList.copyOf(checkNotNull(archiveSizes, "archiveSizes")); } /** * @return the list of allowed archive sizes, in GB */ public List getArchiveSizes() { - return archiveSizes; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - return object instanceof ArchiveAllowedArguments - && Objects.equal(archiveSizes, ((ArchiveAllowedArguments) object).archiveSizes); + return this.archiveSizes; } @Override @@ -89,10 +98,21 @@ public class ArchiveAllowedArguments { } @Override - public String toString() { - Joiner commaJoiner = Joiner.on(", "); - return String.format( - "[archiveSizes=[%s]]", commaJoiner.join(archiveSizes)); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ArchiveAllowedArguments that = ArchiveAllowedArguments.class.cast(obj); + return Objects.equal(this.archiveSizes, that.archiveSizes); } -} + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("archiveSizes", archiveSizes); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveDetails.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveDetails.java deleted file mode 100644 index c3530a7318..0000000000 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveDetails.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.jclouds.glesys.domain; - -/** - * Detailed information about an archive volume. - * - * @author Adam Lowe - * @see - */ -public class ArchiveDetails extends Archive { - public static Builder builder() { - return new Builder(); - } - - public static class Builder extends Archive.Builder { - public ArchiveDetails build() { - return new ArchiveDetails(username, totalSize, freeSize, locked); - } - - public Builder fromArchiveDetails(ArchiveDetails in) { - return username(in.getUsername()).totalSize(in.getTotalSize()).freeSize(in.getFreeSize()).locked(in.isLocked()); - } - - @Override - public Builder username(String username) { - return Builder.class.cast(super.username(username)); - } - - @Override - public Builder totalSize(String size) { - return Builder.class.cast(super.totalSize(size)); - } - - @Override - public Builder freeSize(String size) { - return Builder.class.cast(super.freeSize(size)); - } - - @Override - public Builder locked(boolean locked) { - return Builder.class.cast(super.locked(locked)); - } - } - - public ArchiveDetails(String username, String totalSize, String freeSize, boolean locked) { - super(username, totalSize, freeSize, locked); - } -} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Console.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Console.java index ddcddf856d..851abc337d 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Console.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Console.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +18,12 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Connection information to connect to a server with VNC. @@ -27,44 +32,69 @@ import com.google.common.base.Objects; * @see */ public class Console { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String host; - private int port; - private String protocol; - private String password; + public Builder toBuilder() { + return new ConcreteBuilder().fromConsole(this); + } - public Builder host(String host) { - this.host = host; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String host; + protected int port; + protected String protocol; + protected String password; + + /** + * @see Console#getHost() + */ + public T host(String host) { + this.host = checkNotNull(host, "host"); + return self(); } - public Builder port(int port) { + /** + * @see Console#getPort() + */ + public T port(int port) { this.port = port; - return this; + return self(); } - public Builder password(String password) { - this.password = password; - return this; + /** + * @see Console#getProtocol() + */ + public T protocol(String protocol) { + this.protocol = checkNotNull(protocol, "protocol"); + return self(); } - public Builder protocol(String protocol) { - this.protocol = protocol; - return this; + /** + * @see Console#getPassword() + */ + public T password(String password) { + this.password = checkNotNull(password, "password"); + return self(); } public Console build() { return new Console(host, port, protocol, password); } - - public Builder fromConsole(Console in) { - return host(in.getHost()).port(in.getPort()).password(in.getPassword()).protocol(in.getProtocol()); - } + public T fromConsole(Console in) { + return this.host(in.getHost()).port(in.getPort()).protocol(in.getProtocol()).password(in.getPassword()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } } private final String host; @@ -72,54 +102,42 @@ public class Console { private final String protocol; private final String password; - public Console(String host, int port, String protocol, String password) { - this.host = host; + @ConstructorProperties({ + "host", "port", "protocol", "password" + }) + protected Console(String host, int port, String protocol, String password) { + this.host = checkNotNull(host, "host"); this.port = port; - this.protocol = protocol; - this.password = password; + this.protocol = checkNotNull(protocol, "protocol"); + this.password = checkNotNull(password, "password"); } /** * @return the host name to use to connect to the server */ public String getHost() { - return host; + return this.host; } /** * @return the port to use to connect to the server */ public int getPort() { - return port; + return this.port; } /** * @return the protocol to use to connect to the server */ public String getProtocol() { - return protocol; + return this.protocol; } - + /** * @return the password to use to connect to the server */ public String getPassword() { - return password; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Console) { - final Console other = (Console) object; - return Objects.equal(host, other.host) - && Objects.equal(port, other.port) - && Objects.equal(protocol, other.protocol); - } else { - return false; - } + return this.password; } @Override @@ -128,8 +146,23 @@ public class Console { } @Override - public String toString() { - return String.format("[host=%s, port=%s, protocol=%s, password=%s]", host, port, protocol, password); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Console that = Console.class.cast(obj); + return Objects.equal(this.host, that.host) + && Objects.equal(this.port, that.port) + && Objects.equal(this.protocol, that.protocol); } -} + protected ToStringHelper string() { + return Objects.toStringHelper("").add("host", host).add("port", port).add("protocol", protocol) + .add("password", password); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Cost.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Cost.java index 8f5af3ce41..a868d4d574 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Cost.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Cost.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,8 +20,10 @@ package org.jclouds.glesys.domain; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * The Cost class contains information about the cost of a server @@ -30,84 +32,94 @@ import com.google.gson.annotations.SerializedName; * @see ServerDetails */ public class Cost { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private double amount; - private String currency; - private String timePeriod; + public Builder toBuilder() { + return new ConcreteBuilder().fromCost(this); + } - public Builder amount(double amount) { + public static abstract class Builder> { + protected abstract T self(); + + protected double amount; + protected String currency; + protected String timePeriod; + + /** + * @see Cost#getAmount() + */ + public T amount(double amount) { this.amount = amount; - return this; + return self(); } - public Builder currency(String currency) { - this.currency = currency; - return this; + /** + * @see Cost#getCurrency() + */ + public T currency(String currency) { + this.currency = checkNotNull(currency, "currency"); + return self(); } - public Builder timePeriod(String timePeriod) { - this.timePeriod = timePeriod; - return this; + /** + * @see Cost#getTimePeriod() + */ + public T timePeriod(String timePeriod) { + this.timePeriod = checkNotNull(timePeriod, "timePeriod"); + return self(); } public Cost build() { return new Cost(amount, currency, timePeriod); } - public Builder fromCost(Cost cost) { - return amount(cost.getAmount()).currency(cost.getCurrency()).timePeriod(cost.getTimePeriod()); + public T fromCost(Cost in) { + return this.amount(in.getAmount()).currency(in.getCurrency()).timePeriod(in.getTimePeriod()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } private final double amount; private final String currency; - @SerializedName("timeperiod") private final String timePeriod; - public Cost(double amount, String currency, String timePeriod) { + @ConstructorProperties({ + "amount", "currency", "timeperiod" + }) + protected Cost(double amount, String currency, String timePeriod) { this.amount = amount; this.currency = checkNotNull(currency, "currency"); - this.timePeriod = timePeriod; + this.timePeriod = checkNotNull(timePeriod, "timePeriod"); } /** * @return the numeric cost in #currency / #timePeriod */ public double getAmount() { - return amount; + return this.amount; } /** * @return the currency unit, e.g. "EUR" for Euro */ public String getCurrency() { - return currency; + return this.currency; } /** * @return the time period for which this cost charged, e.g. "month" */ public String getTimePeriod() { - return timePeriod; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Cost) { - Cost other = (Cost) object; - return Objects.equal(amount, other.amount) - && Objects.equal(currency, other.currency) - && Objects.equal(timePeriod, other.timePeriod); - } else { - return false; - } + return this.timePeriod; } @Override @@ -116,8 +128,22 @@ public class Cost { } @Override - public String toString() { - return String.format( - "[amount=%f, currency=%s, timePeriod=%s]", amount, currency, timePeriod); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Cost that = Cost.class.cast(obj); + return Objects.equal(this.amount, that.amount) + && Objects.equal(this.currency, that.currency) + && Objects.equal(this.timePeriod, that.timePeriod); } -} + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("amount", amount).add("currency", currency).add("timePeriod", timePeriod); + } + + @Override + public String toString() { + return string().toString(); + } +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Domain.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Domain.java index 3335c2730a..c98e521e5b 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Domain.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Domain.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +18,15 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.util.Date; +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Domain data for a Glesys account. @@ -29,80 +34,253 @@ import com.google.gson.annotations.SerializedName; * @author Adam Lowe * @see */ -public class Domain implements Comparable { - public static Builder builder() { - return new Builder(); +public class Domain { + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String domainName; - private Date createTime; - private int recordCount; - private boolean useGlesysNameServer; + public Builder toBuilder() { + return new ConcreteBuilder().fromDomain(this); + } - public Builder domainName(String domainName) { - this.domainName = domainName; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String domainName; + protected Date createTime; + protected int recordCount; + protected boolean useGlesysNameServer; + protected String primaryNameServer; + protected String responsiblePerson; + protected int ttl; + protected int refresh; + protected int retry; + protected int expire; + protected int minimum; + + /** + * @see Domain#getDomainName() + */ + public T domainName(String domainName) { + this.domainName = checkNotNull(domainName, "domainName"); + return self(); } - public Builder createTime(Date createTime) { + /** + * @see Domain#getCreateTime() + */ + public T createTime(Date createTime) { this.createTime = createTime; - return this; + return self(); } - public Builder recordCount(int recordCount) { + /** + * @see Domain#getRecordCount() + */ + public T recordCount(int recordCount) { this.recordCount = recordCount; - return this; + return self(); } - public Builder useGlesysNameServer(boolean useGlesysNameServer) { + /** + * @see Domain#isUseGlesysNameServer() + */ + public T useGlesysNameServer(boolean useGlesysNameServer) { this.useGlesysNameServer = useGlesysNameServer; - return this; + return self(); + } + + /** + * @see Domain#getPrimaryNameServer() + */ + public T primaryNameServer(String primaryNameServer) { + this.primaryNameServer = primaryNameServer; + return self(); + } + + /** + * @see Domain#getResponsiblePerson() + */ + public T responsiblePerson(String responsiblePerson) { + this.responsiblePerson = responsiblePerson; + return self(); + } + + /** + * @see Domain#getTtl() + */ + public T ttl(int ttl) { + this.ttl = ttl; + return self(); + } + + /** + * @see Domain#getRefresh() + */ + public T refresh(int refresh) { + this.refresh = refresh; + return self(); + } + + /** + * @see Domain#getRetry() + */ + public T retry(int retry) { + this.retry = retry; + return self(); + } + + /** + * @see Domain#getExpire() + */ + public T expire(int expire) { + this.expire = expire; + return self(); + } + + /** + * @see Domain#getMinimum() + */ + public T minimum(int minimum) { + this.minimum = minimum; + return self(); } public Domain build() { - return new Domain(domainName, createTime, recordCount, useGlesysNameServer); + return new Domain(domainName, createTime, recordCount, new GleSYSBoolean(useGlesysNameServer), primaryNameServer, responsiblePerson, ttl, refresh, retry, expire, minimum); } - public Builder fromDomain(Domain in) { - return new Builder().domainName(in.getDomainName()).createTime(in.getCreateTime()).recordCount(in.getRecordCount()).useGlesysNameServer(in.isGlesysNameServer()); + public T fromDomain(Domain in) { + return this.domainName(in.getDomainName()) + .createTime(in.getCreateTime()) + .recordCount(in.getRecordCount()) + .useGlesysNameServer(in.isUseGlesysNameServer()) + .primaryNameServer(in.getPrimaryNameServer()) + .responsiblePerson(in.getResponsiblePerson()) + .ttl(in.getTtl()) + .refresh(in.getRefresh()) + .retry(in.getRetry()) + .expire(in.getExpire()); } } - @SerializedName("domainname") - private final String domainName; - @SerializedName("createtime") - private final Date createTime; - @SerializedName("recordcount") - private final int recordCount; - @SerializedName("usingglesysnameserver") - private final boolean useGlesysNameServer; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } - public Domain(String domainName, Date createTime, int recordCount, boolean useGlesysNameServer) { - this.domainName = domainName; + private final String domainName; + private final Date createTime; + private final int recordCount; + private final boolean useGlesysNameServer; + private final String primaryNameServer; + private final String responsiblePerson; + private final int ttl; + private final int refresh; + private final int retry; + private final int expire; + private final int minimum; + + @ConstructorProperties({ + "domainname", "createtime", "recordcount", "usingglesysnameserver", "primarynameserver", "responsibleperson", + "ttl", "refresh", "retry", "expire", "minimum" + }) + protected Domain(String domainName, @Nullable Date createTime, int recordCount, GleSYSBoolean useGlesysNameServer, + @Nullable String primaryNameServer, @Nullable String responsiblePerson, + int ttl, int refresh, int retry, int expire, int minimum) { + this.domainName = checkNotNull(domainName, "domainName"); this.createTime = createTime; this.recordCount = recordCount; - this.useGlesysNameServer = useGlesysNameServer; + this.useGlesysNameServer = checkNotNull(useGlesysNameServer, "useGlesysNameServer").getValue(); + this.primaryNameServer = primaryNameServer; + this.responsiblePerson = responsiblePerson; + this.ttl = ttl; + this.refresh = refresh; + this.retry = retry; + this.expire = expire; + this.minimum = minimum; } - /** @return the domain name, ex. "jclouds.org" */ + /** + * @return the domain name, ex. "jclouds.org" + */ public String getDomainName() { - return domainName; + return this.domainName; } - /** @return the date the domain was registered with GleSYS */ + /** + * @return the date the domain was registered with GleSYS + */ public Date getCreateTime() { - return createTime; + return this.createTime; } - /** @return the number of DNS records for this domain */ + /** + * @return the number of DNS records for this domain + */ public int getRecordCount() { - return recordCount; + return this.recordCount; } - /** @return true if a GleSYS nameserver holds the records */ - public boolean isGlesysNameServer() { - return useGlesysNameServer; + /** + * @return true if a GleSYS nameserver holds the records + */ + public boolean isUseGlesysNameServer() { + return this.useGlesysNameServer; + } + + @Nullable + public String getPrimaryNameServer() { + return primaryNameServer; + } + + /** + * The E-mail address of the person responsible for this domain (reformatted with '.' at end). + */ + @Nullable + public String getResponsiblePerson() { + return responsiblePerson; + } + + /** + * TTL (time to live). The number of seconds a domain name is cached locally before expiration and return to authoritative nameServers for updates + */ + public int getTtl() { + return ttl; + } + + /** + * The number of seconds between update requests from secondary and slave name servers + */ + public int getRefresh() { + return refresh; + } + + + /** + * The number of seconds the secondary/slave will wait before retrying when the last attempt failed + */ + public int getRetry() { + return retry; + } + + /** + * The number of seconds a master or slave will wait before considering the data stale if it cannot reach the primary name server + */ + public int getExpire() { + return expire; + } + + /** + * The minimum/default TTL if the domain does not specify ttl + * + * @see #getTtl() + */ + public int getMinimum() { + return minimum; } @Override @@ -111,25 +289,21 @@ public class Domain implements Comparable { } @Override - public int compareTo(Domain other) { - return domainName.compareTo(other.getDomainName()); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Domain that = Domain.class.cast(obj); + return Objects.equal(this.domainName, that.domainName); } - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Domain) { - return Objects.equal(domainName, ((Domain) object).domainName); - } else { - return false; - } + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("domainName", domainName).add("createTime", createTime).add("recordCount", recordCount).add("useGlesysNameServer", useGlesysNameServer); } @Override public String toString() { - return String.format("[domainname=%s, createtime=%s, count=%d, useglesysnameserver=%b]", domainName, createTime, recordCount, useGlesysNameServer); + return string().toString(); } } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/DomainRecord.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/DomainRecord.java index dd3b92cf9f..7e3a6e4fb2 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/DomainRecord.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/DomainRecord.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +18,14 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * DNS record data. @@ -26,55 +33,92 @@ import com.google.common.base.Objects; * @author Adam Lowe * @see */ -public class DomainRecord implements Comparable { - public static Builder builder() { - return new Builder(); +public class DomainRecord { + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String id; - private String domainname; - private String host; - private String type; - private String data; - private int ttl; + public Builder toBuilder() { + return new ConcreteBuilder().fromDomainRecord(this); + } - public Builder id(String id) { - this.id = id; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String id; + protected String domainname; + protected String host; + protected String type; + protected String data; + protected int ttl; + + /** + * @see DomainRecord#getId() + */ + public T id(String id) { + this.id = checkNotNull(id, "id"); + return self(); } - public Builder domainname(String domainname) { - this.domainname = domainname; - return this; + /** + * @see DomainRecord#getDomainname() + */ + public T domainname(String domainname) { + this.domainname = checkNotNull(domainname, "domainname"); + return self(); } - public Builder host(String host) { - this.host = host; - return this; + /** + * @see DomainRecord#getHost() + */ + public T host(String host) { + this.host = checkNotNull(host, "host"); + return self(); } - public Builder type(String type) { - this.type = type; - return this; + /** + * @see DomainRecord#getType() + */ + public T type(String type) { + this.type = checkNotNull(type, "type"); + return self(); } - public Builder data(String data) { - this.data = data; - return this; + /** + * @see DomainRecord#getData() + */ + public T data(String data) { + this.data = checkNotNull(data, "data"); + return self(); } - public Builder ttl(int ttl) { + /** + * @see DomainRecord#getTtl() + */ + public T ttl(int ttl) { this.ttl = ttl; - return this; + return self(); } public DomainRecord build() { return new DomainRecord(id, domainname, host, type, data, ttl); } - public Builder fromDomainRecord(DomainRecord in) { - return new Builder().id(in.getId()).domainname(in.getDomainName()).host(in.getHost()).type(in.getType()).data(in.getData()).ttl(in.getTtl()); + public T fromDomainRecord(DomainRecord in) { + return this.id(in.getId()) + .domainname(in.getDomainname()) + .host(in.getHost()) + .type(in.getType()) + .data(in.getData()) + .ttl(in.getTtl()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } @@ -85,11 +129,14 @@ public class DomainRecord implements Comparable { private final String data; private final int ttl; - public DomainRecord(String id, String domainname, String host, String type, String data, int ttl) { + @ConstructorProperties({ + "recordid", "domainname", "host", "type", "data", "ttl" + }) + protected DomainRecord(@Nullable String id, String domainname, String host, String type, @Nullable String data, int ttl) { this.id = id; - this.domainname = domainname; - this.host = host; - this.type = type; + this.domainname = checkNotNull(domainname, "domainname"); + this.host = checkNotNull(host, "host"); + this.type = checkNotNull(type, "type"); this.data = data; this.ttl = ttl; } @@ -99,47 +146,43 @@ public class DomainRecord implements Comparable { * @see org.jclouds.glesys.features.DomainClient */ public String getId() { - return id; + return this.id; } /** * @return the zone content of the record */ - public String getDomainName() { - return domainname; + public String getDomainname() { + return this.domainname; } /** * @return the host content of the record */ public String getHost() { - return host; + return this.host; } /** * @return the type of the record, ex. "A" */ public String getType() { - return type; + return this.type; } /** * @return the data content of the record */ + @Nullable public String getData() { - return data; + return this.data; } /** * @return the TTL/Time-to-live for the record */ public int getTtl() { - return ttl; - } - - @Override - public int compareTo(DomainRecord other) { - return id.compareTo(other.getId()); + return this.ttl; } @Override @@ -148,21 +191,22 @@ public class DomainRecord implements Comparable { } @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof DomainRecord) { - DomainRecord other = (DomainRecord) object; - return Objects.equal(id, other.id); - } else { - return false; - } + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + DomainRecord that = DomainRecord.class.cast(obj); + return Objects.equal(this.id, that.id); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("id", id).add("domainname", domainname).add("host", host).add("type", type).add("data", data) + .add("ttl", ttl); } @Override public String toString() { - return String.format("[id=%s, domainname=%s, host=%s, type=%s, data=%s, ttl=%d]", id, domainname, host, type, data, ttl); + return string().toString(); } } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAccount.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAccount.java index 54472a02c4..13105a96f1 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAccount.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAccount.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,205 +18,253 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.util.Date; +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Detailed information on an Email Account - * + * * @author Adam Lowe * @see */ -public class EmailAccount implements Comparable { - public static Builder builder() { - return new Builder(); +public class EmailAccount { + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String account; - private String quota; - private String usedQuota; - private int antispamLevel; - private boolean antiVirus; - private boolean autoRespond; - private String autoRespondMessage; - private boolean autoRespondSaveEmail; - private Date created; - private Date modified; + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailAccount(this); + } - public Builder account(String account) { - this.account = account; - return this; - } - - public Builder quota(String quota) { - this.quota = quota; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String account; + protected EmailQuota quota; + protected int antispamLevel; + protected boolean antiVirus; + protected boolean autoRespond; + protected String autoRespondMessage; + protected boolean autoRespondSaveEmail; + protected Date created; + protected Date modified; + + /** + * @see EmailAccount#getAccount() + */ + public T account(String account) { + this.account = checkNotNull(account, "account"); + return self(); } - public Builder usedQuota(String usedQuota) { - this.usedQuota = usedQuota; - return this; + /** + * @see EmailAccount#getQuota() + */ + public T quota(EmailQuota quota) { + this.quota = checkNotNull(quota, "quota"); + return self(); } - - public Builder antispamLevel(int antispamLevel) { + + /** + * @see EmailAccount#getAntispamLevel() + */ + public T antispamLevel(int antispamLevel) { this.antispamLevel = antispamLevel; - return this; + return self(); } - public Builder antiVirus(boolean antiVirus) { + /** + * @see EmailAccount#isAntiVirus() + */ + public T antiVirus(boolean antiVirus) { this.antiVirus = antiVirus; - return this; + return self(); } - - public Builder autoRespond(boolean autoRespond) { + + /** + * @see EmailAccount#isAutoRespond() + */ + public T autoRespond(boolean autoRespond) { this.autoRespond = autoRespond; - return this; - } - - public Builder autoRespondMessage(String autoRespondMessage) { - this.autoRespondMessage = autoRespondMessage; - return this; + return self(); } - public Builder autoRespondSaveEmail(boolean autoRespondSaveEmail) { + /** + * @see EmailAccount#getAutoRespondMessage() + */ + public T autoRespondMessage(String autoRespondMessage) { + this.autoRespondMessage = checkNotNull(autoRespondMessage, "autoRespondMessage"); + return self(); + } + + /** + * @see EmailAccount#isAutoRespondSaveEmail() + */ + public T autoRespondSaveEmail(boolean autoRespondSaveEmail) { this.autoRespondSaveEmail = autoRespondSaveEmail; - return this; + return self(); } - public Builder created(Date created) { - this.created = created; - return this; + /** + * @see EmailAccount#getCreated() + */ + public T created(Date created) { + this.created = checkNotNull(created, "created"); + return self(); } - public Builder modified(Date modified) { - this.modified = modified; - return this; + /** + * @see EmailAccount#getModified() + */ + public T modified(Date modified) { + this.modified = checkNotNull(modified, "modified"); + return self(); } public EmailAccount build() { - return new EmailAccount(account, quota, usedQuota, antispamLevel, antiVirus, autoRespond, autoRespondMessage, - autoRespondSaveEmail, created, modified); + return new EmailAccount(account, quota, antispamLevel, new GleSYSBoolean(antiVirus), new GleSYSBoolean(autoRespond), autoRespondMessage, new GleSYSBoolean(autoRespondSaveEmail), created, modified); } - public Builder fromEmail(EmailAccount in) { - return account(in.getAccount()).quota(in.getQuota()).usedQuota(in.getUsedQuota()).antispamLevel(in.getAntispamLevel()). - antiVirus(in.getAntiVirus()).autoRespond(in.getAutoRespond()).autoRespondMessage(in.getAutoRespondMessage()). - autoRespondSaveEmail(in.getAutoRespondSaveEmail()).created(in.getCreated()).modified(in.getModified()); + public T fromEmailAccount(EmailAccount in) { + return this.account(in.getAccount()) + .quota(in.getQuota()) + .antispamLevel(in.getAntispamLevel()) + .antiVirus(in.isAntiVirus()) + .autoRespond(in.isAutoRespond()) + .autoRespondMessage(in.getAutoRespondMessage()) + .autoRespondSaveEmail(in.isAutoRespondSaveEmail()) + .created(in.getCreated()) + .modified(in.getModified()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } - @SerializedName("emailaccount") private final String account; - private final String quota; - @SerializedName("usedquota") - private final String usedQuota; - @SerializedName("antispamlevel") + private final EmailQuota quota; private final int antispamLevel; - @SerializedName("antivirus") private final boolean antiVirus; - @SerializedName("autorespond") private final boolean autoRespond; - @SerializedName("autorespondmessage") private final String autoRespondMessage; - @SerializedName("autorespondsaveemail") private final boolean autoRespondSaveEmail; private final Date created; private final Date modified; - public EmailAccount(String account, String quota, String usedQuota, int antispamLevel, boolean antiVirus, boolean autoRespond, String autoRespondMessage, boolean autoRespondSaveEmail, Date created, Date modified) { - this.account = account; - this.quota = quota; - this.usedQuota = usedQuota; + @ConstructorProperties({ + "emailaccount", "quota", "antispamlevel", "antivirus", "autorespond", "autorespondmessage", "autorespondsaveemail", "created", "modified" + }) + protected EmailAccount(String account, EmailQuota quota, int antispamLevel, + GleSYSBoolean antiVirus, GleSYSBoolean autoRespond, @Nullable String autoRespondMessage, + GleSYSBoolean autoRespondSaveEmail, Date created, @Nullable Date modified) { + this.account = checkNotNull(account, "account"); + this.quota = checkNotNull(quota, "quota"); this.antispamLevel = antispamLevel; - this.antiVirus = antiVirus; - this.autoRespond = autoRespond; + this.antiVirus = checkNotNull(antiVirus, "antiVirus").getValue(); + this.autoRespond = checkNotNull(autoRespond, "autoRespond").getValue(); this.autoRespondMessage = autoRespondMessage; - this.autoRespondSaveEmail = autoRespondSaveEmail; - this.created = created; + this.autoRespondSaveEmail = checkNotNull(autoRespondSaveEmail, "autoRespondSaveEmail").getValue(); + this.created = checkNotNull(created, "created"); this.modified = modified; } - /** @return the e-mail address for this e-mail account */ + /** + * @return the e-mail address for this e-mail account + */ public String getAccount() { - return account; + return this.account; } - /** @return the quota for this e-mail account */ - public String getQuota() { - return quota; + /** + * @return the quota for this e-mail account + */ + public EmailQuota getQuota() { + return this.quota; } - /** @return the amount of quota currently in use */ - public String getUsedQuota() { - return usedQuota; - } - - /** @return the antispam level of the e-mail account */ + /** + * @return the antispam level of the e-mail account + */ public int getAntispamLevel() { - return antispamLevel; + return this.antispamLevel; } - /** @return true if antivirus is enabled for this e-mail account */ - public boolean getAntiVirus() { - return antiVirus; + /** + * @return true if antivirus is enabled for this e-mail account + */ + public boolean isAntiVirus() { + return this.antiVirus; } - /** @return true if auto-respond is enabled for this e-mail account */ - public boolean getAutoRespond() { - return autoRespond; + /** + * @return true if auto-respond is enabled for this e-mail account + */ + public boolean isAutoRespond() { + return this.autoRespond; } - + /** + * @return the auto-respond message for this e-mail account + */ + @Nullable public String getAutoRespondMessage() { - return autoRespondMessage; + return this.autoRespondMessage; } - /** @return true if saving is enabled for auto-respond e-mails */ - public boolean getAutoRespondSaveEmail() { - return autoRespondSaveEmail; + /** + * @return true if saving is enabled for auto-respond e-mails + */ + public boolean isAutoRespondSaveEmail() { + return this.autoRespondSaveEmail; } - /** @return when this account was created */ + /** + * @return when this account was created + */ public Date getCreated() { - return created; + return this.created; } - /** @return when this account was last modified */ + /** + * @return when this account was last modified + */ + @Nullable public Date getModified() { - return modified; - } - - @Override - public int compareTo(EmailAccount other) { - return account.compareTo(other.getAccount()); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof EmailAccount) { - EmailAccount other = (EmailAccount) object; - return Objects.equal(account, other.account); - } else { - return false; - } + return this.modified; } @Override public int hashCode() { return Objects.hashCode(account); } - + @Override - public String toString() { - return String.format("account=%s, quota=%s, usedquota=%s, antispamLevel=%d, " + - "antiVirus=%b, autoRespond=%b, autoRespondMessage=%s, autoRespondSaveEmail=%b, " + - "created=%s, modified=%s", account, quota, usedQuota, antispamLevel, antiVirus, autoRespond, autoRespondMessage, - autoRespondSaveEmail, created.toString(), modified.toString()); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailAccount that = EmailAccount.class.cast(obj); + return Objects.equal(this.account, that.account); } -} + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("account", account).add("quota", quota).add("antispamLevel", antispamLevel).add("antiVirus", antiVirus).add("autoRespond", autoRespond).add("autoRespondMessage", autoRespondMessage).add("autoRespondSaveEmail", autoRespondSaveEmail).add("created", created).add("modified", modified); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java new file mode 100644 index 0000000000..8f20940dd7 --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java @@ -0,0 +1,130 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Detailed information on an Email Account + * + * @author Adam Lowe + * @see + */ +public class EmailAlias { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailAlias(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected String alias; + protected String forwardTo; + + /** + * @see org.jclouds.glesys.domain.EmailAlias#getAlias() + */ + public T alias(String alias) { + this.alias = checkNotNull(alias, "alias"); + return self(); + } + + /** + * @see EmailAlias#getForwardTo() + */ + public T forwardTo(String forwardTo) { + this.forwardTo = checkNotNull(forwardTo, "forwardTo"); + return self(); + } + + public EmailAlias build() { + return new EmailAlias(alias, forwardTo); + } + + public T fromEmailAlias(EmailAlias in) { + return this.alias(in.getAlias()).forwardTo(in.getForwardTo()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String alias; + private final String forwardTo; + + @ConstructorProperties({ + "emailalias", "goto" + }) + protected EmailAlias(String alias, String forwardTo) { + this.alias = checkNotNull(alias, "alias"); + this.forwardTo = checkNotNull(forwardTo, "forwardTo"); + } + + /** + * @return the e-mail address being forwarded + */ + public String getAlias() { + return this.alias; + } + + /** + * @return the e-mail address this address forwards to + */ + public String getForwardTo() { + return this.forwardTo; + } + + @Override + public int hashCode() { + return Objects.hashCode(alias); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailAlias that = EmailAlias.class.cast(obj); + return Objects.equal(this.alias, that.alias); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("alias", alias).add("forwardTo", forwardTo); + } + + @Override + public String toString() { + return string().toString(); + } + +} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverview.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverview.java index 785f386330..d5419770ce 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverview.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverview.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,69 +18,99 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.util.Set; import com.google.common.annotations.Beta; -import com.google.common.base.Joiner; import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; import com.google.common.collect.ImmutableSet; /** * Structure containing all information about e-mail addresses for a GleSYS account - * + * * @author Adam Lowe * @see */ //TODO: find a better name for this class @Beta public class EmailOverview { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private EmailOverviewSummary summary; - private Set domains; + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailOverview(this); + } - public Builder summary(EmailOverviewSummary summary) { - this.summary = summary; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected EmailOverviewSummary summary; + protected Set domains = ImmutableSet.of(); + + /** + * @see EmailOverview#getSummary() + */ + public T summary(EmailOverviewSummary summary) { + this.summary = checkNotNull(summary, "summary"); + return self(); } - public Builder domains(Set domains) { - this.domains = domains; - return this; + /** + * @see EmailOverview#getDomains() + */ + public T domains(Set domains) { + this.domains = ImmutableSet.copyOf(checkNotNull(domains, "domains")); + return self(); } - public Builder domains(EmailOverviewDomain... domains) { - return domains(ImmutableSet.copyOf(domains)); + public T domains(EmailOverviewDomain... in) { + return domains(ImmutableSet.copyOf(in)); } public EmailOverview build() { return new EmailOverview(summary, domains); } - - public Builder fromEmailOverview(EmailOverview in) { - return summary(in.getSummary()).domains(in.getDomains()); + + public T fromEmailOverview(EmailOverview in) { + return this.summary(in.getSummary()).domains(in.getDomains()); } } - private EmailOverviewSummary summary; - private Set domains; - - public EmailOverview(EmailOverviewSummary summary, Set domains) { - this.summary = summary; - this.domains = domains; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } } - /** @return summary information about the account */ + private final EmailOverviewSummary summary; + private final Set domains; + + @ConstructorProperties({ + "summary", "domains" + }) + protected EmailOverview(EmailOverviewSummary summary, Set domains) { + this.summary = checkNotNull(summary, "summary"); + this.domains = ImmutableSet.copyOf(checkNotNull(domains, "domains")); + } + + /** + * @return summary information about the account + */ public EmailOverviewSummary getSummary() { - return summary; + return this.summary; } - /** @return the set of detailed information about the e-mail addresses and aliases for each domain */ + /** + * @return the set of detailed information about the e-mail addresses and aliases for each domain + */ public Set getDomains() { - return domains == null ? ImmutableSet.of() : domains; + return this.domains; } @Override @@ -89,23 +119,22 @@ public class EmailOverview { } @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - if (object instanceof EmailOverview) { - EmailOverview other = (EmailOverview) object; - return Objects.equal(summary, other.summary) - && Objects.equal(domains, other.domains); - } else { - return false; - } + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailOverview that = EmailOverview.class.cast(obj); + return Objects.equal(this.summary, that.summary) + && Objects.equal(this.domains, that.domains); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("summary", summary).add("domains", domains); } @Override public String toString() { - Joiner commaJoiner = Joiner.on(", "); - return String.format("summary=%s, domains=[%s]", summary, commaJoiner.join(getDomains())); + return string().toString(); } -} +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewDomain.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewDomain.java index 3ae18e0e90..62dcfca8e9 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewDomain.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewDomain.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,48 +18,75 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.annotations.Beta; import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Detailed information about e-mail settings for a single domain - * + * * @author Adam Lowe * @see */ -//TODO: find a better name for this class @Beta public class EmailOverviewDomain { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String domain; - private int accounts; - private int aliases; + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailOverviewDomain(this); + } - public Builder domain(String domain) { - this.domain = domain; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String domain; + protected int accounts; + protected int aliases; + + /** + * @see EmailOverviewDomain#getDomain() + */ + public T domain(String domain) { + this.domain = checkNotNull(domain, "domain"); + return self(); } - public Builder accounts(int accounts) { + /** + * @see EmailOverviewDomain#getAccounts() + */ + public T accounts(int accounts) { this.accounts = accounts; - return this; + return self(); } - - public Builder aliases(int aliases) { + + /** + * @see EmailOverviewDomain#getAliases() + */ + public T aliases(int aliases) { this.aliases = aliases; - return this; + return self(); } - + public EmailOverviewDomain build() { return new EmailOverviewDomain(domain, accounts, aliases); } - - public Builder fromEmailOverview(EmailOverviewDomain in) { - return domain(domain).accounts(in.getAccounts()).aliases(in.getAliases()); + + public T fromEmailOverviewDomain(EmailOverviewDomain in) { + return this.domain(in.getDomain()).accounts(in.getAccounts()).aliases(in.getAliases()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } @@ -67,25 +94,28 @@ public class EmailOverviewDomain { private final int accounts; private final int aliases; - public EmailOverviewDomain(String domain, int accounts, int aliases) { - this.domain = domain; + @ConstructorProperties({ + "domainname", "accounts", "aliases" + }) + protected EmailOverviewDomain(String domain, int accounts, int aliases) { + this.domain = checkNotNull(domain, "domain"); this.accounts = accounts; this.aliases = aliases; } /** @return the domain name */ public String getDomain() { - return domain; + return this.domain; } /** @return the number of e-mail accounts in the domain */ public int getAccounts() { - return accounts; + return this.accounts; } /** @return the number of e-mail aliases in the domain */ public int getAliases() { - return aliases; + return this.aliases; } @Override @@ -94,21 +124,20 @@ public class EmailOverviewDomain { } @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - if (object instanceof EmailOverviewDomain) { - EmailOverviewDomain other = (EmailOverviewDomain) object; - return Objects.equal(domain, other.domain); - } else { - return false; - } + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailOverviewDomain that = EmailOverviewDomain.class.cast(obj); + return Objects.equal(this.domain, that.domain); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("domain", domain).add("accounts", accounts).add("aliases", aliases); } @Override public String toString() { - return String.format("domain=%s, accounts=%d, aliases=%d", domain, accounts, aliases); + return string().toString(); } -} +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewSummary.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewSummary.java index abc674db41..0799722504 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewSummary.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailOverviewSummary.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,90 +18,130 @@ */ package org.jclouds.glesys.domain; +import java.beans.ConstructorProperties; + import com.google.common.annotations.Beta; import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Summary information of e-mail settings and limits for a GleSYS account - * + * * @author Adam Lowe * @see */ //TODO: find a better name for this class @Beta public class EmailOverviewSummary { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private int accounts; - private int maxAccounts; - private int aliases; - private int maxAliases; + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailOverviewSummary(this); + } - public Builder accounts(int accounts) { + public static abstract class Builder> { + protected abstract T self(); + + protected int accounts; + protected int maxAccounts; + protected int aliases; + protected int maxAliases; + + /** + * @see EmailOverviewSummary#getAccounts() + */ + public T accounts(int accounts) { this.accounts = accounts; - return this; + return self(); } - - public Builder maxAccounts(int maxAccounts) { + + /** + * @see EmailOverviewSummary#getMaxAccounts() + */ + public T maxAccounts(int maxAccounts) { this.maxAccounts = maxAccounts; - return this; + return self(); } - - public Builder aliases(int aliases) { + + /** + * @see EmailOverviewSummary#getAliases() + */ + public T aliases(int aliases) { this.aliases = aliases; - return this; + return self(); } - - public Builder maxAliases(int maxAliases) { + + /** + * @see EmailOverviewSummary#getMaxAliases() + */ + public T maxAliases(int maxAliases) { this.maxAliases = maxAliases; - return this; + return self(); } - + public EmailOverviewSummary build() { return new EmailOverviewSummary(accounts, maxAccounts, aliases, maxAliases); } - - public Builder fromEmailOverview(EmailOverviewSummary in) { - return accounts(in.getAccounts()).maxAccounts(in.getMaxAccounts()).aliases(in.getAliases()).maxAliases(in.getMaxAliases()); + + public T fromEmailOverviewSummary(EmailOverviewSummary in) { + return this.accounts(in.getAccounts()) + .maxAccounts(in.getMaxAccounts()) + .aliases(in.getAliases()) + .maxAliases(in.getMaxAliases()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } private final int accounts; - @SerializedName("maxaccounts") private final int maxAccounts; private final int aliases; - @SerializedName("maxaliases") private final int maxAliases; - public EmailOverviewSummary(int accounts, int maxAccounts, int aliases, int maxAliases) { + @ConstructorProperties({ + "accounts", "maxaccounts", "aliases", "maxaliases" + }) + protected EmailOverviewSummary(int accounts, int maxAccounts, int aliases, int maxAliases) { this.accounts = accounts; this.maxAccounts = maxAccounts; this.aliases = aliases; this.maxAliases = maxAliases; } - /** @return the number of e-mail accounts */ + /** + * @return the number of e-mail accounts + */ public int getAccounts() { - return accounts; + return this.accounts; } - /** @return the maximum number of e-mail accounts */ + /** + * @return the maximum number of e-mail accounts + */ public int getMaxAccounts() { - return maxAccounts; + return this.maxAccounts; } - /** @return the number of e-mail aliases */ + /** + * @return the number of e-mail aliases + */ public int getAliases() { - return aliases; + return this.aliases; } - /** @return the maximum number of e-mail aliases */ + /** + * @return the maximum number of e-mail aliases + */ public int getMaxAliases() { - return maxAliases; + return this.maxAliases; } @Override @@ -110,24 +150,24 @@ public class EmailOverviewSummary { } @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - if (object instanceof EmailOverviewSummary) { - EmailOverviewSummary other = (EmailOverviewSummary) object; - return Objects.equal(accounts, other.accounts) - && Objects.equal(maxAccounts, other.maxAccounts) - && Objects.equal(aliases, other.aliases) - && Objects.equal(maxAliases, other.maxAliases); - } else { - return false; - } + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailOverviewSummary that = EmailOverviewSummary.class.cast(obj); + return Objects.equal(this.accounts, that.accounts) + && Objects.equal(this.maxAccounts, that.maxAccounts) + && Objects.equal(this.aliases, that.aliases) + && Objects.equal(this.maxAliases, that.maxAliases); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("accounts", accounts).add("maxAccounts", maxAccounts).add("aliases", aliases).add("maxAliases", maxAliases); } @Override public String toString() { - return String.format("accounts=%d, maxAccounts=%d, aliases=%d, maxAliases=%d", accounts, maxAccounts, aliases, maxAliases); + return string().toString(); } -} +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailQuota.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailQuota.java new file mode 100644 index 0000000000..e587ff023b --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailQuota.java @@ -0,0 +1,130 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Information on an Email Account Quota size + * + * @author Adam Lowe + * @see + */ +public class EmailQuota { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromEmailAccount(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected int max; + protected String unit; + + /** + * @see EmailQuota#getMax() + */ + public T max(int max) { + this.max = max; + return self(); + } + + /** + * @see EmailQuota#getUnit() + */ + public T unit(String unit) { + this.unit = checkNotNull(unit, "unit"); + return self(); + } + + public EmailQuota build() { + return new EmailQuota(max, unit); + } + + public T fromEmailAccount(EmailQuota in) { + return this.max(in.getMax()).unit(in.getUnit()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final int max; + private final String unit; + + @ConstructorProperties({ + "max", "unit" + }) + protected EmailQuota(int max, String unit) { + this.max = max; + this.unit = unit; + } + + /** + * @return the maximum size of the mailbox (in units) + * @see #getUnit + */ + public int getMax() { + return this.max; + } + + /** + * @return the quota for this e-mail account + */ + public String getUnit() { + return this.unit; + } + + @Override + public int hashCode() { + return Objects.hashCode(max, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + EmailQuota that = EmailQuota.class.cast(obj); + return Objects.equal(this.max, that.max) && Objects.equal(this.unit, that.unit); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("max", max).add("unit", unit); + } + + @Override + public String toString() { + return string().toString(); + } + +} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/GleSYSBoolean.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/GleSYSBoolean.java new file mode 100644 index 0000000000..9dc1a51860 --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/GleSYSBoolean.java @@ -0,0 +1,19 @@ +package org.jclouds.glesys.domain; + +/** + * Wrapping booleans for the time being (gson won't allow TypeAdapter<Boolean>) + */ +public class GleSYSBoolean { + public static final GleSYSBoolean TRUE = new GleSYSBoolean(true); + public static final GleSYSBoolean FALSE = new GleSYSBoolean(false); + + private boolean value; + + public GleSYSBoolean(boolean value) { + this.value = value; + } + + public boolean getValue() { + return value; + } +} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Ip.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Ip.java index 2222ae8ed0..0f53453194 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Ip.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Ip.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -16,107 +16,145 @@ * specific language governing permissions and limitations * under the License. */ - package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Represents an ip address used by a server. * * @author Adam Lowe - * @see ServerCreated + * @see Server * @see ServerDetails */ public class Ip { - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { + public Builder toBuilder() { + return new ConcreteBuilder().fromIp(this); + } + + public static abstract class Builder> { + protected abstract T self(); + protected String ip; protected int version; protected double cost; + protected String currency; - protected Builder version(int version) { - this.version = version; - return this; + /** + * @see Ip#getIp() + */ + public T ip(String ip) { + this.ip = checkNotNull(ip, "ip"); + return self(); } - public Builder version4() { + /** + * @see Ip#getVersion() + */ + protected T version(int version) { + this.version = version; + return self(); + } + + /** + * @see Ip#getVersion() + */ + public T version4() { return version(4); } - public Builder version6() { + /** + * @see Ip#getVersion() + */ + public T version6() { return version(6); } - - public Builder ip(String ip) { - this.ip = ip; - return this; + + /** + * @see Ip#getCost() + */ + public T cost(double cost) { + this.cost = cost; + return self(); } - public Builder cost(double cost) { - this.cost = cost; - return this; + /** + * @see Ip#getCurrency() + */ + public T currency(String currency) { + this.currency = currency; + return self(); } public Ip build() { - return new Ip(ip, version, cost); + return new Ip(ip, version, cost, currency); } - public Builder fromIpCreated(Ip from) { - return ip(from.getIp()).version(from.getVersion()).cost(from.getCost()); + public T fromIp(Ip in) { + return this.ip(in.getIp()).version(in.getVersion()).cost(in.getCost()); } } - - @SerializedName("ipaddress") - protected final String ip; - protected final int version; - protected final double cost; - public Ip(String ip, int version, double cost) { - this.ip = ip; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String ip; + private final int version; + private final double cost; + private final String currency; + + @ConstructorProperties({ + "ipaddress", "version", "cost", "currency" + }) + protected Ip(String ip, int version, double cost, String currency) { + this.ip = checkNotNull(ip, "ip"); this.version = version; this.cost = cost; + this.currency = checkNotNull(currency, "currency"); } /** * @return the IP version, ex. 4 */ - public int getVersion() { - return version; + public String getIp() { + return this.ip; } /** * @return the ip address of the new server */ - public String getIp() { - return ip; + public int getVersion() { + return this.version; } /** * @return the cost of the ip address allocated to the new server + * @see #getCurrency() */ public double getCost() { - return cost; + return this.cost; } - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Ip) { - final Ip other = (Ip) object; - return Objects.equal(ip, other.ip) - && Objects.equal(version, other.version) - && Objects.equal(cost, other.cost); - } else { - return false; - } + /** + * @return the currency of the cost + * @see #getCost() + */ + public String getCurrency() { + return currency; } @Override @@ -125,8 +163,24 @@ public class Ip { } @Override - public String toString() { - return String.format("[ip=%s, version=%d, cost=%f]", - ip, version, cost); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Ip that = Ip.class.cast(obj); + return Objects.equal(this.ip, that.ip) + && Objects.equal(this.version, that.version) + && Objects.equal(this.cost, that.cost) + && Objects.equal(this.currency, that.currency); } -} + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("ip", ip).add("version", version).add("cost", cost).add("currency", currency); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java index c16d18d5f1..466c951221 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -16,187 +16,311 @@ * specific language governing permissions and limitations * under the License. */ - package org.jclouds.glesys.domain; -import java.util.Arrays; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; import java.util.List; import org.jclouds.javax.annotation.Nullable; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableList; /** * Represents detailed information about an IP address. */ public class IpDetails { - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { + public Builder toBuilder() { + return new ConcreteBuilder().fromIpDetails(this); + } + + public static abstract class Builder> { + protected abstract T self(); + protected String datacenter; - protected String ipversion; + protected int ipversion; protected String ptr; protected String platform; protected String address; protected String netmask; protected String broadcast; protected String gateway; - protected List nameservers; + protected List nameServers = ImmutableList.of(); + protected String serverId; + protected Cost cost; + protected boolean reserved; - public Builder datacenter(String datacenter) { - this.datacenter = datacenter; - return this; + /** + * @see IpDetails#getDatacenter() + */ + public T datacenter(String datacenter) { + this.datacenter = checkNotNull(datacenter, "datacenter"); + return self(); } - public Builder ipversion(String ipversion) { + protected T version(int ipversion) { this.ipversion = ipversion; - return this; + return self(); } - public Builder ptr(String ptr) { - this.ptr = ptr; - return this; + /* + * @see IpDetails#getVersion() + */ + public T version4() { + return version(4); } - public Builder platform(String platform) { - this.platform = platform; - return this; + /* + * @see IpDetails#getVersion() + */ + public T version6() { + return version(6); + } + + /** + * @see IpDetails#getPtr() + */ + public T ptr(String ptr) { + this.ptr = checkNotNull(ptr, "ptr"); + return self(); + } + + /** + * @see IpDetails#getPlatform() + */ + public T platform(String platform) { + this.platform = checkNotNull(platform, "platform"); + return self(); + } + + /** + * @see IpDetails#getAddress() + */ + public T address(String address) { + this.address = address; + return self(); + } + + /** + * @see IpDetails#getNetmask() + */ + public T netmask(String netmask) { + this.netmask = netmask; + return self(); + } + + /** + * @see IpDetails#getBroadcast() + */ + public T broadcast(String broadcast) { + this.broadcast = broadcast; + return self(); + } + + /** + * @see IpDetails#getGateway() + */ + public T gateway(String gateway) { + this.gateway = gateway; + return self(); + } + + /** + * @see IpDetails#getNameServers() + */ + public T nameServers(List nameservers) { + this.nameServers = ImmutableList.copyOf(checkNotNull(nameservers, "nameServers")); + return self(); + } + + public T nameServers(String... in) { + return nameServers(ImmutableList.copyOf(in)); + } + + /** + * @see IpDetails#getServerId() + */ + public T serverId(String serverId) { + this.serverId = serverId; + return self(); + } + + /** + * @see IpDetails#getCost() + */ + public T cost(Cost cost) { + this.cost = cost; + return self(); + } + + /** + * @see IpDetails#isReserved() + */ + public T reserved(boolean reserved) { + this.reserved = reserved; + return self(); } public IpDetails build() { - return new IpDetails(datacenter, ipversion, ptr, platform, - address, netmask, broadcast, gateway, nameservers); + return new IpDetails(datacenter, ipversion, ptr, platform, address, netmask, broadcast, gateway, nameServers, + serverId, cost, new GleSYSBoolean(reserved)); } - public Builder address(String address) { - this.address = address; - return this; + public T fromIpDetails(IpDetails in) { + return this.datacenter(in.getDatacenter()) + .version(in.getVersion()) + .ptr(in.getPtr()) + .platform(in.getPlatform()) + .address(in.getAddress()) + .netmask(in.getNetmask()) + .broadcast(in.getBroadcast()) + .gateway(in.getGateway()) + .nameServers(in.getNameServers()) + .serverId(in.getServerId()) + .cost(in.getCost()) + .reserved(in.isReserved()); } + } - public Builder netmask(String netmask) { - this.netmask = netmask; - return this; - } - - public Builder broadcast(String broadcast) { - this.broadcast = broadcast; - return this; - } - - public Builder gateway(String gateway) { - this.gateway = gateway; - return this; - } - - public Builder nameServers(String... nameServers) { - this.nameservers = Arrays.asList(nameServers); + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { return this; } } - protected String datacenter; - protected String ipversion; - @SerializedName("PTR") - protected String ptr; - protected String platform; - protected String address; - protected String netmask; - protected String broadcast; - protected String gateway; - protected List nameservers; + private final String datacenter; + private final int version; + private final String ptr; + private final String platform; + private final String address; + private final String netmask; + private final String broadcast; + private final String gateway; + private final List nameServers; + private final String serverId; + private final Cost cost; + private final boolean reserved; - public IpDetails(String datacenter, String ipversion, String ptr, String platform, - @Nullable String address, @Nullable String netmask, - @Nullable String broadcast, @Nullable String gateway, - @Nullable List nameservers) { - this.datacenter = datacenter; - this.ipversion = ipversion; - this.ptr = ptr; - this.platform = platform; + @ConstructorProperties({ + "datacenter", "ipversion", "ptr", "platform", "ipaddress", "netmask", "broadcast", "gateway", "nameservers", + "serverid", "cost", "reserved" + }) + protected IpDetails(String datacenter, int version, String ptr, String platform, String address, + @Nullable String netmask, @Nullable String broadcast, @Nullable String gateway, + List nameServers, @Nullable String serverId, Cost cost, GleSYSBoolean reserved) { + this.datacenter = checkNotNull(datacenter, "datacenter"); + this.version = checkNotNull(version, "version"); + this.ptr = checkNotNull(ptr, "ptr"); + this.platform = checkNotNull(platform, "platform"); this.address = address; this.netmask = netmask; this.broadcast = broadcast; this.gateway = gateway; - this.nameservers = nameservers; + this.nameServers = ImmutableList.copyOf(nameServers); + this.serverId = serverId; + this.cost = checkNotNull(cost, "cost"); + this.reserved = checkNotNull(reserved, "reserved").getValue(); } public String getDatacenter() { - return datacenter; + return this.datacenter; } - public String getIpversion() { - return ipversion; + /** + * @return the IP version, ex. 4 + */ + public int getVersion() { + return this.version; } public String getPtr() { - return ptr; + return this.ptr; } public String getPlatform() { - return platform; + return this.platform; } public String getAddress() { - return address; + return this.address; } + @Nullable public String getNetmask() { - return netmask; + return this.netmask; } + @Nullable public String getBroadcast() { - return broadcast; + return this.broadcast; } + @Nullable public String getGateway() { - return gateway; + return this.gateway; } public List getNameServers() { - return nameservers; + return this.nameServers; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + @Nullable + public String getServerId() { + return serverId; + } - IpDetails ipDetails = (IpDetails) o; + public Cost getCost() { + return cost; + } - if (address != null ? !address.equals(ipDetails.address) : ipDetails.address != null) return false; - if (broadcast != null ? !broadcast.equals(ipDetails.broadcast) : ipDetails.broadcast != null) return false; - if (datacenter != null ? !datacenter.equals(ipDetails.datacenter) : ipDetails.datacenter != null) return false; - if (gateway != null ? !gateway.equals(ipDetails.gateway) : ipDetails.gateway != null) return false; - if (ipversion != null ? !ipversion.equals(ipDetails.ipversion) : ipDetails.ipversion != null) return false; - if (netmask != null ? !netmask.equals(ipDetails.netmask) : ipDetails.netmask != null) return false; - if (platform != null ? !platform.equals(ipDetails.platform) : ipDetails.platform != null) return false; - if (ptr != null ? !ptr.equals(ipDetails.ptr) : ipDetails.ptr != null) return false; - if (nameservers != null ? !nameservers.equals(ipDetails.nameservers) : ipDetails.nameservers != null) - return false; - - return true; + public boolean isReserved() { + return reserved; } @Override public int hashCode() { - int result = datacenter != null ? datacenter.hashCode() : 0; - result = 31 * result + (ipversion != null ? ipversion.hashCode() : 0); - result = 31 * result + (ptr != null ? ptr.hashCode() : 0); - result = 31 * result + (platform != null ? platform.hashCode() : 0); - result = 31 * result + (address != null ? address.hashCode() : 0); - result = 31 * result + (netmask != null ? netmask.hashCode() : 0); - result = 31 * result + (broadcast != null ? broadcast.hashCode() : 0); - result = 31 * result + (gateway != null ? gateway.hashCode() : 0); - return result; + return Objects.hashCode(datacenter, version, ptr, platform, address, netmask, broadcast, gateway, nameServers, + serverId, cost, reserved); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + IpDetails that = IpDetails.class.cast(obj); + return Objects.equal(this.datacenter, that.datacenter) + && Objects.equal(this.version, that.version) + && Objects.equal(this.ptr, that.ptr) + && Objects.equal(this.platform, that.platform) + && Objects.equal(this.address, that.address) + && Objects.equal(this.netmask, that.netmask) + && Objects.equal(this.broadcast, that.broadcast) + && Objects.equal(this.gateway, that.gateway) + && Objects.equal(this.nameServers, that.nameServers) + && Objects.equal(this.serverId, that.serverId) + && Objects.equal(this.cost, that.cost) + && Objects.equal(this.reserved, that.reserved); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("datacenter", datacenter).add("ipversion", version).add("ptr", ptr).add("platform", platform) + .add("address", address).add("netmask", netmask).add("broadcast", broadcast).add("gateway", gateway) + .add("nameServers", nameServers).add("serverId", serverId).add("cost", cost).add("reserved", reserved); } @Override public String toString() { - return String.format("IpDetails[datacenter=%s, ipversion=%s, platform=%s, PTR=%s, " + - "address=%s, netmask=%s, broadcast=%s, gateway=%s", - datacenter, ipversion, platform, ptr, address, netmask, broadcast, gateway); + return string().toString(); } -} + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/OSTemplate.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/OSTemplate.java index e516280554..b96b1c35e0 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/OSTemplate.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/OSTemplate.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,9 +18,12 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; -import com.google.common.collect.Ordering; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Operating system template @@ -28,73 +31,106 @@ import com.google.gson.annotations.SerializedName; * @author Adam Lowe * @see */ -public class OSTemplate implements Comparable{ +public class OSTemplate { - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private String name; - private int minDiskSize; - private int minMemSize; - private String os; - private String platform; + public Builder toBuilder() { + return new ConcreteBuilder().fromOSTemplate(this); + } - public Builder name(String name) { - this.name = name; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected String name; + protected int minDiskSize; + protected int minMemSize; + protected String os; + protected String platform; + + /** + * @see OSTemplate#getName() + */ + public T name(String name) { + this.name = checkNotNull(name, "name"); + return self(); } - public Builder minDiskSize(int minDiskSize) { + /** + * @see OSTemplate#getMinDiskSize() + */ + public T minDiskSize(int minDiskSize) { this.minDiskSize = minDiskSize; - return this; + return self(); } - public Builder minMemSize(int minMemSize) { + /** + * @see OSTemplate#getMinMemSize() + */ + public T minMemSize(int minMemSize) { this.minMemSize = minMemSize; - return this; + return self(); } - public Builder os(String os) { - this.os = os; - return this; + /** + * @see OSTemplate#getOs() + */ + public T os(String os) { + this.os = checkNotNull(os, "os"); + return self(); } - public Builder platform(String platform) { - this.platform = platform; - return this; + /** + * @see OSTemplate#getPlatform() + */ + public T platform(String platform) { + this.platform = checkNotNull(platform, "platform"); + return self(); } public OSTemplate build() { return new OSTemplate(name, minDiskSize, minMemSize, os, platform); } - public Builder fromTemplate(OSTemplate in) { - return name(in.getName()).minDiskSize(in.getMinDiskSize()).minMemSize(in.getMinMemSize()).os(in.getOs()).platform(in.getPlatform()); + public T fromOSTemplate(OSTemplate in) { + return this.name(in.getName()) + .minDiskSize(in.getMinDiskSize()) + .minMemSize(in.getMinMemSize()) + .os(in.getOs()) + .platform(in.getPlatform()); } + } + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } } private final String name; - @SerializedName("minimumdisksize") private final int minDiskSize; - @SerializedName("minimummemorysize") private final int minMemSize; - @SerializedName("operatingsystem") private final String os; private final String platform; - public OSTemplate(String name, int minDiskSize, int minMemSize, String os, String platform) { - this.name = name; + @ConstructorProperties({ + "name", "minimumdisksize", "minimummemorysize", "operatingsystem", "platform" + }) + protected OSTemplate(String name, int minDiskSize, int minMemSize, String os, String platform) { + this.name = checkNotNull(name, "name"); this.minDiskSize = minDiskSize; this.minMemSize = minMemSize; - this.os = os; - this.platform = platform; + this.os = checkNotNull(os, "os"); + this.platform = checkNotNull(platform, "platform"); } + /** + */ public String getName() { - return name; + return this.name; } /** @@ -102,7 +138,7 @@ public class OSTemplate implements Comparable{ * @see org.jclouds.glesys.domain.AllowedArgumentsForCreateServer#getDiskSizesInGB() */ public int getMinDiskSize() { - return minDiskSize; + return this.minDiskSize; } /** @@ -110,35 +146,21 @@ public class OSTemplate implements Comparable{ * @see org.jclouds.glesys.domain.AllowedArgumentsForCreateServer#getMemorySizesInMB() */ public int getMinMemSize() { - return minMemSize; + return this.minMemSize; } /** * @return the name of the operating system type ex. "linux" */ public String getOs() { - return os; + return this.os; } /** * @return the name of the platform this template is available in, ex. "Xen" */ public String getPlatform() { - return platform; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof OSTemplate) { - final OSTemplate other = (OSTemplate) object; - return Objects.equal(name, other.name) - && Objects.equal(platform, other.platform); - } else { - return false; - } + return this.platform; } @Override @@ -147,13 +169,22 @@ public class OSTemplate implements Comparable{ } @Override - public String toString() { - return String.format("[name=%s, min_disk_size=%d, min_mem_size=%d, os=%s, platform=%s]", - name, minDiskSize, minMemSize, os, platform); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + OSTemplate that = OSTemplate.class.cast(obj); + return Objects.equal(this.name, that.name) + && Objects.equal(this.platform, that.platform); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("name", name).add("minDiskSize", minDiskSize).add("minMemSize", minMemSize).add("os", os).add("platform", platform); } @Override - public int compareTo(OSTemplate arg0) { - return Ordering.usingToString().compare(this, arg0); + public String toString() { + return string().toString(); } -} + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceStatus.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceStatus.java new file mode 100644 index 0000000000..edf5a4a918 --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceStatus.java @@ -0,0 +1,149 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Detailed information on usage + * + * @author Adam Lowe + * @see ServerStatus + */ +public class ResourceStatus { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromResourceUsage(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected double usage; + protected double max; + protected String unit; + + /** + * @see ResourceStatus#getUsage() + */ + public T usage(double usage) { + this.usage = usage; + return self(); + } + + /** + * @see ResourceStatus#getMax() + */ + public T max(double max) { + this.max = max; + return self(); + } + + /** + * @see ResourceStatus#getUnit() + */ + public T unit(String unit) { + this.unit = checkNotNull(unit, "unit"); + return self(); + } + + public ResourceStatus build() { + return new ResourceStatus(usage, max, unit); + } + + public T fromResourceUsage(ResourceStatus in) { + return this.usage(in.getUsage()).max(in.getMax()).unit(in.getUnit()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final double usage; + private final double max; + private final String unit; + + @ConstructorProperties({ + "usage", "max", "unit" + }) + protected ResourceStatus(double usage, double max, String unit) { + this.usage = usage; + this.max = max; + this.unit = checkNotNull(unit, "unit"); + } + + /** + * @return the usage in #unit + */ + public double getUsage() { + return this.usage; + } + + /** + * @return the max usage in #unit + */ + public double getMax() { + return this.max; + } + + /** + * @return the unit used + */ + public String getUnit() { + return this.unit; + } + + @Override + public int hashCode() { + return Objects.hashCode(usage, max, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ResourceStatus that = ResourceStatus.class.cast(obj); + return Objects.equal(this.usage, that.usage) + && Objects.equal(this.max, that.max) + && Objects.equal(this.unit, that.unit); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("usage", usage).add("max", max).add("unit", unit); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsage.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsage.java index 6bc3ade688..34c8dcd4c6 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsage.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsage.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,103 +18,120 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; +import java.util.Set; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; /** * Detailed information on usage * * @author Adam Lowe - * @see ServerStatus + * @see ResourceUsageInfo + * @see ResourceUsageValue */ - public class ResourceUsage { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private double usage; - private double max; - private String unit; + public Builder toBuilder() { + return new ConcreteBuilder().fromResourceUsages(this); + } - public Builder usage(double usage) { - this.usage = usage; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected ResourceUsageInfo info; + protected Set values = ImmutableSet.of(); + + /** + * @see ResourceUsage#getInfo() + */ + public T info(ResourceUsageInfo info) { + this.info = checkNotNull(info, "info"); + return self(); } - public Builder max(double max) { - this.max = max; - return this; + /** + * @see ResourceUsage#getValues() + */ + public T values(Set values) { + this.values = ImmutableSet.copyOf(checkNotNull(values, "values")); + return self(); } - public Builder unit(String unit) { - this.unit = unit; - return this; + /** + * @see ResourceUsage#getValues() + */ + public T values(ResourceUsageValue... in) { + return values(ImmutableSet.copyOf(in)); } public ResourceUsage build() { - return new ResourceUsage(usage, max, unit); + return new ResourceUsage(info, values); } - public Builder fromCpu(ResourceUsage in) { - return usage(in.getUsage()).max(in.getMax()).unit(in.getUnit()); + public T fromResourceUsages(ResourceUsage in) { + return this + .info(in.getInfo()) + .values(in.getValues()); } } - private final double usage; - private final double max; - private final String unit; - - public ResourceUsage(double usage, double max, String unit) { - this.usage = usage; - this.max = max; - this.unit = unit; - } - - /** - * @return the usage in #unit - */ - public double getUsage() { - return usage; - } - - /** - * @return the max usage in #unit - */ - public double getMax() { - return max; - } - - /** - * @return the unit used - */ - public String getUnit() { - return unit; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof ResourceUsage) { - ResourceUsage other = (ResourceUsage) object; - return Objects.equal(usage, other.usage) - && Objects.equal(max, other.max) - && Objects.equal(unit, other.unit); - } else { - return false; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } + private final ResourceUsageInfo info; + private final Set values; + + @ConstructorProperties({ + "info", "values" + }) + protected ResourceUsage(ResourceUsageInfo info, Set values) { + this.info = checkNotNull(info, "info"); + this.values = ImmutableSet.copyOf(checkNotNull(values, "values")); + } + + public ResourceUsageInfo getInfo() { + return this.info; + } + + public Set getValues() { + return this.values; + } + @Override public int hashCode() { - return Objects.hashCode(usage, max, unit); + return Objects.hashCode(info, values); } - + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ResourceUsage that = ResourceUsage.class.cast(obj); + return Objects.equal(this.info, that.info) + && Objects.equal(this.values, that.values); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("info", info).add("values", values); + } + @Override public String toString() { - return String.format("[usage=%f, max=%f, unit=%s]", - usage, max, unit); + return string().toString(); } -} + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageInfo.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageInfo.java new file mode 100644 index 0000000000..9a0dbc3633 --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageInfo.java @@ -0,0 +1,144 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Detailed information on usage + * + * @author Adam Lowe + * @see ServerStatus + */ +public class ResourceUsageInfo { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromResourceUsageInfo(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected String resource; + protected String resolution; + protected String unit; + + /** + * @see ResourceUsageInfo#getResource() + */ + public T resource(String resource) { + this.resource = checkNotNull(resource, "resource"); + return self(); + } + + /** + * @see ResourceUsageInfo#getResolution() + */ + public T resolution(String resolution) { + this.resolution = checkNotNull(resolution, "resolution"); + return self(); + } + + /** + * @see ResourceUsageInfo#getUnit() + */ + public T unit(String unit) { + this.unit = checkNotNull(unit, "unit"); + return self(); + } + + public ResourceUsageInfo build() { + return new ResourceUsageInfo(resource, resolution, unit); + } + + public T fromResourceUsageInfo(ResourceUsageInfo in) { + return this + .resource(in.getResource()) + .resolution(in.getResolution()) + .unit(in.getUnit()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String resource; + private final String resolution; + private final String unit; + + @ConstructorProperties({ + "type", "resolution", "unit" + }) + protected ResourceUsageInfo(String resource, String resolution, String unit) { + this.resource = checkNotNull(resource, "resource"); + this.resolution = checkNotNull(resolution, "resolution"); + this.unit = checkNotNull(unit, "unit"); + } + + public String getResource() { + return this.resource; + } + + public String getResolution() { + return this.resolution; + } + + public String getUnit() { + return this.unit; + } + + @Override + public int hashCode() { + return Objects.hashCode(resource, resolution, unit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ResourceUsageInfo that = ResourceUsageInfo.class.cast(obj); + return Objects.equal(this.resource, that.resource) + && Objects.equal(this.resolution, that.resolution) + && Objects.equal(this.unit, that.unit); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("resource", resource).add("resolution", resolution).add("unit", unit); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageValue.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageValue.java new file mode 100644 index 0000000000..3b42ad75ea --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageValue.java @@ -0,0 +1,128 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; +import java.util.Date; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Detailed information on usage + * + * @author Adam Lowe + * @see org.jclouds.glesys.domain.ServerStatus + */ +public class ResourceUsageValue { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromResourceUsage(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected double value; + protected Date timestamp; + + + /** + * @see ResourceUsageValue#getValue() + */ + public T value(double value) { + this.value = value; + return self(); + } + + /** + * @see ResourceUsageValue#getTimestamp() + */ + public T timestamp(Date timestamp) { + this.timestamp = checkNotNull(timestamp, "timestamp"); + return self(); + } + + public ResourceUsageValue build() { + return new ResourceUsageValue(value, timestamp); + } + + public T fromResourceUsage(ResourceUsageValue in) { + return this + .value(in.getValue()) + .timestamp(in.getTimestamp()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final double value; + private final Date timestamp; + + @ConstructorProperties({ + "value", "timestamp" + }) + protected ResourceUsageValue(double value, Date timestamp) { + this.value = value; + this.timestamp = checkNotNull(timestamp, "timestamp"); + } + + public double getValue() { + return this.value; + } + + public Date getTimestamp() { + return this.timestamp; + } + + @Override + public int hashCode() { + return Objects.hashCode(value, timestamp); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ResourceUsageValue that = ResourceUsageValue.class.cast(obj); + return Objects.equal(this.value, that.value) + && Objects.equal(this.timestamp, that.timestamp); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("value", value).add("timestamp", timestamp); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Server.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Server.java index c4cfe3ca7b..535275f354 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/Server.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/Server.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,9 +20,11 @@ package org.jclouds.glesys.domain; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; + import com.google.common.base.CaseFormat; import com.google.common.base.Objects; -import com.google.gson.annotations.SerializedName; +import com.google.common.base.Objects.ToStringHelper; /** * Listing of a server. @@ -30,8 +32,10 @@ import com.google.gson.annotations.SerializedName; * @author Adrian Cole * @see */ -public class Server implements Comparable { - +public class Server { + + /** + */ public static enum State { RUNNING, LOCKED, STOPPED, UNRECOGNIZED; @@ -53,53 +57,80 @@ public class Server implements Comparable { } } } - - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { + public Builder toBuilder() { + return new ConcreteBuilder().fromServer(this); + } + + public static abstract class Builder> { + protected abstract T self(); + protected String id; protected String hostname; protected String datacenter; protected String platform; - public Builder id(String id) { - this.id = id; - return this; + /** + * @see Server#getId() + */ + public T id(String id) { + this.id = checkNotNull(id, "id"); + return self(); } - public Builder hostname(String hostname) { - this.hostname = hostname; - return this; + /** + * @see Server#getHostname() + */ + public T hostname(String hostname) { + this.hostname = checkNotNull(hostname, "hostname"); + return self(); } - public Builder datacenter(String datacenter) { - this.datacenter = datacenter; - return this; + /** + * @see Server#getDatacenter() + */ + public T datacenter(String datacenter) { + this.datacenter = checkNotNull(datacenter, "datacenter"); + return self(); } - public Builder platform(String platform) { - this.platform = platform; - return this; + /** + * @see Server#getPlatform() + */ + public T platform(String platform) { + this.platform = checkNotNull(platform, "platform"); + return self(); } public Server build() { return new Server(id, hostname, datacenter, platform); } - public Builder fromServer(Server in) { - return datacenter(in.getDatacenter()).platform(in.getPlatform()).hostname(in.getHostname()).id(in.getId()); + public T fromServer(Server in) { + return this.id(in.getId()).hostname(in.getHostname()).datacenter(in.getDatacenter()).platform(in.getPlatform()); } } - @SerializedName("serverid") - protected final String id; - protected final String hostname; - protected final String datacenter; - protected final String platform; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } - public Server(String id, String hostname, String datacenter, String platform) { + private final String id; + private final String hostname; + private final String datacenter; + private final String platform; + + @ConstructorProperties({ + "serverid", "hostname", "datacenter", "platform" + }) + protected Server(String id, String hostname, String datacenter, String platform) { this.id = checkNotNull(id, "id"); this.hostname = checkNotNull(hostname, "hostname"); this.datacenter = checkNotNull(datacenter, "datacenter"); @@ -110,45 +141,28 @@ public class Server implements Comparable { * @return the generated id of the server */ public String getId() { - return id; + return this.id; } /** * @return the hostname of the server */ public String getHostname() { - return hostname; + return this.hostname; } /** * @return platform running the server (ex. {@code OpenVZ}) */ - public String getPlatform() { - return platform; + public String getDatacenter() { + return this.datacenter; } /** * @return the datacenter the server exists in (ex. {@code Falkenberg}) */ - public String getDatacenter() { - return datacenter; - } - - @Override - public int compareTo(Server other) { - return id.compareTo(other.getId()); - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof Server) { - return Objects.equal(id, ((Server) object).id); - } else { - return false; - } + public String getPlatform() { + return this.platform; } @Override @@ -157,8 +171,21 @@ public class Server implements Comparable { } @Override - public String toString() { - return String.format("[id=%s, hostname=%s, datacenter=%s, platform=%s]", id, hostname, datacenter, platform); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Server that = Server.class.cast(obj); + return Objects.equal(this.id, that.id); } -} + protected ToStringHelper string() { + return Objects.toStringHelper("").add("id", id).add("hostname", hostname).add("datacenter", datacenter) + .add("platform", platform); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerDetails.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerDetails.java index c18ce42ce6..0e285f1d69 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerDetails.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerDetails.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,221 +20,239 @@ package org.jclouds.glesys.domain; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; import java.util.Set; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects.ToStringHelper; import com.google.common.collect.ImmutableSet; -import com.google.gson.annotations.SerializedName; /** * Detailed information about a server such as cpuCores, hardware configuration * (cpu, memory and disk), ip adresses, cost, transfer, os and more. - * + * * @author Adrian Cole * @see */ public class ServerDetails extends Server { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder extends Server.Builder { - private Server.State state; - private String description; - private String templateName; - private int cpuCores; - private int memorySizeMB; - private int diskSizeGB; - private int transferGB; - private Cost cost; - private Set ips = ImmutableSet.of(); + public Builder toBuilder() { + return new ConcreteBuilder().fromServerDetails(this); + } - public Builder state(Server.State state) { - this.state = state; - return this; + public static abstract class Builder> extends Server.Builder { + protected Server.State state; + protected String description; + protected String templateName; + protected int cpuCores; + protected int memorySizeMB; + protected int diskSizeGB; + protected int transferGB; + protected Cost cost; + protected Set ips = ImmutableSet.of(); + + /** + * @see ServerDetails#getState() + */ + public T state(Server.State state) { + this.state = checkNotNull(state, "state"); + return self(); } - public Builder description(String description) { - this.description = description; - return this; + /** + * @see ServerDetails#getDescription() + */ + public T description(String description) { + this.description = checkNotNull(description, "description"); + return self(); } - public Builder templateName(String templateName) { - this.templateName = templateName; - return this; + /** + * @see ServerDetails#getTemplateName() + */ + public T templateName(String templateName) { + this.templateName = checkNotNull(templateName, "templateName"); + return self(); } - public Builder cpuCores(int cpuCores) { + /** + * @see ServerDetails#getCpuCores() + */ + public T cpuCores(int cpuCores) { this.cpuCores = cpuCores; - return this; + return self(); } - public Builder memorySizeMB(int memorySizeMB) { + /** + * @see ServerDetails#getMemorySizeMB() + */ + public T memorySizeMB(int memorySizeMB) { this.memorySizeMB = memorySizeMB; - return this; + return self(); } - public Builder diskSizeGB(int diskSizeGB) { + /** + * @see ServerDetails#getDiskSizeGB() + */ + public T diskSizeGB(int diskSizeGB) { this.diskSizeGB = diskSizeGB; - return this; + return self(); } - public Builder transferGB(int transferGB) { + /** + * @see ServerDetails#getTransferGB() + */ + public T transferGB(int transferGB) { this.transferGB = transferGB; - return this; + return self(); } - public Builder cost(Cost cost) { - this.cost = cost; - return this; + /** + * @see ServerDetails#getCost() + */ + public T cost(Cost cost) { + this.cost = checkNotNull(cost, "cost"); + return self(); } - public Builder ips(Ip... ips) { - return ips(ImmutableSet.copyOf(ips)); + /** + * @see ServerDetails#getIps() + */ + public T ips(Set ips) { + this.ips = ImmutableSet.copyOf(checkNotNull(ips, "ips")); + return self(); } - public Builder ips(Iterable ips) { - this.ips = ImmutableSet.copyOf(ips); - return this; + public T ips(Ip... in) { + return ips(ImmutableSet.copyOf(in)); } public ServerDetails build() { - return new ServerDetails(id, hostname, datacenter, platform, state, templateName, description, cpuCores, - memorySizeMB, diskSizeGB, transferGB, cost, ips); + return new ServerDetails(id, hostname, datacenter, platform, state, description, templateName, cpuCores, memorySizeMB, diskSizeGB, transferGB, cost, ips); } - public Builder fromServerDetails(ServerDetails in) { - return fromServer(in).templateName(in.getTemplateName()).state(in.getState()).memorySizeMB(in.getMemorySizeMB()) - .diskSizeGB(in.getDiskSizeGB()).cpuCores(in.getCpuCores()).cost(in.getCost()) - .transferGB(in.getTransferGB()).description(in.getDescription()).ips(in.getIps()); + public T fromServerDetails(ServerDetails in) { + return super.fromServer(in) + .state(in.getState()) + .description(in.getDescription()) + .templateName(in.getTemplateName()) + .cpuCores(in.getCpuCores()) + .memorySizeMB(in.getMemorySizeMB()) + .diskSizeGB(in.getDiskSizeGB()) + .transferGB(in.getTransferGB()) + .cost(in.getCost()) + .ips(in.getIps()); } + } + private static class ConcreteBuilder extends Builder { @Override - public Builder id(String id) { - return Builder.class.cast(super.id(id)); - } - - @Override - public Builder hostname(String hostname) { - return Builder.class.cast(super.hostname(hostname)); - } - - @Override - public Builder datacenter(String datacenter) { - return Builder.class.cast(super.datacenter(datacenter)); - } - - @Override - public Builder platform(String platform) { - return Builder.class.cast(super.platform(platform)); - } - - @Override - public Builder fromServer(Server in) { - return Builder.class.cast(super.fromServer(in)); + protected ConcreteBuilder self() { + return this; } } private final Server.State state; private final String description; - @SerializedName("templatename") private final String templateName; - @SerializedName("cpucores") private final int cpuCores; - @SerializedName("memorysize") private final int memorySizeMB; - @SerializedName("disksize") private final int diskSizeGB; - @SerializedName("transfer") private final int transferGB; private final Cost cost; - @SerializedName("iplist") private final Set ips; - public ServerDetails(String id, String hostname, String datacenter, String platform, Server.State state, - String templateName, String description, int cpuCores, int memorySizeMB, int diskSizeGB, int transferGB, - Cost cost, Set ips) { + @ConstructorProperties({ + "serverid", "hostname", "datacenter", "platform", "state", "description", "templatename", "cpucores", + "memorysize", "disksize", "transfer", "cost", "iplist" + }) + protected ServerDetails(String id, String hostname, String datacenter, String platform, @Nullable Server.State state, + @Nullable String description, String templateName, int cpuCores, int memorySizeMB, + int diskSizeGB, int transferGB, Cost cost, @Nullable Set ips) { super(id, hostname, datacenter, platform); this.state = state; - this.templateName = checkNotNull(templateName, "template"); this.description = description; + this.templateName = checkNotNull(templateName, "templateName"); this.cpuCores = cpuCores; this.memorySizeMB = memorySizeMB; this.diskSizeGB = diskSizeGB; this.transferGB = transferGB; this.cost = checkNotNull(cost, "cost"); - this.ips = ImmutableSet. copyOf(ips); + this.ips = ips == null ? ImmutableSet.of() : ImmutableSet.copyOf(checkNotNull(ips, "ips")); } /** * @return the state of the server (e.g. "running") */ public Server.State getState() { - return state; + return this.state; } /** * @return the user-specified description of the server */ public String getDescription() { - return description; - } - - /** - * @return number of cores on the server - */ - public int getCpuCores() { - return cpuCores; - } - - /** - * @return the disk of the server in GB - */ - public int getDiskSizeGB() { - return diskSizeGB; - } - - /** - * @return the memory of the server in MB - */ - public int getMemorySizeMB() { - return memorySizeMB; - } - - /** - * @return the transfer of the server - */ - public int getTransferGB() { - return transferGB; - } - - /** - * @return details of the cost of the server - */ - public Cost getCost() { - return cost; - } - - /** - * @return the ip addresses assigned to the server - */ - public Set getIps() { - return ips; + return this.description; } /** * @return the name of the template used to create the server */ public String getTemplateName() { - return templateName; + return this.templateName; } - @Override - public String toString() { - return String - .format( - "[id=%s, hostname=%s, datacenter=%s, platform=%s, templateName=%s, state=%s, description=%s, cpuCores=%d, memorySizeMB=%d, diskSizeGB=%d, transferGB=%d, cost=%s, ips=%s]", - id, hostname, datacenter, platform, templateName, state, description, cpuCores, memorySizeMB, - diskSizeGB, transferGB, cost, ips); + /** + * @return number of cores on the server + */ + public int getCpuCores() { + return this.cpuCores; } -} + /** + * @return the memory of the server in MB + */ + public int getMemorySizeMB() { + return this.memorySizeMB; + } + + /** + * @return the disk of the server in GB + */ + public int getDiskSizeGB() { + return this.diskSizeGB; + } + + /** + * @return the transfer of the server + */ + public int getTransferGB() { + return this.transferGB; + } + + /** + * @return details of the cost of the server + */ + public Cost getCost() { + return this.cost; + } + + /** + * @return the ip addresses assigned to the server + */ + public Set getIps() { + return this.ips; + } + + protected ToStringHelper string() { + return super.string().add("state", state).add("description", description).add("templateName", templateName) + .add("cpuCores", cpuCores).add("memorySizeMB", memorySizeMB).add("diskSizeGB", diskSizeGB) + .add("transferGB", transferGB).add("cost", cost).add("ips", ips); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerLimit.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerLimit.java index 3a3a60b627..3f13bd0ae0 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerLimit.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerLimit.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,54 +18,94 @@ */ package org.jclouds.glesys.domain; +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Detailed information about an OpenVZ server's limits - * + * * @author Adam Lowe * @see */ public class ServerLimit { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private int held; - private int maxHeld; - private int barrier; - private int limit; - private int failCount; + public Builder toBuilder() { + return new ConcreteBuilder().fromServerLimit(this); + } - public Builder held(int held) { + public static abstract class Builder> { + protected abstract T self(); + + protected long held; + protected long maxHeld; + protected long barrier; + protected long limit; + protected long failCount; + + /** + * @see ServerLimit#getHeld() + */ + public T held(long held) { this.held = held; - return this; + return self(); } - public Builder maxHeld(int maxHeld) { + /** + * @see ServerLimit#getMaxHeld() + */ + public T maxHeld(long maxHeld) { this.maxHeld = maxHeld; - return this; + return self(); } - public Builder barrier(int barrier) { + /** + * @see ServerLimit#getBarrier() + */ + public T barrier(long barrier) { this.barrier = barrier; - return this; + return self(); } - public Builder limit(int limit) { + /** + * @see ServerLimit#getLimit() + */ + public T limit(long limit) { this.limit = limit; - return this; + return self(); } - public Builder failCount(int failCount) { + /** + * @see ServerLimit#getFailCount() + */ + public T failCount(long failCount) { this.failCount = failCount; - return this; + return self(); } public ServerLimit build() { return new ServerLimit(held, maxHeld, barrier, limit, failCount); } + + public T fromServerLimit(ServerLimit in) { + return this.held(in.getHeld()) + .maxHeld(in.getMaxHeld()) + .barrier(in.getBarrier()) + .limit(in.getLimit()) + .failCount(in.getFailCount()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } } private final long held; @@ -74,7 +114,10 @@ public class ServerLimit { private final long limit; private final long failCount; - public ServerLimit(long held, long maxHeld, long barrier, long limit, long failCount) { + @ConstructorProperties({ + "held", "maxHeld", "barrier", "limit", "failCount" + }) + protected ServerLimit(long held, long maxHeld, long barrier, long limit, long failCount) { this.held = held; this.maxHeld = maxHeld; this.barrier = barrier; @@ -83,40 +126,23 @@ public class ServerLimit { } public long getHeld() { - return held; + return this.held; } public long getMaxHeld() { - return maxHeld; + return this.maxHeld; } public long getBarrier() { - return barrier; + return this.barrier; } public long getLimit() { - return limit; + return this.limit; } public long getFailCount() { - return failCount; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof ServerLimit) { - final ServerLimit other = (ServerLimit) object; - return Objects.equal(held, other.held) - && Objects.equal(maxHeld, other.maxHeld) - && Objects.equal(barrier, other.barrier) - && Objects.equal(limit, other.limit) - && Objects.equal(failCount, other.failCount); - } else { - return false; - } + return this.failCount; } @Override @@ -125,7 +151,25 @@ public class ServerLimit { } @Override - public String toString() { - return String.format("[held=%d, maxHeld=%d, barrier=%d, limit=%d, failCount=%d]", held, maxHeld, barrier, limit, failCount); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ServerLimit that = ServerLimit.class.cast(obj); + return Objects.equal(this.held, that.held) + && Objects.equal(this.maxHeld, that.maxHeld) + && Objects.equal(this.barrier, that.barrier) + && Objects.equal(this.limit, that.limit) + && Objects.equal(this.failCount, that.failCount); } -} + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("held", held).add("maxHeld", maxHeld).add("barrier", barrier) + .add("limit", limit).add("failCount", failCount); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerSpec.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerSpec.java index 3ddb6031a1..513b121a9b 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerSpec.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerSpec.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,92 +18,129 @@ */ package org.jclouds.glesys.domain; -import static com.google.common.base.Objects.equal; -import static com.google.common.base.Objects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** - * - * + * Class ServerSpec + * * @author Adrian Cole */ public class ServerSpec { - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new ConcreteBuilder(); } - public Builder toBuilder() { - return Builder.fromServerSpecification(this); + public Builder toBuilder() { + return new ConcreteBuilder().fromServerSpec(this); } - public static class Builder { - protected String datacenter; + public static abstract class Builder> { + protected abstract T self(); + protected String platform; - protected String templateName; - protected int diskSizeGB; + protected String datacenter; protected int memorySizeMB; + protected int diskSizeGB; + protected String templateName; protected int cpuCores; protected int transferGB; - public Builder datacenter(String datacenter) { - this.datacenter = datacenter; - return this; + /** + * @see ServerSpec#getPlatform() + */ + public T platform(String platform) { + this.platform = checkNotNull(platform, "platform"); + return self(); } - public Builder platform(String platform) { - this.platform = platform; - return this; + /** + * @see ServerSpec#getDatacenter() + */ + public T datacenter(String datacenter) { + this.datacenter = checkNotNull(datacenter, "datacenter"); + return self(); } - public Builder templateName(String templateName) { - this.templateName = templateName; - return this; - } - - public Builder diskSizeGB(int diskSizeGB) { - this.diskSizeGB = diskSizeGB; - return this; - } - - public Builder memorySizeMB(int memorySizeMB) { + /** + * @see ServerSpec#getMemorySizeMB() + */ + public T memorySizeMB(int memorySizeMB) { this.memorySizeMB = memorySizeMB; - return this; + return self(); } - public Builder cpuCores(int cpuCores) { + /** + * @see ServerSpec#getDiskSizeGB() + */ + public T diskSizeGB(int diskSizeGB) { + this.diskSizeGB = diskSizeGB; + return self(); + } + + /** + * @see ServerSpec#getTemplateName() + */ + public T templateName(String templateName) { + this.templateName = checkNotNull(templateName, "templateName"); + return self(); + } + + /** + * @see ServerSpec#getCpuCores() + */ + public T cpuCores(int cpuCores) { this.cpuCores = cpuCores; - return this; + return self(); } - public Builder transferGB(int transferGB) { + /** + * @see ServerSpec#getTransferGB() + */ + public T transferGB(int transferGB) { this.transferGB = transferGB; - return this; + return self(); } public ServerSpec build() { return new ServerSpec(platform, datacenter, memorySizeMB, diskSizeGB, templateName, cpuCores, transferGB); } - public static Builder fromServerSpecification(ServerSpec in) { - return new Builder().platform(in.getPlatform()).datacenter(in.getDatacenter()) - .memorySizeMB(in.getMemorySizeMB()).diskSizeGB(in.getDiskSizeGB()).templateName(in.getTemplateName()) - .cpuCores(in.getCpuCores()).transferGB(in.getTransferGB()); + public T fromServerSpec(ServerSpec in) { + return this.platform(in.getPlatform()) + .datacenter(in.getDatacenter()) + .memorySizeMB(in.getMemorySizeMB()) + .diskSizeGB(in.getDiskSizeGB()) + .templateName(in.getTemplateName()) + .cpuCores(in.getCpuCores()) + .transferGB(in.getTransferGB()); } } - protected final String platform; - protected final String datacenter; - protected final int memorySizeMB; - protected final int diskSizeGB; - protected final String templateName; - protected final int cpuCores; - protected final int transferGB; + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } - protected ServerSpec(String platform, String datacenter, int memorySizeMB, int diskSizeGB, String templateName, - int cpuCores, int transferGB) { + private final String platform; + private final String datacenter; + private final int memorySizeMB; + private final int diskSizeGB; + private final String templateName; + private final int cpuCores; + private final int transferGB; + + @ConstructorProperties({ + "platform", "datacenter", "memorySizeMB", "diskSizeGB", "templateName", "cpuCores", "transferGB" + }) + protected ServerSpec(String platform, String datacenter, int memorySizeMB, int diskSizeGB, String templateName, int cpuCores, int transferGB) { this.platform = checkNotNull(platform, "platform"); this.datacenter = checkNotNull(datacenter, "datacenter"); this.memorySizeMB = memorySizeMB; @@ -116,66 +153,50 @@ public class ServerSpec { /** * @return the data center to create the new server in */ - public String getDatacenter() { - return datacenter; + public String getPlatform() { + return this.platform; } /** * @return the platform to use (i.e. "Xen" or "OpenVZ") */ - public String getPlatform() { - return platform; + public String getDatacenter() { + return this.datacenter; } /** * @return the os template to use to create the new server */ - public String getTemplateName() { - return templateName; + public int getMemorySizeMB() { + return this.memorySizeMB; } /** * @return the amount of disk space, in GB, to allocate */ public int getDiskSizeGB() { - return diskSizeGB; + return this.diskSizeGB; } /** * @return the memory, in MB, to allocate */ - public int getMemorySizeMB() { - return memorySizeMB; + public String getTemplateName() { + return this.templateName; } /** * @return the number of CPU cores to allocate */ public int getCpuCores() { - return cpuCores; + return this.cpuCores; } /** * @return bandwidth of in GB */ public int getTransferGB() { - return transferGB; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof ServerSpec) { - final ServerSpec that = ServerSpec.class.cast(object); - return equal(platform, that.platform) && equal(datacenter, that.datacenter) - && equal(memorySizeMB, that.memorySizeMB) && equal(diskSizeGB, that.diskSizeGB) - && equal(templateName, that.templateName) && equal(cpuCores, that.cpuCores) - && equal(transferGB, that.transferGB); - } else { - return false; - } + return this.transferGB; } @Override @@ -184,9 +205,27 @@ public class ServerSpec { } @Override - public String toString() { - return toStringHelper("").add("platform", platform).add("datacenter", datacenter) - .add("templateName", templateName).add("cpuCores", cpuCores).add("memorySizeMB", memorySizeMB) - .add("diskSizeGB", diskSizeGB).add("transferGB", transferGB).toString(); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ServerSpec that = ServerSpec.class.cast(obj); + return Objects.equal(this.platform, that.platform) + && Objects.equal(this.datacenter, that.datacenter) + && Objects.equal(this.memorySizeMB, that.memorySizeMB) + && Objects.equal(this.diskSizeGB, that.diskSizeGB) + && Objects.equal(this.templateName, that.templateName) + && Objects.equal(this.cpuCores, that.cpuCores) + && Objects.equal(this.transferGB, that.transferGB); } -} + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("platform", platform).add("datacenter", datacenter) + .add("memorySizeMB", memorySizeMB).add("diskSizeGB", diskSizeGB).add("templateName", templateName) + .add("cpuCores", cpuCores).add("transferGB", transferGB); + } + + @Override + public String toString() { + return string().toString(); + } +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerStatus.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerStatus.java index 4b3dfc797e..f8cc218c50 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerStatus.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerStatus.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +18,14 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Detailed information server status including hardware usage (cpu, memory and disk), bandwidth and up-time. @@ -26,62 +33,93 @@ import com.google.common.base.Objects; * @author Adam Lowe * @see */ - public class ServerStatus { - public static Builder builder() { - return new Builder(); + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private Server.State state; - private ResourceUsage cpu; - private ResourceUsage memory; - private ResourceUsage disk; - private ServerUptime uptime; + public Builder toBuilder() { + return new ConcreteBuilder().fromServerStatus(this); + } - public Builder state(Server.State state) { - this.state = state; - return this; + public static abstract class Builder> { + protected abstract T self(); + + protected Server.State state; + protected ResourceStatus cpu; + protected ResourceStatus memory; + protected ResourceStatus disk; + protected ServerUptime uptime; + + /** + * @see ServerStatus#getState() + */ + public T state(Server.State state) { + this.state = checkNotNull(state, "state"); + return self(); } - public Builder cpu(ResourceUsage cpu) { - this.cpu = cpu; - return this; + /** + * @see ServerStatus#getCpu() + */ + public T cpu(ResourceStatus cpu) { + this.cpu = checkNotNull(cpu, "cpu"); + return self(); } - public Builder memory(ResourceUsage memory) { - this.memory = memory; - return this; + /** + * @see ServerStatus#getMemory() + */ + public T memory(ResourceStatus memory) { + this.memory = checkNotNull(memory, "memory"); + return self(); } - public Builder disk(ResourceUsage disk) { - this.disk = disk; - return this; + /** + * @see ServerStatus#getDisk() + */ + public T disk(ResourceStatus disk) { + this.disk = checkNotNull(disk, "disk"); + return self(); } - public Builder uptime(ServerUptime uptime) { - this.uptime = uptime; - return this; + /** + * @see ServerStatus#getUptime() + */ + public T uptime(ServerUptime uptime) { + this.uptime = checkNotNull(uptime, "uptime"); + return self(); } public ServerStatus build() { return new ServerStatus(state, cpu, memory, disk, uptime); } - public Builder fromServerStatus(ServerStatus in) { - return state(in.getState()).cpu(in.getCpu()).memory(in.getMemory()).disk(in.getDisk()).uptime(in.getUptime()); + public T fromServerStatus(ServerStatus in) { + return this.state(in.getState()).cpu(in.getCpu()).memory(in.getMemory()).disk(in.getDisk()).uptime(in.getUptime()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } private final Server.State state; - private final ResourceUsage cpu; - private final ResourceUsage memory; - private final ResourceUsage disk; + private final ResourceStatus cpu; + private final ResourceStatus memory; + private final ResourceStatus disk; private final ServerUptime uptime; - public ServerStatus(Server.State state, ResourceUsage cpu, ResourceUsage memory, ResourceUsage disk, ServerUptime uptime) { - this.state = state; + @ConstructorProperties({ + "state", "cpu", "memory", "disk", "uptime" + }) + protected ServerStatus(Server.State state, @Nullable ResourceStatus cpu, @Nullable ResourceStatus memory, + @Nullable ResourceStatus disk, @Nullable ServerUptime uptime) { + this.state = checkNotNull(state, "state"); this.cpu = cpu; this.memory = memory; this.disk = disk; @@ -91,64 +129,68 @@ public class ServerStatus { /** * @return the state of the server (e.g. "running") */ + @Nullable public Server.State getState() { - return state; + return this.state; } /** * @return CPU usage information */ - public ResourceUsage getCpu() { - return cpu; + @Nullable + public ResourceStatus getCpu() { + return this.cpu; } /** * @return details of memory usage and limits */ - public ResourceUsage getMemory() { - return memory; + @Nullable + public ResourceStatus getMemory() { + return this.memory; } /** * @return details of disk usage and limits */ - public ResourceUsage getDisk() { - return disk; + @Nullable + public ResourceStatus getDisk() { + return this.disk; } /** * @return the uptime of the server */ + @Nullable public ServerUptime getUptime() { - return uptime; - } - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object instanceof ServerStatus) { - final ServerStatus other = (ServerStatus) object; - return Objects.equal(state, other.state) - && Objects.equal(cpu, other.cpu) - && Objects.equal(memory, other.memory) - && Objects.equal(disk, other.disk) - && Objects.equal(uptime, other.uptime); - } else { - return false; - } + return this.uptime; } @Override public int hashCode() { return Objects.hashCode(state, cpu, memory, disk, uptime); } - + @Override - public String toString() { - return String.format("[state=%s, cpu=%s, memory=%s, disk=%s, uptime=%s]", - state, cpu, memory, disk, uptime); + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ServerStatus that = ServerStatus.class.cast(obj); + return Objects.equal(this.state, that.state) + && Objects.equal(this.cpu, that.cpu) + && Objects.equal(this.memory, that.memory) + && Objects.equal(this.disk, that.disk) + && Objects.equal(this.uptime, that.uptime); } -} + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("state", state).add("cpu", cpu).add("memory", memory).add("disk", disk).add("uptime", uptime); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerUptime.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerUptime.java index eb44a065ed..5b78d96203 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerUptime.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerUptime.java @@ -1,4 +1,4 @@ -/** +/* * Licensed to jclouds, Inc. (jclouds) under one or more * contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +18,12 @@ */ package org.jclouds.glesys.domain; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; + import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Represents an 'uptime' duration of server in a Glesys cloud @@ -27,64 +32,76 @@ import com.google.common.base.Objects; * @see ServerStatus */ public class ServerUptime { - public static Builder builder() { - return new Builder(); + + public static Builder builder() { + return new ConcreteBuilder(); } - public static class Builder { - private long current; - private String unit; - - public Builder current(long current) { + public Builder toBuilder() { + return new ConcreteBuilder().fromServerUptime(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected long current; + protected String unit; + + /** + * @see ServerUptime#getCurrent() + */ + public T current(long current) { this.current = current; - return this; + return self(); } - public Builder unit(String unit) { - this.unit = unit; - return this; + /** + * @see ServerUptime#getUnit() + */ + public T unit(String unit) { + this.unit = checkNotNull(unit, "unit"); + return self(); } - + public ServerUptime build() { return new ServerUptime(current, unit); } - - public Builder fromServerUptime(ServerUptime from) { - return current(from.getCurrent()).unit(from.getUnit()); + + public T fromServerUptime(ServerUptime in) { + return this.current(in.getCurrent()).unit(in.getUnit()); } } - + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + private final long current; private final String unit; - public ServerUptime(long current, String unit) { + @ConstructorProperties({ + "current", "unit" + }) + protected ServerUptime(long current, String unit) { this.current = current; - this.unit = unit; + this.unit = checkNotNull(unit, "unit"); } - + /** - * @return the time the server has been up in #unit + * @return the time the server has been up in #getUnit() */ public long getCurrent() { - return current; + return this.current; } /** - * @return the unit used for #time + * @return the unit used for #getCurrent() */ public String getUnit() { - return unit; - } - - - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - return object instanceof ServerUptime - && Objects.equal(current, ((ServerUptime) object).getCurrent()) - && Objects.equal(unit, ((ServerUptime) object).getUnit()); + return this.unit; } @Override @@ -92,9 +109,21 @@ public class ServerUptime { return Objects.hashCode(current, unit); } + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ServerUptime that = ServerUptime.class.cast(obj); + return Objects.equal(this.current, that.current) && Objects.equal(this.unit, that.unit); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("current", current).add("unit", unit); + } + @Override public String toString() { - return String.format("[current=%d unit=%s]", current, unit); + return string().toString(); } } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveAsyncClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveAsyncClient.java index a5af736daa..13fd47e76a 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveAsyncClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveAsyncClient.java @@ -29,7 +29,6 @@ import javax.ws.rs.core.MediaType; import org.jclouds.glesys.domain.Archive; import org.jclouds.glesys.domain.ArchiveAllowedArguments; -import org.jclouds.glesys.domain.ArchiveDetails; import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; @@ -61,21 +60,23 @@ public interface ArchiveAsyncClient { ListenableFuture> listArchives(); /** - * @see ArchiveClient#getArchiveDetails + * @see ArchiveClient#getArchive */ @POST @Path("/archive/details/format/json") @SelectJson("details") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getArchiveDetails(@FormParam("username") String username); + ListenableFuture getArchive(@FormParam("username") String username); /** * @see ArchiveClient#createArchive */ @POST @Path("/archive/create/format/json") - ListenableFuture createArchive(@FormParam("username") String username, @FormParam("password") String password, + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture createArchive(@FormParam("username") String username, @FormParam("password") String password, @FormParam("size")int size); /** @@ -90,13 +91,17 @@ public interface ArchiveAsyncClient { */ @POST @Path("/archive/resize/format/json") - ListenableFuture resizeArchive(@FormParam("username") String username, @FormParam("size") int size); + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture resizeArchive(@FormParam("username") String username, @FormParam("size") int size); /** * @see ArchiveClient#changeArchivePassword */ @POST @Path("/archive/changepassword/format/json") - ListenableFuture changeArchivePassword(@FormParam("username") String username, @FormParam("password") String password); + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture changeArchivePassword(@FormParam("username") String username, @FormParam("password") String password); /** * @see org.jclouds.glesys.features.ArchiveClient#getArchiveAllowedArguments diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveClient.java index 5b75a217fb..b3ee9c552e 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/ArchiveClient.java @@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; import org.jclouds.glesys.domain.Archive; import org.jclouds.glesys.domain.ArchiveAllowedArguments; -import org.jclouds.glesys.domain.ArchiveDetails; /** * Provides synchronous access to Archive requests. @@ -48,7 +47,7 @@ public interface ArchiveClient { * @param username the username associated with the archive * @return the archive information or null if not found */ - ArchiveDetails getArchiveDetails(String username); + Archive getArchive(String username); /** * Create a new backup volume. @@ -58,7 +57,7 @@ public interface ArchiveClient { * @param password the new password * @param size the new size required in GB */ - void createArchive(String username, String password, int size); + Archive createArchive(String username, String password, int size); /** * Delete an archive volume. All files on the volume @@ -75,7 +74,7 @@ public interface ArchiveClient { * @param username the username associated with the archive * @param size the new size required, see #getArchiveAllowedArguments for valid values */ - void resizeArchive(String username, int size); + Archive resizeArchive(String username, int size); /** * Change the password for an archive user. @@ -83,7 +82,7 @@ public interface ArchiveClient { * @param username the archive username * @param password the new password */ - void changeArchivePassword(String username, String password); + Archive changeArchivePassword(String username, String password); /** * Lists the allowed arguments for some of the functions in this module such as archive size. diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainAsyncClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainAsyncClient.java index 1bc6b375a7..23224acd3d 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainAsyncClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainAsyncClient.java @@ -37,6 +37,7 @@ import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import com.google.common.util.concurrent.ListenableFuture; @@ -61,19 +62,33 @@ public interface DomainAsyncClient { @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listDomains(); + /** + * @see org.jclouds.glesys.features.DomainClient#getDomain + */ + @POST + @Path("/domain/details/format/json") + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getDomain(@FormParam("domainname") String name); + /** * @see DomainClient#addDomain */ @POST @Path("/domain/add/format/json") - ListenableFuture addDomain(@FormParam("domainname") String name, AddDomainOptions... options); + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addDomain(@FormParam("domainname") String name, AddDomainOptions... options); /** * @see DomainClient#editDomain */ @POST @Path("/domain/edit/format/json") - ListenableFuture editDomain(@FormParam("domainname") String domain, DomainOptions... options); + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture editDomain(@FormParam("domainname") String domain, DomainOptions... options); /** @@ -97,7 +112,9 @@ public interface DomainAsyncClient { */ @POST @Path("/domain/addrecord/format/json") - ListenableFuture addRecord(@FormParam("domainname") String domain, @FormParam("host") String host, + @SelectJson("record") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addRecord(@FormParam("domainname") String domain, @FormParam("host") String host, @FormParam("type") String type, @FormParam("data") String data, AddRecordOptions... options); @@ -106,7 +123,9 @@ public interface DomainAsyncClient { */ @POST @Path("/domain/updaterecord/format/json") - ListenableFuture editRecord(@FormParam("recordid") String record_id, EditRecordOptions... options); + @SelectJson("record") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture editRecord(@FormParam("recordid") String record_id, EditRecordOptions... options); /** * @see DomainClient#deleteRecord diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainClient.java index 571f6d61cd..f4a9eb5f1b 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/DomainClient.java @@ -41,27 +41,36 @@ import org.jclouds.glesys.options.EditRecordOptions; public interface DomainClient { /** - * Get a list of all invoices for this account. + * Get a list of all domains for this account. * - * @return an account's associated invoice objects. + * @return an account's associated domain objects. */ Set listDomains(); /** - * Add a domain to the Glesys dns-system + * Get a specific domain. * - * @param domain the name of the domain to add. - * @param options optional parameters + * @return the requested domain object. */ - void addDomain(String domain, AddDomainOptions... options); + Domain getDomain(String domain); /** * Add a domain to the Glesys dns-system * * @param domain the name of the domain to add. * @param options optional parameters + * @return information about the added domain */ - void editDomain(String domain, DomainOptions... options); + Domain addDomain(String domain, AddDomainOptions... options); + + /** + * Edit a domain to the Glesys dns-system + * + * @param domain the name of the domain to add. + * @param options optional parameters + * @return information about the modified domain + */ + Domain editDomain(String domain, DomainOptions... options); /** * Remove a domain to the Glesys dns-system @@ -80,13 +89,10 @@ public interface DomainClient { /** * Add a DNS Record * - * @param domain the domain to add the record to - * @param host - * @param type - * @param data + * @param domain the domain to add the record to * @param options optional settings for the record */ - void addRecord(String domain, String host, String type, String data, AddRecordOptions... options); + DomainRecord addRecord(String domain, String host, String type, String data, AddRecordOptions... options); /** * Modify a specific DNS Record @@ -95,7 +101,7 @@ public interface DomainClient { * @param options the settings to change * @see #listRecords to retrieve the necessary ids */ - void editRecord(String recordId, EditRecordOptions... options); + DomainRecord editRecord(String recordId, EditRecordOptions... options); /** * Delete a DNS record diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailAsyncClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailAsyncClient.java index b418d48f2d..82f1620b66 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailAsyncClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailAsyncClient.java @@ -27,6 +27,7 @@ import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import org.jclouds.glesys.domain.EmailAccount; +import org.jclouds.glesys.domain.EmailAlias; import org.jclouds.glesys.domain.EmailOverview; import org.jclouds.glesys.options.CreateAccountOptions; import org.jclouds.glesys.options.EditAccountOptions; @@ -55,7 +56,7 @@ public interface EmailAsyncClient { */ @POST @Path("/email/overview/format/json") - @SelectJson("response") + @SelectJson("overview") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture getEmailOverview(); @@ -68,41 +69,59 @@ public interface EmailAsyncClient { @SelectJson("emailaccounts") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listAccounts(@FormParam("domain") String domain); + ListenableFuture> listAccounts(@FormParam("domainname") String domain); + + /** + * @see org.jclouds.glesys.features.EmailClient#listAccounts + */ + @POST + @Path("/email/list/format/json") + @SelectJson("emailaliases") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listAliases(@FormParam("domainname") String domain); /** * @see org.jclouds.glesys.features.EmailClient#createAccount */ @POST + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("emailaccount") @Path("/email/createaccount/format/json") - ListenableFuture createAccount(@FormParam("emailaccount") String accountAddress, @FormParam("password") String password, CreateAccountOptions... options); + ListenableFuture createAccount(@FormParam("emailaccount") String accountAddress, @FormParam("password") String password, CreateAccountOptions... options); /** * @see org.jclouds.glesys.features.EmailClient#createAlias */ @POST + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("alias") @Path("/email/createalias/format/json") - ListenableFuture createAlias(@FormParam("emailalias") String aliasAddress, @FormParam("goto") String toEmailAddress); + ListenableFuture createAlias(@FormParam("emailalias") String aliasAddress, @FormParam("goto") String toEmailAddress); /** * @see org.jclouds.glesys.features.EmailClient#editAccount */ @POST + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("emailaccount") @Path("/email/editaccount/format/json") - ListenableFuture editAccount(@FormParam("emailaccount") String accountAddress, EditAccountOptions... options); + ListenableFuture editAccount(@FormParam("emailaccount") String accountAddress, EditAccountOptions... options); /** * @see org.jclouds.glesys.features.EmailClient#editAlias */ @POST + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("alias") @Path("/email/editalias/format/json") - ListenableFuture editAlias(@FormParam("emailalias") String aliasAddress, @FormParam("goto") String toEmailAddress); + ListenableFuture editAlias(@FormParam("emailalias") String aliasAddress, @FormParam("goto") String toEmailAddress); /** * @see org.jclouds.glesys.features.EmailClient#delete */ @POST @Path("/email/delete/format/json") - ListenableFuture delete(@FormParam("email") String accountAddress); + ListenableFuture delete(@FormParam("email") String accountAddress); } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailClient.java index 4346ada4dd..1dc546030b 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/EmailClient.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; import org.jclouds.glesys.domain.EmailAccount; +import org.jclouds.glesys.domain.EmailAlias; import org.jclouds.glesys.domain.EmailOverview; import org.jclouds.glesys.options.CreateAccountOptions; import org.jclouds.glesys.options.EditAccountOptions; @@ -52,6 +53,13 @@ public interface EmailClient { */ Set listAccounts(String domain); + /** + * Get the set of details about e-mail aliases + * + * @return the relevant set of details + */ + Set listAliases(String domain); + /** * Create a new e-mail account * @@ -60,7 +68,7 @@ public interface EmailClient { * @param options optional parameters * @see DomainClient#addDomain */ - void createAccount(String accountAddress, String password, CreateAccountOptions... options); + EmailAccount createAccount(String accountAddress, String password, CreateAccountOptions... options); /** * Create an e-mail alias for an e-mail account @@ -69,7 +77,7 @@ public interface EmailClient { * @param toEmailAddress the existing e-mail account address the alias should forward to * @see DomainClient#addDomain */ - void createAlias(String aliasAddress, String toEmailAddress); + EmailAlias createAlias(String aliasAddress, String toEmailAddress); /** * Adjust an e-mail account's settings @@ -77,7 +85,7 @@ public interface EmailClient { * @param accountAddress the existing e-mail account address * @param options optional parameters */ - void editAccount(String accountAddress, EditAccountOptions... options); + EmailAccount editAccount(String accountAddress, EditAccountOptions... options); /** * Adjust (re-target) an e-mail alias @@ -85,13 +93,13 @@ public interface EmailClient { * @param aliasAddress the existing alias e-mail address * @param toEmailAddress the existing e-mail account address the alias should forward to */ - void editAlias(String aliasAddress, String toEmailAddress); + EmailAlias editAlias(String aliasAddress, String toEmailAddress); /** * Delete an e-mail account or alias * * @param accountAddress the existing alias e-mail account or alias address */ - void delete(String accountAddress); + boolean delete(String accountAddress); } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java index d61f84a59a..383eda5d00 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java @@ -29,8 +29,10 @@ import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; import org.jclouds.glesys.domain.IpDetails; +import org.jclouds.glesys.options.ListIpOptions; import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; @@ -42,70 +44,111 @@ import com.google.common.util.concurrent.ListenableFuture; * Provides asynchronous access to IP Addresses via their REST API. *

* - * @author Adrian Cole, Mattias Holmqvist - * - * @see ServerClient + * @author Adrian Cole, Mattias Holmqvist, Adam Lowe + * @see IpClient * @see */ @RequestFilters(BasicAuthentication.class) public interface IpAsyncClient { - - - /** - * @see IpClient#take - */ - @POST - @Path("/ip/take/format/json") - ListenableFuture take(@FormParam("ipaddress") String ipAddress); - - - /** - * @see IpClient#release - */ - @POST - @Path("/ip/release/format/json") - ListenableFuture release(@FormParam("ipaddress") String ipAddress); - - /** - * @see IpClient#add - */ - @POST - @Path("/ip/add/format/json") - ListenableFuture addIpToServer(@FormParam("ipaddress") String ipAddress, - @FormParam("serverid") String serverId); - - - /** - * @see IpClient#remove - * - * TODO: add optional release_ip parameter - */ - @POST - @Path("/ip/remove/format/json") - ListenableFuture removeIpFromServer(@FormParam("ipaddress") String ipAddress, - @FormParam("serverid") String serverId); - - /** * @see IpClient#listFree */ @GET @Path("/ip/listfree/ipversion/{ipversion}/datacenter/{datacenter}/platform/{platform}/format/json") @Consumes(MediaType.APPLICATION_JSON) - @SelectJson("iplist") + @SelectJson("ipaddresses") @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listFree(@PathParam("ipversion") String ipversion, + ListenableFuture> listFree(@PathParam("ipversion") int ipversion, @PathParam("datacenter") String datacenter, @PathParam("platform") String platform); /** - * @see IpClient#getIpDetails + * @see IpClient#take + */ + @POST + @Path("/ip/take/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture take(@FormParam("ipaddress") String ipAddress); + + /** + * @see IpClient#release + */ + @POST + @Path("/ip/release/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture release(@FormParam("ipaddress") String ipAddress); + + /** + * @see IpClient#listIps + */ + @GET + @Path("/ip/listown/format/json") + @Consumes(MediaType.APPLICATION_JSON) + @SelectJson("iplist") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listIps(ListIpOptions... options); + + /** + * @see IpClient#getIp */ @GET @Path("/ip/details/ipaddress/{ipaddress}/format/json") - @Consumes(MediaType.APPLICATION_JSON) @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getIpDetails(@PathParam("ipaddress") String ipAddress); + ListenableFuture getIp(@PathParam("ipaddress") String ipAddress); + + /** + * @see IpClient#addIpToServer + */ + @POST + @Path("/ip/add/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addIpToServer(@FormParam("ipaddress") String ipAddress, + @FormParam("serverid") String serverId); + + /** + * @see IpClient#removeIpFromServer + */ + @POST + @Path("/ip/remove/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture removeIpFromServer(@FormParam("ipaddress") String ipAddress, + @FormParam("serverid") String serverId); + + /** + * @see IpClient#removeIpFromServer + */ + @POST + @FormParams(keys = "release", values = "true") + @Path("/ip/remove/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture removeIpFromServerAndRelease(@FormParam("ipaddress") String ipAddress, + @FormParam("serverid") String serverId); + + /** + * @see IpClient#setPtr + */ + @POST + @Path("/ip/setptr/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture setPtr(@FormParam("ipaddress") String ipAddress, + @FormParam("data") String ptr); + + /** + * @see IpClient#resetPtr + */ + @POST + @Path("/ip/resetptr/format/json") + @SelectJson("details") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture resetPtr(@FormParam("ipaddress") String ipAddress); + } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java index 4335c87845..7e0c9844a6 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java @@ -23,72 +23,100 @@ import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; import org.jclouds.glesys.domain.IpDetails; +import org.jclouds.glesys.options.ListIpOptions; /** * Provides synchronous access to IP Addresses. *

* - * @author Adrian Cole, Mattias Holmqvist + * @author Adrian Cole, Mattias Holmqvist, Adam Lowe * @see IpAsyncClient * @see */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) public interface IpClient { + /** + * Get a set of all IP addresses that are available and not used on any account or server. + * + * @param ipVersion 4 or 6, for IPV4 or IPV6, respectively + * @param datacenter the datacenter + * @param platform the platform + * @return a set of free IP addresses + */ + Set listFree(int ipVersion, String datacenter, String platform); - /** - * Take a free IP address and add it to this account. You can list free IP addresses with the function listFree(). - * Once your free IP on this account you can add it to a server with the add() function. - * - * @param ipAddress - */ - void take(String ipAddress); + /** + * Take a free IP address and add it to this account. You can list free IP addresses with the function listFree(). + * Once your free IP on this account you can add it to a server with the add() function. + * + * @param ipAddress the IP address to be add to this account (reserve) + */ + IpDetails take(String ipAddress); - /** - * Return an unused IP address to the pool of free ips. If the IP address is allocated to a server, - * it must first be removed by calling remove(ipAddress) before it can be released. - * - * @param ipAddress the IP address to be released - */ - void release(String ipAddress); + /** + * Return an unused IP address to the pool of free ips. If the IP address is allocated to a server, + * it must first be removed by calling remove(ipAddress) before it can be released. + * + * @param ipAddress the IP address to be released + */ + IpDetails release(String ipAddress); - /** - * Add an IP address to an server. The IP has to be free, but reserved to this account. You are able to list such addresses - * with listOwn() and reserve an address for this account by using take(). To find free ips you can use ip/listfree - * ip to an Xen-server you have to configure the server yourself, unless the ip was added during the c - * server (server/create). You can get detailed information such as gateway and netmask using the ip - * - * @param ipAddress the IP address to remove - * @param serverId the server to add the IP address to - */ - void addIpToServer(String ipAddress, String serverId); + /** + * Get IP addresses associated with your account (reserved, assigned to servers, etc) + * + * @param options options to filter the results (by IPV4/6, serverId, etc) + * @return the set of IP addresses + */ + Set listIps(ListIpOptions... options); - /** - * Remove an IP address from a server. This does not release it back to GleSYS pool of free ips. The address will be - * kept on the account so that you can use it for other servers or the same server at a later time. To completely remove - * the IP address from this account, use the function release(). - * - * @param ipAddress the IP address to remove - * @param serverId the server to remove the IP address from - */ - void removeIpFromServer(String ipAddress, String serverId); + /** + * Get details about the given IP address such as gateway and netmask. Different details are available + * on different platforms. + * + * @param ipAddress the ip address + * @return details about the given IP address + */ + IpDetails getIp(String ipAddress); - /** - * Get a set of all IP addresses that are available and not used on any account or server. - * - * @param ipversion "4" or "6", for IPV4 or IPV6, respectively - * @param datacenter the datacenter - * @param platform the platform - * @return a set of free IP addresses - */ - Set listFree(String ipversion, String datacenter, String platform); + /** + * Add an IP address to an server. The IP has to be free, but reserved to this account. You are able to list such addresses + * with listOwn() and reserve an address for this account by using take(). To find free ips you can use ip/listfree + * ip to an Xen-server you have to configure the server yourself, unless the ip was added during the c + * server (server/create). You can get detailed information such as gateway and netmask using the ip + * + * @param ipAddress the IP address to remove + * @param serverId the server to add the IP address to + */ + IpDetails addIpToServer(String ipAddress, String serverId); - /** - * Get details about the given IP address such as gateway and netmask. Different details are available - * on different platforms. - * - * @param ipAddress the ip address - * @return details about the given IP address - */ - IpDetails getIpDetails(String ipAddress); + /** + * Remove an IP address from a server. This does not release it back to GleSYS pool of free ips. The address will be + * kept on the account so that you can use it for other servers or the same server at a later time. To completely remove + * the IP address from this account, use removeIpFromServerAndRelease to do so + * + * @param ipAddress the IP address to remove + * @param serverId the server to remove the IP address from + * @see #removeIpFromServerAndRelease + */ + IpDetails removeIpFromServer(String ipAddress, String serverId); + + /** + * Remove an IP address from a server and release it back to GleSYS pool of free ips. + * + * @param ipAddress the IP address to remove + * @param serverId the server to remove the IP address from + * @see #removeIpFromServer + */ + IpDetails removeIpFromServerAndRelease(String ipAddress, String serverId); + + /** + * Sets PTR data for an IP. Use ip/listown or ip/details to get current PTR data + */ + IpDetails setPtr(String ipAddress, String ptr); + + /** + * Resets PTR data for an IP back to the default value + */ + IpDetails resetPtr(String ipAddress); } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerAsyncClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerAsyncClient.java index bb6942ce0c..0bd400f000 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerAsyncClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerAsyncClient.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.MediaType; import org.jclouds.glesys.domain.AllowedArgumentsForCreateServer; import org.jclouds.glesys.domain.Console; import org.jclouds.glesys.domain.OSTemplate; +import org.jclouds.glesys.domain.ResourceUsage; import org.jclouds.glesys.domain.Server; import org.jclouds.glesys.domain.ServerDetails; import org.jclouds.glesys.domain.ServerLimit; @@ -225,15 +226,19 @@ public interface ServerAsyncClient { * @see ServerClient#resetPassword */ @POST - @Path("/server/destroy/format/json") - ListenableFuture resetPassword(@FormParam("serverid") String id, @FormParam("newpassword") String password); + @Path("/server/resetpassword/format/json") + @SelectJson("server") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture resetPassword(@FormParam("serverid") String id, @FormParam("rootpassword") String password); /** - * @see ServerClient#resourceUsage + * @see ServerClient#getResourceUsage */ @POST @Path("/server/resourceusage/format/json") - void resourceUsage(@FormParam("serverid") String id, @FormParam("resource") String resource, + @SelectJson("usage") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture getResourceUsage(@FormParam("serverid") String id, @FormParam("resource") String resource, @FormParam("resolution") String resolution); } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerClient.java b/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerClient.java index aa21075ca0..ddb6dc0b5e 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerClient.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/features/ServerClient.java @@ -26,6 +26,7 @@ import org.jclouds.concurrent.Timeout; import org.jclouds.glesys.domain.AllowedArgumentsForCreateServer; import org.jclouds.glesys.domain.Console; import org.jclouds.glesys.domain.OSTemplate; +import org.jclouds.glesys.domain.ResourceUsage; import org.jclouds.glesys.domain.Server; import org.jclouds.glesys.domain.ServerDetails; import org.jclouds.glesys.domain.ServerLimit; @@ -42,7 +43,7 @@ import com.google.common.annotations.Beta; /** * Provides synchronous access to Server. *

- * + * * @author Adrian Cole * @author Adam Lowe * @see ServerAsyncClient @@ -53,7 +54,7 @@ public interface ServerClient { /** * Get a list of all servers on this account. - * + * * @return an account's associated server objects. */ Set listServers(); @@ -62,9 +63,8 @@ public interface ServerClient { * Get detailed information about a server such as hostname, hardware * configuration (cpu, memory and disk), ip addresses, cost, transfer, os and * more. - * - * @param id - * id of the server + * + * @param id id of the server * @return server or null if not found */ ServerDetails getServerDetails(String id); @@ -72,11 +72,9 @@ public interface ServerClient { /** * Get detailed information about a server status including up-time and * hardware usage (cpu, disk, memory and bandwidth) - * - * @param id - * id of the server - * @param options - * optional parameters + * + * @param id id of the server + * @param options optional parameters * @return the status of the server or null if not found */ ServerStatus getServerStatus(String id, ServerStatusOptions... options); @@ -84,87 +82,76 @@ public interface ServerClient { /** * Get detailed information about a server's limits (for OpenVZ only). *

- * - * @param id - * id of the server + * + * @param id id of the server * @return the requested information about the server or null if not found */ Map getServerLimits(String id); /** * Get information about how to connect to a server via VNC - * - * @param id - * id of the server + * + * @param id id of the server * @return the requested information about the server or null if not found */ Console getConsole(String id); /** * Get information about the OS templates available - * + * * @return the set of information about each template */ Set listTemplates(); /** * Get information about valid arguments to #createServer for each platform - * + * * @return a map of argument lists, keyed on platform */ Map getAllowedArgumentsForCreateServerByPlatform(); /** * Reset the fail count for a server limit (for OpenVZ only). - * - * @param id - * id of the server - * @param type - * the type of limit to reset + * + * @param id id of the server + * @param type the type of limit to reset */ Map resetServerLimit(String id, String type); /** * Reboot a server - * - * @param id - * id of the server + * + * @param id id of the server */ ServerDetails rebootServer(String id); /** * Start a server - * - * @param id - * id of the server + * + * @param id id of the server */ ServerDetails startServer(String id); /** * Stop a server - * - * @param id - * id of the server + * + * @param id id of the server */ - void stopServer(String id); + ServerDetails stopServer(String id); /** * hard stop a server - * - * @param id - * id of the server + * + * @param id id of the server */ - void hardStopServer(String id); + ServerDetails hardStopServer(String id); /** * Create a new server - * - * @param hostname - * the host name of the new server - * @param rootPassword - * the root password to use - * @param options - * optional settings ex. description + * + * @param hostname the host name of the new server + * @param rootPassword the root password to use + * @param options optional settings ex. description */ @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) ServerDetails createServerWithHostnameAndRootPassword(ServerSpec serverSpec, String hostname, String rootPassword, @@ -172,58 +159,47 @@ public interface ServerClient { /** * Edit the configuration of a server - * - * @param serverid - * the serverId of the server to edit - * @param options - * the settings to change + * + * @param serverid the serverId of the server to edit + * @param options the settings to change */ ServerDetails editServer(String serverid, EditServerOptions... options); /** * Clone a server - * - * @param serverid - * the serverId of the server to clone - * @param hostname - * the new host name of the cloned server - * @param options - * the settings to change + * + * @param serverid the serverId of the server to clone + * @param hostname the new host name of the cloned server + * @param options the settings to change */ @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) ServerDetails cloneServer(String serverid, String hostname, CloneServerOptions... options); /** * Destroy a server - * - * @param id - * the id of the server - * @param keepIp - * if DestroyServerOptions.keepIp(true) the servers ip will be - * retained for use in your GleSYS account + * + * @param id the id of the server + * @param keepIp if DestroyServerOptions.keepIp(true) the servers ip will be retained for use in your GleSYS account */ ServerDetails destroyServer(String id, DestroyServerOptions keepIp); /** * Reset the root password of a server - * - * @param id - * the id of the server - * @param password - * the new password to use + * + * @param id the id of the server + * @param password the new password to use */ - void resetPassword(String id, String password); + ServerDetails resetPassword(String id, String password); /** * Return resource usage over time for server - * - * @param id - * the id of the server - * @param resource - * the name of the resource to retrieve usage information for + * + * @param id the id of the server + * @param resource the name of the resource to retrieve usage information for (e.g. "cpuusage") + * @param resolution the time-period to extract data for (one of "minute", "hour" or "day) */ @Beta // TODO: better name - void resourceUsage(String id, String resource, String resolution); + ResourceUsage getResourceUsage(String id, String resource, String resolution); } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GleSYSTypeAdapters.java b/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GleSYSTypeAdapters.java index 070c9f186b..5ba16dedfe 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GleSYSTypeAdapters.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GleSYSTypeAdapters.java @@ -20,10 +20,13 @@ package org.jclouds.glesys.functions.internal; import java.io.IOException; +import org.jclouds.glesys.domain.GleSYSBoolean; import org.jclouds.glesys.domain.Server; +import com.google.common.base.Objects; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; /** @@ -43,4 +46,24 @@ public class GleSYSTypeAdapters { } } + public static class GleSYSBooleanAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter writer, GleSYSBoolean value) throws IOException { + writer.value(value.getValue() ? "yes" : "no"); + } + + @Override + public GleSYSBoolean read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.BOOLEAN) { + return new GleSYSBoolean(in.nextBoolean()); + } else if (in.peek() == JsonToken.NULL) { + return GleSYSBoolean.FALSE; + } else { + return new GleSYSBoolean(Objects.equal(in.nextString(), "yes")); + } + } + + } + } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GlesysDateAdapter.java b/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GlesysDateAdapter.java deleted file mode 100644 index 281b3e847c..0000000000 --- a/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GlesysDateAdapter.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.jclouds.glesys.functions.internal; - -import java.io.IOException; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.inject.Singleton; - -import org.jclouds.date.DateService; -import org.jclouds.json.config.GsonModule; - -import com.google.common.base.Throwables; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import com.google.inject.Inject; - -/** - * Parser for Glesys Date formats - * - * @deprecated this should be replaced by standard ISO8601 parser in the next week or so - * - * @author Adam Lowe - */ -@Singleton -public class GlesysDateAdapter extends GsonModule.DateAdapter { - private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - private final DateService standardDateService; - - @Inject - public GlesysDateAdapter(DateService service) { - this.standardDateService = service; - } - - public void write(JsonWriter writer, Date value) throws IOException { - try { - writer.value(standardDateService.iso8601SecondsDateFormat(value)); - } catch (Exception ex) { - synchronized (dateFormat) { - writer.value(dateFormat.format(value)); - } - } - } - - public Date read(JsonReader reader) throws IOException { - String toParse = reader.nextString(); - try { - return standardDateService.iso8601SecondsDateParse(toParse); - } catch (Exception ex) { - try { - synchronized (dateFormat) { - return dateFormat.parse(toParse); - } - } catch (ParseException e) { - throw Throwables.propagate(e); - } - } - } -} diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/options/AddDomainOptions.java b/labs/glesys/src/main/java/org/jclouds/glesys/options/AddDomainOptions.java index 473d68b9f9..44c15623d9 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/options/AddDomainOptions.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/options/AddDomainOptions.java @@ -85,7 +85,7 @@ public class AddDomainOptions extends DomainOptions { * Ensure only NS and SOA records will be created by default, when this option is not used a number of default records will be created on the domain. */ public DomainOptions minimalRecords() { - formParameters.put("createrecords", "0"); + formParameters.put("createrecords", Boolean.FALSE.toString()); return this; } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/options/CreateAccountOptions.java b/labs/glesys/src/main/java/org/jclouds/glesys/options/CreateAccountOptions.java index 4a915e0f62..fa16f63dad 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/options/CreateAccountOptions.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/options/CreateAccountOptions.java @@ -70,19 +70,19 @@ public class CreateAccountOptions extends BaseHttpRequestOptions { /** Enable or disable virus checking */ public CreateAccountOptions antiVirus(boolean antiVirus) { - formParameters.put("antivirus", Integer.toString(antiVirus ? 1 : 0)); + formParameters.put("antivirus", Boolean.toString(antiVirus)); return this; } /** Enable or disable auto-respond */ public CreateAccountOptions autorespond(boolean autorespond) { - formParameters.put("autorespond", Integer.toString(autorespond ? 1 : 0)); + formParameters.put("autorespond", Boolean.toString(autorespond)); return this; } /** Enable or disable saving of auto-respond e-mails */ public CreateAccountOptions autorespondSaveEmail(boolean autorespondSaveEmail) { - formParameters.put("autorespondsaveemail", Integer.toString(autorespondSaveEmail ? 1 : 0)); + formParameters.put("autorespondsaveemail", Boolean.toString(autorespondSaveEmail)); return this; } diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/options/DestroyServerOptions.java b/labs/glesys/src/main/java/org/jclouds/glesys/options/DestroyServerOptions.java index 61ede83e49..1f8f562c98 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/options/DestroyServerOptions.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/options/DestroyServerOptions.java @@ -47,7 +47,7 @@ public class DestroyServerOptions extends BaseHttpRequestOptions { * @param keepIp if true, keep the ip address */ public DestroyServerOptions keepIp(boolean keepIp) { - formParameters.put("keepip", Integer.toString(keepIp ? 1 : 0)); + formParameters.put("keepip", Boolean.toString(keepIp)); return this; } } \ No newline at end of file diff --git a/labs/glesys/src/main/java/org/jclouds/glesys/options/ListIpOptions.java b/labs/glesys/src/main/java/org/jclouds/glesys/options/ListIpOptions.java new file mode 100644 index 0000000000..09350e24fa --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/options/ListIpOptions.java @@ -0,0 +1,106 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.options; + +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * @author Adam Lowe + */ +public class ListIpOptions extends BaseHttpRequestOptions { + + public static class Builder { + /** + * @see org.jclouds.glesys.options.ListIpOptions#used + */ + public static ListIpOptions used(boolean used) { + return new ListIpOptions().used(used); + } + + /** + * @see org.jclouds.glesys.options.ListIpOptions#serverId + */ + public static ListIpOptions serverId(String serverId) { + return new ListIpOptions().serverId(serverId); + } + + /** + * @see org.jclouds.glesys.options.ListIpOptions#ipVersion + */ + public static ListIpOptions ipVersion(int ipVersion) { + return new ListIpOptions().ipVersion(ipVersion); + } + + /** + * @see org.jclouds.glesys.options.ListIpOptions#datacenter + */ + public static ListIpOptions datacenter(String datacenter) { + return new ListIpOptions().datacenter(datacenter); + } + + /** + * @see org.jclouds.glesys.options.ListIpOptions#platform + */ + public static ListIpOptions platform(String platform) { + return new ListIpOptions().platform(platform); + } + + } + + /** + * Retrieve only IPs that are in use + */ + public ListIpOptions used(boolean used) { + formParameters.put("used", Boolean.toString(used)); + return this; + } + + /** + * Retrieve only IP assigned to the specified server + */ + public ListIpOptions serverId(String serverId) { + formParameters.put("serverid", serverId); + return this; + } + + /** + * Retrieve only IPs of the requested version + */ + public ListIpOptions ipVersion(int ipVersion) { + formParameters.put("ipversion", Integer.toString(ipVersion)); + return this; + } + + /** + * Retrieve only IPs served in the specified datacenter + */ + public ListIpOptions datacenter(String datacenter) { + formParameters.put("datacenter", datacenter); + return this; + } + + /** + * Retrieve only IPs served on the specified platform + */ + public ListIpOptions platform(String platform) { + formParameters.put("platform", platform); + return this; + } + +} \ No newline at end of file diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/GleSYSAsyncClientTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/GleSYSAsyncClientTest.java index 55872e6a85..eaab64a4d1 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/GleSYSAsyncClientTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/GleSYSAsyncClientTest.java @@ -21,8 +21,9 @@ package org.jclouds.glesys; import java.io.IOException; import java.util.concurrent.ExecutionException; -import org.jclouds.glesys.internal.BaseGleSYSAsyncClientTest; import org.jclouds.http.HttpRequest; +import org.jclouds.providers.ProviderMetadata; +import org.jclouds.rest.internal.BaseAsyncClientTest; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -37,11 +38,15 @@ import com.google.inject.TypeLiteral; // NOTE:without testName, this will not call @Before* and fail w/NPE during // surefire @Test(groups = "unit", testName = "GleSYSAsyncClientTest") -public class GleSYSAsyncClientTest extends BaseGleSYSAsyncClientTest { - +public class GleSYSAsyncClientTest extends BaseAsyncClientTest { private GleSYSAsyncClient asyncClient; private GleSYSClient syncClient; + @Override + public ProviderMetadata createProviderMetadata() { + return new GleSYSProviderMetadata(); + } + public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException { assert syncClient.getServerClient() != null; assert syncClient.getIpClient() != null; diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/compute/functions/ServerDetailsToNodeMetadataTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/compute/functions/ServerDetailsToNodeMetadataTest.java index 516283cf64..1e77c014d0 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/compute/functions/ServerDetailsToNodeMetadataTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/compute/functions/ServerDetailsToNodeMetadataTest.java @@ -20,10 +20,12 @@ package org.jclouds.glesys.compute.functions; import static org.jclouds.io.Payloads.newUrlEncodedFormPayload; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; import java.net.URI; import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OsFamily; @@ -73,22 +75,25 @@ public class ServerDetailsToNodeMetadataTest extends BaseGleSYSComputeServiceExp ).getInstance(ServerDetailsToNodeMetadata.class); + NodeMetadata actual = toTest.apply(ServerClientExpectTest.expectedServerDetails()); + assertNotNull(actual); + assertEquals( - toTest.apply(ServerClientExpectTest.expectedServerDetails()), + actual.toString(), new NodeMetadataBuilder() - .ids("xm3276891") - .name("glesys-s-6dd") - .hostname("glesys-s-6dd") + .ids("vz1840356") + .name("test-email-jclouds") + .hostname("test-email-jclouds") .group("glesys-s") - .imageId("Ubuntu 11.04 x64") + .imageId("Ubuntu 10.04 LTS 32-bit") .operatingSystem( - OperatingSystem.builder().name("Ubuntu 11.04 x64").family(OsFamily.UBUNTU).version("11.04") - .is64Bit(true).description("Ubuntu 11.04 x64").build()) - .publicAddresses(ImmutableSet.of("109.74.10.45")) + OperatingSystem.builder().name("Ubuntu 10.04 LTS 32-bit").family(OsFamily.UBUNTU).version("10.04") + .is64Bit(false).description("Ubuntu 10.04 LTS 32-bit").build()) + .publicAddresses(ImmutableSet.of("31.192.231.254")) .hardware( - new HardwareBuilder().ids("xm3276891").ram(512) + new HardwareBuilder().ids("vz1840356").ram(512) .processors(ImmutableList.of(new Processor(1, 1.0))) - .volumes(ImmutableList. of(new VolumeImpl(5f, true, true))).hypervisor("Xen") - .build()).status(Status.RUNNING).build()); + .volumes(ImmutableList. of(new VolumeImpl(5f, true, true))).hypervisor("OpenVZ") + .build()).status(Status.RUNNING).build().toString()); } } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientExpectTest.java index b7d165ff4f..a7d2c74c56 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientExpectTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientExpectTest.java @@ -26,15 +26,13 @@ import static org.testng.Assert.assertTrue; import java.net.URI; import java.util.List; -import org.jclouds.glesys.GleSYSClient; import org.jclouds.glesys.domain.Archive; import org.jclouds.glesys.domain.ArchiveAllowedArguments; -import org.jclouds.glesys.domain.ArchiveDetails; +import org.jclouds.glesys.internal.BaseGleSYSClientExpectTest; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.rest.ResourceNotFoundException; -import org.jclouds.rest.internal.BaseRestClientExpectTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; @@ -46,10 +44,7 @@ import com.google.common.collect.ImmutableMultimap; * @author Adam Lowe */ @Test(groups = "unit", testName = "ArchiveClientExpectTest") -public class ArchiveClientExpectTest extends BaseRestClientExpectTest { - public ArchiveClientExpectTest() { - provider = "glesys"; - } +public class ArchiveClientExpectTest extends BaseGleSYSClientExpectTest { public void testListArchivesWhenReponseIs2xx() throws Exception { ArchiveClient client = requestSendsResponse( @@ -61,8 +56,8 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTest expected = ImmutableList.of( - Archive.builder().username("xxxxx_test1").freeSize("20 GB").totalSize("20 GB").locked(false).build()); + List expected = ImmutableList.of( + Archive.builder().username("xxxxx_test1").freeSize("20 GB").totalSize("30 GB").locked(false).build()); assertEquals(client.listArchives(), expected); } @@ -88,9 +83,12 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTestbuilder().put("username", "xxxxxx_test1").build())).build(), HttpResponse.builder().statusCode(200).payload(payloadFromResource("/archive_details.json")).build()) .getArchiveClient(); - ArchiveDetails expected = ArchiveDetails.builder().username("xxxxxx_test1").freeSize("30 GB").totalSize("30 GB").locked(false).build(); - assertEquals(client.getArchiveDetails("xxxxxx_test1"), expected); + assertEquals(client.getArchive("xxxxxx_test1"), detailsInArchiveDetails()); + } + + private Archive detailsInArchiveDetails() { + return Archive.builder().username("xxxxxx_test1").freeSize("30 GB").totalSize("30 GB").locked(false).build(); } public void testArchiveDetailsWhenResponseIs4xxReturnsNull() { @@ -103,20 +101,21 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTestbuilder().put("username", "xxxxxx_test1").build())).build(), HttpResponse.builder().statusCode(404).build()) .getArchiveClient(); - assertNull(client.getArchiveDetails("xxxxxx_test1")); + assertNull(client.getArchive("xxxxxx_test1")); } public void testCreateArchiveWhenResponseIs2xx() throws Exception { ArchiveClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/archive/create/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("username", "xxxxxx_test1") .put("size", "5") .put("password", "somepass").build())).build(), - HttpResponse.builder().statusCode(200).build()).getArchiveClient(); - client.createArchive("xxxxxx_test1", "somepass", 5); + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/archive_details.json")).build()).getArchiveClient(); + assertEquals(client.createArchive("xxxxxx_test1", "somepass", 5), detailsInArchiveDetails()); } public void testDeleteArchiveWhenResponseIs2xx() throws Exception { @@ -146,22 +145,24 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTestbuilder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("username", "username1") .put("size", "5").build())).build(), - HttpResponse.builder().statusCode(200).build()).getArchiveClient(); + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/archive_details.json")).build()).getArchiveClient(); - client.resizeArchive("username1", 5); + assertEquals(client.resizeArchive("username1", 5), detailsInArchiveDetails()); } @Test(expectedExceptions = {ResourceNotFoundException.class}) public void testResizeArchiveWhenResponseIs4xxThrows() throws Exception { ArchiveClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/archive/resize/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("username", "username1") .put("size", "5").build())).build(), @@ -174,14 +175,15 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTestbuilder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("username", "username") .put("password", "newpass").build())).build(), - HttpResponse.builder().statusCode(200).build()).getArchiveClient(); - - client.changeArchivePassword("username", "newpass"); + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/archive_details.json")).build()).getArchiveClient(); + + assertEquals(client.changeArchivePassword("username", "newpass"), detailsInArchiveDetails()); } @Test(expectedExceptions = {ResourceNotFoundException.class}) @@ -189,8 +191,9 @@ public class ArchiveClientExpectTest extends BaseRestClientExpectTestbuilder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("username", "username") .put("password", "newpass").build())).build(), diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientLiveTest.java index e71ca77225..e0d843feed 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/ArchiveClientLiveTest.java @@ -24,8 +24,8 @@ import static org.testng.Assert.assertTrue; import java.util.concurrent.TimeUnit; +import org.jclouds.glesys.domain.Archive; import org.jclouds.glesys.domain.ArchiveAllowedArguments; -import org.jclouds.glesys.domain.ArchiveDetails; import org.jclouds.glesys.internal.BaseGleSYSClientLiveTest; import org.jclouds.predicates.RetryablePredicate; import org.testng.annotations.AfterClass; @@ -47,7 +47,7 @@ public class ArchiveClientLiveTest extends BaseGleSYSClientLiveTest { super.setupContext(); client = gleContext.getApi().getArchiveClient(); - archiveUser = gleContext.getIdentity().toLowerCase() + "_jcloudstest9"; + archiveUser = gleContext.getIdentity().toLowerCase() + "_test9"; archiveCounter = new RetryablePredicate( new Predicate() { public boolean apply(Integer value){ @@ -97,10 +97,8 @@ public class ArchiveClientLiveTest extends BaseGleSYSClientLiveTest { @Test(dependsOnMethods = "testCreateArchive") public void testArchiveDetails() throws Exception { - ArchiveDetails details = client.getArchiveDetails(archiveUser); + Archive details = client.getArchive(archiveUser); assertEquals(details.getUsername(), archiveUser); - assertNotNull(details.getFreeSize()); - assertNotNull(details.getTotalSize()); } @Test(dependsOnMethods = "testCreateArchive") @@ -116,7 +114,7 @@ public class ArchiveClientLiveTest extends BaseGleSYSClientLiveTest { assertTrue(new RetryablePredicate( new Predicate() { public boolean apply(String value){ - return client.getArchiveDetails(archiveUser) != null && value.equals(client.getArchiveDetails(archiveUser).getTotalSize()); + return client.getArchive(archiveUser) != null && value.equals(client.getArchive(archiveUser).getTotalSize()); } }, 30, 1, TimeUnit.SECONDS).apply("20 GB")); } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientExpectTest.java index f03e3ada48..b348ba7528 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientExpectTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientExpectTest.java @@ -20,17 +20,22 @@ package org.jclouds.glesys.features; import static org.jclouds.io.Payloads.newUrlEncodedFormPayload; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.net.URI; import java.util.Set; +import javax.ws.rs.core.MediaType; + import org.jclouds.date.DateService; import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.glesys.GleSYSClient; import org.jclouds.glesys.domain.Domain; import org.jclouds.glesys.domain.DomainRecord; +import org.jclouds.glesys.internal.BaseGleSYSClientExpectTest; import org.jclouds.glesys.options.AddDomainOptions; +import org.jclouds.glesys.options.EditRecordOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.ResourceNotFoundException; @@ -38,7 +43,7 @@ import org.jclouds.rest.internal.BaseRestClientExpectTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; /** @@ -47,13 +52,8 @@ import com.google.common.collect.Iterables; * @author Adam Lowe */ @Test(groups = "unit", testName = "DomainClientExpectTest") -public class DomainClientExpectTest extends BaseRestClientExpectTest { - private DateService dateService = new SimpleDateFormatDateService(); +public class DomainClientExpectTest extends BaseGleSYSClientExpectTest { - public DomainClientExpectTest() { - provider = "glesys"; - } - public void testListDomainsWhenResponseIs2xx() throws Exception { DomainClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/list/format/json")) @@ -93,7 +93,7 @@ public class DomainClientExpectTest extends BaseRestClientExpectTest expected = ImmutableSortedSet.of( + Set expected = ImmutableSet.of( DomainRecord.builder().id("224538").domainname("testglesys.jclouds.org").host("@").type("NS").data("ns1.namesystem.se.").ttl(3600).build(), DomainRecord.builder().id("224539").domainname("testglesys.jclouds.org").host("@").type("NS").data("ns2.namesystem.se.").ttl(3600).build(), DomainRecord.builder().id("224540").domainname("testglesys.jclouds.org").host("@").type("NS").data("ns3.namesystem.se.").ttl(3600).build(), @@ -104,13 +104,13 @@ public class DomainClientExpectTest extends BaseRestClientExpectTest actual = client.listRecords("testglesys.jclouds.org"); - + assertEquals(actual, expected); - for(DomainRecord result : actual) { - for(DomainRecord expect : expected) { + for (DomainRecord result : actual) { + for (DomainRecord expect : expected) { if (result.equals(expect)) { assertEquals(result.toString(), expect.toString(), "Deep comparison using toString() failed!"); } @@ -130,24 +130,150 @@ public class DomainClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("domainname=jclouds.org&type=A&host=jclouds.org&data=", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_record.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); + + assertEquals(client.addRecord("jclouds.org", "jclouds.org", "A", ""), recordInDomainRecord()); + } + + protected DomainRecord recordInDomainRecord() { + return DomainRecord.builder().id("256151").domainname("cl13016-domain.jclouds.org").host("test").type("A").data("127.0.0.1").ttl(3600).build(); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testAddDomainRecordsWhenResponseIs4xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/addrecord/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("domainname=jclouds.org&type=A&host=jclouds.org&data=", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(404).build()).getDomainClient(); + + client.addRecord("jclouds.org", "jclouds.org", "A", ""); + } + + public void testEditDomainRecordsWhenResponseIs2xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/updaterecord/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("recordid=256151&host=somehost&ttl=1800", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_record.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); + + assertEquals(client.editRecord("256151", EditRecordOptions.Builder.host("somehost"), EditRecordOptions.Builder.ttl(1800)), recordInDomainRecord()); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testEditDomainRecordsWhenResponseIs4xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/updaterecord/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("recordid=256151&host=somehost&ttl=1800", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(404).build()).getDomainClient(); + + client.editRecord("256151", EditRecordOptions.Builder.host("somehost"), EditRecordOptions.Builder.ttl(1800)); + } + + public void testDeleteDomainRecordsWhenResponseIs2xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/deleterecord/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("recordid=256151", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_record.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); + + client.deleteRecord("256151"); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testDeleteDomainRecordsWhenResponseIs4xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/deleterecord/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromStringWithContentType("recordid=256151", MediaType.APPLICATION_FORM_URLENCODED)) + .build(), + HttpResponse.builder().statusCode(404).build()).getDomainClient(); + + client.deleteRecord("256151"); + } + + public void testGetDomainWhenResponseIs2xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/details/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("domainname", "cl66666_x").build())).build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_details.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); + + assertEquals(client.getDomain("cl66666_x"), domainInDomainDetails()); + } + + + public void testGetDomainWhenResponseIs4xx() throws Exception { + DomainClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/details/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("domainname", "cl66666_x").build())).build(), + HttpResponse.builder().statusCode(404).build()) + .getDomainClient(); + + assertNull(client.getDomain("cl66666_x")); + } + + protected Domain domainInDomainDetails() { + return Domain.builder().domainName("cl13016-domain.jclouds.org").createTime(dateService.iso8601SecondsDateParse("2012-06-24T11:52:49+02:00")).recordCount(9).build(); + } + public void testAddDomainWhenResponseIs2xx() throws Exception { DomainClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/add/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("domainname", "cl66666_x").build())).build(), - HttpResponse.builder().statusCode(200).build()).getDomainClient(); + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_details.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); - client.addDomain("cl66666_x"); + assertEquals(client.addDomain("cl66666_x"), domainInDomainDetails()); } - public void testAddDomainWithOptsWhenResponseIs2xx() throws Exception { DomainClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/add/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("domainname", "cl66666_x") .put("primarynameserver", "ns1.somewhere.x") @@ -158,31 +284,37 @@ public class DomainClientExpectTest extends BaseRestClientExpectTestbuilder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("domainname", "x").build())).build(), - HttpResponse.builder().statusCode(200).build()).getDomainClient(); + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/domain_details.json", MediaType.APPLICATION_JSON)).build()) + .getDomainClient(); - client.editDomain("x"); + assertEquals(client.editDomain("x"), domainInDomainDetails()); } @Test(expectedExceptions = {ResourceNotFoundException.class}) public void testEditDomainWhenResponseIs4xxThrows() throws Exception { DomainClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/domain/edit/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("domainname", "x").build())).build(), HttpResponse.builder().statusCode(404).build()).getDomainClient(); diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientLiveTest.java index 78ec75774a..7592289726 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/DomainClientLiveTest.java @@ -44,12 +44,12 @@ import com.google.common.base.Predicate; */ @Test(groups = "live", testName = "DomainClientLiveTest", singleThreaded = true) public class DomainClientLiveTest extends BaseGleSYSClientLiveTest { - public final String testDomain = "glesystest.jclouds.org"; + public String testDomain; @BeforeGroups(groups = {"live"}) public void setupContext() { super.setupContext(); - + testDomain = identity.toLowerCase() + "-domain.jclouds.org"; client = gleContext.getApi().getDomainClient(); domainCounter = new RetryablePredicate( new Predicate() { @@ -85,10 +85,19 @@ public class DomainClientLiveTest extends BaseGleSYSClientLiveTest { private RetryablePredicate domainCounter; private RetryablePredicate recordCounter; + @Test + public void testGetDomain() throws Exception { + Domain domain = client.getDomain(testDomain); + assertNotNull(domain); + assertEquals(domain.getDomainName(), testDomain); + assertNotNull(domain.getCreateTime()); + } + @Test public void testEditDomain() throws Exception { - client.editDomain(testDomain, DomainOptions.Builder.responsiblePerson("tester.jclouds.org")); - assertTrue(client.listDomains().contains(Domain.builder().domainName(testDomain).build())); + client.editDomain(testDomain, DomainOptions.Builder.responsiblePerson("another-tester.jclouds.org.")); + Domain domain = client.getDomain(testDomain); + assertEquals(domain.getResponsiblePerson(), "another-tester.jclouds.org."); } @Test diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientExpectTest.java index c27bf7dd0d..0bbba36b37 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientExpectTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientExpectTest.java @@ -24,24 +24,27 @@ import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.net.URI; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Set; -import org.jclouds.glesys.GleSYSClient; +import javax.ws.rs.core.MediaType; + import org.jclouds.glesys.domain.EmailAccount; +import org.jclouds.glesys.domain.EmailAlias; import org.jclouds.glesys.domain.EmailOverview; import org.jclouds.glesys.domain.EmailOverviewDomain; import org.jclouds.glesys.domain.EmailOverviewSummary; +import org.jclouds.glesys.domain.EmailQuota; +import org.jclouds.glesys.internal.BaseGleSYSClientExpectTest; +import org.jclouds.glesys.options.EditAccountOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; -import org.jclouds.rest.internal.BaseRestClientExpectTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; /** * Tests annotation parsing of {@code EmailClient} @@ -49,10 +52,7 @@ import com.google.common.collect.ImmutableSet; * @author Adam Lowe */ @Test(groups = "unit", testName = "EmailAsyncClientTest") -public class EmailClientExpectTest extends BaseRestClientExpectTest { - public EmailClientExpectTest() { - provider = "glesys"; - } +public class EmailClientExpectTest extends BaseGleSYSClientExpectTest { public void testListWhenResponseIs2xx() throws Exception { EmailClient client = requestSendsResponse( @@ -61,18 +61,22 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder().put("domain", "test").build())).build(), + ImmutableMultimap.builder().put("domainname", "cl13016.test.jclouds.org").build())).build(), HttpResponse.builder().statusCode(200).payload(payloadFromResource("/email_list.json")).build()).getEmailClient(); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - EmailAccount.Builder builder = EmailAccount.builder().quota("200 MB").usedQuota("0 MB").antispamLevel(3).antiVirus(true).autoRespond(false).autoRespondSaveEmail(true).autoRespondMessage("false"); + EmailAccount.Builder builder = EmailAccount.builder().quota(EmailQuota.builder().max(200).unit("MB").build()).antispamLevel(3).antiVirus(true).autoRespond(false).autoRespondSaveEmail(true); Set expected = ImmutableSet.of( - builder.account("test@adamlowe.net").created(dateFormat.parse("2011-12-22T12:13:14")).modified(dateFormat.parse("2011-12-22T12:13:35")).build(), - builder.account("test2@adamlowe.net").created(dateFormat.parse("2011-12-22T12:14:29")).modified(dateFormat.parse("2011-12-22T12:14:31")).build() + builder.account("test1@cl13016.test.jclouds.org").antispamLevel(3) + .created(dateService.iso8601SecondsDateParse("2012-06-24T11:53:45+02:00")).build(), + builder.account("test@cl13016.test.jclouds.org").antispamLevel(3) + .created(dateService.iso8601SecondsDateParse("2012-06-21T11:26:09+02:00")) + .modified(dateService.iso8601SecondsDateParse("2012-06-24T11:53:48+02:00")).build() ); - assertEquals(client.listAccounts("test"), expected); + Set actual = client.listAccounts("cl13016.test.jclouds.org"); + assertEquals(actual, expected); + assertEquals(Iterables.get(actual, 0).toString(), Iterables.get(expected, 0).toString()); } public void testListWhenResponseIs404IsEmpty() throws Exception { @@ -82,12 +86,40 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder().put("domain", "test").build())).build(), + ImmutableMultimap.builder().put("domainname", "test").build())).build(), HttpResponse.builder().statusCode(404).build()).getEmailClient(); assertTrue(client.listAccounts("test").isEmpty()); } + public void testListAliasesWhenResponseIs2xx() throws Exception { + EmailClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/list/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("domainname", "cl13016.test.jclouds.org").build())).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/email_list.json")).build()).getEmailClient(); + + EmailAlias expected = EmailAlias.builder().alias("test2@cl13016.test.jclouds.org").forwardTo("test2@cl13016.test.jclouds.org").build(); + EmailAlias actual = Iterables.getOnlyElement(client.listAliases("cl13016.test.jclouds.org")); + assertEquals(actual, expected); + } + + public void testListAliasesWhenResponseIs404IsEmpty() throws Exception { + EmailClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/list/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("domainname", "test").build())).build(), + HttpResponse.builder().statusCode(404).build()).getEmailClient(); + + assertTrue(client.listAliases("test").isEmpty()); + } + public void testOverviewWhenResponseIs2xx() throws Exception { EmailClient client = requestSendsResponse( HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/overview/format/json")) @@ -97,8 +129,8 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailaccount", "test@jclouds.org") .put("password", "newpass") .build())) .build(), - HttpResponse.builder().statusCode(200).build()).getEmailClient(); + HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/email_details.json", MediaType.APPLICATION_JSON)).build()) + .getEmailClient(); - client.createAccount("test@jclouds.org", "newpass"); + assertEquals(client.createAccount("test@jclouds.org", "newpass").toString(), getEmailAccountInDetails().toString()); + } + + public void testEditAccountWhenResponseIs2xx() throws Exception { + EmailClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/editaccount/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("emailaccount", "test@jclouds.org") + .put("password", "anotherpass") + .build())) + .build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/email_details.json", MediaType.APPLICATION_JSON)).build()) + .getEmailClient(); + + assertEquals(client.editAccount("test@jclouds.org", EditAccountOptions.Builder.password("anotherpass")).toString(), getEmailAccountInDetails().toString()); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testEditAccountWhenResponseIs4xx() throws Exception { + EmailClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/editaccount/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("emailaccount", "test@jclouds.org") + .put("password", "anotherpass") + .build())) + .build(), + HttpResponse.builder().statusCode(404).build()) + .getEmailClient(); + + assertEquals(client.editAccount("test@jclouds.org", EditAccountOptions.Builder.password("anotherpass")).toString(), getEmailAccountInDetails().toString()); + } + + private EmailAccount getEmailAccountInDetails() { + return EmailAccount.builder().account("test@CL13016.jclouds.org") + .antispamLevel(3) + .antiVirus(true) + .autoRespondSaveEmail(true) + .created(dateService.iso8601SecondsDateParse("2012-06-20T12:01:01+02:00")) + .quota(EmailQuota.builder().max(200).unit("MB").build()).build(); } @Test(expectedExceptions = {ResourceNotFoundException.class}) @@ -136,6 +214,7 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailaccount", "test@jclouds.org") @@ -151,6 +230,7 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailalias", "test2@jclouds.org") @@ -167,6 +247,7 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailalias", "test2@jclouds.org") @@ -182,6 +263,7 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailalias", "test2@jclouds.org") @@ -198,6 +280,7 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Accept", "application/json") .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() .put("emailalias", "test2@jclouds.org") @@ -208,4 +291,33 @@ public class EmailClientExpectTest extends BaseRestClientExpectTestbuilder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("email", "test2@jclouds.org") + .build())) + .build(), + HttpResponse.builder().statusCode(200).build()).getEmailClient(); + + client.delete("test2@jclouds.org"); + } + + @Test(expectedExceptions = {ResourceNotFoundException.class}) + public void testDeleteWhenResponseIs4xxThrows() throws Exception { + EmailClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/email/delete/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("email", "test2@jclouds.org") + .build())) + .build(), + HttpResponse.builder().statusCode(404).build()).getEmailClient(); + + client.delete("test2@jclouds.org"); + } } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientLiveTest.java index 6db98945fb..58bd3b49a6 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/EmailClientLiveTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.glesys.features; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; @@ -26,11 +27,11 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import org.jclouds.glesys.domain.EmailAccount; +import org.jclouds.glesys.domain.EmailAlias; import org.jclouds.glesys.domain.EmailOverview; import org.jclouds.glesys.domain.EmailOverviewDomain; -import org.jclouds.glesys.internal.BaseGleSYSClientLiveTest; +import org.jclouds.glesys.internal.BaseGleSYSClientWithAServerLiveTest; import org.jclouds.glesys.options.CreateAccountOptions; -import org.jclouds.glesys.options.DestroyServerOptions; import org.jclouds.glesys.options.EditAccountOptions; import org.jclouds.predicates.RetryablePredicate; import org.testng.annotations.AfterGroups; @@ -38,6 +39,7 @@ import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; /** * Tests behavior of {@code EmailClient} @@ -45,15 +47,13 @@ import com.google.common.base.Predicate; * @author Adam Lowe */ @Test(groups = "live", testName = "EmailClientLiveTest", singleThreaded = true) -public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { +public class EmailClientLiveTest extends BaseGleSYSClientWithAServerLiveTest { @BeforeGroups(groups = {"live"}) - public void setupContext() { - super.setupContext(); + public void setupDomains() { + testDomain = identity + ".test.jclouds.org"; client = gleContext.getApi().getEmailClient(); - serverId = createServer("test-email-jclouds").getServerId(); - createDomain(testDomain); emailAccountCounter = new RetryablePredicate( @@ -61,24 +61,26 @@ public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { public boolean apply(Integer value) { return client.listAccounts(testDomain).size() == value; } - }, 90, 5, TimeUnit.SECONDS); + }, 180, 5, TimeUnit.SECONDS); assertTrue(emailAccountCounter.apply(0)); + + try { + client.delete("test2@" + testDomain); + } catch(Exception e) { + } } @AfterGroups(groups = {"live"}) - public void tearDownContext() { + public void tearDownDomains() { client.delete("test@" + testDomain); client.delete("test1@" + testDomain); assertTrue(emailAccountCounter.apply(0)); gleContext.getApi().getDomainClient().deleteDomain(testDomain); - gleContext.getApi().getServerClient().destroyServer(serverId, DestroyServerOptions.Builder.discardIp()); - super.tearDownContext(); } private EmailClient client; - private String serverId; - private final String testDomain = "email-test.jclouds.org"; + private String testDomain; private RetryablePredicate emailAccountCounter; @Test @@ -95,14 +97,24 @@ public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { @Test(dependsOnMethods = "testCreateEmail") public void testAliases() { - client.createAlias("test2@" + testDomain, "test@" + testDomain); + assertTrue(client.listAliases(testDomain).isEmpty()); + + EmailAlias alias = client.createAlias("test2@" + testDomain, "test@" + testDomain); + assertEquals(alias.getAlias(), "test2@" + testDomain); + assertEquals(alias.getForwardTo(), "test@" + testDomain); + + EmailAlias aliasFromList = Iterables.getOnlyElement(client.listAliases(testDomain)); + assertEquals(aliasFromList, alias); + EmailOverview overview = client.getEmailOverview(); assertTrue(overview.getSummary().getAliases() == 1); - // TODO verify the result of editing the alias - client.editAlias("test2@" + testDomain, "test1@" + testDomain); + alias = client.editAlias("test2@" + testDomain, "test1@" + testDomain); overview = client.getEmailOverview(); assertTrue(overview.getSummary().getAliases() == 1); + + aliasFromList = Iterables.getOnlyElement(client.listAliases(testDomain)); + assertEquals(aliasFromList, alias); client.delete("test2@" + testDomain); overview = client.getEmailOverview(); @@ -113,8 +125,8 @@ public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { public void testOverview() throws Exception { EmailOverview overview = client.getEmailOverview(); assertNotNull(overview.getSummary()); - assertTrue(overview.getSummary().getAccounts() >= 1); - assertTrue(overview.getSummary().getAliases() == 0); + assertTrue(overview.getSummary().getAccounts() > 0); + assertTrue(overview.getSummary().getAliases() > -1); assertTrue(overview.getSummary().getMaxAccounts() > 0); assertTrue(overview.getSummary().getMaxAliases() > 0); assertNotNull(overview.getDomains()); @@ -135,7 +147,7 @@ public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { Set accounts = client.listAccounts(testDomain); for (EmailAccount account : accounts) { if (account.getAccount().equals("test@" + testDomain)) { - assertTrue(account.getAntiVirus()); + assertTrue(account.isAntiVirus()); } } @@ -144,7 +156,7 @@ public class EmailClientLiveTest extends BaseGleSYSClientLiveTest { accounts = client.listAccounts(testDomain); for (EmailAccount account : accounts) { if (account.getAccount().equals("test@" + testDomain)) { - assertFalse(account.getAntiVirus()); + assertFalse(account.isAntiVirus()); } } } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpAsyncClientTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpAsyncClientTest.java deleted file mode 100644 index c43079c9f5..0000000000 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpAsyncClientTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.jclouds.glesys.features; - -import java.io.IOException; -import java.lang.reflect.Method; - -import org.jclouds.glesys.internal.BaseGleSYSAsyncClientTest; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.functions.ParseFirstJsonValueNamed; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import org.jclouds.rest.internal.RestAnnotationProcessor; -import org.testng.annotations.Test; - -import com.google.inject.TypeLiteral; - -/** - * Tests annotation parsing of {@code IpAsyncClient} - * - * @author Adrian Cole - */ -@Test(groups = "unit", testName = "IpAsyncClientTest") -public class IpAsyncClientTest extends BaseGleSYSAsyncClientTest { - - public void testGetIpDetails() throws SecurityException, NoSuchMethodException, IOException { - Method method = IpAsyncClient.class.getMethod("getIpDetails", String.class); - HttpRequest request = processor.createRequest(method, "31.192.227.37"); - - assertRequestLineEquals(request, - "GET https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json HTTP/1.1"); - assertNonPayloadHeadersEqual(request, "Accept: application/json\n"); - assertPayloadEquals(request, null, "application/xml", false); - - assertResponseParserClassEquals(method, request, ParseFirstJsonValueNamed.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); - - checkFilters(request); - } - - @Override - protected TypeLiteral> createTypeLiteral() { - return new TypeLiteral>() { - }; - } -} diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java index 6acb032cab..d5761b9272 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java @@ -18,234 +18,345 @@ */ package org.jclouds.glesys.features; -import static java.util.Arrays.asList; import static java.util.Collections.emptySet; import static org.jclouds.io.Payloads.newUrlEncodedFormPayload; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; -import static org.testng.collections.Sets.newHashSet; +import static org.testng.Assert.assertTrue; import java.net.URI; -import java.util.Set; -import org.jclouds.glesys.GleSYSClient; +import javax.ws.rs.core.MediaType; + +import org.jclouds.glesys.domain.Cost; import org.jclouds.glesys.domain.IpDetails; +import org.jclouds.glesys.internal.BaseGleSYSClientExpectTest; +import org.jclouds.glesys.parse.ParseIpAddressFromResponseTest; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; -import org.jclouds.rest.internal.BaseRestClientExpectTest; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; /** * Allows us to test a client via its side effects. * - * @author Adrian Cole + * @author Adrian Cole, Adam Lowe */ @Test(groups = "unit", testName = "IpClientExpectTest") -public class IpClientExpectTest extends BaseRestClientExpectTest { - public IpClientExpectTest() { - provider = "glesys"; +public class IpClientExpectTest extends BaseGleSYSClientExpectTest { + + public void testListIpsWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listown/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_list_own.json")).build()) + .getIpClient(); + + IpDetails.Builder builder = IpDetails.builder().datacenter("Falkenberg").version4().reserved(true) + .platform("OpenVZ") + .nameServers("79.99.4.100", "79.99.4.101") + .cost(Cost.builder().amount(2.0).currency("EUR").timePeriod("month").build()); + + assertEquals(client.listIps().toString(), ImmutableSet.of( + builder.ptr("31-192-230-68-static.serverhotell.net.").address("31.192.230.68").serverId(null).build(), + builder.ptr("31-192-231-148-static.serverhotell.net.").address("31.192.231.148").serverId("vz1609110").build()).toString()); + } + + public void testListIpsWhenResponseIs4xxReturnsEmpty() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listown/format/json")).headers( + ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(404).build()).getIpClient(); + + assertTrue(client.listIps().isEmpty()); } public void testGetIpDetailsWhenResponseIs2xx() { - IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( - ImmutableMultimap.builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_get_details.json")).build()) - .getIpClient(); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.113/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_get_details.json")).build()) + .getIpClient(); - assertEquals(client.getIpDetails("31.192.227.37"), IpDetails.builder().datacenter("Falkenberg").ipversion("4") - .platform("OpenVZ").ptr("31-192-227-37-static.serverhotell.net.").build()); + assertEquals(client.getIp("31.192.227.113"), getIpInIpDetails()); + } + protected IpDetails getIpInIpDetails() { + return IpDetails.builder().datacenter("Falkenberg").version4() + .platform("OpenVZ").ptr("31-192-227-113-static.serverhotell.net.") + .nameServers("79.99.4.100", "79.99.4.101") + .address("31.192.227.113") + .cost(Cost.builder().amount(2.0).currency("EUR").timePeriod("month").build()).build(); } public void testGetIpDetailsWhenResponseIs4xxReturnsNull() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( - ImmutableMultimap.builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(404).build()).getIpClient(); - - assertEquals(client.getIpDetails("31.192.227.37"), null); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( + ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(404).build()).getIpClient(); + assertEquals(client.getIp("31.192.227.37"), null); } public void testTakeWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/take/format/json")) - .headers(ImmutableMultimap.builder() - .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() - )).build(), - HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_take.json")).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/take/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_take.json")).build()) + .getIpClient(); client.take("46.21.105.186"); } + @Test(expectedExceptions = HttpResponseException.class) public void testTakeWhenResponseIs4xxThrowsResponseException() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/take/format/json")) - .headers(ImmutableMultimap.builder() - .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() - )).build(), - HttpResponse.builder().statusCode(400).build()) - .getIpClient(); - - try { - client.take("46.21.105.186"); - fail(); - } catch (HttpResponseException e) { - // Expected - } + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/take/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(400).build()).getIpClient(); + client.take("46.21.105.186"); } public void testReleaseWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/release/format/json")) - .headers(ImmutableMultimap.builder() - .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() - )).build(), - HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_release.json")).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/release/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_release.json")).build()) + .getIpClient(); client.release("46.21.105.186"); } + @Test(expectedExceptions = ResourceNotFoundException.class) public void testReleaseWhenResponseIs4xxThrowsResponseException() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/release/format/json")) - .headers(ImmutableMultimap.builder() - .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() - )).build(), - HttpResponse.builder().statusCode(400).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/release/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(404).build()) + .getIpClient(); - try { - client.release("46.21.105.186"); - fail(); - } catch (HttpResponseException e) { - // Expected - } + client.release("46.21.105.186"); } public void testListFreeWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/listfree/ipversion/4/datacenter/Falkenberg/platform/OpenVZ/format/json")) - .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_list_free.json")).build()) - .getIpClient(); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listfree/ipversion/4/datacenter/Falkenberg/platform/OpenVZ/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_list_free.json")).build()) + .getIpClient(); - Set expectedIps = newHashSet(); - expectedIps.addAll(asList("31.192.226.131", "31.192.226.133")); - assertEquals(client.listFree("4", "Falkenberg", "OpenVZ"), expectedIps); + assertEquals(client.listFree(4, "Falkenberg", "OpenVZ"), ParseIpAddressFromResponseTest.EXPECTED_IPS); } public void testListFreeWhenResponseIs404ReturnsEmptySet() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/listfree/ipversion/4/datacenter/Falkenberg/platform/OpenVZ/format/json")) - .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(404).build()) - .getIpClient(); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listfree/ipversion/6/datacenter/Falkenberg/platform/OpenVZ/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(404).build()) + .getIpClient(); - assertEquals(client.listFree("4", "Falkenberg", "OpenVZ"), emptySet()); + assertEquals(client.listFree(6, "Falkenberg", "OpenVZ"), emptySet()); } public void testAddWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/add/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder() - .put("ipaddress", "31.192.227.37") - .put("serverid", "vz1946889").build())).build(), - HttpResponse.builder().statusCode(200).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/add/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(200).build()) + .getIpClient(); client.addIpToServer("31.192.227.37", "vz1946889"); } + @Test(expectedExceptions = AuthorizationException.class) public void testAddWhenResponseIs4xxThrowsHttpException() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/add/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder() - .put("ipaddress", "31.192.227.37") - .put("serverid", "vz1946889") - .build())).build(), - HttpResponse.builder().statusCode(400).build()) - .getIpClient(); - - try { - client.addIpToServer("31.192.227.37", "vz1946889"); - fail(); - } catch (HttpResponseException e) { - // Expected - } + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/add/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889") + .build())).build(), + HttpResponse.builder().statusCode(401).build()) + .getIpClient(); + client.addIpToServer("31.192.227.37", "vz1946889"); } public void testRemoveWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/remove/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder() - .put("ipaddress", "31.192.227.37") - .put("serverid", "vz1946889").build())).build(), - HttpResponse.builder().statusCode(200).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(200).build()) + .getIpClient(); client.removeIpFromServer("31.192.227.37", "vz1946889"); } + @Test(expectedExceptions = HttpResponseException.class) public void testRemoveWhenResponseIs4xxThrowsHttpException() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("POST").endpoint( - URI.create("https://api.glesys.com/ip/remove/format/json")) - .headers(ImmutableMultimap.builder().put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) - .payload(newUrlEncodedFormPayload( - ImmutableMultimap.builder() - .put("ipaddress", "31.192.227.37") - .put("serverid", "vz1946889").build())).build(), - HttpResponse.builder().statusCode(400).build()) - .getIpClient(); + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); - try { - client.removeIpFromServer("31.192.227.37", "vz1946889"); - fail(); - } catch (HttpResponseException e) { - // Expected - } + client.removeIpFromServer("31.192.227.37", "vz1946889"); } + public void testRemoveAndReleaseWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("release", "true") + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(200).build()) + .getIpClient(); + + client.removeIpFromServerAndRelease("31.192.227.37", "vz1946889"); + } + + @Test(expectedExceptions = HttpResponseException.class) + public void testRemoveAndReleaseWhenResponseIs4xxThrowsHttpException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("release", "true") + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); + + client.removeIpFromServerAndRelease("31.192.227.37", "vz1946889"); + } + + public void testSetPrtWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/setptr/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("data", "sommeptr.").build())).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/ip_get_details.json", MediaType.APPLICATION_JSON)).build()) + .getIpClient(); + + assertEquals(client.setPtr("31.192.227.37", "sommeptr."), getIpInIpDetails()); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testSetPtrWhenResponseIs4xxThrowsHttpException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/setptr/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("data", "sommeptr.").build())).build(), + HttpResponse.builder().statusCode(404).build()) + .getIpClient(); + + client.setPtr("31.192.227.37", "sommeptr."); + } + + public void testResetPrtWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/resetptr/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37").build())).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/ip_get_details.json", MediaType.APPLICATION_JSON)).build()) + .getIpClient(); + + assertEquals(client.resetPtr("31.192.227.37"), getIpInIpDetails()); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testResetPtrWhenResponseIs4xxThrowsHttpException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/resetptr/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37").build())).build(), + HttpResponse.builder().statusCode(401).build()) + .getIpClient(); + + client.resetPtr("31.192.227.37"); + } } \ No newline at end of file diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java index 092f16d1f5..461d4f3cd6 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java @@ -19,69 +19,173 @@ package org.jclouds.glesys.features; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; -import java.util.List; import java.util.Set; import org.jclouds.glesys.domain.IpDetails; -import org.jclouds.glesys.internal.BaseGleSYSClientLiveTest; -import org.testng.annotations.BeforeGroups; +import org.jclouds.glesys.internal.BaseGleSYSClientWithAServerLiveTest; +import org.jclouds.glesys.options.ListIpOptions; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + /** * Tests behavior of {@code IpClient} * * @author Adrian Cole, Mattias Holmqvist */ -@Test(groups = "live", testName = "IpClientLiveTest") -public class IpClientLiveTest extends BaseGleSYSClientLiveTest { +@Test(groups = "live", testName = "IpClientLiveTest", singleThreaded = true) +public class IpClientLiveTest extends BaseGleSYSClientWithAServerLiveTest { - @BeforeGroups(groups = {"live"}) - public void setupContext() { - super.setupContext(); + @BeforeMethod + public void setupClient() { client = gleContext.getApi().getIpClient(); } + @AfterGroups(groups = {"live"}) + public void releaseIp() { + if (reservedIp != null) { + client.release(reservedIp.getAddress()); + } + } + private IpClient client; + private IpDetails reservedIp; @Test public void testListFree() throws Exception { - Set freeIps = client.listFree("4", "Falkenberg", "Xen"); - assertTrue(freeIps.size() >= 1); + Set freeIps = client.listFree(4, "Falkenberg", "Xen"); + assertFalse(freeIps.isEmpty()); } @Test - public void testGetOpenVZDetails() throws Exception { - Set openVzIps = client.listFree("4", "Falkenberg", "OpenVZ"); - assertTrue(openVzIps.size() >= 1); - String openVzIp = openVzIps.iterator().next(); - IpDetails ipDetails = client.getIpDetails(openVzIp); + public void reserveIp() throws Exception { + Set openVzIps = client.listFree(4, "Falkenberg", "OpenVZ"); + assertFalse(openVzIps.isEmpty()); + reservedIp = client.take(Iterables.get(openVzIps, 0)); + assertTrue(reservedIp.isReserved()); + checkOpenVZDefailsInFalkenberg(reservedIp); + } + + @Test(dependsOnMethods = "reserveIp") + public void reserveAndReleaseIp() throws Exception { + IpDetails details = client.release(reservedIp.getAddress()); + assertEquals(details.getAddress(), reservedIp.getAddress()); + assertFalse(details.isReserved()); + + // reserve an address again! + reserveIp(); + } + + @Test(dependsOnMethods = "reserveIp") + public void testList() throws Exception { + Set ownIps = client.listIps(); + assertTrue(ownIps.contains(reservedIp)); + ownIps = client.listIps(ListIpOptions.Builder.datacenter(reservedIp.getDatacenter())); + assertTrue(ownIps.contains(reservedIp)); + ownIps = client.listIps(ListIpOptions.Builder.platform(reservedIp.getPlatform())); + assertTrue(ownIps.contains(reservedIp)); + ownIps = client.listIps(ListIpOptions.Builder.ipVersion(reservedIp.getVersion())); + assertTrue(ownIps.contains(reservedIp)); + + ownIps = client.listIps(ListIpOptions.Builder.datacenter(reservedIp.getDatacenter()), + ListIpOptions.Builder.platform(reservedIp.getPlatform()), + ListIpOptions.Builder.ipVersion(reservedIp.getVersion())); + assertTrue(ownIps.contains(reservedIp)); + + ownIps = client.listIps(ListIpOptions.Builder.serverId("xmthisisnotaserverid")); + assertTrue(ownIps.isEmpty()); + } + + private void checkOpenVZDefailsInFalkenberg(IpDetails ipDetails) { assertEquals(ipDetails.getDatacenter(), "Falkenberg"); assertEquals(ipDetails.getPlatform(), "OpenVZ"); - assertEquals(ipDetails.getIpversion(), "4"); - - // TODO: Ask Glesys to include address in response for OpenVZ? - // assertEquals(ipDetails.getHostText(), openVzIp); + assertEquals(ipDetails.getVersion(), 4); + assertFalse(ipDetails.getPtr().isEmpty()); + // broadcast, gateway and netmask are null for OpenVZ + assertFalse(ipDetails.getNameServers().isEmpty()); + } + + @Test + public void testGetOpenVZDetails() throws Exception { + Set openVzIps = client.listFree(4, "Falkenberg", "OpenVZ"); + assertFalse(openVzIps.isEmpty()); + String openVzIp = openVzIps.iterator().next(); + IpDetails ipDetails = client.getIp(openVzIp); + checkOpenVZDefailsInFalkenberg(ipDetails); + assertEquals(ipDetails.getAddress(), openVzIp); } @Test public void testGetXenDetails() throws Exception { - Set xenVzIps = client.listFree("4", "Falkenberg", "Xen"); - assertTrue(xenVzIps.size() >= 1); + Set xenVzIps = client.listFree(4, "Falkenberg", "Xen"); + assertFalse(xenVzIps.isEmpty()); String xenIp = xenVzIps.iterator().next(); - IpDetails ipDetails = client.getIpDetails(xenIp); + IpDetails ipDetails = client.getIp(xenIp); assertEquals(ipDetails.getDatacenter(), "Falkenberg"); assertEquals(ipDetails.getPlatform(), "Xen"); - assertEquals(ipDetails.getIpversion(), "4"); + assertEquals(ipDetails.getVersion(), 4); assertEquals(ipDetails.getAddress(), xenIp); - assertNotNull(ipDetails.getPtr()); + assertFalse(ipDetails.getPtr().isEmpty()); assertNotNull(ipDetails.getBroadcast()); assertNotNull(ipDetails.getGateway()); assertNotNull(ipDetails.getNetmask()); - List nameServers = ipDetails.getNameServers(); - assertNotNull(nameServers); + assertFalse(ipDetails.getNameServers().isEmpty()); } + @Test(dependsOnMethods = "reserveIp") + public void testPtrSetReset() throws Exception { + IpDetails original = reservedIp; + + IpDetails modified = client.setPtr(reservedIp.getAddress(), "wibble."); + IpDetails modified2 = client.getIp(reservedIp.getAddress()); + + assertEquals(modified.getPtr(), "wibble."); + assertEquals(modified2, modified); + + reservedIp = client.resetPtr(reservedIp.getAddress()); + + assertEquals(reservedIp, original); + } + + @Test(dependsOnMethods = "reserveIp") + public void testAddRemove() throws Exception { + IpDetails added = client.addIpToServer(reservedIp.getAddress(), serverId); + + assertEquals(added.getAddress(), reservedIp.getAddress()); + assertEquals(added.getPtr(), reservedIp.getPtr()); + assertEquals(added.getServerId(), serverId); + + IpDetails again = client.getIp(reservedIp.getAddress()); + assertEquals(again, added); + + IpDetails removed = client.removeIpFromServer(reservedIp.getAddress(), serverId); + assertEquals(removed, added.toBuilder().serverId(null).build()); + + assertEquals(removed, reservedIp); + + Set openVzIps = Sets.newHashSet(client.listFree(4, "Falkenberg", "OpenVZ")); + openVzIps.remove(reservedIp.getAddress()); + assertFalse(openVzIps.isEmpty()); + + added = client.addIpToServer(reservedIp.getAddress(), serverId); + + assertEquals(added.getServerId(), serverId); + + removed = client.removeIpFromServerAndRelease(reservedIp.getAddress(), serverId); + + assertNull(removed.getServerId()); + assertFalse(removed.isReserved()); + + + // reserve an address again! + reserveIp(); + } } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientExpectTest.java index c6d591d19a..7af58c3c8b 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientExpectTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientExpectTest.java @@ -27,18 +27,10 @@ import java.net.URI; import java.util.LinkedHashMap; import java.util.Map; -import org.jclouds.glesys.GleSYSClient; -import org.jclouds.glesys.domain.AllowedArgumentsForCreateServer; -import org.jclouds.glesys.domain.Console; -import org.jclouds.glesys.domain.Cost; -import org.jclouds.glesys.domain.Ip; -import org.jclouds.glesys.domain.OSTemplate; -import org.jclouds.glesys.domain.ResourceUsage; -import org.jclouds.glesys.domain.Server; -import org.jclouds.glesys.domain.ServerDetails; -import org.jclouds.glesys.domain.ServerSpec; -import org.jclouds.glesys.domain.ServerStatus; -import org.jclouds.glesys.domain.ServerUptime; +import javax.ws.rs.core.MediaType; + +import org.jclouds.glesys.domain.*; +import org.jclouds.glesys.internal.BaseGleSYSClientExpectTest; import org.jclouds.glesys.options.CloneServerOptions; import org.jclouds.glesys.options.CreateServerOptions; import org.jclouds.glesys.options.DestroyServerOptions; @@ -48,7 +40,6 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; -import org.jclouds.rest.internal.BaseRestClientExpectTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; @@ -61,11 +52,7 @@ import com.google.common.collect.ImmutableSet; * @author Adam Lowe */ @Test(groups = "unit", testName = "ServerAsyncClientTest") -public class ServerClientExpectTest extends BaseRestClientExpectTest { - - public ServerClientExpectTest() { - provider = "glesys"; - } +public class ServerClientExpectTest extends BaseGleSYSClientExpectTest { public void testListServersWhenResponseIs2xx() throws Exception { ServerClient client = requestSendsResponse( @@ -136,23 +123,24 @@ public class ServerClientExpectTest extends BaseRestClientExpectTest expectedBuilder = ImmutableSet.builder(); - for (String name : new String[] { "Centos 5", "Centos 5 64-bit", "Centos 6 32-bit", "Centos 6 64-bit", + for (String name : new String[]{"Centos 5", "Centos 5 64-bit", "Centos 6 32-bit", "Centos 6 64-bit", "Debian 5.0 32-bit", "Debian 5.0 64-bit", "Debian 6.0 32-bit", "Debian 6.0 64-bit", "Fedora Core 11", "Fedora Core 11 64-bit", "Gentoo", "Gentoo 64-bit", "Scientific Linux 6", "Scientific Linux 6 64-bit", - "Slackware 12", "Ubuntu 10.04 LTS 32-bit", "Ubuntu 10.04 LTS 64-bit", "Ubuntu 11.04 64-bit" }) { - expectedBuilder.add(new OSTemplate(name, 5, 128, "linux", "OpenVZ")); + "Slackware 12", "Ubuntu 10.04 LTS 32-bit", "Ubuntu 10.04 LTS 64-bit", "Ubuntu 11.04 64-bit"}) { + expectedBuilder.add(OSTemplate.builder().name(name).minDiskSize(5).minMemSize(128).os("linux").platform("OpenVZ").build()); } - for (String name : new String[] { "CentOS 5.5 x64", "CentOS 5.5 x86", "Centos 6 x64", "Centos 6 x86", + for (String name : new String[]{"CentOS 5.5 x64", "CentOS 5.5 x86", "Centos 6 x64", "Centos 6 x86", "Debian-6 x64", "Debian 5.0.1 x64", "FreeBSD 8.2", "Gentoo 10.1 x64", "Ubuntu 8.04 x64", - "Ubuntu 10.04 LTS 64-bit", "Ubuntu 10.10 x64", "Ubuntu 11.04 x64" }) { - expectedBuilder.add(new OSTemplate(name, 5, 512, name.startsWith("FreeBSD") ? "freebsd" : "linux", "Xen")); + "Ubuntu 10.04 LTS 64-bit", "Ubuntu 10.10 x64", "Ubuntu 11.04 x64"}) { + expectedBuilder.add(OSTemplate.builder().name(name).minDiskSize(5).minMemSize(512) + .os(name.startsWith("FreeBSD") ? "freebsd" : "linux").platform("Xen").build()); } - for (String name : new String[] { "Windows Server 2008 R2 x64 std", "Windows Server 2008 R2 x64 web", - "Windows Server 2008 x64 web", "Windows Server 2008 x86 web" }) { - expectedBuilder.add(new OSTemplate(name, 20, 1024, "windows", "Xen")); + for (String name : new String[]{"Windows Server 2008 R2 x64 std", "Windows Server 2008 R2 x64 web", + "Windows Server 2008 x64 web", "Windows Server 2008 x86 web"}) { + expectedBuilder.add(OSTemplate.builder().name(name).minDiskSize(20).minMemSize(1024).os("windows").platform("Xen").build()); } - + assertEquals(client.listTemplates(), expectedBuilder.build()); } @@ -172,11 +160,11 @@ public class ServerClientExpectTest extends BaseRestClientExpectTestbuilder() - .put("serverid", "xm3276891").build())).build(), + .put("serverid", "xm3276891") + .put("description", "this is a different description!") + .put("hostname", "new-hostname") + .build())).build(), HttpResponse.builder().statusCode(206).build()).getServerClient(); - client.editServer("xm3276891"); + client.editServer("xm3276891", EditServerOptions.Builder.description("this is a different description!"), + EditServerOptions.Builder.hostname("new-hostname")); } @Test @@ -290,7 +282,7 @@ public class ServerClientExpectTest extends BaseRestClientExpectTestbuilder() .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() - .put("serverid", "server777").put("keepip", "1").build())).build(), + .put("serverid", "server777").put("keepip", "true").build())).build(), HttpResponse.builder().statusCode(200).build()) .getServerClient(); @@ -548,21 +540,63 @@ public class ServerClientExpectTest extends BaseRestClientExpectTestbuilder() .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() - .put("serverid", "server777").put("keepip", "0").build())).build(), + .put("serverid", "server777").put("keepip", "false").build())).build(), HttpResponse.builder().statusCode(401).build()) .getServerClient(); client.destroyServer("server777", DestroyServerOptions.Builder.discardIp()); } + public void testResourceUsageWhenResponseIs2xx() throws Exception { + ServerClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/server/resourceusage/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("serverid", "server777").put("resolution", "minute").put("resource", "diskioread").build())).build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/server_resource_usage.json", MediaType.APPLICATION_JSON)) + .build()) + .getServerClient(); + + ResourceUsage expected = ResourceUsage.builder().info( + ResourceUsageInfo.builder().resolution("minute").resource("diskioread").unit("KB").build()) + .values( + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:21:07+02:00")).build(), + ResourceUsageValue.builder().value(5.1).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:22:05+02:00")).build(), + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:23:05+02:00")).build(), + ResourceUsageValue.builder().value(10.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:24:08+02:00")).build(), + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:25:12+02:00")).build(), + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:26:07+02:00")).build(), + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:27:12+02:00")).build(), + ResourceUsageValue.builder().value(0.0).timestamp(dateService.iso8601SecondsDateParse("2012-06-24T14:28:05+02:00")).build() + ).build(); + assertEquals(client.getResourceUsage("server777", "diskioread", "minute").toString(), expected.toString()); + } + + @Test(expectedExceptions = {AuthorizationException.class}) + public void testResouceUsageWhenResponseIs4xx() throws Exception { + ServerClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint(URI.create("https://api.glesys.com/server/resourceusage/format/json")) + .headers(ImmutableMultimap.builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload(ImmutableMultimap.builder() + .put("serverid", "server777").put("resolution", "minute").put("resource", "diskioread").build())).build(), + HttpResponse.builder().statusCode(401).build()) + .getServerClient(); + + client.getResourceUsage("server777", "diskioread", "minute"); + } private ServerStatus expectedServerStatus() { - ResourceUsage cpu = ResourceUsage.builder().unit("cores").max(1.0).usage(0.0).build(); - ResourceUsage disk = ResourceUsage.builder().unit("GB").usage(0.0).max(5).build(); - ResourceUsage memory = ResourceUsage.builder().unit("MB").usage(0.0).max(512).build(); - ServerUptime uptime = ServerUptime.builder().current(0).unit("seconds").build(); + ResourceStatus cpu = ResourceStatus.builder().unit("cores").max(1.0).usage(0.0).build(); + ResourceStatus disk = ResourceStatus.builder().unit("MB").usage(0.0).max(5120).build(); + ResourceStatus memory = ResourceStatus.builder().unit("MB").usage(2.0).max(512).build(); + ServerUptime uptime = ServerUptime.builder().current(21).unit("seconds").build(); return ServerStatus.builder().state(Server.State.RUNNING).uptime(uptime). cpu(cpu).disk(disk).memory(memory).build(); } - + } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientLiveTest.java index 6ff5e39fed..033a869cd2 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/ServerClientLiveTest.java @@ -26,21 +26,14 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; -import org.jclouds.glesys.domain.AllowedArgumentsForCreateServer; -import org.jclouds.glesys.domain.Console; -import org.jclouds.glesys.domain.OSTemplate; -import org.jclouds.glesys.domain.ResourceUsage; -import org.jclouds.glesys.domain.Server; -import org.jclouds.glesys.domain.ServerDetails; -import org.jclouds.glesys.domain.ServerLimit; -import org.jclouds.glesys.domain.ServerStatus; -import org.jclouds.glesys.internal.BaseGleSYSClientLiveTest; +import org.jclouds.glesys.domain.*; +import org.jclouds.glesys.internal.BaseGleSYSClientWithAServerLiveTest; import org.jclouds.glesys.options.CloneServerOptions; import org.jclouds.glesys.options.DestroyServerOptions; +import org.jclouds.glesys.options.EditServerOptions; import org.jclouds.glesys.options.ServerStatusOptions; import org.jclouds.predicates.RetryablePredicate; import org.testng.annotations.AfterGroups; -import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -52,31 +45,23 @@ import com.google.common.base.Predicate; * @author Adrian Cole * @author Adam Lowe */ -@Test(groups = "live", testName = "ServerClientLiveTest") -public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { - public static final String testHostName1 = "jclouds-test"; +@Test(groups = "live", testName = "ServerClientLiveTest", singleThreaded = true) +public class ServerClientLiveTest extends BaseGleSYSClientWithAServerLiveTest { public static final String testHostName2 = "jclouds-test2"; - @BeforeGroups(groups = {"live"}) - public void setupContext() { - super.setupContext(); + @BeforeMethod + public void setupClient() { client = gleContext.getApi().getServerClient(); - serverStatusChecker = createServer(testHostName1); - testServerId = serverStatusChecker.getServerId(); } @AfterGroups(groups = {"live"}) - public void tearDownContext() { - client.destroyServer(testServerId, DestroyServerOptions.Builder.discardIp()); + public void deleteExtraServer() { if (testServerId2 != null) { client.destroyServer(testServerId2, DestroyServerOptions.Builder.discardIp()); } - super.tearDownContext(); } private ServerClient client; - private ServerStatusChecker serverStatusChecker; - private String testServerId; private String testServerId2; @BeforeMethod @@ -107,7 +92,6 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { assert t.getTransfersInGB().size() > 0 : t; } - @Test public void testListTemplates() throws Exception { Set oSTemplates = client.listTemplates(); @@ -126,7 +110,6 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { assert t.getMinMemSize() > 0 : t; } - @Test public void testListServers() throws Exception { Set response = client.listServers(); assertNotNull(response); @@ -142,9 +125,8 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { } } - @Test public void testServerDetails() throws Exception { - ServerDetails details = client.getServerDetails(testServerId); + ServerDetails details = client.getServerDetails(serverId); checkServer(details); assertEquals("Ubuntu 10.04 LTS 32-bit", details.getTemplateName()); assertEquals("Falkenberg", details.getDatacenter()); @@ -155,48 +137,50 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { assertEquals(50, details.getTransferGB()); } - @Test public void testServerStatus() throws Exception { - ServerStatus newStatus = client.getServerStatus(testServerId); + ServerStatus newStatus = client.getServerStatus(serverId); checkStatus(newStatus); } - @Test(enabled=false) // TODO work a better plan + public void testEditServer() throws Exception { + ServerDetails edited = client.editServer(serverId, EditServerOptions.Builder.description("this is a different description!")); + assertEquals(edited.getDescription(), "this is a different description!"); + + edited = client.editServer(serverId, EditServerOptions.Builder.description("another description!"), EditServerOptions.Builder.hostname("host-name1")); + assertEquals(edited.getDescription(), "another description!"); + assertEquals(edited.getHostname(), "host-name1"); + + edited = client.resetPassword(serverId, "anotherpass"); + assertEquals(edited.getHostname(), "host-name1"); + + edited = client.editServer(serverId, EditServerOptions.Builder.hostname(hostName)); + assertEquals(edited.getHostname(), hostName); + } + + @Test public void testRebootServer() throws Exception { - long uptime = 0; - - while(uptime < 20) { - uptime = client.getServerStatus(testServerId).getUptime().getCurrent(); - } - - assertTrue(uptime > 19); - - client.rebootServer(testServerId); - - Thread.sleep(1000); + assertTrue(serverStatusChecker.apply(Server.State.RUNNING)); - uptime = client.getServerStatus(testServerId).getUptime().getCurrent(); + client.rebootServer(serverId); - assertTrue(uptime < 20); - assertTrue(serverStatusChecker.apply(Server.State.RUNNING)); } - @Test(enabled=false) // TODO + @Test public void testStopAndStartServer() throws Exception { - client.stopServer(testServerId); + assertTrue(serverStatusChecker.apply(Server.State.RUNNING)); + + client.stopServer(serverId); assertTrue(serverStatusChecker.apply(Server.State.STOPPED)); - client.startServer(testServerId); + client.startServer(serverId); assertTrue(serverStatusChecker.apply(Server.State.RUNNING)); } - - @Test public void testServerLimits() throws Exception { - Map limits = client.getServerLimits(testServerId); + Map limits = client.getServerLimits(serverId); assertNotNull(limits); for (Map.Entry entry : limits.entrySet()) { assertNotNull(entry.getKey()); @@ -210,19 +194,31 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { } } - @Test + public void testResourceUsage() throws Exception { + // test server has only been in existence for less than a minute - check all servers + for (Server server : client.listServers()) { + ResourceUsage usage = client.getResourceUsage(server.getId(), "diskioread", "minute"); + assertEquals(usage.getInfo().getResource(), "diskioread"); + assertEquals(usage.getInfo().getResolution(), "minute"); + + usage = client.getResourceUsage(server.getId(), "cpuusage", "minute"); + assertEquals(usage.getInfo().getResource(), "cpuusage"); + assertEquals(usage.getInfo().getResolution(), "minute"); + } + } + public void testConsole() throws Exception { - Console console = client.getConsole(testServerId); + Console console = client.getConsole(serverId); assertNotNull(console); assertNotNull(console.getHost()); assertTrue(console.getPort() > 0 && console.getPort() < 65537); assertNotNull(console.getPassword()); } - // takes a few minutes and requires an extra server (using 2 already) + // takes a few minutes and requires an extra server (used 1 already) @Test(enabled=false) public void testCloneServer() throws Exception { - ServerDetails testServer2 = client.cloneServer(testServerId, testHostName2, CloneServerOptions.Builder.cpucores(1)); + ServerDetails testServer2 = client.cloneServer(serverId, testHostName2, CloneServerOptions.Builder.cpucores(1)); assertNotNull(testServer2.getId()); assertEquals(testServer2.getHostname(), "jclouds-test2"); @@ -249,11 +245,9 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { return false; } - }, 300, 10, TimeUnit.SECONDS); + }, 600, 30, TimeUnit.SECONDS); - assertTrue(cloneChecker.apply(Server.State.RUNNING) - - ); + assertTrue(cloneChecker.apply(Server.State.RUNNING)); } private void checkServer(ServerDetails server) { @@ -273,7 +267,7 @@ public class ServerClientLiveTest extends BaseGleSYSClientLiveTest { assertNotNull(status.getUptime()); - for (ResourceUsage usage : new ResourceUsage[] { status.getCpu(), status.getDisk(), status.getMemory() }) { + for (ResourceStatus usage : new ResourceStatus[] { status.getCpu(), status.getDisk(), status.getMemory() }) { assertNotNull(usage); assert usage.getMax() >= 0.0 : status; assert usage.getUsage() >= 0.0 : status; diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java new file mode 100644 index 0000000000..db294669ef --- /dev/null +++ b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java @@ -0,0 +1,37 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.internal; + +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.glesys.GleSYSClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +/** + * Configures a glesys client expect test - provides a dateService + * + * @author Adam Lowe + */ +public class BaseGleSYSClientExpectTest extends BaseRestClientExpectTest { + protected DateService dateService = new SimpleDateFormatDateService(); + + public BaseGleSYSClientExpectTest() { + provider = "glesys"; + } +} \ No newline at end of file diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientLiveTest.java index 8db9fff181..9c75151b4b 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientLiveTest.java @@ -18,24 +18,14 @@ */ package org.jclouds.glesys.internal; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; -import java.util.UUID; import java.util.concurrent.TimeUnit; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.glesys.GleSYSAsyncClient; import org.jclouds.glesys.GleSYSClient; -import org.jclouds.glesys.domain.Server; -import org.jclouds.glesys.domain.ServerDetails; -import org.jclouds.glesys.domain.ServerSpec; -import org.jclouds.glesys.domain.ServerStatus; import org.jclouds.glesys.features.DomainClient; -import org.jclouds.glesys.features.ServerClient; -import org.jclouds.glesys.options.ServerStatusOptions; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; import org.testng.annotations.BeforeGroups; @@ -77,43 +67,4 @@ public class BaseGleSYSClientLiveTest extends BaseComputeServiceContextLiveTest assertTrue(result.apply(before + 1)); } - protected ServerStatusChecker createServer(String hostName) { - ServerClient client = gleContext.getApi().getServerClient(); - - ServerDetails testServer = client.createServerWithHostnameAndRootPassword( - ServerSpec.builder().datacenter("Falkenberg").platform("OpenVZ").templateName("Ubuntu 10.04 LTS 32-bit") - .diskSizeGB(5).memorySizeMB(512).cpuCores(1).transferGB(50).build(), hostName, UUID.randomUUID() - .toString().replace("-","")); - - assertNotNull(testServer.getId()); - assertEquals(testServer.getHostname(), hostName); - assertFalse(testServer.getIps().isEmpty()); - - ServerStatusChecker runningServerCounter = new ServerStatusChecker(client, testServer.getId(), 180, 10, - TimeUnit.SECONDS); - - assertTrue(runningServerCounter.apply(Server.State.RUNNING)); - return runningServerCounter; - } - - public static class ServerStatusChecker extends RetryablePredicate { - private final String serverId; - - public String getServerId() { - return serverId; - } - - public ServerStatusChecker(final ServerClient client, final String serverId, long maxWait, long period, - TimeUnit unit) { - super(new Predicate() { - - public boolean apply(Server.State value) { - ServerStatus status = client.getServerStatus(serverId, ServerStatusOptions.Builder.state()); - return status.getState() == value; - } - - }, maxWait, period, unit); - this.serverId = serverId; - } - } } diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientWithAServerLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientWithAServerLiveTest.java new file mode 100644 index 0000000000..61436cd1fb --- /dev/null +++ b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientWithAServerLiveTest.java @@ -0,0 +1,128 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.glesys.internal; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.jclouds.glesys.domain.Server; +import org.jclouds.glesys.domain.ServerDetails; +import org.jclouds.glesys.domain.ServerSpec; +import org.jclouds.glesys.domain.ServerStatus; +import org.jclouds.glesys.features.DomainClient; +import org.jclouds.glesys.features.ServerClient; +import org.jclouds.glesys.options.DestroyServerOptions; +import org.jclouds.glesys.options.ServerStatusOptions; +import org.jclouds.predicates.RetryablePredicate; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; + +/** + * Tests behavior of {@code GleSYSClient} + * + * @author Adrian Cole, Adam Lowe + */ +@Test(groups = "live", singleThreaded = true) +public class BaseGleSYSClientWithAServerLiveTest extends BaseGleSYSClientLiveTest { + protected String serverId; + protected String hostName = "test-server-jclouds"; + protected ServerStatusChecker serverStatusChecker; + + public BaseGleSYSClientWithAServerLiveTest() { + provider = "glesys"; + } + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public final void setupContext() { + assertNull(serverId, "This method should be called EXACTLY once per run"); + super.setupContext(); + serverStatusChecker = createServer(hostName); + serverId = serverStatusChecker.getServerId(); + } + + @AfterGroups(groups = {"integration", "live"}) + @Override + public final void tearDownContext() { + gleContext.getApi().getServerClient().destroyServer(serverId, DestroyServerOptions.Builder.discardIp()); + super.tearDownContext(); + } + + protected void createDomain(String domain) { + final DomainClient client = gleContext.getApi().getDomainClient(); + int before = client.listDomains().size(); + client.addDomain(domain); + RetryablePredicate result = new RetryablePredicate(new Predicate() { + public boolean apply(Integer value) { + return client.listDomains().size() == value; + } + }, 30, 1, TimeUnit.SECONDS); + + assertTrue(result.apply(before + 1)); + } + + protected ServerStatusChecker createServer(String hostName) { + ServerClient client = gleContext.getApi().getServerClient(); + + ServerDetails testServer = client.createServerWithHostnameAndRootPassword( + ServerSpec.builder().datacenter("Falkenberg").platform("OpenVZ").templateName("Ubuntu 10.04 LTS 32-bit") + .diskSizeGB(5).memorySizeMB(512).cpuCores(1).transferGB(50).build(), hostName, UUID.randomUUID() + .toString().replace("-","")); + + assertNotNull(testServer.getId()); + assertEquals(testServer.getHostname(), hostName); + assertFalse(testServer.getIps().isEmpty()); + + ServerStatusChecker runningServerCounter = new ServerStatusChecker(client, testServer.getId(), 180, 10, + TimeUnit.SECONDS); + + assertTrue(runningServerCounter.apply(Server.State.RUNNING)); + return runningServerCounter; + } + + public static class ServerStatusChecker extends RetryablePredicate { + private final String serverId; + + public String getServerId() { + return serverId; + } + + public ServerStatusChecker(final ServerClient client, final String serverId, long maxWait, long period, + TimeUnit unit) { + super(new Predicate() { + + public boolean apply(Server.State value) { + ServerStatus status = client.getServerStatus(serverId, ServerStatusOptions.Builder.state()); + return status.getState() == value; + } + + }, maxWait, period, unit); + this.serverId = serverId; + } + } +} \ No newline at end of file diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseFullIpDetailsTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseFullIpDetailsTest.java index 81c7b8619b..6f4ae89887 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseFullIpDetailsTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseFullIpDetailsTest.java @@ -23,6 +23,7 @@ import javax.ws.rs.Consumes; import javax.ws.rs.core.MediaType; import org.jclouds.glesys.config.GleSYSParserModule; +import org.jclouds.glesys.domain.Cost; import org.jclouds.glesys.domain.IpDetails; import org.jclouds.json.BaseItemParserTest; import org.jclouds.json.config.GsonModule; @@ -42,9 +43,11 @@ public class ParseFullIpDetailsTest extends BaseItemParserTest { @SelectJson("details") @Consumes(MediaType.APPLICATION_JSON) public IpDetails expected() { - return IpDetails.builder().datacenter("Falkenberg").ipversion("4").platform("Xen") - .ptr("109-74-10-146-static.serverhotell.net.").address("109.74.10.146").netmask("255.255.254.0") - .broadcast("109.74.11.255").gateway("109.74.10.1").nameServers("79.99.4.100", "79.99.4.103").build(); + return IpDetails.builder().datacenter("Falkenberg").version4() + .address("109.74.10.13") + .platform("Xen").ptr("109-74-10-13-static.serverhotell.net.").netmask("255.255.254.0").broadcast("109.74.11.255") + .gateway("109.74.10.1").nameServers("79.99.4.100", "79.99.4.101") + .cost(Cost.builder().amount(2.0).currency("EUR").timePeriod("month").build()).build(); } protected Injector injector() { diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseIpAddressFromResponseTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseIpAddressFromResponseTest.java index 6ad2e03f03..242b005dab 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseIpAddressFromResponseTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/parse/ParseIpAddressFromResponseTest.java @@ -18,9 +18,6 @@ */ package org.jclouds.glesys.parse; -import static java.util.Arrays.asList; - -import java.util.HashSet; import java.util.Set; import javax.ws.rs.Consumes; @@ -32,22 +29,31 @@ import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.SelectJson; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableSet; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = "unit", testName = "ParseIpAddressFromResponseTest") public class ParseIpAddressFromResponseTest extends BaseSetParserTest { - + public static final Set EXPECTED_IPS = ImmutableSet.of("109.74.10.13", "109.74.10.50", "109.74.10.109", "109.74.10.125", + "109.74.10.131", "109.74.10.148", "109.74.10.171", "109.74.10.173", "109.74.10.191", "109.74.10.215", + "109.74.10.216", "109.74.10.219", "109.74.10.223", "109.74.10.224", "109.74.10.236", "109.74.10.249", + "109.74.11.49", "109.74.11.58", "109.74.11.62", "109.74.11.63", "109.74.11.73", "109.74.11.76", + "109.74.11.86", "109.74.11.98", "109.74.11.118", "109.74.11.124", "109.74.11.131", "109.74.11.137", + "109.74.11.146", "109.74.11.157", "109.74.11.159", "109.74.11.173", "109.74.11.178", "109.74.11.187", + "109.74.11.190", "109.74.11.205", "109.74.11.213", "109.74.11.234", "109.74.11.236", "109.74.11.241", + "109.74.11.243", "109.74.11.246", "109.74.11.247"); + @Override public String resource() { return "/ip_list_free.json"; } @Override - @SelectJson("iplist") + @SelectJson("ipaddresses") @Consumes(MediaType.APPLICATION_JSON) public Set expected() { - return new HashSet(asList("31.192.226.131", "31.192.226.133")); + return EXPECTED_IPS; } protected Injector injector() { diff --git a/labs/glesys/src/test/resources/archive_details.json b/labs/glesys/src/test/resources/archive_details.json index 04be81faa7..ed0f6b8cd8 100644 --- a/labs/glesys/src/test/resources/archive_details.json +++ b/labs/glesys/src/test/resources/archive_details.json @@ -1 +1 @@ -{"response":{"status":{"code":"200","text":"OK"},"details":{"username":"xxxxxx_test1","size_total":"30 GB","size_free":"30 GB","locked":false},"debug":{"input":{"username":"xxxxxx_test1"}}}} \ No newline at end of file +{"response":{"status":{"code":"200","text":"OK"},"details":{"username":"xxxxxx_test1","sizetotal":"30 GB","sizefree":"30 GB","locked":false},"debug":{"input":{"username":"xxxxxx_test1"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/archive_list.json b/labs/glesys/src/test/resources/archive_list.json index 0144c66e94..31662fff9c 100644 --- a/labs/glesys/src/test/resources/archive_list.json +++ b/labs/glesys/src/test/resources/archive_list.json @@ -1 +1 @@ -{"response":{"status":{"code":"200","text":"OK"},"archives":[{"username":"xxxxx_test1","size_total":"30 GB","size_free":"30 GB","locked":false}],"debug":{"input":[]}}} \ No newline at end of file +{"response":{"status":{"code":"200","text":"OK"},"archives":[{"username":"xxxxx_test1","sizetotal":"30 GB","sizefree":"20 GB","locked":false}],"debug":{"input":[]}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/domain_details.json b/labs/glesys/src/test/resources/domain_details.json new file mode 100644 index 0000000000..2f1afbe77f --- /dev/null +++ b/labs/glesys/src/test/resources/domain_details.json @@ -0,0 +1 @@ +{"response":{"status":{"code":200,"timestamp":"2012-06-24T11:52:49+02:00","text":"Domain added"},"domain":{"domainname":"cl13016-domain.jclouds.org","createtime":"2012-06-24T11:52:49+02:00","recordcount":9,"usingglesysnameserver":"no"},"debug":{"input":{"domainname":"cl13016-domain.jclouds.org"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/domain_list_records.json b/labs/glesys/src/test/resources/domain_list_records.json index 96d0277148..3bee5f2d37 100644 --- a/labs/glesys/src/test/resources/domain_list_records.json +++ b/labs/glesys/src/test/resources/domain_list_records.json @@ -1 +1 @@ -{"response":{"status":{"code":200,"text":"OK"},"records":[{"id":224546,"domainname":"testglesys.jclouds.org","host":"@","type":"TXT","data":"v=spf1 include:spf.glesys.se -all","ttl":3600},{"id":224545,"domainname":"testglesys.jclouds.org","host":"@","type":"MX","data":"20 mx02.glesys.se.","ttl":3600},{"id":224543,"domainname":"testglesys.jclouds.org","host":"mail","type":"A","data":"79.99.4.40","ttl":3600},{"id":224544,"domainname":"testglesys.jclouds.org","host":"@","type":"MX","data":"10 mx01.glesys.se.","ttl":3600},{"id":224542,"domainname":"testglesys.jclouds.org","host":"www","type":"A","data":"127.0.0.1","ttl":3600},{"id":224541,"domainname":"testglesys.jclouds.org","host":"@","type":"A","data":"127.0.0.1","ttl":3600},{"id":224540,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns3.namesystem.se.","ttl":3600},{"id":224539,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns2.namesystem.se.","ttl":3600},{"id":224538,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns1.namesystem.se.","ttl":3600}],"debug":{"input":{"domainname":"testglesys.jclouds.org"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"text":"OK"},"records":[{"recordid":224546,"domainname":"testglesys.jclouds.org","host":"@","type":"TXT","data":"v=spf1 include:spf.glesys.se -all","ttl":3600},{"recordid":224545,"domainname":"testglesys.jclouds.org","host":"@","type":"MX","data":"20 mx02.glesys.se.","ttl":3600},{"recordid":224543,"domainname":"testglesys.jclouds.org","host":"mail","type":"A","data":"79.99.4.40","ttl":3600},{"recordid":224544,"domainname":"testglesys.jclouds.org","host":"@","type":"MX","data":"10 mx01.glesys.se.","ttl":3600},{"recordid":224542,"domainname":"testglesys.jclouds.org","host":"www","type":"A","data":"127.0.0.1","ttl":3600},{"recordid":224541,"domainname":"testglesys.jclouds.org","host":"@","type":"A","data":"127.0.0.1","ttl":3600},{"recordid":224540,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns3.namesystem.se.","ttl":3600},{"recordid":224539,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns2.namesystem.se.","ttl":3600},{"recordid":224538,"domainname":"testglesys.jclouds.org","host":"@","type":"NS","data":"ns1.namesystem.se.","ttl":3600}],"debug":{"input":{"domainname":"testglesys.jclouds.org"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/domain_record.json b/labs/glesys/src/test/resources/domain_record.json new file mode 100644 index 0000000000..1efda7b882 --- /dev/null +++ b/labs/glesys/src/test/resources/domain_record.json @@ -0,0 +1 @@ +{"response":{"status":{"code":200,"timestamp":"2012-06-24T11:52:51+02:00","text":"Record added."},"record":{"recordid":256151,"domainname":"cl13016-domain.jclouds.org","host":"test","type":"A","data":"127.0.0.1","ttl":3600},"debug":{"input":{"domainname":"cl13016-domain.jclouds.org","type":"A","host":"test","data":"127.0.0.1"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/email_details.json b/labs/glesys/src/test/resources/email_details.json new file mode 100644 index 0000000000..e42fd53e1c --- /dev/null +++ b/labs/glesys/src/test/resources/email_details.json @@ -0,0 +1 @@ +{"response":{"status":{"code":200,"timestamp":"2012-06-20T12:01:01+02:00","text":"Account created"},"emailaccount":{"emailaccount":"test@CL13016.jclouds.org","quota":{"max":200,"unit":"MB"},"antispamlevel":3,"antivirus":"yes","autorespond":"no","autorespondmessage":null,"autorespondsaveemail":"yes","created":"2012-06-20T12:01:01+02:00","modified":null},"debug":{"input":{"emailaccount":"test@CLXXXX.jclouds.org","password":"password","antivirus":"1","autorespond":"1","autorespondmessage":"out of office"}}}} diff --git a/labs/glesys/src/test/resources/email_list.json b/labs/glesys/src/test/resources/email_list.json index b970ad8068..5e37373618 100644 --- a/labs/glesys/src/test/resources/email_list.json +++ b/labs/glesys/src/test/resources/email_list.json @@ -1 +1,12 @@ -{"response":{"status":{"code":"200","text":"OK"},"list":{"emailaccounts":[{"emailaccount":"test2@adamlowe.net","quota":"200 MB","usedquota":"0 MB","antispamlevel":3,"antivirus":true,"autorespond":false,"autorespondmessage":false,"autorespondsaveemail":true,"created":"2011-12-22 12:14:29","modified":"2011-12-22 12:14:31"},{"emailaccount":"test@adamlowe.net","quota":"200 MB","usedquota":"0 MB","antispamlevel":3,"antivirus":true,"autorespond":false,"autorespondmessage":false,"autorespondsaveemail":true,"created":"2011-12-22 12:13:14","modified":"2011-12-22 12:13:35"}]},"debug":{"input":{"domain":"adamlowe.net"}}}} \ No newline at end of file +{"response":{ + "status":{"code":200,"timestamp":"2012-06-24T11:53:55+02:00","text":"OK"}, + "list":{ + "emailaccounts":[ + {"emailaccount":"test1@cl13016.test.jclouds.org","quota":{"max":200,"unit":"MB"},"antispamlevel":3,"antivirus":"yes","autorespond":"no","autorespondmessage":null,"autorespondsaveemail":"yes","created":"2012-06-24T11:53:45+02:00","modified":null}, + {"emailaccount":"test@cl13016.test.jclouds.org","quota":{"max":200,"unit":"MB"},"antispamlevel":3,"antivirus":"no","autorespond":"no","autorespondmessage":null,"autorespondsaveemail":"yes","created":"2012-06-24T11:53:44+02:00","modified":"2012-06-24T11:53:48+02:00"} + ], + "emailaliases":[ + {"emailalias":"test2@cl13016.test.jclouds.org","goto":"test1@cl13016.test.jclouds.org"} + ] + }, + "debug":{"input":{"domainname":"cl13016.test.jclouds.org"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/email_overview.json b/labs/glesys/src/test/resources/email_overview.json index d98a8c852e..42858145cc 100644 --- a/labs/glesys/src/test/resources/email_overview.json +++ b/labs/glesys/src/test/resources/email_overview.json @@ -1 +1,6 @@ -{"response":{"status":{"code":"200","text":"OK"},"summary":{"accounts":2,"maxaccounts":"50","aliases":0,"maxaliases":1000},"domains":[{"domain":"adamlowe.net","accounts":2,"aliases":0}],"debug":{"input":[]}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-24T11:53:53+02:00","text":"OK"}, + "overview":{ + "summary":{"accounts":2,"maxaccounts":50,"aliases":1,"maxaliases":1000}, + "domains":[{ + "domainname":"cl13016.test.jclouds.org","accounts":2,"aliases":1,"usingglesysemailserver":"no"}]}, + "debug":{"input":[]}}}" diff --git a/labs/glesys/src/test/resources/ip_get_details.json b/labs/glesys/src/test/resources/ip_get_details.json index ec6724e7b3..e3e3babf7b 100644 --- a/labs/glesys/src/test/resources/ip_get_details.json +++ b/labs/glesys/src/test/resources/ip_get_details.json @@ -1 +1,16 @@ -{"response":{"status":{"code":"200","text":"OK"},"details":{"datacenter":"Falkenberg","ipversion":4,"PTR":"31-192-227-37-static.serverhotell.net.","platform":"OpenVZ"},"debug":{"input":{"ipaddress":"31.192.227.37"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-21T13:11:26+02:00","text":"OK"}, + "details":{ + "ipaddress":"31.192.227.113", + "netmask":null, + "broadcast":null, + "gateway":null, + "nameservers":["79.99.4.100","79.99.4.101"], + "platform":"OpenVZ", + "datacenter":"Falkenberg", + "ipversion":4, + "serverid":null, + "reserved":"no", + "ptr":"31-192-227-113-static.serverhotell.net.", + "cost":{"amount":2,"currency":"EUR","timeperiod":"month"} + }, + "debug":{"input":{"ipaddress":"31.192.227.113"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/ip_get_details_xen.json b/labs/glesys/src/test/resources/ip_get_details_xen.json index d34ce20e56..d98977bb55 100644 --- a/labs/glesys/src/test/resources/ip_get_details_xen.json +++ b/labs/glesys/src/test/resources/ip_get_details_xen.json @@ -1 +1,15 @@ -{"response":{"status":{"code":"200","text":"OK"},"details":{"datacenter":"Falkenberg","ipversion":4,"PTR":"109-74-10-146-static.serverhotell.net.","address":"109.74.10.146","netmask":"255.255.254.0","broadcast":"109.74.11.255","gateway":"109.74.10.1","nameservers":["79.99.4.100","79.99.4.103"],"platform":"Xen"},"debug":{"input":{"ipaddress":"109.74.10.146"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-21T13:11:25+02:00","text":"OK"}, + "details":{ + "ipaddress":"109.74.10.13", + "netmask":"255.255.254.0", + "broadcast":"109.74.11.255", + "gateway":"109.74.10.1", + "nameservers":["79.99.4.100","79.99.4.101"], + "platform":"Xen", + "datacenter":"Falkenberg", + "ipversion":4, + "serverid":null, + "reserved":"no", + "ptr":"109-74-10-13-static.serverhotell.net.", + "cost":{"amount":2,"currency":"EUR","timeperiod":"month"}}, + "debug":{"input":{"ipaddress":"109.74.10.13"}}}} diff --git a/labs/glesys/src/test/resources/ip_list_free.json b/labs/glesys/src/test/resources/ip_list_free.json index 3583d21467..f4fe35310e 100644 --- a/labs/glesys/src/test/resources/ip_list_free.json +++ b/labs/glesys/src/test/resources/ip_list_free.json @@ -1 +1 @@ -{"response":{"status":{"code":"200","text":"OK"},"ipinfo":{"ipversion":4,"datacenter":"Falkenberg","platform":"OpenVZ"},"iplist":["31.192.226.131","31.192.226.133"],"debug":{"input":{"ipversion":"4","datacenter":"Falkenberg","platform":"OpenVZ"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-21T13:01:55+02:00","text":"OK"},"iplist":{"ipversion":4,"datacenter":"Falkenberg","platform":"Xen","ipaddresses":["109.74.10.13","109.74.10.50","109.74.10.109","109.74.10.125","109.74.10.131","109.74.10.148","109.74.10.171","109.74.10.173","109.74.10.191","109.74.10.215","109.74.10.216","109.74.10.219","109.74.10.223","109.74.10.224","109.74.10.236","109.74.10.249","109.74.11.49","109.74.11.58","109.74.11.62","109.74.11.63","109.74.11.73","109.74.11.76","109.74.11.86","109.74.11.98","109.74.11.118","109.74.11.124","109.74.11.131","109.74.11.137","109.74.11.146","109.74.11.157","109.74.11.159","109.74.11.173","109.74.11.178","109.74.11.187","109.74.11.190","109.74.11.205","109.74.11.213","109.74.11.234","109.74.11.236","109.74.11.241","109.74.11.243","109.74.11.246","109.74.11.247"]},"debug":{"input":{"ipversion":"4","datacenter":"Falkenberg","platform":"Xen"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/ip_list_own.json b/labs/glesys/src/test/resources/ip_list_own.json new file mode 100644 index 0000000000..4d1818b557 --- /dev/null +++ b/labs/glesys/src/test/resources/ip_list_own.json @@ -0,0 +1,5 @@ +{"response":{"status":{"code":200,"timestamp":"2012-06-24T11:54:43+02:00","text":"OK"}, + "iplist":[ + {"ipaddress":"31.192.230.68","netmask":null,"broadcast":null,"gateway":null,"nameservers":["79.99.4.100","79.99.4.101"],"platform":"OpenVZ","datacenter":"Falkenberg","ipversion":4,"serverid":null,"reserved":"yes","ptr":"31-192-230-68-static.serverhotell.net.","cost":{"amount":2,"currency":"EUR","timeperiod":"month"}}, + {"ipaddress":"31.192.231.148","netmask":null,"broadcast":null,"gateway":null,"nameservers":["79.99.4.100","79.99.4.101"],"platform":"OpenVZ","datacenter":"Falkenberg","ipversion":4,"serverid":"vz1609110","reserved":"yes","ptr":"31-192-231-148-static.serverhotell.net.","cost":{"amount":2,"currency":"EUR","timeperiod":"month"}} + ],"debug":{"input":[]}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/server_created.json b/labs/glesys/src/test/resources/server_created.json deleted file mode 100644 index 417d5cee92..0000000000 --- a/labs/glesys/src/test/resources/server_created.json +++ /dev/null @@ -1 +0,0 @@ -{"response":{"status":{"code":"200","text":"OK"},"server":{"serverid":"xm3630641","hostname":"jclouds-test-host","iplist":[{"ip":"109.74.10.27","version":"4","cost":"2.00"}]},"debug":{"input":{"cpucores":"1","memorysize":"512","datacenter":"Falkenberg","transfer":"500","rootpw":"password","hostname":"jclouds-test-host","platform":"Xen","template":"Debian-6 x64","disksize":"10","description":""}}}} diff --git a/labs/glesys/src/test/resources/server_details.json b/labs/glesys/src/test/resources/server_details.json index 2083d23c54..55a79c498d 100644 --- a/labs/glesys/src/test/resources/server_details.json +++ b/labs/glesys/src/test/resources/server_details.json @@ -1 +1,16 @@ -{"response":{"status":{"code":200,"timestamp":"2012-02-10T11:11:05+01:00","text":"OK"},"server":{"serverid":"xm3276891","hostname":"glesys-s-6dd","description":"glesys-s-6dd","cpucores":1,"memorysize":512,"disksize":5,"transfer":50,"templatename":"Ubuntu 11.04 x64","datacenter":"Falkenberg","managedhosting":"no","platform":"Xen","cost":{"amount":13.22,"currency":"EUR","timeperiod":"month"},"iplist":[{"ipaddress":"109.74.10.45","version":4,"cost":2,"currency":"EUR"}], "state":"locked"},"debug":{"input":{"serverid":"xm3276891"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-21T14:10:57+02:00","text":"OK"}, + "server":{ + "serverid":"vz1840356", + "hostname":"test-email-jclouds", + "description":"glesys-s-6dd", + "cpucores":1, + "memorysize":512, + "disksize":5, + "transfer":50, + "templatename":"Ubuntu 10.04 LTS 32-bit", + "datacenter":"Falkenberg", + "managedhosting":"no", + "platform":"OpenVZ", + "cost":{"amount":10.22,"currency":"EUR","timeperiod":"month"}, + "iplist":[{"ipaddress":"31.192.231.254","version":4,"cost":2,"currency":"EUR"}],"state":"running"}, + "debug":{"input":{"includestate":"1","serverid":"vz1840356"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/server_resource_usage.json b/labs/glesys/src/test/resources/server_resource_usage.json new file mode 100644 index 0000000000..744e3b0c9b --- /dev/null +++ b/labs/glesys/src/test/resources/server_resource_usage.json @@ -0,0 +1,16 @@ +{"response":{ + "status":{"code":200,"timestamp":"2012-06-24T14:28:10+02:00","text":"OK"}, + "usage":{ + "info":{"type":"diskioread","resolution":"minute","unit":"KB"}, + "values":[ + {"timestamp":"2012-06-24T14:21:07+02:00","value":0}, + {"timestamp":"2012-06-24T14:22:05+02:00","value":5.1}, + {"timestamp":"2012-06-24T14:23:05+02:00","value":0}, + {"timestamp":"2012-06-24T14:24:08+02:00","value":10}, + {"timestamp":"2012-06-24T14:25:12+02:00","value":0}, + {"timestamp":"2012-06-24T14:26:07+02:00","value":0}, + {"timestamp":"2012-06-24T14:27:12+02:00","value":0}, + {"timestamp":"2012-06-24T14:28:05+02:00","value":0} + ] + }, + "debug":{"input":{"serverid":"vz1166090","resolution":"minute","resource":"diskioread"}}}} \ No newline at end of file diff --git a/labs/glesys/src/test/resources/server_status.json b/labs/glesys/src/test/resources/server_status.json index 5c3ac6a032..d2a7f82eaa 100644 --- a/labs/glesys/src/test/resources/server_status.json +++ b/labs/glesys/src/test/resources/server_status.json @@ -1 +1 @@ -{"response":{"status":{"code":200,"timestamp":"2012-02-10T11:21:50+01:00","text":"OK"},"server":{"state":"running","cpu":{"usage":0,"max":1,"unit":"cores"},"memory":{"usage":null,"max":512,"unit":"MB"},"disk":{"usage":null,"max":5,"unit":"GB"},"transfer":{"usage":0,"max":50,"unit":"GB last 30 days"},"uptime":{"current":null,"unit":"seconds"}},"debug":{"input":{"serverid":"xm3276891"}}}} \ No newline at end of file +{"response":{"status":{"code":200,"timestamp":"2012-06-21T15:29:31+02:00","text":"OK"},"server":{"state":"running","cpu":{"usage":0,"max":1,"unit":"cores"},"memory":{"usage":2,"max":512,"unit":"MB"},"disk":{"usage":0,"max":5120,"unit":"MB"},"transfer":{"usage":0,"max":50,"unit":"GB last 30 days"},"uptime":{"current":21,"unit":"seconds"},"warnings":[]},"debug":{"input":{"serverid":"vz1321233"}}}} \ No newline at end of file diff --git a/labs/iam/pom.xml b/labs/iam/pom.xml new file mode 100644 index 0000000000..99a6e1ff51 --- /dev/null +++ b/labs/iam/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + iam + jcloud iam api + jclouds components to access an implementation of Identity and Access Management (IAM) + bundle + + + https://iam.amazonaws.com + 2010-05-08 + + ${test.aws.identity} + ${test.aws.credential} + + org.jclouds.iam*;version="${project.version}" + org.jclouds*;version="${project.version}",* + + + + + org.jclouds.common + aws-common + ${project.version} + jar + + + org.jclouds + jclouds-core + ${project.version} + test-jar + test + + + org.jclouds.driver + jclouds-log4j + ${project.version} + test + + + log4j + log4j + 1.2.16 + test + + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + ${test.iam.endpoint} + ${test.iam.api-version} + ${test.iam.build-version} + ${test.iam.identity} + ${test.iam.credential} + + + + + + + + + + + + diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAM.java b/labs/iam/src/main/java/org/jclouds/iam/IAM.java new file mode 100644 index 0000000000..a79fcb2d67 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/IAM.java @@ -0,0 +1,43 @@ +package org.jclouds.iam; + +import org.jclouds.collect.PaginatedSet; +import org.jclouds.collect.PaginatedSets; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.UserClient; +import org.jclouds.iam.options.ListUsersOptions; + +import com.google.common.base.Function; + +/** + * Utilities for using IAM. + * + * @author Adrian Cole + */ +public class IAM { + + /** + * List users based on the criteria in the {@link ListUsersOptions} passed in. + * + * @param userClient + * the {@link UserClient} to use for the request + * @param options + * the {@link ListUsersOptions} describing the ListUsers request + * + * @return iterable of users fitting the criteria + */ + public static Iterable list(final UserClient userClient, final ListUsersOptions options) { + return PaginatedSets.lazyContinue(userClient.list(options), new Function>() { + + @Override + public PaginatedSet apply(String input) { + return userClient.list(options.clone().marker(input)); + } + + @Override + public String toString() { + return "listUsers(" + options + ")"; + } + }); + } + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAMApiMetadata.java b/labs/iam/src/main/java/org/jclouds/iam/IAMApiMetadata.java new file mode 100644 index 0000000000..639a6eb259 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/IAMApiMetadata.java @@ -0,0 +1,95 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam; + +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG; +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.iam.config.IAMRestClientModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.internal.BaseRestApiMetadata; + +import com.google.common.reflect.TypeToken; + +/** + * Implementation of {@link ApiMetadata} for Amazon's IAM api. + * + * @author Adrian Cole + */ +public class IAMApiMetadata extends BaseRestApiMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 3450830053589179249L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -5070937833892503232L; + }; + + @Override + public Builder toBuilder() { + return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this); + } + + public IAMApiMetadata() { + this(new Builder(IAMClient.class, IAMAsyncClient.class)); + } + + protected IAMApiMetadata(Builder builder) { + super(Builder.class.cast(builder)); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + properties.setProperty(PROPERTY_AUTH_TAG, "AWS"); + properties.setProperty(PROPERTY_HEADER_TAG, "amz"); + return properties; + } + + public static class Builder extends BaseRestApiMetadata.Builder { + + protected Builder(Class client, Class asyncClient) { + super(client, asyncClient); + id("iam") + .name("Amazon IAM Api") + .identityName("Access Key ID") + .credentialName("Secret Access Key") + .version("2010-05-08") + .documentation(URI.create("http://docs.amazonwebservices.com/IAM/latest/APIReference/")) + .defaultEndpoint("https://iam.amazonaws.com") + .defaultProperties(IAMApiMetadata.defaultProperties()) + .defaultModule(IAMRestClientModule.class); + } + + @Override + public IAMApiMetadata build() { + return new IAMApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + } + +} \ No newline at end of file diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncClient.java b/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncClient.java new file mode 100644 index 0000000000..a1be67c615 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/IAMAsyncClient.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.UserAsyncClient; +import org.jclouds.iam.xml.UserHandler; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides access to Amazon IAM via the Query API + *

+ * + * @see + * @author Adrian Cole + */ +@RequestFilters(FormSigner.class) +@VirtualHost +public interface IAMAsyncClient { + + /** + * @see IAMClient#getCurrentUser() + */ + @POST + @Path("/") + @XMLResponseParser(UserHandler.class) + @FormParams(keys = "Action", values = "GetUser") + ListenableFuture getCurrentUser(); + + /** + * Provides asynchronous access to User features. + */ + @Delegate + UserAsyncClient getUserClient(); + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/IAMClient.java b/labs/iam/src/main/java/org/jclouds/iam/IAMClient.java new file mode 100644 index 0000000000..1a8ee42b8c --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/IAMClient.java @@ -0,0 +1,49 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.UserClient; +import org.jclouds.rest.annotations.Delegate; + +/** + * Provides access to Amazon IAM via the Query API + *

+ * + * @see + * @author Adrian Cole + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface IAMClient { + /** + * Retrieves information about the current user, including the user's path, GUID, and ARN. + */ + User getCurrentUser(); + + /** + * Provides synchronous access to User features. + */ + @Delegate + UserClient getUserClient(); +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java b/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java new file mode 100644 index 0000000000..c570fec38c --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java @@ -0,0 +1,48 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.config; + +import java.util.Map; + +import org.jclouds.aws.config.FormSigningRestClientModule; +import org.jclouds.iam.IAMAsyncClient; +import org.jclouds.iam.IAMClient; +import org.jclouds.iam.features.UserAsyncClient; +import org.jclouds.iam.features.UserClient; +import org.jclouds.rest.ConfiguresRestClient; + +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; + +/** + * Configures the Monitoring connection. + * + * @author Adrian Cole + */ +@ConfiguresRestClient +public class IAMRestClientModule extends FormSigningRestClientModule { + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// + .put(UserClient.class, UserAsyncClient.class) + .build(); + + public IAMRestClientModule() { + super(TypeToken.of(IAMClient.class), TypeToken.of(IAMAsyncClient.class), DELEGATE_MAP); + } + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/domain/User.java b/labs/iam/src/main/java/org/jclouds/iam/domain/User.java new file mode 100644 index 0000000000..124bbcb372 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/domain/User.java @@ -0,0 +1,209 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.domain; + +import java.util.Date; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; + +/** + * @see + * + * @author Adrian Cole + */ +public class User { + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromUser(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + private Optional path = Optional.absent(); + private String id; + private Optional name = Optional.absent(); + private String arn; + private Date createDate; + + /** + * @see User#getPath() + */ + public T path(String path) { + this.path = Optional.fromNullable(path); + return self(); + } + + /** + * @see User#getId() + */ + public T id(String id) { + this.id = id; + return self(); + } + + /** + * @see User#getName() + */ + public T name(String name) { + this.name = Optional.fromNullable(name); + return self(); + } + + /** + * @see User#getArn() + */ + public T arn(String arn) { + this.arn = arn; + return self(); + } + + /** + * @see User#getCreateDate() + */ + public T createDate(Date createDate) { + this.createDate = createDate; + return self(); + } + + public User build() { + return new User(path, name, id, arn, createDate); + } + + public T fromUser(User in) { + return this + .path(in.getPath().orNull()) + .name(in.getName().orNull()) + .id(in.getId()) + .arn(in.getArn()) + .createDate(in.getCreateDate()) + ; + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final Optional path; + private final Optional name; + private final String id; + private final String arn; + private final Date createDate; + + protected User(Optional path, Optional name, String id, String arn, Date createDate) { + this.path = path; + this.name = name; + this.id = id; + this.arn = arn; + this.createDate = createDate; + } + + /** + * you can also optionally give the entity a path that you define. You might use the path to + * identify which division or part of the organization the entity belongs in. For example: + * /division_abc/subdivision_xyz/product_1234/engineering/ + */ + public Optional getPath() { + return path; + } + + /** + * When you create a user, a role, or a group, or when you upload a server certificate, you give + * it a friendly name, such as Bob, TestApp1, Developers, or ProdServerCert. Whenever you need to + * specify a particular entity in an API call to IAM (for example, to delete a user, or update a + * group with a new user), you use the friendly name. + */ + public Optional getName() { + return name; + } + + /** + * We assign each user, group, and server certificate a globally unique identifier (GUID), which + * we return to you when you use the API or CLI to create it. We recommend you store the GUID in + * your own database along with the user, group, or certificate name. Internally we use the GUID + * to identify the user, group, or certificate, and we translate the value into the ARN or + * friendly name as appropriate when displaying the user, group, or certificate information to + * you. If you delete a user, group, or server certificate, any residual remote references to + * that item display the GUID as the friendly name part in the ARN. If you've stored the GUID in + * your own system, you can then use the displayed GUID to identify the deleted item being + * referred to. + */ + public String getId() { + return id; + } + + /** + * Although most resources have a friendly name (for example, a user named Bob or a group named + * Developers), the access policy language requires you to specify the resource or resources + * using the following Amazon Resource Name (ARN) format. + * + * {@code arn:aws::::} + */ + public String getArn() { + return arn; + } + + /** + * Date the user was created + */ + public Date getCreateDate() { + return createDate; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(id, arn); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + return Objects.equal(this.id, other.id) && Objects.equal(this.arn, other.arn); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this).add("path", path).add("name", name).add("id", id).add("arn", arn).add( + "createDate", createDate).toString(); + } + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/UserAsyncClient.java b/labs/iam/src/main/java/org/jclouds/iam/features/UserAsyncClient.java new file mode 100644 index 0000000000..a36749bfca --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/features/UserAsyncClient.java @@ -0,0 +1,88 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.features; + +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.collect.PaginatedSet; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.options.ListUsersOptions; +import org.jclouds.iam.xml.ListUsersResultHandler; +import org.jclouds.iam.xml.UserHandler; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides access to Amazon IAM via the Query API + *

+ * + * @see + * @author Adrian Cole + */ +@RequestFilters(FormSigner.class) +@VirtualHost +public interface UserAsyncClient { + + /** + * @see UserClient#getCurrent() + */ + @POST + @Path("/") + @XMLResponseParser(UserHandler.class) + @FormParams(keys = "Action", values = "GetUser") + ListenableFuture getCurrent(); + + /** + * @see UserClient#get() + */ + @POST + @Path("/") + @XMLResponseParser(UserHandler.class) + @FormParams(keys = "Action", values = "GetUser") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@FormParam("UserName") String name); + + /** + * @see UserClient#list() + */ + @POST + @Path("/") + @XMLResponseParser(ListUsersResultHandler.class) + @FormParams(keys = "Action", values = "ListUsers") + ListenableFuture> list(); + + /** + * @see UserClient#list(ListUsersOptions) + */ + @POST + @Path("/") + @XMLResponseParser(ListUsersResultHandler.class) + @FormParams(keys = "Action", values = "ListUsers") + ListenableFuture> list(ListUsersOptions options); + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/features/UserClient.java b/labs/iam/src/main/java/org/jclouds/iam/features/UserClient.java new file mode 100644 index 0000000000..9e7205d607 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/features/UserClient.java @@ -0,0 +1,75 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.collect.PaginatedSet; +import org.jclouds.concurrent.Timeout; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.options.ListUsersOptions; +import org.jclouds.javax.annotation.Nullable; + +/** + * Provides access to Amazon IAM via the Query API + *

+ * + * @see + * @author Adrian Cole + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface UserClient { + /** + * Retrieves information about the current user, including the user's path, GUID, and ARN. + */ + User getCurrent(); + + /** + * Retrieves information about the specified user, including the user's path, GUID, and ARN. + * + * @param name + * Name of the user to get information about. + * @return null if not found + */ + @Nullable + User get(String name); + + /** + * Lists the users that have the specified path prefix. If there are none, the action returns an + * empty list. + * + *
+ * You can paginate the results using the {@link ListUsersOptions parameter} + * + * @param options + * the options describing the users query + * + * @return the response object + */ + PaginatedSet list(ListUsersOptions options); + + /** + * Lists the users that have the specified path prefix. If there are none, the action returns an + * empty list. + * + * @return the response object + */ + PaginatedSet list(); + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/options/ListUsersOptions.java b/labs/iam/src/main/java/org/jclouds/iam/options/ListUsersOptions.java new file mode 100644 index 0000000000..0fc2ad4893 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/options/ListUsersOptions.java @@ -0,0 +1,169 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.options; + +import org.jclouds.http.options.BaseHttpRequestOptions; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.collect.Multimap; + +/** + * Options used to list available users. + * + * @see
+ * + * @author Adrian Cole + */ +public class ListUsersOptions extends BaseHttpRequestOptions implements Cloneable { + + private Integer maxItems; + private String pathPrefix; + private String marker; + + /** + * @see ListUsersOptions#getMarker() + */ + public ListUsersOptions marker(String marker) { + this.marker = marker; + return this; + } + + /** + * @see ListUsersOptions#getMaxItems() + */ + public ListUsersOptions maxItems(Integer maxItems) { + this.maxItems = maxItems; + return this; + } + + /** + * @see ListUsersOptions#getPathPrefix() + */ + public ListUsersOptions pathPrefix(String pathPrefix) { + this.pathPrefix = pathPrefix; + return this; + } + + /** + * Use this parameter only when paginating results to indicate the maximum number of user names + * you want in the response. If there are additional user names beyond the maximum you specify, + * the IsTruncated response element is true. + */ + @Nullable + public Integer getMaxItems() { + return maxItems; + } + + /** + * The path prefix for filtering the results. For example: /division_abc/subdivision_xyz/, which + * would get all user names whose path starts with /division_abc/subdivision_xyz/. + *

+ * This parameter is optional. If it is not included, it defaults to a slash (/), listing all + * user names. + */ + @Nullable + public String getPathPrefix() { + return pathPrefix; + } + + /** + * Use this parameter only when paginating results, and only in a subsequent request after you've + * received a response where the results are truncated. Set it to the value of the Marker element + * in the response you just received. + */ + @Nullable + public String getMarker() { + return marker; + } + + public static class Builder { + + /** + * @see ListUsersOptions#getMarker() + */ + public static ListUsersOptions marker(String marker) { + return new ListUsersOptions().marker(marker); + } + + /** + * @see ListUsersOptions#getMaxItems() + */ + public static ListUsersOptions maxItems(Integer maxItems) { + return new ListUsersOptions().maxItems(maxItems); + } + + /** + * @see ListUsersOptions#getPathPrefix() + */ + public static ListUsersOptions pathPrefix(String pathPrefix) { + return new ListUsersOptions().pathPrefix(pathPrefix); + } + } + + @Override + public Multimap buildFormParameters() { + Multimap params = super.buildFormParameters(); + if (marker != null) + params.put("Marker", marker); + if (maxItems != null) + params.put("MaxItems", maxItems.toString()); + if (pathPrefix != null) + params.put("PathPrefix", pathPrefix); + return params; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(marker, maxItems, pathPrefix); + } + + @Override + public ListUsersOptions clone() { + return new ListUsersOptions().marker(marker).maxItems(maxItems).pathPrefix(pathPrefix); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ListUsersOptions other = ListUsersOptions.class.cast(obj); + return Objects.equal(this.marker, other.marker) && Objects.equal(this.maxItems, other.maxItems) + && Objects.equal(this.pathPrefix, other.pathPrefix); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this).omitNullValues().add("marker", marker).add("maxItems", maxItems).add( + "pathPrefix", pathPrefix).toString(); + } +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/xml/ListUsersResultHandler.java b/labs/iam/src/main/java/org/jclouds/iam/xml/ListUsersResultHandler.java new file mode 100644 index 0000000000..11a9dfadb4 --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/xml/ListUsersResultHandler.java @@ -0,0 +1,105 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.xml; + +import java.util.Set; + +import org.jclouds.collect.PaginatedSet; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.iam.domain.User; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; + +/** + * @see + * + * @author Adrian Cole + */ +public class ListUsersResultHandler extends ParseSax.HandlerForGeneratedRequestWithResult> { + + private final UserHandler userHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set users = Sets.newLinkedHashSet(); + private boolean inUsers; + private String marker; + + @Inject + public ListUsersResultHandler(UserHandler userHandler) { + this.userHandler = userHandler; + } + + /** + * {@inheritDoc} + */ + @Override + public PaginatedSet getResult() { + return PaginatedSet.copyOfWithMarker(users, marker); + } + + /** + * {@inheritDoc} + */ + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "Users")) { + inUsers = true; + } + if (inUsers) { + userHandler.startElement(url, name, qName, attributes); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inUsers) { + if (qName.equals("Users")) { + inUsers = false; + } else if (qName.equals("member")) { + users.add(userHandler.getResult()); + } else { + userHandler.endElement(uri, name, qName); + } + } else if (qName.equals("Marker")) { + marker = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + public void characters(char ch[], int start, int length) { + if (inUsers) { + userHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + +} diff --git a/labs/iam/src/main/java/org/jclouds/iam/xml/UserHandler.java b/labs/iam/src/main/java/org/jclouds/iam/xml/UserHandler.java new file mode 100644 index 0000000000..35db67d42a --- /dev/null +++ b/labs/iam/src/main/java/org/jclouds/iam/xml/UserHandler.java @@ -0,0 +1,84 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.xml; + +import javax.inject.Inject; + +import org.jclouds.date.DateService; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.iam.domain.User; +import org.jclouds.util.SaxUtils; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Adrian Cole + */ +public class UserHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + private final DateService dateService; + + @Inject + protected UserHandler(DateService dateService){ + this.dateService = dateService; + } + + private StringBuilder currentText = new StringBuilder(); + private User.Builder builder = User.builder(); + + /** + * {@inheritDoc} + */ + @Override + public User getResult() { + try { + return builder.build(); + } finally { + builder = User.builder(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (qName.equals("Path")) { + builder.path(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("UserName")) { + builder.name(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("UserId")) { + builder.id(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("Arn")) { + builder.arn(SaxUtils.currentOrNull(currentText)); + } else if (qName.equals("CreateDate")) { + builder.createDate(dateService.iso8601SecondsDateParse(SaxUtils.currentOrNull(currentText))); + } + currentText = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } + +} diff --git a/labs/iam/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/iam/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..5dd93026e5 --- /dev/null +++ b/labs/iam/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.iam.IAMApiMetadata \ No newline at end of file diff --git a/labs/iam/src/test/java/org/jclouds/iam/IAMApiMetadataTest.java b/labs/iam/src/test/java/org/jclouds/iam/IAMApiMetadataTest.java new file mode 100644 index 0000000000..a637870591 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/IAMApiMetadataTest.java @@ -0,0 +1,39 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam; + +import org.jclouds.View; +import org.jclouds.rest.internal.BaseRestApiMetadataTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.TypeToken; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "IAMApiMetadataTest") +public class IAMApiMetadataTest extends BaseRestApiMetadataTest { + + // no tenant abstraction, yet + public IAMApiMetadataTest() { + super(new IAMApiMetadata(), ImmutableSet.> of()); + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/IAMClientLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/IAMClientLiveTest.java new file mode 100644 index 0000000000..46678dd54c --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/IAMClientLiveTest.java @@ -0,0 +1,58 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.rest.RestContext; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; + +/** + * Tests behavior of {@code IAM}. + * + * @author Adrian Cole + */ +public class IAMClientLiveTest extends BaseContextLiveTest> { + + public IAMClientLiveTest() { + provider = "iam"; + } + + private IAMClient client; + + @Override + @BeforeClass(groups = { "integration", "live" }) + public void setupContext() { + super.setupContext(); + client = context.getApi(); + } + + @Override + protected TypeToken> contextType() { + return IAMApiMetadata.CONTEXT_TOKEN; + } + + @Test + protected void testWired() { + client.getCurrentUser(); + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/IAMTest.java b/labs/iam/src/test/java/org/jclouds/iam/IAMTest.java new file mode 100644 index 0000000000..a376d8a6bf --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/IAMTest.java @@ -0,0 +1,62 @@ +package org.jclouds.iam; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; + +import org.easymock.EasyMock; +import org.jclouds.collect.PaginatedSet; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.features.UserClient; +import org.jclouds.iam.options.ListUsersOptions; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * Tests behavior of {@code IAM}. + * + * @author Adrian Cole + */ +@Test(testName = "IAMTest") +public class IAMTest { + + + @Test + public void testSinglePageResult() throws Exception { + UserClient userClient = createMock(UserClient.class); + ListUsersOptions options = new ListUsersOptions(); + PaginatedSet response = PaginatedSet.copyOf(ImmutableSet.of(createMock(User.class))); + + expect(userClient.list(options)) + .andReturn(response) + .once(); + + EasyMock.replay(userClient); + + Assert.assertEquals(1, Iterables.size(IAM.list(userClient, options))); + } + + + @Test + public void testMultiPageResult() throws Exception { + UserClient userClient = createMock(UserClient.class); + ListUsersOptions options = new ListUsersOptions(); + PaginatedSet response1 = PaginatedSet.copyOfWithMarker(ImmutableSet.of(createMock(User.class)), "NEXTTOKEN"); + PaginatedSet response2 = PaginatedSet.copyOf(ImmutableSet.of(createMock(User.class))); + + expect(userClient.list(anyObject(ListUsersOptions.class))) + .andReturn(response1) + .once(); + expect(userClient.list(anyObject(ListUsersOptions.class))) + .andReturn(response2) + .once(); + + EasyMock.replay(userClient); + + Assert.assertEquals(2, Iterables.size(IAM.list(userClient, options))); + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/UserClientExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/UserClientExpectTest.java new file mode 100644 index 0000000000..2ed548e164 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/features/UserClientExpectTest.java @@ -0,0 +1,188 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unles required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.iam.features; + +import static org.jclouds.iam.options.ListUsersOptions.Builder.pathPrefix; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import java.net.URI; +import java.util.TimeZone; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.iam.IAMClient; +import org.jclouds.iam.internal.BaseIAMClientExpectTest; +import org.jclouds.iam.parse.GetUserResponseTest; +import org.jclouds.iam.parse.ListUsersResponseTest; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "UserClientExpectTest") +public class UserClientExpectTest extends BaseIAMClientExpectTest { + + public UserClientExpectTest() { + TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles")); + } + + public void testGetCurrentWhenResponseIs2xx() throws Exception { + HttpRequest get = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://iam.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "iam.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + "Action=GetUser" + + "&Signature=2UamWqKKgoSbaZpvixX0LKqGW%2FIIP9L319DLEUtYu3A%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + + "&Version=2010-05-08" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + HttpResponse getResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/get_user.xml", "text/xml")).build(); + + IAMClient clientWhenExist = requestSendsResponse( + get, getResponse); + + assertEquals(clientWhenExist.getUserClient().getCurrent().toString(), new GetUserResponseTest().expected().toString()); + } + + HttpRequest get = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://iam.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "iam.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + "Action=GetUser" + + "&Signature=cnY%2FAaG656cruOmb3y7YHtjnPB1qg3aavff6PPxIMs0%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + + "&UserName=name" + + "&Version=2010-05-08" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + + + public void testGetWhenResponseIs2xx() throws Exception { + + HttpResponse getResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/get_user.xml", "text/xml")).build(); + + IAMClient clientWhenExist = requestSendsResponse( + get, getResponse); + + assertEquals(clientWhenExist.getUserClient().get("name").toString(), new GetUserResponseTest().expected().toString()); + } + + public void testGetWhenResponseIs404() throws Exception { + + HttpResponse getResponse = HttpResponse.builder().statusCode(404).build(); + + IAMClient clientWhenDontExist = requestSendsResponse( + get, getResponse); + + assertNull(clientWhenDontExist.getUserClient().get("name")); + } + + HttpRequest list = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://iam.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "iam.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + "Action=ListUsers" + + "&Signature=ed4OrONGuVlGpHSY8u5X2m9LVwx6oiihu7HbvA0iZkY%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + + "&Version=2010-05-08" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + + public void testListWhenResponseIs2xx() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_users.xml", "text/xml")).build(); + + IAMClient clientWhenExist = requestSendsResponse( + list, listResponse); + + assertEquals(clientWhenExist.getUserClient().list().toString(), new ListUsersResponseTest().expected().toString()); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testListWhenResponseIs404() throws Exception { + + HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); + + IAMClient clientWhenDontExist = requestSendsResponse( + list, listResponse); + + clientWhenDontExist.getUserClient().list(); + } + + public void testListWithOptionsWhenResponseIs2xx() throws Exception { + HttpRequest listWithOptions = + HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://iam.amazonaws.com/")) + .headers(ImmutableMultimap.builder() + .put("Host", "iam.amazonaws.com") + .build()) + .payload(payloadFromStringWithContentType( + "Action=ListUsers" + + "&Marker=MARKER" + + "&PathPrefix=%2Ffoo" + + "&Signature=1%2BeCgNIAjHr%2BraNdDd3rsVC5Qok3AuTrJOa5mZwmE7g%3D" + + "&SignatureMethod=HmacSHA256" + + "&SignatureVersion=2" + + "&Timestamp=2009-11-08T15%3A54%3A08.897Z" + + "&Version=2010-05-08" + + "&AWSAccessKeyId=identity", + "application/x-www-form-urlencoded")) + .build(); + + HttpResponse listWithOptionsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_users.xml", "text/xml")).build(); + + IAMClient clientWhenWithOptionsExist = requestSendsResponse(listWithOptions, + listWithOptionsResponse); + + assertEquals(clientWhenWithOptionsExist.getUserClient().list(pathPrefix("/foo").marker("MARKER")).toString(), + new ListUsersResponseTest().expected().toString()); + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/features/UserClientLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/features/UserClientLiveTest.java new file mode 100644 index 0000000000..d635e0af44 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/features/UserClientLiveTest.java @@ -0,0 +1,73 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.features; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.jclouds.collect.PaginatedSet; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.internal.BaseIAMClientLiveTest; +import org.jclouds.iam.options.ListUsersOptions; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "UserClientLiveTest") +public class UserClientLiveTest extends BaseIAMClientLiveTest { + + @Test + protected void testGetCurrentUser() { + User user = client().getCurrent(); + checkUser(user); + } + + private void checkUser(User user) { + checkNotNull(user.getArn(), "Arn cannot be null for a User."); + checkNotNull(user.getId(), "Id cannot be null for a User."); + checkNotNull(user.getName(), "While Name can be null for a User, its Optional wrapper cannot."); + checkNotNull(user.getPath(), "While Path can be null for a User, its Optional wrapper cannot."); + checkNotNull(user.getCreateDate(), "CreateDate cannot be null for a User."); + } + + @Test + protected void testListUsers() { + PaginatedSet response = client().list(); + + for (User user : response) { + checkUser(user); + } + + if (response.size() > 0) { + User user = response.iterator().next(); + Assert.assertEquals(client().get(user.getName().get()), user); + } + + // Test with a Marker, even if it's null + response = client().list(ListUsersOptions.Builder.marker(response.getNextMarker())); + for (User user : response) { + checkUser(user); + } + } + + protected UserClient client() { + return context.getApi().getUserClient(); + } +} diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSAsyncClientTest.java b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java similarity index 55% rename from labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSAsyncClientTest.java rename to labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java index eb767553ef..daa3407fd9 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSAsyncClientTest.java +++ b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java @@ -16,29 +16,23 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.glesys.internal; +package org.jclouds.iam.internal; -import static org.testng.Assert.assertEquals; +import java.util.Properties; -import org.jclouds.glesys.GleSYSProviderMetadata; import org.jclouds.http.HttpRequest; -import org.jclouds.http.filters.BasicAuthentication; -import org.jclouds.providers.ProviderMetadata; -import org.jclouds.rest.internal.BaseAsyncClientTest; +import org.jclouds.http.HttpResponse; +import org.jclouds.iam.IAMAsyncClient; + +import com.google.common.base.Function; +import com.google.inject.Module; /** + * * @author Adrian Cole */ -public abstract class BaseGleSYSAsyncClientTest extends BaseAsyncClientTest { - - @Override - protected void checkFilters(HttpRequest request) { - assertEquals(request.getFilters().size(), 1); - assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); - } - - @Override - public ProviderMetadata createProviderMetadata() { - return new GleSYSProviderMetadata(); +public class BaseIAMAsyncClientExpectTest extends BaseIAMExpectTest { + public IAMAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(IAMAsyncClient.class); } } diff --git a/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientExpectTest.java new file mode 100644 index 0000000000..6e8dd28cb9 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientExpectTest.java @@ -0,0 +1,29 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.internal; + +import org.jclouds.iam.IAMClient; + +/** + * + * @author Adrian Cole + */ +public class BaseIAMClientExpectTest extends BaseIAMExpectTest { + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientLiveTest.java b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientLiveTest.java new file mode 100644 index 0000000000..617f7f2cf4 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientLiveTest.java @@ -0,0 +1,47 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.internal; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.iam.IAMApiMetadata; +import org.jclouds.iam.IAMAsyncClient; +import org.jclouds.iam.IAMClient; +import org.jclouds.rest.RestContext; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseIAMClientLiveTest extends + BaseContextLiveTest> { + + public BaseIAMClientLiveTest() { + provider = "iam"; + } + + @Override + protected TypeToken> contextType() { + return IAMApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMExpectTest.java new file mode 100644 index 0000000000..da0b890ccc --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMExpectTest.java @@ -0,0 +1,51 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.internal; + +import org.jclouds.date.DateService; +import org.jclouds.iam.config.IAMRestClientModule; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class BaseIAMExpectTest extends BaseRestClientExpectTest { + + public BaseIAMExpectTest() { + provider = "iam"; + } + + @ConfiguresRestClient + private static final class TestIAMRestClientModule extends IAMRestClientModule { + + @Override + protected String provideTimeStamp(final DateService dateService) { + return "2009-11-08T15:54:08.897Z"; + } + } + + @Override + protected Module createModule() { + return new TestIAMRestClientModule(); + } +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/options/ListUsersOptionsTest.java b/labs/iam/src/test/java/org/jclouds/iam/options/ListUsersOptionsTest.java new file mode 100644 index 0000000000..57e77c2ef4 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/options/ListUsersOptionsTest.java @@ -0,0 +1,68 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.options; + +import static org.jclouds.iam.options.ListUsersOptions.Builder.marker; +import static org.jclouds.iam.options.ListUsersOptions.Builder.maxItems; +import static org.jclouds.iam.options.ListUsersOptions.Builder.pathPrefix; +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests behavior of {@code ListUsersOptions} + * + * @author Adrian Cole + */ +@Test(groups = "maxItems", testName = "ListUsersOptionsTest") +public class ListUsersOptionsTest { + + public void testMarker() { + ListUsersOptions options = new ListUsersOptions().marker("FFFFF"); + assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker")); + } + + public void testMarkerStatic() { + ListUsersOptions options = marker("FFFFF"); + assertEquals(ImmutableSet.of("FFFFF"), options.buildFormParameters().get("Marker")); + } + + public void testMaxItems() { + ListUsersOptions options = new ListUsersOptions().maxItems(1000); + assertEquals(ImmutableSet.of("1000"), options.buildFormParameters().get("MaxItems")); + } + + public void testMaxItemsStatic() { + ListUsersOptions options = maxItems(1000); + assertEquals(ImmutableSet.of("1000"), options.buildFormParameters().get("MaxItems")); + } + + public void testPathPrefix() { + ListUsersOptions options = new ListUsersOptions().pathPrefix("/division_abc/subdivision_xyz/"); + assertEquals(ImmutableSet.of("/division_abc/subdivision_xyz/"), options.buildFormParameters().get("PathPrefix")); + } + + public void testPathPrefixStatic() { + ListUsersOptions options = pathPrefix("/division_abc/subdivision_xyz/"); + assertEquals(ImmutableSet.of("/division_abc/subdivision_xyz/"), options.buildFormParameters().get("PathPrefix")); + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/parse/GetUserResponseTest.java b/labs/iam/src/test/java/org/jclouds/iam/parse/GetUserResponseTest.java new file mode 100644 index 0000000000..d274cb9218 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/parse/GetUserResponseTest.java @@ -0,0 +1,60 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.parse; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.xml.UserHandler; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "GetUserResponseTest") +public class GetUserResponseTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/get_user.xml"); + + User expected = expected(); + + UserHandler handler = injector.getInstance(UserHandler.class); + User result = factory.create(handler).parse(is); + + assertEquals(result, expected); + assertEquals(result.getPath(), expected.getPath()); + assertEquals(result.getName(), expected.getName()); + } + + public User expected() { + return User.builder() + .path("/division_abc/subdivision_xyz/") + .name("Bob") + .id("AIDACKCEVSQ6C2EXAMPLE") + .arn("arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob") + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2009-03-06T21:47:48Z")).build(); + } + +} diff --git a/labs/iam/src/test/java/org/jclouds/iam/parse/ListUsersResponseTest.java b/labs/iam/src/test/java/org/jclouds/iam/parse/ListUsersResponseTest.java new file mode 100644 index 0000000000..27c9f3ac35 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/parse/ListUsersResponseTest.java @@ -0,0 +1,69 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.iam.parse; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.collect.PaginatedSet; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.functions.BaseHandlerTest; +import org.jclouds.iam.domain.User; +import org.jclouds.iam.xml.ListUsersResultHandler; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "ListUsersResponseTest") +public class ListUsersResponseTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/list_users.xml"); + + PaginatedSet expected = expected(); + + ListUsersResultHandler handler = injector.getInstance(ListUsersResultHandler.class); + PaginatedSet result = factory.create(handler).parse(is); + + assertEquals(result.toString(), expected.toString()); + + } + + public PaginatedSet expected() { + return PaginatedSet.copyOf(ImmutableSet.of( + User.builder() + .path("/division_abc/subdivision_xyz/engineering/") + .name("Andrew") + .id("AID2MAB8DPLSRHEXAMPLE") + .arn("arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/engineering/Andrew") + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2009-03-06T21:47:48Z")).build(), + User.builder() + .path("/division_abc/subdivision_xyz/engineering/") + .name("Jackie") + .id("AIDIODR4TAW7CSEXAMPLE") + .arn("arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/engineering/Jackie") + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2009-03-06T21:47:48Z")).build())); + } + +} diff --git a/labs/iam/src/test/resources/get_user.xml b/labs/iam/src/test/resources/get_user.xml new file mode 100644 index 0000000000..f4d1704843 --- /dev/null +++ b/labs/iam/src/test/resources/get_user.xml @@ -0,0 +1,16 @@ + + + + /division_abc/subdivision_xyz/ + Bob + AIDACKCEVSQ6C2EXAMPLE + + arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob + + 2009-03-06T21:47:48Z + + + + 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE + + \ No newline at end of file diff --git a/labs/iam/src/test/resources/list_users.xml b/labs/iam/src/test/resources/list_users.xml new file mode 100644 index 0000000000..a5e36af2d0 --- /dev/null +++ b/labs/iam/src/test/resources/list_users.xml @@ -0,0 +1,24 @@ + + + + + /division_abc/subdivision_xyz/engineering/ + Andrew + AID2MAB8DPLSRHEXAMPLE + arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/engineering/Andrew + 2009-03-06T21:47:48Z + + + /division_abc/subdivision_xyz/engineering/ + Jackie + AIDIODR4TAW7CSEXAMPLE + arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/engineering/Jackie + 2009-03-06T21:47:48Z + + + false + + + 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE + + \ No newline at end of file diff --git a/labs/iam/src/test/resources/log4j.xml b/labs/iam/src/test/resources/log4j.xml new file mode 100644 index 0000000000..7527432931 --- /dev/null +++ b/labs/iam/src/test/resources/log4j.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labs/pom.xml b/labs/pom.xml index b223764636..617545bd2d 100644 --- a/labs/pom.xml +++ b/labs/pom.xml @@ -52,5 +52,7 @@ rackspace-cloudservers-us greenqloud-compute greenqloud-storage + iam + aws-iam diff --git a/pom.xml b/pom.xml index 2092ec5300..ecde0de4f7 100644 --- a/pom.xml +++ b/pom.xml @@ -54,38 +54,6 @@ - - maven-javadoc-plugin - - - javadoc - package - - aggregate-jar - - - - - -J-Xmx512m - ${project.build.sourceEncoding} - true - - http://download.oracle.com/javase/6/docs/api/ - -

- - com.mycila.maven-license-plugin maven-license-plugin @@ -144,5 +112,24 @@ pageTracker._trackPageview(); + + doc + + + + maven-javadoc-plugin + + + javadoc + package + + aggregate-jar + + + + + + + diff --git a/project/pom.xml b/project/pom.xml index d978027be6..34756c478f 100644 --- a/project/pom.xml +++ b/project/pom.xml @@ -429,52 +429,6 @@ - - - maven-source-plugin - 2.1.2 - - - attach-sources - - jar-no-fork - - - - - - maven-javadoc-plugin - 2.8.1 - - - javadoc - package - - jar - - - - - -J-Xmx256m - ${project.build.sourceEncoding} - true - - http://download.oracle.com/javase/6/docs/api/ - -
- - - ]]>
-
-
maven-enforcer-plugin 1.1 @@ -612,6 +566,9 @@ pageTracker._trackPageview(); maven-release-plugin 2.3.1 + + doc + maven-pmd-plugin @@ -746,6 +703,32 @@ pageTracker._trackPageview(); + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + -J-Xmx256m + ${project.build.sourceEncoding} + true + + http://download.oracle.com/javase/6/docs/api/ + +
+ + +]]> +
+
+
@@ -914,5 +897,45 @@ pageTracker._trackPageview(); + + doc + + + + maven-javadoc-plugin + 2.8.1 + + + javadoc + package + + jar + + + + + + + + + src + + + + + maven-source-plugin + 2.1.2 + + + attach-sources + + jar-no-fork + + + + + + + diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java index 9f6e5d9ce3..ac0ec71c0b 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/AWSS3AsyncClient.java @@ -21,7 +21,6 @@ package org.jclouds.aws.s3; import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER; import java.util.Map; - import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -68,7 +67,7 @@ import com.google.common.util.concurrent.ListenableFuture; /** * Provides access to amazon-specific S3 features * - * @author Adrian Cole + * @author Adrian Cole, Jeremy Whitlock */ @SkipEncoding('/') @RequestFilters(RequestAuthorizeSignature.class) diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java index 93e4538f3d..aab19e953d 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java @@ -23,13 +23,13 @@ import static org.jclouds.location.reference.LocationConstants.ENDPOINT; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGION; import java.net.URI; - import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.aws.s3.AWSS3AsyncClient; import org.jclouds.aws.s3.AWSS3Client; import org.jclouds.aws.s3.binders.AssignCorrectHostnameAndBindAsHostPrefixIfConfigured; +import org.jclouds.aws.s3.predicates.validators.AWSS3BucketNameValidator; import org.jclouds.location.Region; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.RestContext; @@ -38,6 +38,7 @@ import org.jclouds.s3.S3AsyncClient; import org.jclouds.s3.S3Client; import org.jclouds.s3.binders.BindAsHostPrefixIfConfigured; import org.jclouds.s3.config.S3RestClientModule; +import org.jclouds.s3.predicates.validators.BucketNameValidator; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; @@ -64,6 +65,7 @@ public class AWSS3RestClientModule extends S3RestClientModule { + @Override + public void testCopyObjectInvalidName() throws ArrayIndexOutOfBoundsException, SecurityException, + IllegalArgumentException, NoSuchMethodException, IOException { + // For AWS S3, S3AsyncClientTest#testCopyObjectInvalidName() will not throw an exception + Method method = S3AsyncClient.class.getMethod("copyObject", String.class, String.class, String.class, + String.class, + Array.newInstance(CopyObjectOptions.class, 0).getClass()); + processor.createRequest(method, "sourceBucket", "sourceObject", "destinationBucket", "destinationObject"); + } + public void testGetBucketLocationEU() throws SecurityException, NoSuchMethodException, IOException { Method method = AWSS3AsyncClient.class.getMethod("getBucketLocation", String.class); HttpRequest request = processor.createRequest(method, "eubucket"); diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3ClientLiveTest.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3ClientLiveTest.java index 61339bcd6a..568a7f8f71 100644 --- a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3ClientLiveTest.java +++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3ClientLiveTest.java @@ -26,6 +26,8 @@ import static org.jclouds.crypto.CryptoStreams.md5; import static org.jclouds.io.Payloads.newByteArrayPayload; import static org.jclouds.s3.options.ListBucketOptions.Builder.withPrefix; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; @@ -34,11 +36,15 @@ import java.io.IOException; import java.io.InputStream; import java.util.zip.GZIPInputStream; +import org.jclouds.aws.AWSResponseException; +import org.jclouds.aws.domain.Region; import org.jclouds.blobstore.AsyncBlobStore; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.domain.Blob; +import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.options.PutOptions; +import org.jclouds.domain.Location; import org.jclouds.http.BaseJettyTest; import org.jclouds.io.Payload; import org.jclouds.s3.S3Client; @@ -48,14 +54,16 @@ import org.jclouds.s3.domain.ObjectMetadata; import org.jclouds.s3.domain.ObjectMetadata.StorageClass; import org.jclouds.s3.domain.ObjectMetadataBuilder; import org.jclouds.s3.domain.S3Object; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.io.ByteStreams; +import com.google.common.io.InputSupplier; + import org.testng.ITestContext; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMap; -import com.google.common.io.ByteStreams; -import com.google.common.io.InputSupplier; - /** * Tests behavior of {@code S3Client} * @@ -197,4 +205,59 @@ public class AWSS3ClientLiveTest extends S3ClientLiveTest { returnContainer(containerName); } } + + /** + * http://code.google.com/p/jclouds/issues/detail?id=992 + */ + public void testUseBucketWithUpperCaseName() throws Exception { + String bucketName = CONTAINER_PREFIX + "-TestBucket"; + String blobName = "TestBlob.txt"; + StorageMetadata container = null; + BlobStore store = view.getBlobStore(); + + // Create and use a valid bucket name with uppercase characters in the bucket name (US regions only) + try { + store.createContainerInLocation(null, bucketName); + + for (StorageMetadata metadata : store.list()) { + if (metadata.getName().equals(bucketName)) { + container = metadata; + break; + } + } + + assertNotNull(container); + + store.putBlob(bucketName, store.blobBuilder(blobName) + .payload("This is a test!") + .contentType("text/plain") + .build()); + + assertNotNull(store.getBlob(bucketName, blobName)); + } finally { + if (container != null) { + store.deleteContainer(bucketName); + } + } + + // Try to create the same bucket successfully created above in one of the non-US regions to ensure an error is + // encountered as expected. + Location location = null; + + for (Location pLocation : store.listAssignableLocations()) { + if (!ImmutableSet.of(Region.US_STANDARD, Region.US_EAST_1, Region.US_WEST_1, Region.US_WEST_2) + .contains(pLocation.getId())) { + location = pLocation; + break; + } + } + + try { + store.createContainerInLocation(location, bucketName); + fail("Should had failed because in non-US regions, mixed-case bucket names are invalid."); + } catch (AWSResponseException e) { + assertEquals("InvalidBucketName", e.getError().getCode()); + } + } + } diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java index aeb795f2d2..ea318327eb 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java @@ -19,6 +19,8 @@ package org.jclouds.hpcloud.objectstorage; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import java.net.URI; import java.util.Properties; @@ -26,6 +28,9 @@ import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule; import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.swift.SwiftApiMetadata; import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule; import org.jclouds.rest.RestContext; @@ -66,6 +71,10 @@ public class HPCloudObjectStorageApiMetadata extends SwiftApiMetadata { public static Properties defaultProperties() { Properties properties = SwiftApiMetadata.defaultProperties(); + properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE); + // TODO: this doesn't actually do anything yet. + properties.setProperty(KeystoneProperties.VERSION, "2.0"); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.API_ACCESS_KEY_CREDENTIALS); properties.remove(PROPERTY_REGIONS); return properties; } diff --git a/providers/ninefold-storage/src/test/java/org/jclouds/ninefold/storage/NinefoldStorageClientLiveTest.java b/providers/ninefold-storage/src/test/java/org/jclouds/ninefold/storage/NinefoldStorageClientLiveTest.java index e96403d101..22dd71b8b6 100644 --- a/providers/ninefold-storage/src/test/java/org/jclouds/ninefold/storage/NinefoldStorageClientLiveTest.java +++ b/providers/ninefold-storage/src/test/java/org/jclouds/ninefold/storage/NinefoldStorageClientLiveTest.java @@ -26,7 +26,9 @@ import org.testng.annotations.Test; * * @author Adrian Cole */ -@Test(groups = "live", sequential = true, testName = "NinefoldStorageClientLiveTest") +@Test(groups = "live", singleThreaded = true, testName = "NinefoldStorageClientLiveTest") public class NinefoldStorageClientLiveTest extends AtmosClientLiveTest { - + public NinefoldStorageClientLiveTest() { + provider = "ninefold-storage"; + } }