From 932b738026213a7dd81b011ed0cdb8fd0b182b18 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Tue, 19 Jun 2012 15:20:13 -0700 Subject: [PATCH 01/20] Eliminate unlikely transient blobstore TOCTOU bug --- .../java/org/jclouds/blobstore/TransientStorageStrategy.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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) { From edf99657c026b657fba7b45e10a89c67cb5cec08 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 19 Jun 2012 18:01:13 -0600 Subject: [PATCH 02/20] fixed missing provider name on ninefold test --- .../ninefold/storage/NinefoldStorageClientLiveTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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"; + } } From 09d5e8add4232741e719bd5a6496295c37c2cd59 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 19 Jun 2012 18:01:38 -0600 Subject: [PATCH 03/20] consistent ordering of hardware --- .../org/jclouds/compute/domain/internal/HardwareImpl.java | 7 +++---- .../compute/domain/internal/TemplateBuilderImpl.java | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/HardwareImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/HardwareImpl.java index 717e3b0cd2..52e1bd92a1 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/HardwareImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/HardwareImpl.java @@ -19,7 +19,7 @@ package org.jclouds.compute.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.compute.util.ComputeServiceUtils.getCoresAndSpeed; +import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.compute.util.ComputeServiceUtils.getSpace; import java.net.URI; @@ -104,9 +104,8 @@ public class HardwareImpl extends ComputeMetadataImpl implements Hardware { public int compareTo(ResourceMetadata 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 From 8311d0a4e49f5e7be41d48b511ff705b8d18a432 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 19 Jun 2012 18:02:39 -0600 Subject: [PATCH 04/20] Issue 988:Extra port added to swift url --- .../openstack/swift/SwiftApiMetadata.java | 15 +--- .../swift/SwiftKeystoneApiMetadata.java | 12 +++ .../swift/SwiftClientExpectTest.java | 73 ++++++++++++++++++ .../swift/internal/BaseSwiftExpectTest.java | 75 +++++++++++++++++++ ...arseAuthenticationResponseFromHeaders.java | 3 - .../HPCloudObjectStorageApiMetadata.java | 9 +++ 6 files changed, 172 insertions(+), 15 deletions(-) create mode 100644 apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java create mode 100644 apis/swift/src/test/java/org/jclouds/openstack/swift/internal/BaseSwiftExpectTest.java 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/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 Date: Tue, 19 Jun 2012 18:40:45 -0600 Subject: [PATCH 05/20] added min-disk to compute2.clj --- compute/src/main/clojure/org/jclouds/compute2.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compute/src/main/clojure/org/jclouds/compute2.clj b/compute/src/main/clojure/org/jclouds/compute2.clj index 8d9147ed8c..fc75cd7205 100644 --- a/compute/src/main/clojure/org/jclouds/compute2.clj +++ b/compute/src/main/clojure/org/jclouds/compute2.clj @@ -332,7 +332,7 @@ Here's an example of creating and running a small linux node in the group webser :os-name-matches :os-description-matches :os-version-matches :os-arch-matches :os-64-bit :image-name-matches :image-version-matches :image-description-matches :image-matches - :min-cores :min-ram]))) + :min-cores :min-ram :min-disk]))) (def ^{:doc "TemplateOptions functions" :private true} @@ -425,7 +425,7 @@ Options correspond to TemplateBuilder methods." os-name-matches os-description-matches os-version-matches os-arch-matches os-64-bit mage-name-matches image-version-matches image-description-matches image-matches - min-cores min-ram smallest fastest biggest any] + min-cores min-ram min-disk smallest fastest biggest any] :as options}] (let [builder (.. compute (templateBuilder))] (doseq [[option value] options] From 21802d467aca3dcce8478ae7cdde58080452015a Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Wed, 20 Jun 2012 11:35:06 +0300 Subject: [PATCH 06/20] Adjusting general strategy to accept @Named in place of @SerializedName. Adding TypeAdapterFactory to handle deserialization based on constructor annotations (Inject/Named and/or ConstructorProperties). --- .../org/jclouds/json/config/GsonModule.java | 26 +- ...ructorAndReflectiveTypeAdapterFactory.java | 256 ++++++++++++++++++ .../json/internal/NamingStrategies.java | 226 ++++++++++++++++ ...orAndReflectiveTypeAdapterFactoryTest.java | 245 +++++++++++++++++ .../json/internal/NamingStrategiesTest.java | 203 ++++++++++++++ 5 files changed, 954 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactory.java create mode 100644 core/src/main/java/org/jclouds/json/internal/NamingStrategies.java create mode 100644 core/src/test/java/org/jclouds/json/internal/DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java create mode 100644 core/src/test/java/org/jclouds/json/internal/NamingStrategiesTest.java 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/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"); + } + +} From 0cf4d2b35bc59111f9ca99d3ee6a8af30ed721ca Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Wed, 20 Jun 2012 16:59:33 +0300 Subject: [PATCH 07/20] Fix for iptonetworklist (was incorrectly sending ipnetworklist) --- .../cloudstack/options/DeployVirtualMachineOptions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; } From 2526e7adeb10202750cdc1e4ea9d45018aed481a Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Wed, 20 Jun 2012 19:24:32 +0300 Subject: [PATCH 08/20] cloudstack: don't set networkId to default when iptonetworklist is populated --- .../compute/strategy/AdvancedNetworkOptionsConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) { From cf422fb68304d22b32bb9d21ddc7e1e687a84360 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Thu, 21 Jun 2012 15:35:12 +0100 Subject: [PATCH 09/20] Issue 994: fix vcloud sax parsing of namespaces Handles when xml tags are qualified with and without xmlns. --- .../jclouds/vcloud/xml/CatalogHandler.java | 14 ++-- .../vcloud/xml/CatalogItemHandler.java | 10 +-- .../org/jclouds/vcloud/xml/ErrorHandler.java | 2 +- .../jclouds/vcloud/xml/OrgNetworkHandler.java | 76 +++++++++---------- .../vcloud/xml/SupportedVersionsHandler.java | 7 +- .../jclouds/vcloud/xml/TasksListHandler.java | 6 +- .../org/jclouds/vcloud/xml/VmHandler.java | 8 +- .../vcloud/xml/CatalogItemHandlerTest.java | 26 +++++++ ...ogItem-carrenza-with-default-namespace.xml | 8 ++ ...logItem-carrenza-with-vcloud-namespace.xml | 8 ++ 10 files changed, 104 insertions(+), 61 deletions(-) create mode 100644 apis/vcloud/src/test/resources/catalogItem-carrenza-with-default-namespace.xml create mode 100644 apis/vcloud/src/test/resources/catalogItem-carrenza-with-vcloud-namespace.xml diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogHandler.java index d2ec855de5..b3e5d35083 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/CatalogHandler.java @@ -70,13 +70,13 @@ public class CatalogHandler 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("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/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 @@ + + + + + + + + From 8e1542e90a76da703b8c93e59ca645f954e5de5d Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Thu, 21 Jun 2012 14:49:24 +0100 Subject: [PATCH 10/20] Issue 995: handle illegal argument in vcloud images --- .../strategy/VCloudComputeServiceAdapter.java | 9 + .../BaseVCloudComputeServiceExpectTest.java | 8 + .../VCloudComputeServiceAdapterTest.java | 74 +++++ .../src/test/resources/ovf-multi-vm.xml | 285 ++++++++++++++++++ .../resources/template1.0-vcd15-multi-vm.xml | 68 +++++ 5 files changed, 444 insertions(+) create mode 100644 apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/VCloudComputeServiceAdapterTest.java create mode 100644 apis/vcloud/src/test/resources/ovf-multi-vm.xml create mode 100644 apis/vcloud/src/test/resources/template1.0-vcd15-multi-vm.xml 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 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/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 + + + From 2702e942d214b71c784c9e3375127ef5e5cebb67 Mon Sep 17 00:00:00 2001 From: Jeremy Whitlock Date: Thu, 21 Jun 2012 17:05:20 -0600 Subject: [PATCH 11/20] Issue 992: Fix AWS S3 to work with non-DNS, but still valid, named buckets. Prior to this commit, jclouds wouldn't allow you to interact with any buckets in S3 that were named with uppercase characters. Per AWS S3 docs, this non-standard naming is valid in US regions only. This update fixes jclouds so that it can interact with, and even attempt to create, buckets with uppercase characters for AWS S3 without actually impacting other S3 implementations. This fix also will not have any impact in non-US regions other than instead of a bucket name validation error you'll get an InvalidBucketName error back from AWS S3 when you attempt to create a bucket with an uppercase character in a non-US region. To summarize, nothing changes other than US regions now allow creation of bucket names with upper case characters and jclouds now can interact with these non-standard named buckets without failure. --- .../binders/BindAsHostPrefixIfConfigured.java | 11 ++- .../s3/filters/RequestAuthorizeSignature.java | 41 +++++++---- .../handlers/ParseS3ErrorFromXmlContent.java | 23 ++++-- .../validators/BucketNameValidator.java | 2 +- .../org/jclouds/aws/s3/AWSS3AsyncClient.java | 3 +- .../aws/s3/config/AWSS3RestClientModule.java | 4 +- .../validators/AWSS3BucketNameValidator.java | 57 +++++++++++++++ .../jclouds/aws/s3/AWSS3AsyncClientTest.java | 24 +++++-- .../jclouds/aws/s3/AWSS3ClientLiveTest.java | 71 +++++++++++++++++-- 9 files changed, 199 insertions(+), 37 deletions(-) create mode 100644 providers/aws-s3/src/main/java/org/jclouds/aws/s3/predicates/validators/AWSS3BucketNameValidator.java 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/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()); + } + } + } From 9112a832fc9491c905a2c0c14f68f87ced133559 Mon Sep 17 00:00:00 2001 From: Andrew Bayer Date: Thu, 21 Jun 2012 11:37:06 -0700 Subject: [PATCH 12/20] Improve Maven build time dramatically by moving source and javadoc to profiles. This makes a *huge* difference in build time (mvn clean install -DskipTests takes about 1/3 as long with this in place). It moves source and javadoc into profiles, so that if you want to build the source jars and javadoc jars, you specify -Psrc and -Pdoc respectively. --- pom.xml | 51 ++++++++------------- project/pom.xml | 115 +++++++++++++++++++++++++++++------------------- 2 files changed, 88 insertions(+), 78 deletions(-) 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 + + + + + + + From e5731df9229780added113dfbc80d4efc28428d4 Mon Sep 17 00:00:00 2001 From: Nirmal Date: Sat, 23 Jun 2012 09:48:48 +0530 Subject: [PATCH 13/20] Upgrading commons-io dependency of sshj driver to 2.0 --- drivers/sshj/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sshj/pom.xml b/drivers/sshj/pom.xml index e76230570f..fbb1c99920 100644 --- a/drivers/sshj/pom.xml +++ b/drivers/sshj/pom.xml @@ -97,7 +97,7 @@ commons-io commons-io - 1.4 + 2.0 From 955cd540ceeacdd7034f6e1ebea68e8fd09f8351 Mon Sep 17 00:00:00 2001 From: Nirmal Date: Sun, 24 Jun 2012 16:52:01 +0530 Subject: [PATCH 14/20] Specifically adding the osgi import org.apache.commons.io.input;version=[1.4,3) --- drivers/sshj/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sshj/pom.xml b/drivers/sshj/pom.xml index fbb1c99920..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)",* From fd79c479afd8e4e42f3cb417cb86cb663036db23 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Sun, 24 Jun 2012 10:58:09 +0300 Subject: [PATCH 15/20] glesys: adjusting ParserModule - removing support for odd dates (no longer present in api) and adding support for "yes"/"no" Boolean fields --- .../glesys/config/GleSYSParserModule.java | 9 ++- .../jclouds/glesys/domain/GlesysBoolean.java | 16 ++++ .../internal/GleSYSTypeAdapters.java | 22 ++++++ .../functions/internal/GlesysDateAdapter.java | 78 ------------------- 4 files changed, 44 insertions(+), 81 deletions(-) create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/GlesysBoolean.java delete mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GlesysDateAdapter.java 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/GlesysBoolean.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/GlesysBoolean.java new file mode 100644 index 0000000000..5b10803202 --- /dev/null +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/GlesysBoolean.java @@ -0,0 +1,16 @@ +package org.jclouds.glesys.domain; + +/** + * Wrapping booleans for the time being (gson won't allow TypeAdapter<Boolean>) + */ +public class GleSYSBoolean { + 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/functions/internal/GleSYSTypeAdapters.java b/labs/glesys/src/main/java/org/jclouds/glesys/functions/internal/GleSYSTypeAdapters.java index 070c9f186b..04eae31cc1 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,23 @@ 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 { + 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); - } - } - } -} From b1877bbee57afc4886627c4ad69cda50aca622ab Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Sun, 24 Jun 2012 11:12:26 +0300 Subject: [PATCH 16/20] glesys: bean cleaning, using ConstructorProperties for deserialization (note no serialization annotations as we don't currently serialize any of these beans) --- .../AllowedArgumentsForCreateServer.java | 232 +++++++------ .../org/jclouds/glesys/domain/Archive.java | 145 +++++--- .../domain/ArchiveAllowedArguments.java | 92 +++-- .../org/jclouds/glesys/domain/Console.java | 133 ++++--- .../java/org/jclouds/glesys/domain/Cost.java | 112 +++--- .../org/jclouds/glesys/domain/Domain.java | 284 ++++++++++++--- .../jclouds/glesys/domain/DomainRecord.java | 158 ++++++--- .../jclouds/glesys/domain/EmailAccount.java | 296 +++++++++------- .../org/jclouds/glesys/domain/EmailAlias.java | 130 +++++++ .../jclouds/glesys/domain/EmailOverview.java | 115 +++--- .../glesys/domain/EmailOverviewDomain.java | 105 ++++-- .../glesys/domain/EmailOverviewSummary.java | 142 +++++--- .../org/jclouds/glesys/domain/EmailQuota.java | 130 +++++++ .../java/org/jclouds/glesys/domain/Ip.java | 156 ++++++--- .../org/jclouds/glesys/domain/IpDetails.java | 326 ++++++++++++------ .../org/jclouds/glesys/domain/OSTemplate.java | 149 ++++---- .../jclouds/glesys/domain/ResourceUsage.java | 111 +++--- .../org/jclouds/glesys/domain/Server.java | 135 +++++--- .../jclouds/glesys/domain/ServerDetails.java | 279 ++++++++------- .../jclouds/glesys/domain/ServerLimit.java | 136 +++++--- .../org/jclouds/glesys/domain/ServerSpec.java | 199 ++++++----- .../jclouds/glesys/domain/ServerStatus.java | 154 ++++++--- .../jclouds/glesys/domain/ServerUptime.java | 101 ++++-- 23 files changed, 2507 insertions(+), 1313 deletions(-) create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailQuota.java 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/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..3642ff4715 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", "usedquota", "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..21ec5d59cd --- /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().fromEmailAccount(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + protected String account; + protected String forwardTo; + + /** + * @see org.jclouds.glesys.domain.EmailAlias#getAccount() + */ + public T account(String account) { + this.account = checkNotNull(account, "account"); + return self(); + } + + /** + * @see EmailAlias#getForwardTo() + */ + public T forwardTo(String forwardTo) { + this.forwardTo = checkNotNull(forwardTo, "forwardTo"); + return self(); + } + + public EmailAlias build() { + return new EmailAlias(account, forwardTo); + } + + public T fromEmailAccount(EmailAlias in) { + return this.account(in.getAccount()).forwardTo(in.getForwardTo()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String account; + private final String forwardTo; + + @ConstructorProperties({ + "emailalias", "goto" + }) + protected EmailAlias(String account, String forwardTo) { + this.account = checkNotNull(account, "account"); + this.forwardTo = checkNotNull(forwardTo, "forwardTo"); + } + + /** + * @return the e-mail address being forwarded + */ + public String getAccount() { + return this.account; + } + + /** + * @return the e-mail address this address forwards to + */ + public String getForwardTo() { + return this.forwardTo; + } + + @Override + public int hashCode() { + return Objects.hashCode(account); + } + + @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.account, that.account); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("account", account).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/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/ResourceUsage.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsage.java index 6bc3ade688..bc5483f1ef 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,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; /** * Detailed information on usage @@ -26,38 +31,60 @@ import com.google.common.base.Objects; * @author Adam Lowe * @see ServerStatus */ - 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().fromResourceUsage(this); + } - public Builder usage(double usage) { + public static abstract class Builder> { + protected abstract T self(); + + protected double usage; + protected double max; + protected String unit; + + /** + * @see ResourceUsage#getUsage() + */ + public T usage(double usage) { this.usage = usage; - return this; + return self(); } - public Builder max(double max) { + /** + * @see ResourceUsage#getMax() + */ + public T max(double max) { this.max = max; - return this; + return self(); } - public Builder unit(String unit) { - this.unit = unit; - return this; + /** + * @see ResourceUsage#getUnit() + */ + public T unit(String unit) { + this.unit = checkNotNull(unit, "unit"); + return self(); } public ResourceUsage build() { return new ResourceUsage(usage, max, unit); } - public Builder fromCpu(ResourceUsage in) { - return usage(in.getUsage()).max(in.getMax()).unit(in.getUnit()); + public T fromResourceUsage(ResourceUsage in) { + return this.usage(in.getUsage()).max(in.getMax()).unit(in.getUnit()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; } } @@ -65,56 +92,58 @@ public class ResourceUsage { private final double max; private final String unit; - public ResourceUsage(double usage, double max, String unit) { + @ConstructorProperties({ + "usage", "max", "unit" + }) + protected ResourceUsage(double usage, double max, String unit) { this.usage = usage; this.max = max; - this.unit = unit; + this.unit = checkNotNull(unit, "unit"); } /** * @return the usage in #unit */ public double getUsage() { - return usage; + return this.usage; } /** * @return the max usage in #unit */ public double getMax() { - return max; + return this.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; - } + 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; + ResourceUsage that = ResourceUsage.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.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/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..2af987350e 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,236 @@ 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..78ba1a791d 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,51 +33,78 @@ 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 ResourceUsage cpu; + protected ResourceUsage memory; + protected ResourceUsage 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(ResourceUsage cpu) { + this.cpu = checkNotNull(cpu, "cpu"); + return self(); } - public Builder memory(ResourceUsage memory) { - this.memory = memory; - return this; + /** + * @see ServerStatus#getMemory() + */ + public T memory(ResourceUsage memory) { + this.memory = checkNotNull(memory, "memory"); + return self(); } - public Builder disk(ResourceUsage disk) { - this.disk = disk; - return this; + /** + * @see ServerStatus#getDisk() + */ + public T disk(ResourceUsage 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; } } @@ -80,8 +114,12 @@ public class ServerStatus { private final ResourceUsage 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 ResourceUsage cpu, @Nullable ResourceUsage memory, + @Nullable ResourceUsage 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 */ + @Nullable public ResourceUsage getCpu() { - return cpu; + return this.cpu; } /** * @return details of memory usage and limits */ + @Nullable public ResourceUsage getMemory() { - return memory; + return this.memory; } /** * @return details of disk usage and limits */ + @Nullable public ResourceUsage getDisk() { - return disk; + 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 From 9b4e68cc6b3371036bd7b27440a072bcaca4b9e7 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Sun, 24 Jun 2012 11:13:08 +0300 Subject: [PATCH 17/20] glesys: removing ArchiveDetails (duplicate of Archive) --- .../jclouds/glesys/domain/ArchiveDetails.java | 65 ------------------- .../glesys/features/ArchiveAsyncClient.java | 17 +++-- .../glesys/features/ArchiveClient.java | 9 ++- 3 files changed, 15 insertions(+), 76 deletions(-) delete mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/ArchiveDetails.java 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/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. From 79dc8b91aff949ea841f32bbf1375bbf904f9514 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Sun, 24 Jun 2012 19:04:19 +0300 Subject: [PATCH 18/20] glesys: updating to API version 0.1.29 --- .../jclouds/glesys/domain/EmailAccount.java | 2 +- .../org/jclouds/glesys/domain/EmailAlias.java | 32 +- ...{GlesysBoolean.java => GleSYSBoolean.java} | 3 + .../jclouds/glesys/domain/ResourceStatus.java | 149 +++++++ .../jclouds/glesys/domain/ResourceUsage.java | 84 ++-- .../glesys/domain/ResourceUsageInfo.java | 144 +++++++ .../glesys/domain/ResourceUsageValue.java | 128 ++++++ .../jclouds/glesys/domain/ServerDetails.java | 7 +- .../jclouds/glesys/domain/ServerStatus.java | 28 +- .../glesys/features/DomainAsyncClient.java | 27 +- .../jclouds/glesys/features/DomainClient.java | 32 +- .../glesys/features/EmailAsyncClient.java | 33 +- .../jclouds/glesys/features/EmailClient.java | 18 +- .../glesys/features/IpAsyncClient.java | 133 ++++-- .../org/jclouds/glesys/features/IpClient.java | 130 +++--- .../glesys/features/ServerAsyncClient.java | 13 +- .../jclouds/glesys/features/ServerClient.java | 124 +++--- .../internal/GleSYSTypeAdapters.java | 3 +- .../glesys/options/AddDomainOptions.java | 2 +- .../glesys/options/CreateAccountOptions.java | 6 +- .../glesys/options/DestroyServerOptions.java | 2 +- .../jclouds/glesys/options/ListIpOptions.java | 106 +++++ .../jclouds/glesys/GleSYSAsyncClientTest.java | 11 +- .../ServerDetailsToNodeMetadataTest.java | 27 +- .../features/ArchiveClientExpectTest.java | 61 +-- .../features/ArchiveClientLiveTest.java | 10 +- .../features/DomainClientExpectTest.java | 186 ++++++-- .../glesys/features/DomainClientLiveTest.java | 17 +- .../features/EmailClientExpectTest.java | 150 ++++++- .../glesys/features/EmailClientLiveTest.java | 52 ++- .../glesys/features/IpAsyncClientTest.java | 62 --- .../glesys/features/IpClientExpectTest.java | 401 +++++++++++------- .../glesys/features/IpClientLiveTest.java | 156 +++++-- .../features/ServerClientExpectTest.java | 122 ++++-- .../glesys/features/ServerClientLiveTest.java | 112 +++-- ...t.java => BaseGleSYSClientExpectTest.java} | 31 +- .../internal/BaseGleSYSClientLiveTest.java | 49 --- .../BaseGleSYSClientWithAServerLiveTest.java | 128 ++++++ .../glesys/parse/ParseFullIpDetailsTest.java | 9 +- .../parse/ParseIpAddressFromResponseTest.java | 18 +- .../src/test/resources/archive_details.json | 2 +- .../src/test/resources/archive_list.json | 2 +- .../src/test/resources/domain_details.json | 1 + .../test/resources/domain_list_records.json | 2 +- .../src/test/resources/domain_record.json | 1 + .../src/test/resources/email_details.json | 1 + .../glesys/src/test/resources/email_list.json | 13 +- .../src/test/resources/email_overview.json | 7 +- .../src/test/resources/ip_get_details.json | 17 +- .../test/resources/ip_get_details_xen.json | 16 +- .../src/test/resources/ip_list_free.json | 2 +- .../src/test/resources/ip_list_own.json | 5 + .../src/test/resources/server_created.json | 1 - .../src/test/resources/server_details.json | 17 +- .../test/resources/server_resource_usage.json | 16 + .../src/test/resources/server_status.json | 2 +- 56 files changed, 2080 insertions(+), 833 deletions(-) rename labs/glesys/src/main/java/org/jclouds/glesys/domain/{GlesysBoolean.java => GleSYSBoolean.java} (69%) create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceStatus.java create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageInfo.java create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/domain/ResourceUsageValue.java create mode 100644 labs/glesys/src/main/java/org/jclouds/glesys/options/ListIpOptions.java delete mode 100644 labs/glesys/src/test/java/org/jclouds/glesys/features/IpAsyncClientTest.java rename labs/glesys/src/test/java/org/jclouds/glesys/internal/{BaseGleSYSAsyncClientTest.java => BaseGleSYSClientExpectTest.java} (54%) create mode 100644 labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientWithAServerLiveTest.java create mode 100644 labs/glesys/src/test/resources/domain_details.json create mode 100644 labs/glesys/src/test/resources/domain_record.json create mode 100644 labs/glesys/src/test/resources/email_details.json create mode 100644 labs/glesys/src/test/resources/ip_list_own.json delete mode 100644 labs/glesys/src/test/resources/server_created.json create mode 100644 labs/glesys/src/test/resources/server_resource_usage.json 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 3642ff4715..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 @@ -164,7 +164,7 @@ public class EmailAccount { private final Date modified; @ConstructorProperties({ - "emailaccount", "quota", "usedquota", "antispamlevel", "antivirus", "autorespond", "autorespondmessage", "autorespondsaveemail", "created", "modified" + "emailaccount", "quota", "antispamlevel", "antivirus", "autorespond", "autorespondmessage", "autorespondsaveemail", "created", "modified" }) protected EmailAccount(String account, EmailQuota quota, int antispamLevel, GleSYSBoolean antiVirus, GleSYSBoolean autoRespond, @Nullable String autoRespondMessage, 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 index 21ec5d59cd..8f20940dd7 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/EmailAlias.java @@ -38,20 +38,20 @@ public class EmailAlias { } public Builder toBuilder() { - return new ConcreteBuilder().fromEmailAccount(this); + return new ConcreteBuilder().fromEmailAlias(this); } public static abstract class Builder> { protected abstract T self(); - protected String account; + protected String alias; protected String forwardTo; /** - * @see org.jclouds.glesys.domain.EmailAlias#getAccount() + * @see org.jclouds.glesys.domain.EmailAlias#getAlias() */ - public T account(String account) { - this.account = checkNotNull(account, "account"); + public T alias(String alias) { + this.alias = checkNotNull(alias, "alias"); return self(); } @@ -64,11 +64,11 @@ public class EmailAlias { } public EmailAlias build() { - return new EmailAlias(account, forwardTo); + return new EmailAlias(alias, forwardTo); } - public T fromEmailAccount(EmailAlias in) { - return this.account(in.getAccount()).forwardTo(in.getForwardTo()); + public T fromEmailAlias(EmailAlias in) { + return this.alias(in.getAlias()).forwardTo(in.getForwardTo()); } } @@ -79,22 +79,22 @@ public class EmailAlias { } } - private final String account; + private final String alias; private final String forwardTo; @ConstructorProperties({ "emailalias", "goto" }) - protected EmailAlias(String account, String forwardTo) { - this.account = checkNotNull(account, "account"); + 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 getAccount() { - return this.account; + public String getAlias() { + return this.alias; } /** @@ -106,7 +106,7 @@ public class EmailAlias { @Override public int hashCode() { - return Objects.hashCode(account); + return Objects.hashCode(alias); } @Override @@ -114,12 +114,12 @@ public class EmailAlias { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; EmailAlias that = EmailAlias.class.cast(obj); - return Objects.equal(this.account, that.account); + return Objects.equal(this.alias, that.alias); } protected ToStringHelper string() { return Objects.toStringHelper("") - .add("account", account).add("forwardTo", forwardTo); + .add("alias", alias).add("forwardTo", forwardTo); } @Override 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 similarity index 69% rename from labs/glesys/src/main/java/org/jclouds/glesys/domain/GlesysBoolean.java rename to labs/glesys/src/main/java/org/jclouds/glesys/domain/GleSYSBoolean.java index 5b10803202..9dc1a51860 100644 --- a/labs/glesys/src/main/java/org/jclouds/glesys/domain/GlesysBoolean.java +++ b/labs/glesys/src/main/java/org/jclouds/glesys/domain/GleSYSBoolean.java @@ -4,6 +4,9 @@ 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) { 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 bc5483f1ef..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 @@ -21,15 +21,18 @@ 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 { @@ -38,46 +41,46 @@ public class ResourceUsage { } public Builder toBuilder() { - return new ConcreteBuilder().fromResourceUsage(this); + return new ConcreteBuilder().fromResourceUsages(this); } public static abstract class Builder> { protected abstract T self(); - protected double usage; - protected double max; - protected String unit; + protected ResourceUsageInfo info; + protected Set values = ImmutableSet.of(); /** - * @see ResourceUsage#getUsage() + * @see ResourceUsage#getInfo() */ - public T usage(double usage) { - this.usage = usage; + public T info(ResourceUsageInfo info) { + this.info = checkNotNull(info, "info"); return self(); } /** - * @see ResourceUsage#getMax() + * @see ResourceUsage#getValues() */ - public T max(double max) { - this.max = max; + public T values(Set values) { + this.values = ImmutableSet.copyOf(checkNotNull(values, "values")); return self(); } /** - * @see ResourceUsage#getUnit() + * @see ResourceUsage#getValues() */ - public T unit(String unit) { - this.unit = checkNotNull(unit, "unit"); - return self(); + 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 T fromResourceUsage(ResourceUsage in) { - return this.usage(in.getUsage()).max(in.getMax()).unit(in.getUnit()); + public T fromResourceUsages(ResourceUsage in) { + return this + .info(in.getInfo()) + .values(in.getValues()); } } @@ -88,43 +91,28 @@ public class ResourceUsage { } } - private final double usage; - private final double max; - private final String unit; + private final ResourceUsageInfo info; + private final Set values; @ConstructorProperties({ - "usage", "max", "unit" + "info", "values" }) - protected ResourceUsage(double usage, double max, String unit) { - this.usage = usage; - this.max = max; - this.unit = checkNotNull(unit, "unit"); + protected ResourceUsage(ResourceUsageInfo info, Set values) { + this.info = checkNotNull(info, "info"); + this.values = ImmutableSet.copyOf(checkNotNull(values, "values")); } - /** - * @return the usage in #unit - */ - public double getUsage() { - return this.usage; + public ResourceUsageInfo getInfo() { + return this.info; } - /** - * @return the max usage in #unit - */ - public double getMax() { - return this.max; - } - - /** - * @return the unit used - */ - public String getUnit() { - return this.unit; + public Set getValues() { + return this.values; } @Override public int hashCode() { - return Objects.hashCode(usage, max, unit); + return Objects.hashCode(info, values); } @Override @@ -132,13 +120,13 @@ public class ResourceUsage { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; ResourceUsage that = ResourceUsage.class.cast(obj); - return Objects.equal(this.usage, that.usage) - && Objects.equal(this.max, that.max) - && Objects.equal(this.unit, that.unit); + return Objects.equal(this.info, that.info) + && Objects.equal(this.values, that.values); } protected ToStringHelper string() { - return Objects.toStringHelper("").add("usage", usage).add("max", max).add("unit", unit); + return Objects.toStringHelper("") + .add("info", info).add("values", values); } @Override 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/ServerDetails.java b/labs/glesys/src/main/java/org/jclouds/glesys/domain/ServerDetails.java index 2af987350e..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 @@ -168,9 +168,12 @@ public class ServerDetails extends Server { private final Set ips; @ConstructorProperties({ - "serverid", "hostname", "datacenter", "platform", "state", "description", "templatename", "cpucores", "memorysize", "disksize", "transfer", "cost", "iplist" + "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) { + 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.description = description; 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 78ba1a791d..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 @@ -47,9 +47,9 @@ public class ServerStatus { protected abstract T self(); protected Server.State state; - protected ResourceUsage cpu; - protected ResourceUsage memory; - protected ResourceUsage disk; + protected ResourceStatus cpu; + protected ResourceStatus memory; + protected ResourceStatus disk; protected ServerUptime uptime; /** @@ -63,7 +63,7 @@ public class ServerStatus { /** * @see ServerStatus#getCpu() */ - public T cpu(ResourceUsage cpu) { + public T cpu(ResourceStatus cpu) { this.cpu = checkNotNull(cpu, "cpu"); return self(); } @@ -71,7 +71,7 @@ public class ServerStatus { /** * @see ServerStatus#getMemory() */ - public T memory(ResourceUsage memory) { + public T memory(ResourceStatus memory) { this.memory = checkNotNull(memory, "memory"); return self(); } @@ -79,7 +79,7 @@ public class ServerStatus { /** * @see ServerStatus#getDisk() */ - public T disk(ResourceUsage disk) { + public T disk(ResourceStatus disk) { this.disk = checkNotNull(disk, "disk"); return self(); } @@ -109,16 +109,16 @@ public class ServerStatus { } 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; @ConstructorProperties({ "state", "cpu", "memory", "disk", "uptime" }) - protected ServerStatus(Server.State state, @Nullable ResourceUsage cpu, @Nullable ResourceUsage memory, - @Nullable ResourceUsage disk, @Nullable ServerUptime 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; @@ -138,7 +138,7 @@ public class ServerStatus { * @return CPU usage information */ @Nullable - public ResourceUsage getCpu() { + public ResourceStatus getCpu() { return this.cpu; } @@ -146,7 +146,7 @@ public class ServerStatus { * @return details of memory usage and limits */ @Nullable - public ResourceUsage getMemory() { + public ResourceStatus getMemory() { return this.memory; } @@ -154,7 +154,7 @@ public class ServerStatus { * @return details of disk usage and limits */ @Nullable - public ResourceUsage getDisk() { + public ResourceStatus getDisk() { return this.disk; } 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 04eae31cc1..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 @@ -57,6 +57,8 @@ public class GleSYSTypeAdapters { 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")); } @@ -64,5 +66,4 @@ public class GleSYSTypeAdapters { } - } \ No newline at end of file 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/BaseGleSYSAsyncClientTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java similarity index 54% rename from labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSAsyncClientTest.java rename to labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java index eb767553ef..db294669ef 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSAsyncClientTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/internal/BaseGleSYSClientExpectTest.java @@ -18,27 +18,20 @@ */ package org.jclouds.glesys.internal; -import static org.testng.Assert.assertEquals; - -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.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.glesys.GleSYSClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; /** - * @author Adrian Cole + * Configures a glesys client expect test - provides a dateService + * + * @author Adam Lowe */ -public abstract class BaseGleSYSAsyncClientTest extends BaseAsyncClientTest { +public class BaseGleSYSClientExpectTest extends BaseRestClientExpectTest { + protected DateService dateService = new SimpleDateFormatDateService(); - @Override - protected void checkFilters(HttpRequest request) { - assertEquals(request.getFilters().size(), 1); - assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + public BaseGleSYSClientExpectTest() { + provider = "glesys"; } - - @Override - public ProviderMetadata createProviderMetadata() { - return new GleSYSProviderMetadata(); - } -} +} \ 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 From 763572f8ee187fef2e55afa07a11887dec37a1cc Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 24 Jun 2012 11:47:49 -0700 Subject: [PATCH 19/20] added paginated set functionality --- .../org/jclouds/collect/PaginatedSet.java | 103 ++++++++++++++++++ .../org/jclouds/collect/PaginatedSets.java | 86 +++++++++++++++ .../jclouds/collect/PaginatedSetsTest.java | 76 +++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 core/src/main/java/org/jclouds/collect/PaginatedSet.java create mode 100644 core/src/main/java/org/jclouds/collect/PaginatedSets.java create mode 100644 core/src/test/java/org/jclouds/collect/PaginatedSetsTest.java 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/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); + + } + +} From 5687a6d8eac118f6b73e8e061040f5e497021f0c Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 24 Jun 2012 11:48:05 -0700 Subject: [PATCH 20/20] Issue 997:support AWS IAM api --- labs/aws-iam/pom.xml | 108 +++++++++ .../aws/iam/AWSIAMProviderMetadata.java | 87 ++++++++ .../org.jclouds.providers.ProviderMetadata | 1 + .../jclouds/aws/iam/AWSIAMClientLiveTest.java | 35 +++ .../jclouds/aws/iam/AWSIAMProviderTest.java | 37 ++++ .../iam/features/AWSUserClientLiveTest.java | 32 +++ labs/iam/pom.xml | 108 +++++++++ .../src/main/java/org/jclouds/iam/IAM.java | 43 ++++ .../java/org/jclouds/iam/IAMApiMetadata.java | 95 ++++++++ .../java/org/jclouds/iam/IAMAsyncClient.java | 64 ++++++ .../main/java/org/jclouds/iam/IAMClient.java | 49 ++++ .../iam/config/IAMRestClientModule.java | 48 ++++ .../java/org/jclouds/iam/domain/User.java | 209 ++++++++++++++++++ .../jclouds/iam/features/UserAsyncClient.java | 88 ++++++++ .../org/jclouds/iam/features/UserClient.java | 75 +++++++ .../jclouds/iam/options/ListUsersOptions.java | 169 ++++++++++++++ .../iam/xml/ListUsersResultHandler.java | 105 +++++++++ .../java/org/jclouds/iam/xml/UserHandler.java | 84 +++++++ .../services/org.jclouds.apis.ApiMetadata | 1 + .../org/jclouds/iam/IAMApiMetadataTest.java | 39 ++++ .../org/jclouds/iam/IAMClientLiveTest.java | 58 +++++ .../test/java/org/jclouds/iam/IAMTest.java | 62 ++++++ .../iam/features/UserClientExpectTest.java | 188 ++++++++++++++++ .../iam/features/UserClientLiveTest.java | 73 ++++++ .../BaseIAMAsyncClientExpectTest.java | 38 ++++ .../iam/internal/BaseIAMClientExpectTest.java | 29 +++ .../iam/internal/BaseIAMClientLiveTest.java | 47 ++++ .../iam/internal/BaseIAMExpectTest.java | 51 +++++ .../iam/options/ListUsersOptionsTest.java | 68 ++++++ .../iam/parse/GetUserResponseTest.java | 60 +++++ .../iam/parse/ListUsersResponseTest.java | 69 ++++++ labs/iam/src/test/resources/get_user.xml | 16 ++ labs/iam/src/test/resources/list_users.xml | 24 ++ labs/iam/src/test/resources/log4j.xml | 166 ++++++++++++++ labs/pom.xml | 2 + 35 files changed, 2428 insertions(+) create mode 100644 labs/aws-iam/pom.xml create mode 100644 labs/aws-iam/src/main/java/org/jclouds/aws/iam/AWSIAMProviderMetadata.java create mode 100644 labs/aws-iam/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata create mode 100644 labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMClientLiveTest.java create mode 100644 labs/aws-iam/src/test/java/org/jclouds/aws/iam/AWSIAMProviderTest.java create mode 100644 labs/aws-iam/src/test/java/org/jclouds/aws/iam/features/AWSUserClientLiveTest.java create mode 100644 labs/iam/pom.xml create mode 100644 labs/iam/src/main/java/org/jclouds/iam/IAM.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/IAMApiMetadata.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/IAMAsyncClient.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/IAMClient.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/config/IAMRestClientModule.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/domain/User.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/features/UserAsyncClient.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/features/UserClient.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/options/ListUsersOptions.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/xml/ListUsersResultHandler.java create mode 100644 labs/iam/src/main/java/org/jclouds/iam/xml/UserHandler.java create mode 100644 labs/iam/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata create mode 100644 labs/iam/src/test/java/org/jclouds/iam/IAMApiMetadataTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/IAMClientLiveTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/IAMTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/features/UserClientExpectTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/features/UserClientLiveTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientExpectTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMClientLiveTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMExpectTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/options/ListUsersOptionsTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/parse/GetUserResponseTest.java create mode 100644 labs/iam/src/test/java/org/jclouds/iam/parse/ListUsersResponseTest.java create mode 100644 labs/iam/src/test/resources/get_user.xml create mode 100644 labs/iam/src/test/resources/list_users.xml create mode 100644 labs/iam/src/test/resources/log4j.xml 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/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/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java new file mode 100644 index 0000000000..daa3407fd9 --- /dev/null +++ b/labs/iam/src/test/java/org/jclouds/iam/internal/BaseIAMAsyncClientExpectTest.java @@ -0,0 +1,38 @@ +/** + * 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 java.util.Properties; + +import org.jclouds.http.HttpRequest; +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 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