issue #1165: add read-only zone api for route53

This commit is contained in:
adriancole 2013-01-21 19:57:16 -08:00
parent fbbce9e430
commit c165fd62b2
44 changed files with 2933 additions and 0 deletions

108
labs/aws-route53/pom.xml Normal file
View File

@ -0,0 +1,108 @@
<?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>aws-route53</artifactId>
<name>jclouds Amazon Route 53 provider</name>
<description>Route 53 targeted to Amazon Web Services</description>
<packaging>bundle</packaging>
<properties>
<test.aws-route53.endpoint>https://route53.amazonaws.com</test.aws-route53.endpoint>
<test.aws-route53.api-version>2012-02-29</test.aws-route53.api-version>
<test.aws-route53.build-version></test.aws-route53.build-version>
<test.aws-route53.identity>${test.aws.identity}</test.aws-route53.identity>
<test.aws-route53.credential>${test.aws.credential}</test.aws-route53.credential>
<jclouds.osgi.export>org.jclouds.aws.route53*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds.labs</groupId>
<artifactId>route53</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.jclouds.labs</groupId>
<artifactId>route53</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</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-log4j</artifactId>
<version>${project.version}</version>
<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.aws-route53.endpoint>${test.aws-route53.endpoint}</test.aws-route53.endpoint>
<test.aws-route53.api-version>${test.aws-route53.api-version}</test.aws-route53.api-version>
<test.aws-route53.build-version>${test.aws-route53.build-version}</test.aws-route53.build-version>
<test.aws-route53.identity>${test.aws-route53.identity}</test.aws-route53.identity>
<test.aws-route53.credential>${test.aws-route53.credential}</test.aws-route53.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,85 @@
/**
* 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.route53;
import java.net.URI;
import java.util.Properties;
import org.jclouds.route53.Route53ApiMetadata;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
/**
* Implementation of @ link org.jclouds.types.ProviderMetadata} for Amazon's Route53
* provider.
*
* @author Adrian Cole
*/
public class AWSRoute53ProviderMetadata extends BaseProviderMetadata {
public static Builder builder() {
return new Builder();
}
@Override
public Builder toBuilder() {
return builder().fromProviderMetadata(this);
}
public AWSRoute53ProviderMetadata() {
super(builder());
}
public AWSRoute53ProviderMetadata(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-route53")
.name("Amazon Route53")
.endpoint("https://route53.amazonaws.com")
.homepage(URI.create("http://aws.amazon.com/route53/"))
.console(URI.create("https://console.aws.amazon.com/route53/home"))
.linkedServices("aws-ec2", "aws-elb", "aws-iam", "aws-route53", "aws-sts", "aws-cloudwatch", "aws-s3",
"aws-sqs", "aws-simpledb")
.iso3166Codes("US-VA")
.apiMetadata(new Route53ApiMetadata())
.defaultProperties(AWSRoute53ProviderMetadata.defaultProperties());
}
@Override
public AWSRoute53ProviderMetadata build() {
return new AWSRoute53ProviderMetadata(this);
}
@Override
public Builder fromProviderMetadata(ProviderMetadata in) {
super.fromProviderMetadata(in);
return this;
}
}
}

View File

@ -0,0 +1 @@
org.jclouds.aws.route53.AWSRoute53ProviderMetadata

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.aws.route53;
import org.jclouds.route53.Route53ApiLiveTest;
import org.testng.annotations.Test;
/**
* Teroute53 behavior of {@code Route53Api}
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "AWSRoute53ApiLiveTest")
public class AWSRoute53ApiLiveTest extends Route53ApiLiveTest {
public AWSRoute53ApiLiveTest() {
provider = "aws-route53";
}
}

View File

@ -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.route53;
import org.jclouds.aws.route53.AWSRoute53ProviderMetadata;
import org.jclouds.route53.Route53ApiMetadata;
import org.jclouds.providers.internal.BaseProviderMetadataTest;
import org.testng.annotations.Test;
/**
* The AWSRoute53ProviderTest teroute53 the org.jclouds.providers.AWSRoute53Provider class.
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "AWSRoute53ProviderTest")
public class AWSRoute53ProviderTest extends BaseProviderMetadataTest {
public AWSRoute53ProviderTest() {
super(new AWSRoute53ProviderMetadata(), new Route53ApiMetadata());
}
}

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.aws.route53.features;
import org.jclouds.route53.features.ZoneApiLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "AWSZoneApiLiveTest")
public class AWSZoneApiLiveTest extends ZoneApiLiveTest {
public AWSZoneApiLiveTest() {
provider = "aws-route53";
}
}

View File

@ -65,5 +65,7 @@
<module>openstack-glance</module> <module>openstack-glance</module>
<module>sts</module> <module>sts</module>
<module>aws-sts</module> <module>aws-sts</module>
<module>route53</module>
<module>aws-route53</module>
</modules> </modules>
</project> </project>

107
labs/route53/pom.xml Normal file
View File

@ -0,0 +1,107 @@
<?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>route53</artifactId>
<name>jcloud route53 api</name>
<description>jclouds components to access an implementation of Route 53</description>
<packaging>bundle</packaging>
<properties>
<test.route53.endpoint>https://route53.amazonaws.com</test.route53.endpoint>
<test.route53.api-version>2012-02-29</test.route53.api-version>
<test.route53.build-version></test.route53.build-version>
<test.route53.identity>${test.aws.identity}</test.route53.identity>
<test.route53.credential>${test.aws.credential}</test.route53.credential>
<jclouds.osgi.export>org.jclouds.route53*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>aws-common</artifactId>
<version>${project.version}</version>
<type>jar</type>
</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-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</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.route53.endpoint>${test.route53.endpoint}</test.route53.endpoint>
<test.route53.api-version>${test.route53.api-version}</test.route53.api-version>
<test.route53.build-version>${test.route53.build-version}</test.route53.build-version>
<test.route53.identity>${test.route53.identity}</test.route53.identity>
<test.route53.credential>${test.route53.credential}</test.route53.credential>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,50 @@
/**
* 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.route53;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.route53.domain.Change;
import org.jclouds.route53.features.ZoneApi;
/**
* Provides access to Amazon Route53 via the Query API
* <p/>
*
* @see Route53AsyncApi
* @see <a href="http://docs.amazonwebservices.com/Route53/latest/APIReference"
* />
* @author Adrian Cole
*/
public interface Route53Api {
/**
* returns the current status of a change batch request.
*
* @param changeID
* The ID of the change batch request.
* @return nulll, if not found
*/
Change getChange(String changeID);
/**
* Provides synchronous access to Zone features.
*/
@Delegate
ZoneApi getZoneApi();
}

