Merge pull request #1227 from jclouds/dynect

DynECT initial implementation: SessionApi
This commit is contained in:
Adrian Cole 2013-01-22 18:25:35 -08:00
commit 992def18b0
29 changed files with 1345 additions and 2 deletions

View File

@ -59,6 +59,8 @@ 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.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -88,12 +90,14 @@ public class GsonModule extends AbstractModule {
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings,
OptionalTypeAdapterFactory optional, SetTypeAdapterFactory set, MapTypeAdapterFactory map,
MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
CollectionTypeAdapterFactory collection, FluentIterableTypeAdapterFactory fluentIterable) throws Exception {
CollectionTypeAdapterFactory collection, FluentIterableTypeAdapterFactory fluentIterable,
DefaultExclusionStrategy exclusionStrategy) {
FieldNamingStrategy serializationPolicy = new AnnotationOrNameFieldNamingStrategy(ImmutableSet.of(
new ExtractSerializedName(), new ExtractNamed()));
GsonBuilder builder = new GsonBuilder().setFieldNamingStrategy(serializationPolicy);
GsonBuilder builder = new GsonBuilder().setFieldNamingStrategy(serializationPolicy)
.setExclusionStrategies(exclusionStrategy);
// simple (type adapters)
builder.registerTypeAdapter(Properties.class, propertiesAdapter.nullSafe());
@ -130,6 +134,20 @@ public class GsonModule extends AbstractModule {
return builder.create();
}
@ImplementedBy(NoExclusions.class)
public static interface DefaultExclusionStrategy extends ExclusionStrategy {
}
public static class NoExclusions implements DefaultExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f) {
return false;
}
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
@ImplementedBy(CDateAdapter.class)
public abstract static class DateAdapter extends TypeAdapter<Date> {

View File

@ -24,11 +24,14 @@ import java.util.Map;
import java.util.Properties;
import org.jclouds.json.config.GsonModule;
import org.jclouds.json.config.GsonModule.DefaultExclusionStrategy;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.gson.FieldAttributes;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.TypeLiteral;
@ -81,6 +84,26 @@ public class JsonTest {
assertEquals(obj2, obj);
assertEquals(json.toJson(obj2), json.toJson(obj));
}
static class ExcludeStringValue implements DefaultExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().equals("stringValue");
}
}
public void testExcluder() {
Json excluder = Guice.createInjector(new GsonModule(), new AbstractModule() {
protected void configure() {
bind(DefaultExclusionStrategy.class).to(ExcludeStringValue.class);
}
}).getInstance(Json.class);
ObjectNoDefaultConstructor obj = new ObjectNoDefaultConstructor("foo", 1);
assertEquals(excluder.toJson(obj), "{\"intValue\":1}");
}
private static class EnumInside {
private static enum Test {

109
labs/dynect/pom.xml Normal file
View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>dynect</artifactId>
<name>jcloud dynect api</name>
<description>jclouds components for DynECT Managed DNS</description>
<packaging>bundle</packaging>
<properties>
<test.dynect.endpoint>https://api2.dynect.net/REST</test.dynect.endpoint>
<test.dynect.api-version>3.3.7</test.dynect.api-version>
<test.dynect.build-version></test.dynect.build-version>
<test.dynect.identity></test.dynect.identity>
<test.dynect.credential></test.dynect.credential>
<jclouds.osgi.export>org.jclouds.dynect.v3*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.dynect.endpoint>${test.dynect.endpoint}</test.dynect.endpoint>
<test.dynect.api-version>${test.dynect.api-version}</test.dynect.api-version>
<test.dynect.build-version>${test.dynect.build-version}</test.dynect.build-version>
<test.dynect.identity>${test.dynect.identity}</test.dynect.identity>
<test.dynect.credential>${test.dynect.credential}</test.dynect.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,40 @@
/**
* 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.dynect.v3;
import org.jclouds.dynect.v3.features.SessionApi;
import org.jclouds.rest.annotations.Delegate;
/**
* Provides access to DynECT Managed DNS through the API2 api
* <p/>
*
* @see DynECTAsyncApi
* @see <a href="https://manage.dynect.net/help/docs/api2/rest/"
* />
* @author Adrian Cole
*/
public interface DynECTApi {
/**
* Provides synchronous access to Session features.
*/
@Delegate
SessionApi getSessionApi();
}

View File

@ -0,0 +1,98 @@
/**
* 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.dynect.v3;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.dynect.v3.config.DynECTParserModule;
import org.jclouds.dynect.v3.config.DynECTRestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for DynECT 1.0 API
*
* @author Adrian Cole
*/
public class DynECTApiMetadata extends BaseRestApiMetadata {
public static final String ANONYMOUS_IDENTITY = "ANONYMOUS";
public static final TypeToken<RestContext<DynECTApi, DynECTAsyncApi>> CONTEXT_TOKEN = new TypeToken<RestContext<DynECTApi, DynECTAsyncApi>>() {
private static final long serialVersionUID = 1L;
};
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public DynECTApiMetadata() {
this(new Builder());
}
protected DynECTApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", MINUTES.toMillis(3) + "");
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
protected Builder() {
super(DynECTApi.class, DynECTAsyncApi.class);
id("dynect")
.name("DynECT API2")
.identityName("Username (or " + ANONYMOUS_IDENTITY + " if anonymous)")
.defaultIdentity(ANONYMOUS_IDENTITY)
.credentialName("Password")
.defaultCredential(ANONYMOUS_IDENTITY)
.documentation(URI.create("https://manage.dynect.net/help/docs/api2/rest/"))
.version("3.3.7")
.defaultEndpoint("https://api2.dynect.net/REST")
.defaultProperties(DynECTApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(DynECTParserModule.class)
.add(DynECTRestClientModule.class).build());
}
@Override
public DynECTApiMetadata build() {
return new DynECTApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
}
}

View File

@ -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.dynect.v3;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import javax.ws.rs.Produces;
import org.jclouds.dynect.v3.features.SessionAsyncApi;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Headers;
/**
* Provides access to DynECT Managed DNS through the API2 api
* <p/>
*
* @see DynECTApi
* @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
* @author Adrian Cole
*/
// required for all calls
@Produces(APPLICATION_JSON)
@Headers(keys = "API-Version", values = "{jclouds.api-version}")
public interface DynECTAsyncApi {
/**
* Provides asynchronous access to Session features.
*/
@Delegate
SessionAsyncApi getSessionApi();
}

View File

@ -0,0 +1,44 @@
/**
* 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.dynect.v3;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
public final class DynECTFallbacks {
private DynECTFallbacks() {
}
public static class FalseOn400 implements FutureFallback<Boolean> {
public ListenableFuture<Boolean> create(Throwable t) {
if (returnValueOnCodeOrNull(t, false, equalTo(400)) != null)
return immediateFuture(false);
throw propagate(t);
}
}
}

View File

@ -0,0 +1,80 @@
/**
* 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.dynect.v3;
import java.net.URI;
import java.util.Properties;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
/**
* Implementation of {@link org.jclouds.types.ProviderMetadata} for DynECT Managed DNS.
* @author Adrian Cole
*/
public class DynECTProviderMetadata extends BaseProviderMetadata {
public static Builder builder() {
return new Builder();
}
@Override
public Builder toBuilder() {
return builder().fromProviderMetadata(this);
}
public DynECTProviderMetadata() {
super(builder());
}
public DynECTProviderMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = new Properties();
return properties;
}
public static class Builder extends BaseProviderMetadata.Builder {
protected Builder() {
id("dynect")
.name("DynECT Managed DNS")
.apiMetadata(new DynECTApiMetadata())
.homepage(URI.create("http://dyn.com/dns/dynect-managed-dns/"))
.console(URI.create("https://manage.dynect.net"))
.iso3166Codes("US-CA", "US-VA")
.endpoint("https://api2.dynect.net/REST")
.defaultProperties(DynECTProviderMetadata.defaultProperties());
}
@Override
public DynECTProviderMetadata build() {
return new DynECTProviderMetadata(this);
}
@Override
public Builder fromProviderMetadata(ProviderMetadata in) {
super.fromProviderMetadata(in);
return this;
}
}
}

View File

@ -0,0 +1,63 @@
/**
* 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.dynect.v3.config;
import java.lang.reflect.Type;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.dynect.v3.domain.SessionCredentials;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* @author Adrian Cole
*/
public class DynECTParserModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides
@Singleton
public Map<Type, Object> provideCustomAdapterBindings() {
return new ImmutableMap.Builder<Type, Object>()
.put(SessionCredentials.class, new SessionCredentialsTypeAdapter())
.build();
}
private static class SessionCredentialsTypeAdapter implements JsonSerializer<SessionCredentials> {
@Override
public JsonElement serialize(SessionCredentials src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject metadataObject = new JsonObject();
metadataObject.addProperty("customer_name", src.getCustomerName());
metadataObject.addProperty("user_name", src.getUserName());
metadataObject.addProperty("password", src.getPassword());
return metadataObject;
}
}
}