View File

@ -0,0 +1,93 @@
/**
* 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.route53;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
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.route53.config.Route53RestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import com.google.common.reflect.TypeToken;
/**
* Implementation of {@link ApiMetadata} for Amazon's Route53 api.
*
* @author Adrian Cole
*/
public class Route53ApiMetadata extends BaseRestApiMetadata {
public static final TypeToken<RestContext<? extends Route53Api, ? extends Route53AsyncApi>> CONTEXT_TOKEN = new TypeToken<RestContext<? extends Route53Api, ? extends Route53AsyncApi>>() {
private static final long serialVersionUID = 1L;
};
@Override
public Builder toBuilder() {
return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
}
public Route53ApiMetadata() {
this(new Builder(Route53Api.class, Route53AsyncApi.class));
}
protected Route53ApiMetadata(Builder builder) {
super(Builder.class.cast(builder));
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + "");
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
protected Builder(Class<?> api, Class<?> asyncApi) {
super(api, asyncApi);
id("route53")
.name("Amazon Route 53 Api")
.identityName("Access Key ID")
.credentialName("Secret Access Key")
.version("2012-02-29")
.documentation(URI.create("http://docs.aws.amazon.com/Route53/latest/APIReference/"))
.defaultEndpoint("https://route53.amazonaws.com")
.defaultProperties(Route53ApiMetadata.defaultProperties())
.defaultModule(Route53RestClientModule.class);
}
@Override
public Route53ApiMetadata build() {
return new Route53ApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
}
}

View File

@ -0,0 +1,67 @@
/**
* 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.route53;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.route53.domain.Change;
import org.jclouds.route53.features.ZoneAsyncApi;
import org.jclouds.route53.filters.RestAuthentication;
import org.jclouds.route53.xml.ChangeHandler;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to Amazon Route53 via the Query API
* <p/>
*
* @see <a href="http://docs.amazonwebservices.com/Route53/latest/APIReference"
* />
* @author Adrian Cole
*/
@RequestFilters(RestAuthentication.class)
@VirtualHost
@Path("/{jclouds.api-version}")
public interface Route53AsyncApi {
/**
* @see Route53Api#getChange()
*/
@Named("GetChange")
@GET
@Path("/change/{changeId}")
@XMLResponseParser(ChangeHandler.class)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<Change> getChange(@PathParam("changeId") String changeID);
/**
* Provides asynchronous access to Zone features.
*/
@Delegate
ZoneAsyncApi getZoneApi();
}

View File

@ -0,0 +1,67 @@
/**
* 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.route53.config;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.util.Date;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.aws.config.AWSRestClientModule;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RequestSigner;
import org.jclouds.route53.Route53Api;
import org.jclouds.route53.Route53AsyncApi;
import org.jclouds.route53.features.ZoneApi;
import org.jclouds.route53.features.ZoneAsyncApi;
import org.jclouds.route53.filters.RestAuthentication;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
/**
* Configures the Route53 connection.
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class Route53RestClientModule extends AWSRestClientModule<Route53Api, Route53AsyncApi> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(ZoneApi.class, ZoneAsyncApi.class).build();
public Route53RestClientModule() {
super(typeToken(Route53Api.class), typeToken(Route53AsyncApi.class), DELEGATE_MAP);
}
@Provides
@TimeStamp
protected String provideTimeStamp(DateService dateService) {
return dateService.rfc1123DateFormat(new Date(System.currentTimeMillis()));
}
@Provides
@Singleton
RequestSigner provideRequestSigner(RestAuthentication in) {
return in;
}
}

View File

@ -0,0 +1,151 @@
/**
* 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.route53.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import com.google.common.base.Objects;
/**
* @author Adrian Cole
*/
public final class Change {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().from(this);
}
public final static class Builder {
private String id;
private Status status;
private Date submittedAt;
/**
* @see Change#getId()
*/
public Builder id(String id) {
this.id = id;
return this;
}
/**
* @see Change#getStatus()
*/
public Builder status(Status status) {
this.status = status;
return this;
}
/**
* @see Change#getSubmittedAt()
*/
public Builder submittedAt(Date submittedAt) {
this.submittedAt = submittedAt;
return this;
}
public Change build() {
return new Change(id, status, submittedAt);
}
public Builder from(Change in) {
return this.id(in.id).status(in.status).submittedAt(in.submittedAt);
}
}
private final String id;
private final Status status;
private final Date submittedAt;
private Change(String id, Status status, Date submittedAt) {
this.id = checkNotNull(id, "id");
this.status = checkNotNull(status, "status for %s", id);
this.submittedAt = checkNotNull(submittedAt, "submittedAt for %s", id);
}
/**
* The ID of the change batch.
*/
public String getId() {
return id;
}
/**
* The current status of the change batch request.
*/
public Status getStatus() {
return status;
}
/**
* The date and time that the change batch request was submitted.
*/
public Date getSubmittedAt() {
return submittedAt;
}
public enum Status {
/**
* indicates that the changes in this request have not replicated to all
* Amazon Route 53 DNS servers.
*/
PENDING,
/**
* indicates that the changes have replicated to all Amazon Route 53 DNS
* servers.
*/
INSYNC, UNRECOGNIZED;
public static Status fromValue(String status) {
try {
return valueOf(checkNotNull(status, "status"));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Change other = (Change) obj;
return Objects.equal(this.id, other.id);
}
@Override
public String toString() {
return Objects.toStringHelper(this).add("id", id).add("status", status).add("submittedAt", submittedAt)
.toString();
}
}

View File

@ -0,0 +1,167 @@
/**
* 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.route53.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
/**
*
* @author Adrian Cole
*/
public final class Zone {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().from(this);
}
public final static class Builder {
private String id;
private String name;
private String callerReference;
private int resourceRecordSetCount = 0;
private Optional<String> comment = Optional.absent();
/**
* @see Zone#getId()
*/
public Builder id(String id) {
this.id = id;
return this;
}
/**
* @see Zone#getName()
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @see Zone#getCallerReference()
*/
public Builder callerReference(String callerReference) {
this.callerReference = callerReference;
return this;
}
/**
* @see Zone#getResourceRecordSetCount()
*/
public Builder resourceRecordSetCount(int resourceRecordSetCount) {
this.resourceRecordSetCount = resourceRecordSetCount;
return this;
}
/**
* @see Zone#getComment()
*/
public Builder comment(String comment) {
this.comment = Optional.fromNullable(comment);
return this;
}
public Zone build() {
return new Zone(id, name, callerReference, resourceRecordSetCount, comment);
}
public Builder from(Zone in) {
return this.id(in.id).name(in.name).callerReference(in.callerReference)
.resourceRecordSetCount(in.resourceRecordSetCount).comment(in.comment.orNull());
}
}
private final String id;
private final String name;
private final String callerReference;
private final int resourceRecordSetCount;
private final Optional<String> comment;
private Zone(String id, String name, String callerReference, int resourceRecordSetCount,
Optional<String> comment) {
this.id = checkNotNull(id, "id");
this.name = checkNotNull(name, "name");
this.callerReference = checkNotNull(callerReference, "callerReference for %s", name);
this.resourceRecordSetCount = checkNotNull(resourceRecordSetCount, "resourceRecordSetCount for %s", name);
this.comment = checkNotNull(comment, "comment for %s", comment);
}
/**
* The ID of the hosted zone.
*/
public String getId() {
return id;
}
/**
* The name of the domain.
*/
public String getName() {
return name;
}
/**
* A unique string that identifies the request to create the hosted zone.
*/
public String getCallerReference() {
return callerReference;
}
/**
* A percentage value that indicates the size of the policy in packed form.
*/
public int getResourceRecordSetCount() {
return resourceRecordSetCount;
}
public Optional<String> getComment() {
return comment;
}
@Override
public int hashCode() {
return Objects.hashCode(id, name, callerReference);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Zone other = (Zone) obj;
return Objects.equal(this.id, other.id) && Objects.equal(this.name, other.name)
&& Objects.equal(this.callerReference, other.callerReference);
}
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("id", id).add("name", name)
.add("callerReference", callerReference).add("resourceRecordSetCount", resourceRecordSetCount)
.add("comment", comment.orNull()).toString();
}
}

View File

@ -0,0 +1,121 @@
/**
* 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.route53.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
public final class ZoneAndNameServers {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().from(this);
}
public final static class Builder {
private Zone zone;
private ImmutableSet.Builder<String> nameServers = ImmutableSet.<String> builder();
/**
* @see ZoneAndNameServers#getZone()
*/
public Builder zone(Zone zone) {
this.zone = zone;
return this;
}
/**
* @see ZoneAndNameServers#getNameServers()
*/
public Builder nameServers(Iterable<String> nameServers) {
this.nameServers = ImmutableSet.<String> builder().addAll(checkNotNull(nameServers, "nameServers"));
return this;
}
/**
* @see ZoneAndNameServers#getNameServers()
*/
public Builder addNameServer(String nameServer) {
this.nameServers.add(checkNotNull(nameServer, "nameServer"));
return this;
}
public ZoneAndNameServers build() {
return new ZoneAndNameServers(zone, nameServers.build());
}
public Builder from(ZoneAndNameServers in) {
return this.zone(in.zone).nameServers(in.nameServers);
}
}
private final Zone zone;
private final ImmutableSet<String> nameServers;
private ZoneAndNameServers(Zone zone, ImmutableSet<String> nameServers) {
this.zone = checkNotNull(zone, "zone");
this.nameServers = checkNotNull(nameServers, "nameServers for %s", zone);
}
/**
* the hosted zone
*/
public Zone getZone() {
return zone;
}
/**
* the authoritative name servers for the hosted zone
*/
public Set<String> getNameServers() {
return nameServers;
}
@Override
public int hashCode() {
return Objects.hashCode(zone, nameServers);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ZoneAndNameServers that = (ZoneAndNameServers) obj;
return Objects.equal(this.zone, that.zone) && Objects.equal(this.nameServers, that.nameServers);
}
@Override
public String toString() {
return Objects.toStringHelper("").add("zone", zone).add("nameServers", nameServers).toString();
}
}

View File

@ -0,0 +1,67 @@
/**
* 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.route53.features;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.domain.ZoneAndNameServers;
import org.jclouds.route53.options.ListZonesOptions;
/**
* @see ZoneAsyncApi
* @see <a href="http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnHostedZones.html" />
* @author Adrian Cole
*/
public interface ZoneApi {
/**
* Retrieves information about the specified zone, including its nameserver configuration
*
* @param name
* Name of the zone to get information about.
* @return null if not found
*/
@Nullable
ZoneAndNameServers get(String name);
/**
* Lists the zones that have the specified path prefix. If there are none, the action returns an
* empty list.
*
* <br/>
* You can paginate the results using the {@link ListZonesOptions parameter}
*
* @param options
* the options describing the zones query
*
* @return the response object
*/
IterableWithMarker<Zone> list(ListZonesOptions options);
/**
* Lists the zones that have the specified path prefix. If there are none, the action returns an
* empty list.
*
* @return the response object
*/
PagedIterable<Zone> list();
}

View File