View File

@ -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.dynect.v3.config;
import java.util.Map;
import org.jclouds.dynect.v3.DynECTApi;
import org.jclouds.dynect.v3.DynECTAsyncApi;
import org.jclouds.dynect.v3.features.SessionApi;
import org.jclouds.dynect.v3.features.SessionAsyncApi;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.collect.ImmutableMap;
/**
* Configures the DynECT connection.
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class DynECTRestClientModule extends RestClientModule<DynECTApi, DynECTAsyncApi> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
.put(SessionApi.class, SessionAsyncApi.class)
.build();
public DynECTRestClientModule() {
super(DELEGATE_MAP);
}
}

View File

@ -0,0 +1,80 @@
/**
* 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, String 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.dynect.v3.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import com.google.common.base.Objects;
/**
* @author Adrian Cole
*/
public final class Session {
public static Session forTokenAndVersion(String token, String version) {
return new Session(token, version);
}
private final String token;
private final String version;
@ConstructorProperties({"token", "version"})
private Session(String token, String version) {
this.token = checkNotNull(token, "token");
this.version = checkNotNull(version, "version for %s", token);
}
/**
* The authentication token
*/
public String getToken() {
return token;
}
/**
* The current version of the server
*/
public String getVersion() {
return version;
}
@Override
public int hashCode() {
return Objects.hashCode(token, version);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Session other = Session.class.cast(obj);
return Objects.equal(this.token, other.token) && Objects.equal(this.version, other.version);
}
@Override
public String toString() {
return Objects.toStringHelper(this).add("token", token).add("version", version).toString();
}
}