@ -0,0 +1,85 @@
/**
* 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.route53.features;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.domain.ZoneAndNameServers;
import org.jclouds.route53.filters.RestAuthentication;
import org.jclouds.route53.functions.ZonesToPagedIterable;
import org.jclouds.route53.options.ListZonesOptions;
import org.jclouds.route53.xml.GetHostedZoneResponseHandler;
import org.jclouds.route53.xml.ListHostedZonesResponseHandler;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @see ZoneApi
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnHostedZones.html"
* />
* @author Adrian Cole
*/
@RequestFilters(RestAuthentication.class)
@VirtualHost
@Path("/{jclouds.api-version}")
public interface ZoneAsyncApi {
/**
* @see ZoneApi#get()
*/
@Named("GetHostedZone")
@GET
@Path("{zoneId}")
@XMLResponseParser(GetHostedZoneResponseHandler.class)
@Fallback(NullOnNotFoundOr404.class)
ListenableFuture<ZoneAndNameServers> get(@PathParam("zoneId") String zoneId);
/**
* @see ZoneApi#list()
*/
@Named("ListHostedZones")
@GET
@Path("/hostedzone")
@XMLResponseParser(ListHostedZonesResponseHandler.class)
@Transform(ZonesToPagedIterable.class)
ListenableFuture<PagedIterable<Zone>> list();
/**
* @see ZoneApi#list(ListZonesOptions)
*/
@Named("ListHostedZones")
@GET
@Path("/hostedzone")
@XMLResponseParser(ListHostedZonesResponseHandler.class)
ListenableFuture<IterableWithMarker<Zone>> list(ListZonesOptions options);
}

View File

@ -0,0 +1,118 @@
/**
* 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.route53.filters;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.io.BaseEncoding.base64;
import static com.google.common.io.ByteStreams.readBytes;
import static javax.ws.rs.core.HttpHeaders.DATE;
import static org.jclouds.crypto.Macs.asByteProcessor;
import static org.jclouds.util.Strings2.toInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.aws.domain.TemporaryCredentials;
import org.jclouds.crypto.Crypto;
import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.RequestSigner;
import com.google.common.base.Supplier;
import com.google.common.io.ByteProcessor;
/**
* Signs the Route53 request.
*
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/RESTAuthentication.html#StringToSign"
* />
* @author Adrian Cole
*
*/
@Singleton
public class RestAuthentication implements HttpRequestFilter, RequestSigner {
private final Supplier<Credentials> creds;
private final Provider<String> timeStampProvider;
private final Crypto crypto;
@Inject
public RestAuthentication(@org.jclouds.location.Provider Supplier<Credentials> creds,
@TimeStamp Provider<String> timeStampProvider, Crypto crypto) {
this.creds = creds;
this.timeStampProvider = timeStampProvider;
this.crypto = crypto;
}
public HttpRequest filter(HttpRequest request) throws HttpException {
Credentials current = creds.get();
if (current instanceof TemporaryCredentials) {
request = replaceSecurityTokenHeader(request, TemporaryCredentials.class.cast(current));
}
request = replaceDateHeader(request, timeStampProvider.get());
String signature = sign(createStringToSign(request));
return replaceAuthorizationHeader(request, signature);
}
private HttpRequest replaceSecurityTokenHeader(HttpRequest request, TemporaryCredentials current) {
return request.toBuilder().replaceHeader("x-amz-security-token", current.getSessionToken()).build();
}
private HttpRequest replaceDateHeader(HttpRequest request, String timestamp) {
request = request.toBuilder().replaceHeader(DATE, timestamp).build();
return request;
}
@Override
public String createStringToSign(HttpRequest input) {
return input.getFirstHeaderOrNull(DATE);
}
@Override
public String sign(String toSign) {
try {
ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(creds.get().credential.getBytes(UTF_8)));
return base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
} catch (InvalidKeyException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
}
}
private HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
request = request
.toBuilder()
.replaceHeader("X-Amzn-Authorization",
"AWS3-HTTPS AWSAccessKeyId=" + creds.get().identity + ",Algorithm=HmacSHA256,Signature=" + signature)
.build();
return request;
}
}

View File