View File

@ -0,0 +1,135 @@
package org.jclouds.dynect.v3.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import javax.inject.Named;
import org.jclouds.domain.Credentials;
import com.google.common.base.Objects;
/**
* Session credentials for API authentication.
*
* @see <a href= "https://manage.dynect.net/help/docs/api2/rest/" />
*
* @author Adrian Cole
*/
public final class SessionCredentials extends Credentials {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().from(this);
}
public final static class Builder extends Credentials.Builder<SessionCredentials> {
private String customerName;
private String userName;
private String password;
/**
* @see SessionCredentials#getCustomerName()
*/
public Builder customerName(String customerName) {
this.customerName = customerName;
return this;
}
@Override
public Builder identity(String identity) {
return userName(identity);
}
@Override
public Builder credential(String credential) {
return password(credential);
}
/**
* @see SessionCredentials#getUserName()
*/
public Builder userName(String userName) {
this.userName = userName;
return this;
}
/**
* @see SessionCredentials#getPassword()
*/
public Builder password(String password) {
this.password = password;
return this;
}
public SessionCredentials build() {
return new SessionCredentials(customerName, userName, password);
}
public Builder from(SessionCredentials in) {
return this.userName(in.identity).password(in.credential).customerName(in.customerName);
}
}
@Named("customer_name")
private final String customerName;
@Named("user_name")
private final String userName;
private final String password;
@ConstructorProperties({ "customer_name", "user_name", "password" })
private SessionCredentials(String customerName, String userName, String password) {
super(checkNotNull(userName, "userName"), checkNotNull(password, "password for %s", userName));
this.userName = userName;
this.password = password;
this.customerName = checkNotNull(customerName, "customerName for %s", userName);
}
/**
* UserName ID that identifies the temporary credentials.
*/
public String getUserName() {
return userName;
}
/**
* The Secret Access Key to sign requests.
*/
public String getPassword() {
return password;
}
/**
* The security token that users must pass to the service API to use the
* temporary credentials.
*/
public String getCustomerName() {
return customerName;
}
@Override
public int hashCode() {
return Objects.hashCode(customerName, userName, password);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SessionCredentials other = SessionCredentials.class.cast(obj);
return Objects.equal(this.userName, other.userName) && Objects.equal(this.password, other.password)
&& Objects.equal(this.customerName, other.customerName);
}
@Override
public String toString() {
return Objects.toStringHelper(this).add("userName", identity).add("customerName", customerName).toString();
}
}

View File

@ -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.dynect.v3.features;
import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials;
/**
* @see SessionAsyncApi
* @see <a
* href="https://manage.dynect.net/help/docs/api2/rest/resources/Session.html"
* />
* @author Adrian Cole
*/
public interface SessionApi {
Session login(SessionCredentials credentials);
boolean isValid(String token);
void logout(String token);
}

View File