@ -0,0 +1,65 @@
/**
* 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.route53.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
import org.jclouds.route53.Route53Api;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.features.ZoneApi;
import org.jclouds.route53.options.ListZonesOptions;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
/**
* @author Adrian Cole
*/
@Beta
public class ZonesToPagedIterable extends CallerArg0ToPagedIterable<Zone, ZonesToPagedIterable> {
private final Route53Api api;
@Inject
protected ZonesToPagedIterable(Route53Api api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Zone>> markerToNextForCallingArg0(String ignored) {
final ZoneApi zoneApi = api.getZoneApi();
return new Function<Object, IterableWithMarker<Zone>>() {
@Override
public IterableWithMarker<Zone> apply(Object input) {
return zoneApi.list(ListZonesOptions.Builder.afterMarker(input.toString()));
}
@Override
public String toString() {
return "listZones()";
}
};
}
}

View File

@ -0,0 +1,121 @@
/**
* 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.route53.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.base.Objects;
import com.google.common.collect.Multimap;
/**
* Options used to list available zones.
*
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/APIReference/API_ListHostedZones.html"
* />
*
* @author Adrian Cole
*/
public class ListZonesOptions extends BaseHttpRequestOptions implements Cloneable {
private Integer maxItems;
private Object afterMarker;
/**
* corresponds to {@link org.jclouds.collect.IterableWithMarker#nextMarker}
*/
public ListZonesOptions afterMarker(Object afterMarker) {
this.afterMarker = afterMarker;
return this;
}
/**
* Use this parameter only when paginating results to indicate the maximum
* number of zone names you want in the response. If there are
* additional zone names beyond the maximum you specify, the
* IsTruncated response element is true.
*/
public ListZonesOptions maxItems(Integer maxItems) {
this.maxItems = maxItems;
return this;
}
public static class Builder {
/**
* @see ListZonesOptions#afterMarker
*/
public static ListZonesOptions afterMarker(Object afterMarker) {
return new ListZonesOptions().afterMarker(afterMarker);
}
/**
* @see ListZonesOptions#maxItems
*/
public static ListZonesOptions maxItems(Integer maxItems) {
return new ListZonesOptions().maxItems(maxItems);
}
}
@Override
public Multimap<String, String> buildQueryParameters() {
Multimap<String, String> params = super.buildQueryParameters();
if (afterMarker != null)
params.put("marker", afterMarker.toString());
if (maxItems != null)
params.put("maxitems", maxItems.toString());
return params;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(afterMarker, maxItems);
}
@Override
public ListZonesOptions clone() {
return new ListZonesOptions().afterMarker(afterMarker).maxItems(maxItems);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ListZonesOptions other = ListZonesOptions.class.cast(obj);
return Objects.equal(this.afterMarker, other.afterMarker) && Objects.equal(this.maxItems, other.maxItems);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("afterMarker", afterMarker).add("maxItems", maxItems).toString();
}
}

View File

@ -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.route53.xml;
import javax.inject.Inject;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.route53.domain.Change;
import org.jclouds.route53.domain.Change.Status;
import org.jclouds.util.SaxUtils;
/**
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/APIReference/API_GetChange.html"
* />
*
* @author Adrian Cole
*/
public class ChangeHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Change> {
private final DateService dateService;
@Inject
protected ChangeHandler(DateService dateService) {
this.dateService = dateService;
}
private StringBuilder currentText = new StringBuilder();
private Change.Builder builder = Change.builder();
@Override
public Change getResult() {
try {
return builder.build();
} finally {
builder = Change.builder();
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (qName.equals("Id")) {
builder.id(SaxUtils.currentOrNull(currentText));
} else if (qName.equals("Status")) {
builder.status(Status.fromValue(SaxUtils.currentOrNull(currentText)));
} else if (qName.equals("SubmittedAt")) {
builder.submittedAt(dateService.iso8601DateParse(SaxUtils.currentOrNull(currentText)));
}
currentText = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -0,0 +1,93 @@
/**
* 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.route53.xml;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.route53.domain.ZoneAndNameServers;
import org.jclouds.util.SaxUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
/**
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/APIReference/API_GetHostedZone.html"
* />
*
* @author Adrian Cole
*/
public class GetHostedZoneResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<ZoneAndNameServers> {
private final ZoneHandler zoneHandler;
private StringBuilder currentText = new StringBuilder();
private ZoneAndNameServers.Builder builder = ZoneAndNameServers.builder();
private boolean inZone;
@Inject
public GetHostedZoneResponseHandler(ZoneHandler zoneHandler) {
this.zoneHandler = zoneHandler;
}
@Override
public ZoneAndNameServers getResult() {
try {
return builder.build();
} finally {
builder = ZoneAndNameServers.builder();
}
}
@Override
public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
if (SaxUtils.equalsOrSuffix(qName, "HostedZone")) {
inZone = true;
}
if (inZone) {
zoneHandler.startElement(url, name, qName, attributes);
}
}
@Override
public void endElement(String uri, String name, String qName) throws SAXException {
if (inZone) {
if (qName.equals("HostedZone")) {
inZone = false;
builder.zone(zoneHandler.getResult());
} else {
zoneHandler.endElement(uri, name, qName);
}
} else if (qName.equals("NameServer")) {
builder.addNameServer(SaxUtils.currentOrNull(currentText));
}
currentText = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
if (inZone) {
zoneHandler.characters(ch, start, length);
} else {
currentText.append(ch, start, length);
}
}
}

View File

@ -0,0 +1,112 @@
/**
* 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.route53.xml;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.IterableWithMarkers;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.route53.domain.Zone;
import org.jclouds.util.SaxUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.inject.Inject;
/**
* @see <a href=
* "http://docs.aws.amazon.com/Route53/latest/APIReference/API_ListHostedZones.html"
* />
*
* @author Adrian Cole
*/
public class ListHostedZonesResponseHandler extends
ParseSax.HandlerForGeneratedRequestWithResult<IterableWithMarker<Zone>> {
private final ZoneHandler zoneHandler;
private StringBuilder currentText = new StringBuilder();
private Builder<Zone> zones = ImmutableList.<Zone> builder();
private boolean inZones;
private String afterMarker;
@Inject
public ListHostedZonesResponseHandler(ZoneHandler zoneHandler) {
this.zoneHandler = zoneHandler;
}
/**
* {@inheritDoc}
*/
@Override
public IterableWithMarker<Zone> getResult() {
try {
return IterableWithMarkers.from(zones.build(), afterMarker);
} finally {
zones = ImmutableList.<Zone> builder();
}
}
/**
* {@inheritDoc}
*/
@Override
public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
if (SaxUtils.equalsOrSuffix(qName, "HostedZones")) {
inZones = true;
}
if (inZones) {
zoneHandler.startElement(url, name, qName, attributes);
}
}
/**
* {@inheritDoc}
*/
@Override
public void endElement(String uri, String name, String qName) throws SAXException {
if (inZones) {
if (qName.equals("HostedZones")) {
inZones = false;
} else if (qName.equals("HostedZone")) {
zones.add(zoneHandler.getResult());
} else {
zoneHandler.endElement(uri, name, qName);
}
} else if (qName.equals("NextMarker")) {
afterMarker = SaxUtils.currentOrNull(currentText);
}
currentText = new StringBuilder();
}
/**
* {@inheritDoc}
*/
@Override
public void characters(char ch[], int start, int length) {
if (inZones) {
zoneHandler.characters(ch, start, length);
} else {
currentText.append(ch, start, length);
}
}
}

View File

@ -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.route53.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.route53.domain.Zone;
/**
*
* @author Adrian Cole
*/
public class ZoneHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Zone> {
private StringBuilder currentText = new StringBuilder();
private Zone.Builder builder = Zone.builder();
/**
* {@inheritDoc}
*/
@Override
public Zone getResult() {
try {
return builder.build();
} finally {
builder = Zone.builder();
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (qName.equals("Id")) {
builder.id(currentOrNull(currentText));
} else if (qName.equals("Name")) {
builder.name(currentOrNull(currentText));
} else if (qName.equals("CallerReference")) {
builder.callerReference(currentOrNull(currentText));
} else if (qName.equals("Comment")) {
builder.comment(currentOrNull(currentText));
} else if (qName.equals("ResourceRecordSetCount")) {
builder.resourceRecordSetCount(Integer.parseInt(currentOrNull(currentText)));
}
currentText = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -0,0 +1 @@
org.jclouds.route53.Route53ApiMetadata

View File

@ -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
*
* 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.route53;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.route53.internal.BaseRoute53ApiExpectTest;
import org.jclouds.route53.parse.GetChangeResponseTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "Route53ApiExpectTest")
public class Route53ApiExpectTest extends BaseRoute53ApiExpectTest {
HttpRequest getChange = HttpRequest.builder().method("GET")
.endpoint("https://route53.amazonaws.com/2012-02-29/change/C2682N5HXP0BZ4")
.addHeader("Host", "route53.amazonaws.com")
.addHeader("Date", "Mon, 21 Jan 02013 19:29:03 -0800")
.addHeader("X-Amzn-Authorization",
"AWS3-HTTPS AWSAccessKeyId=identity,Algorithm=HmacSHA256,Signature=pylxNiLcrsjNRZOsxyT161JCwytVPHyc2rFfmNCuZKI=")
.build();
HttpResponse getChangeResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/change.xml", "text/xml")).build();
public void testGetChangeWhenResponseIs2xx() {
Route53Api api = requestSendsResponse(getChange, getChangeResponse);
assertEquals(api.getChange("C2682N5HXP0BZ4").toString(), new GetChangeResponseTest().expected().toString());
}
HttpResponse notFound = HttpResponse.builder().statusCode(404).build();
public void testGetChangeNullWhenResponseIs404() {
Route53Api api = requestSendsResponse(getChange, notFound);
assertNull(api.getChange("C2682N5HXP0BZ4"));
}
}

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.route53;
import static org.testng.Assert.assertNull;
import org.jclouds.route53.internal.BaseRoute53ApiLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "Route53ApiLiveTest")
public class Route53ApiLiveTest extends BaseRoute53ApiLiveTest {
@Test
protected void testGetChangeReturnsNullOnNotFound() {
assertNull(api().getChange("FOOOBAR"));
}
protected Route53Api api() {
return context.getApi();
}
}

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.route53;
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 = "Route53ApiMetadataTest")
public class Route53ApiMetadataTest extends BaseRestApiMetadataTest {
// no tenant abstraction, yet
public Route53ApiMetadataTest() {
super(new Route53ApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
}
}

View File

@ -0,0 +1,113 @@
/**
* 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.route53.features;
import static org.jclouds.route53.options.ListZonesOptions.Builder.afterMarker;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.route53.Route53Api;
import org.jclouds.route53.internal.BaseRoute53ApiExpectTest;
import org.jclouds.route53.parse.GetHostedZoneResponseTest;
import org.jclouds.route53.parse.ListHostedZonesResponseTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ZoneApiExpectTest")
public class ZoneApiExpectTest extends BaseRoute53ApiExpectTest {
HttpRequest get = HttpRequest.builder().method("GET")
.endpoint("https://route53.amazonaws.com/2012-02-29//hostedzone/Z1XTHCPEFRWV1X")
.addHeader("Host", "route53.amazonaws.com")
.addHeader("Date", "Mon, 21 Jan 02013 19:29:03 -0800")
.addHeader("X-Amzn-Authorization",
"AWS3-HTTPS AWSAccessKeyId=identity,Algorithm=HmacSHA256,Signature=pylxNiLcrsjNRZOsxyT161JCwytVPHyc2rFfmNCuZKI=")
.build();
HttpResponse getResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/hosted_zone.xml", "text/xml")).build();
public void testGetWhenResponseIs2xx() {
Route53Api apiWhenExist = requestSendsResponse(get, getResponse);
assertEquals(apiWhenExist.getZoneApi().get("/hostedzone/Z1XTHCPEFRWV1X").toString(), new GetHostedZoneResponseTest().expected()
.toString());
}
HttpResponse notFound = HttpResponse.builder().statusCode(404).build();
public void testGetWhenResponseIs404() {
Route53Api apiWhenDontExist = requestSendsResponse(get, notFound);
assertNull(apiWhenDontExist.getZoneApi().get("/hostedzone/Z1XTHCPEFRWV1X"));
}
HttpRequest list = HttpRequest.builder().method("GET")
.endpoint("https://route53.amazonaws.com/2012-02-29/hostedzone")
.addHeader("Host", "route53.amazonaws.com")
.addHeader("Date", "Mon, 21 Jan 02013 19:29:03 -0800")
.addHeader("X-Amzn-Authorization",
"AWS3-HTTPS AWSAccessKeyId=identity,Algorithm=HmacSHA256,Signature=pylxNiLcrsjNRZOsxyT161JCwytVPHyc2rFfmNCuZKI=")
.build();
HttpResponse listResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/hosted_zones.xml", "text/xml")).build();
public void testListWhenResponseIs2xx() {
Route53Api apiWhenExist = requestSendsResponse(list, listResponse);
assertEquals(apiWhenExist.getZoneApi().list().get(0).toString(), new ListHostedZonesResponseTest().expected()
.toString());
}
// TODO: this should really be an empty set
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testListWhenResponseIs404() {
Route53Api apiWhenDontExist = requestSendsResponse(list, notFound);
assertEquals(apiWhenDontExist.getZoneApi().list().get(0).toSet(), ImmutableSet.of());
}
HttpRequest listWithOptions = HttpRequest.builder().method("GET")
.endpoint("https://route53.amazonaws.com/2012-02-29/hostedzone?marker=Z333333YYYYYYY")
.addHeader("Host", "route53.amazonaws.com")
.addHeader("Date", "Mon, 21 Jan 02013 19:29:03 -0800")
.addHeader("X-Amzn-Authorization",
"AWS3-HTTPS AWSAccessKeyId=identity,Algorithm=HmacSHA256,Signature=pylxNiLcrsjNRZOsxyT161JCwytVPHyc2rFfmNCuZKI=")
.build();
public void testListWithOptionsWhenResponseIs2xx() {
Route53Api apiWhenWithOptionsExist = requestSendsResponse(listWithOptions, listResponse);
assertEquals(apiWhenWithOptionsExist.getZoneApi().list(afterMarker("Z333333YYYYYYY")).toString(),
new ListHostedZonesResponseTest().expected().toString());
}
public void testList2PagesWhenResponseIs2xx() {
HttpResponse noMore = HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("<ListHostedZonesResponse />", "text/xml")).build();
Route53Api apiWhenExist = requestsSendResponses(list, listResponse, listWithOptions, noMore);
assertEquals(apiWhenExist.getZoneApi().list().concat().toString(), new ListHostedZonesResponseTest().expected()
.toString());
}
}

View File

@ -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.route53.features;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.internal.BaseRoute53ApiLiveTest;
import org.jclouds.route53.options.ListZonesOptions;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ZoneApiLiveTest")
public class ZoneApiLiveTest extends BaseRoute53ApiLiveTest {
private void checkZone(Zone zone) {
checkNotNull(zone.getId(), "Id cannot be null for a Zone.");
checkNotNull(zone.getName(), "Id cannot be null for a Zone.");
checkNotNull(zone.getCallerReference(), "CallerReference cannot be null for a Zone.");
checkNotNull(zone.getComment(), "While Comment can be null for a Zone, its Optional wrapper cannot.");
}
@Test
protected void testListZones() {
IterableWithMarker<Zone> response = api().list().get(0);
for (Zone zone : response) {
checkZone(zone);
}
if (Iterables.size(response) > 0) {
Zone zone = response.iterator().next();
Assert.assertEquals(api().get(zone.getId()).getZone(), zone);
}
// Test with a Marker, even if it's null
response = api().list(ListZonesOptions.Builder.afterMarker(response.nextMarker().orNull()));
for (Zone zone : response) {
checkZone(zone);
}
}
protected ZoneApi api() {
return context.getApi().getZoneApi();
}
}

View File

@ -0,0 +1,36 @@
/**
* 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.route53.filters;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code RestAuthentication}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "RestAuthenticationTest")
public class RestAuthenticationTest {
@Test
void test() {
}
}

View File

@ -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.route53.internal;
import org.jclouds.route53.Route53Api;
/**
*
* @author Adrian Cole
*/
public class BaseRoute53ApiExpectTest extends BaseRoute53ExpectTest<Route53Api> {
}

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.route53.internal;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.route53.Route53ApiMetadata;
import org.jclouds.route53.Route53AsyncApi;
import org.jclouds.route53.Route53Api;
import org.jclouds.rest.RestContext;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BaseRoute53ApiLiveTest extends
BaseContextLiveTest<RestContext<? extends Route53Api, ? extends Route53AsyncApi>> {
public BaseRoute53ApiLiveTest() {
provider = "route53";
}
@Override
protected TypeToken<RestContext<? extends Route53Api, ? extends Route53AsyncApi>> contextType() {
return Route53ApiMetadata.CONTEXT_TOKEN;
}
}

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.route53.internal;
import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.route53.Route53AsyncApi;
import com.google.common.base.Function;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BaseRoute53AsyncApiExpectTest extends BaseRoute53ExpectTest<Route53AsyncApi> {
public Route53AsyncApi createApi(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return createInjector(fn, module, props).getInstance(Route53AsyncApi.class);
}
}

View File

@ -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.route53.internal;
import org.jclouds.date.DateService;
import org.jclouds.route53.config.Route53RestClientModule;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class BaseRoute53ExpectTest<T> extends BaseRestApiExpectTest<T> {
public BaseRoute53ExpectTest() {
provider = "route53";
}
@ConfiguresRestClient
private static final class TestRoute53RestClientModule extends Route53RestClientModule {
@Override
protected String provideTimeStamp(final DateService dateService) {
return "Mon, 21 Jan 02013 19:29:03 -0800";
}
}
@Override
protected Module createModule() {
return new TestRoute53RestClientModule();
}
}

View File

@ -0,0 +1,56 @@
/**
* 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.route53.options;
import static org.jclouds.route53.options.ListZonesOptions.Builder.afterMarker;
import static org.jclouds.route53.options.ListZonesOptions.Builder.maxItems;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code ListZonesOptions}
*
* @author Adrian Cole
*/
@Test(groups = "maxItems", testName = "ListZonesOptionsTest")
public class ListZonesOptionsTest {
public void testMarker() {
ListZonesOptions options = new ListZonesOptions().afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildQueryParameters().get("marker"));
}
public void testMarkerStatic() {
ListZonesOptions options = afterMarker("FFFFF");
assertEquals(ImmutableSet.of("FFFFF"), options.buildQueryParameters().get("marker"));
}
public void testMaxItems() {
ListZonesOptions options = new ListZonesOptions().maxItems(1000);
assertEquals(ImmutableSet.of("1000"), options.buildQueryParameters().get("maxitems"));
}
public void testMaxItemsStatic() {
ListZonesOptions options = maxItems(1000);
assertEquals(ImmutableSet.of("1000"), options.buildQueryParameters().get("maxitems"));
}
}

View File

@ -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.route53.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.route53.domain.Change;
import org.jclouds.route53.domain.Change.Status;
import org.jclouds.route53.xml.ChangeHandler;
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 = "GetChangeResponseTest")
public class GetChangeResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/change.xml");
Change expected = expected();
ChangeHandler handler = injector.getInstance(ChangeHandler.class);
Change result = factory.create(handler).parse(is);
assertEquals(result, expected);
assertEquals(result.getStatus(), expected.getStatus());
assertEquals(result.getSubmittedAt(), expected.getSubmittedAt());
}
public Change expected() {
return Change.builder()
.id("C2682N5HXP0BZ4")
.status(Status.INSYNC)
.submittedAt(new SimpleDateFormatDateService().iso8601DateParse("2011-09-10T01:36:41.958Z"))
.build();
}
}