@ -0,0 +1,78 @@
/**
* 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.dynect.v3.features;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import javax.inject.Named;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.jclouds.dynect.v3.DynECTFallbacks.FalseOn400;
import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to DynECT Managed DNS through the API2 api
* <p/>
*
* @see SessionApi
* @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
* @author Adrian Cole
*/
// required for all calls
@Produces(APPLICATION_JSON)
@Headers(keys = "API-Version", values = "{jclouds.api-version}")
@Path("/Session")
public interface SessionAsyncApi {
/**
* @see SessionApi#create
*/
@Named("POST:Session")
@POST
@SelectJson("data")
ListenableFuture<Session> login(@BinderParam(BindToJsonPayload.class) SessionCredentials credentials);
/**
* @see SessionApi#isValid
*/
@Named("GET:Session")
@GET
@Fallback(FalseOn400.class)
ListenableFuture<Boolean> isValid(@HeaderParam("Auth-Token") String token);
/**
* @see SessionApi#logout
*/
@Named("DELETE:Session")
@DELETE
ListenableFuture<Void> logout(@HeaderParam("Auth-Token") String token);
}

View File

@ -0,0 +1 @@
org.jclouds.dynect.v3.DynECTProviderMetadata

View File

@ -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.dynect.v3;
import org.jclouds.dynect.v3.DynECTApiMetadata;
import org.jclouds.dynect.v3.DynECTProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadataTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "DynECTProviderMetadataTest")
public class DynECTProviderMetadataTest extends BaseProviderMetadataTest {
public DynECTProviderMetadataTest() {
super(new DynECTProviderMetadata(), new DynECTApiMetadata());
}
}

View File

@ -0,0 +1,97 @@
/**
* 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.dynect.v3.features;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.jclouds.dynect.v3.DynECTApi;
import org.jclouds.dynect.v3.domain.SessionCredentials;
import org.jclouds.dynect.v3.internal.BaseDynECTApiExpectTest;
import org.jclouds.dynect.v3.parse.ParseSessionTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SessionApiExpectTest")
public class SessionApiExpectTest extends BaseDynECTApiExpectTest {
private String authToken = "FFFFFFFFFF";
HttpRequest create = HttpRequest.builder().method("POST")
.endpoint("https://api2.dynect.net/REST/Session")
.addHeader("API-Version", "3.3.7")
.payload(payloadFromStringWithContentType("{\"customer_name\":\"jclouds\",\"user_name\":\"joe\",\"password\":\"letmein\"}",APPLICATION_JSON))
.build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/create_session.json", APPLICATION_JSON)).build();
public void testCreateWhenResponseIs2xx() {
DynECTApi apiCreatesSession = requestSendsResponse(create, createResponse);
assertEquals(apiCreatesSession.getSessionApi().login(SessionCredentials.builder()
.customerName("jclouds")
.userName("joe")
.password("letmein").build()).toString(),
new ParseSessionTest().expected().toString());
}
HttpRequest isValid = HttpRequest.builder().method("GET")
.endpoint("https://api2.dynect.net/REST/Session")
.addHeader("API-Version", "3.3.7")
.addHeader("Auth-Token", authToken)
.payload(emptyJsonPayload())
.build();
HttpResponse validResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/session_valid.json", APPLICATION_JSON)).build();
HttpResponse invalidResponse = HttpResponse.builder().statusCode(400)
.payload(payloadFromResourceWithContentType("/session_invalid.json", APPLICATION_JSON)).build();
public void testSessionValid() {
DynECTApi apiWhenValid = requestSendsResponse(isValid, validResponse);
assertTrue(apiWhenValid.getSessionApi().isValid(authToken));
}
public void testSessionInvalid() {
DynECTApi apiWhenInvalid = requestSendsResponse(isValid, invalidResponse);
assertFalse(apiWhenInvalid.getSessionApi().isValid(authToken));
}
HttpRequest logout = HttpRequest.builder().method("DELETE")
.endpoint("https://api2.dynect.net/REST/Session")
.addHeader("API-Version", "3.3.7")
.addHeader("Auth-Token", authToken)
.payload(emptyJsonPayload())
.build();
HttpResponse logoutResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/logout.json", APPLICATION_JSON)).build();
public void testLogout() {
DynECTApi apiWhenLogoutSuccess = requestSendsResponse(logout, logoutResponse);
apiWhenLogoutSuccess.getSessionApi().logout(authToken);
}
}

View File

@ -0,0 +1,63 @@
/**
* 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.dynect.v3.features;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.domain.SessionCredentials;
import org.jclouds.dynect.v3.internal.BaseDynECTApiLiveTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "SessionApiLiveTest")
public class SessionApiLiveTest extends BaseDynECTApiLiveTest {
private Session session;
private void checkSession(Session zone) {
checkNotNull(zone.getToken(), "Token cannot be null for a Session.");
checkNotNull(zone.getVersion(), "Version cannot be null for a Session.");
}
@Test
protected void testCreateSession() {
SessionCredentials credentials = SessionCredentials.builder()
.customerName(identity.substring(0, identity.indexOf(':')))
.userName(identity.substring(identity.indexOf(':') + 1))
.password(credential).build();
session = api().login(credentials);
checkSession(session);
}
protected SessionApi api() {
return context.getApi().getSessionApi();
}
@AfterClass(groups = { "integration", "live" })
@Override
protected void tearDownContext() {
if (session != null)
api().logout(session.getToken());
super.tearDownContext();
}
}

View File

@ -0,0 +1,45 @@
/**
* 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.dynect.v3.internal;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import org.jclouds.dynect.v3.DynECTApi;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
/**
* Base class for writing DynECT Expect tests
*
* @author Adrian Cole
*/
public class BaseDynECTApiExpectTest extends BaseDynECTExpectTest<DynECTApi> {
public static Payload emptyJsonPayload() {
Payload p = Payloads.newByteArrayPayload(new byte[] {});
p.getContentMetadata().setContentType(APPLICATION_JSON);
return p;
}
@Override
protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
return HttpRequestComparisonType.JSON;
}
}

View File

@ -0,0 +1,41 @@
/**
* 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.dynect.v3.internal;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.dynect.v3.DynECTApi;
import org.jclouds.dynect.v3.DynECTApiMetadata;
import org.jclouds.dynect.v3.DynECTAsyncApi;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
@Test(groups = "live")
public class BaseDynECTApiLiveTest extends BaseContextLiveTest<RestContext<DynECTApi, DynECTAsyncApi>> {
public BaseDynECTApiLiveTest() {
provider = "dynect";
}
@Override
protected TypeToken<RestContext<DynECTApi, DynECTAsyncApi>> contextType() {
return DynECTApiMetadata.CONTEXT_TOKEN;
}
}

View File

@ -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.dynect.v3.internal;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
/**
* Base class for writing DynECT Expect tests
*
* @author Adrian Cole
*/
public class BaseDynECTExpectTest<T> extends BaseRestApiExpectTest<T> {
public BaseDynECTExpectTest() {
provider = "dynect";
}
}

View File

@ -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.dynect.v3.internal;
import org.jclouds.dynect.v3.config.DynECTParserModule;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* @author David Alves
*/
public abstract class BaseDynECTParseTest<T> extends BaseItemParserTest<T> {
@Override
protected Injector injector() {
return Guice.createInjector(new GsonModule(), new DynECTParserModule());
}
}

View File

@ -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.dynect.v3.parse;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.dynect.v3.domain.Session;
import org.jclouds.dynect.v3.internal.BaseDynECTParseTest;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseSessionTest extends BaseDynECTParseTest<Session> {
@Override
public String resource() {
return "/create_session.json";
}
@Override
@SelectJson("data")
@Consumes(MediaType.APPLICATION_JSON)
public Session expected() {
return Session.forTokenAndVersion("FFFFFFFFFF", "3.3.7");
}
}

View File

@ -0,0 +1 @@
{"status": "success", "data": {"token": "FFFFFFFFFF", "version": "3.3.7"}, "job_id": 254417252, "msgs": [{"INFO": "login: Login successful", "SOURCE": "BLL", "ERR_CD": null, "LVL": "INFO"}]}

View File

@ -0,0 +1,38 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
</configuration>

View File

@ -0,0 +1 @@
{"status": "success", "data": {}, "job_id": 254506373, "msgs": [{"INFO": "logout: Logout successful", "SOURCE": "BLL", "ERR_CD": null, "LVL": "INFO"}]}

View File

@ -0,0 +1 @@
{"status": "failure", "data": {}, "job_id": 254505048, "msgs": [{"INFO": "login: Bad or expired credentials", "SOURCE": "BLL", "ERR_CD": "INVALID_DATA", "LVL": "ERROR"}, {"INFO": "login: There was a problem with your credentials", "SOURCE": "BLL", "ERR_CD": null, "LVL": "INFO"}]}

View File

@ -0,0 +1 @@
{"status": "success", "data": {}, "job_id": 254504748, "msgs": [{"INFO": "isalive: User session is still active", "SOURCE": "BLL", "ERR_CD": null, "LVL": "INFO"}]}

View File

@ -64,6 +64,7 @@
<module>openstack-quantum</module>
<module>openstack-glance</module>
<module>route53</module>
<module>dynect</module>
<module>aws-route53</module>
</modules>
</project>