View File

@ -0,0 +1,61 @@
/**
* 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.route53.parse;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.domain.ZoneAndNameServers;
import org.jclouds.route53.xml.GetHostedZoneResponseHandler;
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 = "GetHostedZoneResponseTest")
public class GetHostedZoneResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/hosted_zone.xml");
ZoneAndNameServers expected = expected();
GetHostedZoneResponseHandler handler = injector.getInstance(GetHostedZoneResponseHandler.class);
ZoneAndNameServers result = factory.create(handler).parse(is);
assertEquals(result, expected);
}
public ZoneAndNameServers expected() {
return ZoneAndNameServers.builder()
.addNameServer("ns-1638.awsdns-12.co.uk")
.addNameServer("ns-144.awsdns-18.com")
.addNameServer("ns-781.awsdns-33.net")
.addNameServer("ns-1478.awsdns-56.org")
.zone(Zone.builder()
.id("/hostedzone/Z21DW1QVGID6NG")
.name("example.com.")
.callerReference("a_unique_reference")
.comment("Migrate an existing domain to Route 53").build()).build();
}
}

View File

@ -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.route53.parse;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.IterableWithMarkers;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.route53.domain.Zone;
import org.jclouds.route53.xml.ListHostedZonesResponseHandler;
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 = "ListHostedZonesResponseTest")
public class ListHostedZonesResponseTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/hosted_zones.xml");
IterableWithMarker<Zone> expected = expected();
ListHostedZonesResponseHandler handler = injector.getInstance(ListHostedZonesResponseHandler.class);
IterableWithMarker<Zone> result = factory.create(handler).parse(is);
assertEquals(result.toString(), expected.toString());
}
public IterableWithMarker<Zone> expected() {
return IterableWithMarkers.from(
ImmutableSet.of(
Zone.builder()
.id("/hostedzone/Z21DW1QVGID6NG")
.name("example.com.")
.callerReference("a_unique_reference")
.resourceRecordSetCount(17)
.comment("Migrate an existing domain to Route 53").build(),
Zone.builder()
.id("/hostedzone/Z2682N5HXP0BZ4")
.name("example2.com.")
.callerReference("a_unique_reference2")
.resourceRecordSetCount(117)
.comment("This is my 2nd hosted zone.").build()), "Z333333YYYYYYY");
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<GetChangeResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
<ChangeInfo>
<Id>C2682N5HXP0BZ4</Id>
<Status>INSYNC</Status>
<SubmittedAt>2011-09-10T01:36:41.958Z</SubmittedAt>
</ChangeInfo>
</GetChangeResponse>

View File

@ -0,0 +1,23 @@
<CreateHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2010-10-01/">
<HostedZone>
<Id>/hostedzone/Z21DW1QVGID6NG</Id>
<Name>example.com.</Name>
<CallerReference>a_unique_reference</CallerReference>
<Config>
<Comment>Migrate an existing domain to Route 53</Comment>
</Config>
</HostedZone>
<ChangeInfo>
<Id>/change/C24LD0DUV5VOVE</Id>
<Status>PENDING</Status>
<SubmittedAt>2010-12-02T01:34:20.633Z</SubmittedAt>
</ChangeInfo>
<DelegationSet>
<NameServers>
<NameServer>ns-1638.awsdns-12.co.uk</NameServer>
<NameServer>ns-144.awsdns-18.com</NameServer>
<NameServer>ns-781.awsdns-33.net</NameServer>
<NameServer>ns-1478.awsdns-56.org</NameServer>
</NameServers>
</DelegationSet>
</CreateHostedZoneResponse>

View File

@ -0,0 +1,18 @@
<GetHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
<HostedZone>
<Id>/hostedzone/Z21DW1QVGID6NG</Id>
<Name>example.com.</Name>
<CallerReference>a_unique_reference</CallerReference>
<Config>
<Comment>Migrate an existing domain to Route 53</Comment>
</Config>
</HostedZone>
<DelegationSet>
<NameServers>
<NameServer>ns-1638.awsdns-12.co.uk</NameServer>
<NameServer>ns-144.awsdns-18.com</NameServer>
<NameServer>ns-781.awsdns-33.net</NameServer>
<NameServer>ns-1478.awsdns-56.org</NameServer>
</NameServers>
</DelegationSet>
</GetHostedZoneResponse>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<ListHostedZonesResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
<HostedZones>
<HostedZone>
<Id>/hostedzone/Z21DW1QVGID6NG</Id>
<Name>example.com.</Name>
<CallerReference>a_unique_reference</CallerReference>
<Config>
<Comment>Migrate an existing domain to Route 53</Comment>
</Config>
<ResourceRecordSetCount>17</ResourceRecordSetCount>
</HostedZone>
<HostedZone>
<Id>/hostedzone/Z2682N5HXP0BZ4</Id>
<Name>example2.com.</Name>
<CallerReference>a_unique_reference2</CallerReference>
<Config>
<Comment>This is my 2nd hosted zone.</Comment>
</Config>
<ResourceRecordSetCount>117</ResourceRecordSetCount>
</HostedZone>
</HostedZones>
<Marker>Z222222VVVVVVV</Marker>
<IsTruncated>true</IsTruncated>
<NextMarker>Z333333YYYYYYY</NextMarker>
<MaxItems>10</MaxItems>
</ListHostedZonesResponse>

View File

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache
Log4j website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="BLOBSTOREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-blobstore.log" />
<param name="Append" value="true" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-ssh.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE" />
</appender>
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="SSHFILE" />
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<appender name="ASYNCBLOBSTORE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="BLOBSTOREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.ssh">
<priority value="DEBUG" />
<appender-ref ref="ASYNCSSH" />
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.blobstore">
<priority value="DEBUG" />
<appender-ref ref="ASYNCBLOBSTORE" />
</category>
<category name="jclouds.compute">
<priority value="TRACE" />
<appender-ref ref="ASYNCCOMPUTE" />
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>