From b822dc405baf15a3ae3771d6ced6899edbd74311 Mon Sep 17 00:00:00 2001 From: adriancole Date: Mon, 28 Jan 2013 18:50:14 -0800 Subject: [PATCH] added list api for route53 resource record sets --- .../AWSResourceRecordSetApiLiveTest.java | 32 +++ .../java/org/jclouds/route53/Route53Api.java | 9 + .../org/jclouds/route53/Route53AsyncApi.java | 7 + .../route53/binders/BindNextRecord.java | 45 ++++ .../config/Route53RestClientModule.java | 5 +- .../route53/domain/ResourceRecordSet.java | 167 +++++++++++++++ .../domain/ResourceRecordSetIterable.java | 196 ++++++++++++++++++ .../features/ResourceRecordSetApi.java | 54 +++++ .../features/ResourceRecordSetAsyncApi.java | 80 +++++++ .../org/jclouds/route53/features/ZoneApi.java | 13 +- .../ResourceRecordSetsToPagedIterable.java | 65 ++++++ ...ListResourceRecordSetsResponseHandler.java | 101 +++++++++ .../route53/xml/ResourceRecordSetHandler.java | 68 ++++++ .../jclouds/route53/Route53ApiExpectTest.java | 2 - .../ResourceRecordSetApiExpectTest.java | 88 ++++++++ .../ResourceRecordSetApiLiveTest.java | 64 ++++++ .../route53/features/ZoneApiExpectTest.java | 2 - .../route53/features/ZoneApiLiveTest.java | 5 +- .../internal/BaseRoute53ApiExpectTest.java | 3 +- .../route53/options/ListZonesOptionsTest.java | 2 +- .../ListResourceRecordSetsResponseTest.java | 72 +++++++ labs/route53/src/test/resources/rrsets.xml | 39 ++++ 22 files changed, 1100 insertions(+), 19 deletions(-) create mode 100644 labs/aws-route53/src/test/java/org/jclouds/aws/route53/features/AWSResourceRecordSetApiLiveTest.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/binders/BindNextRecord.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSet.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSetIterable.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/functions/ResourceRecordSetsToPagedIterable.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/xml/ListResourceRecordSetsResponseHandler.java create mode 100644 labs/route53/src/main/java/org/jclouds/route53/xml/ResourceRecordSetHandler.java create mode 100644 labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiExpectTest.java create mode 100644 labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiLiveTest.java create mode 100644 labs/route53/src/test/java/org/jclouds/route53/parse/ListResourceRecordSetsResponseTest.java create mode 100644 labs/route53/src/test/resources/rrsets.xml diff --git a/labs/aws-route53/src/test/java/org/jclouds/aws/route53/features/AWSResourceRecordSetApiLiveTest.java b/labs/aws-route53/src/test/java/org/jclouds/aws/route53/features/AWSResourceRecordSetApiLiveTest.java new file mode 100644 index 0000000000..7d6e517f4d --- /dev/null +++ b/labs/aws-route53/src/test/java/org/jclouds/aws/route53/features/AWSResourceRecordSetApiLiveTest.java @@ -0,0 +1,32 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.aws.route53.features; + +import org.jclouds.route53.features.ResourceRecordSetApiLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "AWSResourceRecordSetApiLiveTest") +public class AWSResourceRecordSetApiLiveTest extends ResourceRecordSetApiLiveTest { + public AWSResourceRecordSetApiLiveTest() { + provider = "aws-route53"; + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/Route53Api.java b/labs/route53/src/main/java/org/jclouds/route53/Route53Api.java index a10f438fb7..f981f7c595 100644 --- a/labs/route53/src/main/java/org/jclouds/route53/Route53Api.java +++ b/labs/route53/src/main/java/org/jclouds/route53/Route53Api.java @@ -20,9 +20,12 @@ package org.jclouds.route53; import java.util.concurrent.TimeUnit; +import javax.ws.rs.PathParam; + import org.jclouds.concurrent.Timeout; import org.jclouds.rest.annotations.Delegate; import org.jclouds.route53.domain.Change; +import org.jclouds.route53.features.ResourceRecordSetApi; import org.jclouds.route53.features.ZoneApi; /** @@ -51,4 +54,10 @@ public interface Route53Api { */ @Delegate ZoneApi getZoneApi(); + + /** + * Provides synchronous access to ResourceRecordSet features. + */ + @Delegate + ResourceRecordSetApi getResourceRecordSetApiForZone(@PathParam("zoneId") String zoneId); } diff --git a/labs/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java b/labs/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java index 79019d9422..edf09ee1b1 100644 --- a/labs/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java +++ b/labs/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java @@ -30,6 +30,7 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.route53.domain.Change; +import org.jclouds.route53.features.ResourceRecordSetAsyncApi; import org.jclouds.route53.features.ZoneAsyncApi; import org.jclouds.route53.filters.RestAuthentication; import org.jclouds.route53.xml.ChangeHandler; @@ -64,4 +65,10 @@ public interface Route53AsyncApi { */ @Delegate ZoneAsyncApi getZoneApi(); + + /** + * Provides asynchronous access to ResourceRecordSet features. + */ + @Delegate + ResourceRecordSetAsyncApi getResourceRecordSetApiForZone(@PathParam("zoneId") String zoneId); } diff --git a/labs/route53/src/main/java/org/jclouds/route53/binders/BindNextRecord.java b/labs/route53/src/main/java/org/jclouds/route53/binders/BindNextRecord.java new file mode 100644 index 0000000000..ef024c88b4 --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/binders/BindNextRecord.java @@ -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.route53.binders; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequest.Builder; +import org.jclouds.rest.Binder; +import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindNextRecord implements Binder { + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Object payload) { + NextRecord from = NextRecord.class.cast(payload); + Builder builder = request.toBuilder(); + builder.addQueryParam("name", from.getName()); + builder.addQueryParam("type", from.getType().toString()); + if (from.getIdentifier().isPresent()) + builder.addQueryParam("identifier", from.getIdentifier().get()); + return (R) builder.build(); + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java b/labs/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java index 29b0dbe2e0..adca0446d1 100644 --- a/labs/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java +++ b/labs/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java @@ -30,6 +30,8 @@ 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.ResourceRecordSetApi; +import org.jclouds.route53.features.ResourceRecordSetAsyncApi; import org.jclouds.route53.features.ZoneApi; import org.jclouds.route53.features.ZoneAsyncApi; import org.jclouds.route53.filters.RestAuthentication; @@ -46,7 +48,8 @@ import com.google.inject.Provides; @ConfiguresRestClient public class Route53RestClientModule extends AWSRestClientModule { public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// - .put(ZoneApi.class, ZoneAsyncApi.class).build(); + .put(ZoneApi.class, ZoneAsyncApi.class) + .put(ResourceRecordSetApi.class, ResourceRecordSetAsyncApi.class).build(); public Route53RestClientModule() { super(TypeToken.of(Route53Api.class), TypeToken.of(Route53AsyncApi.class), DELEGATE_MAP); diff --git a/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSet.java b/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSet.java new file mode 100644 index 0000000000..a27e31e6cd --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSet.java @@ -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.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ForwardingList; +import com.google.common.collect.ImmutableList; + +/** + * + * @author Adrian Cole + */ +public final class ResourceRecordSet extends ForwardingList { + + private final String name; + private final Type type; + private final Optional ttl; + private final ImmutableList items; + + private ResourceRecordSet(String name, Type type, Optional ttl, ImmutableList items) { + this.name = checkNotNull(name, "name"); + this.type = checkNotNull(type, "type of %s", name); + this.ttl = checkNotNull(ttl, "ttl for %s", name); + this.items = checkNotNull(items, "items for %s", name); + } + + /** + * The name of the domain. + */ + public String getName() { + return name; + } + + /** + * The resource record set type. + */ + public Type getType() { + return type; + } + + /** + * Present in all resource record sets except aliases. The resource record + * cache time to live (TTL), in seconds. + */ + public Optional getTTL() { + return ttl; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, type, ttl, items); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + ResourceRecordSet other = ResourceRecordSet.class.cast(obj); + return equal(this.name, other.name) && equal(this.type, other.type) && equal(this.ttl, other.ttl) + && equal(this.items, other.items); + } + + @Override + public String toString() { + return toStringHelper("").omitNullValues().add("name", name).add("type", type).add("ttl", ttl.orNull()) + .add("resourceRecords", items).toString(); + } + + @Override + protected List delegate() { + return items; + } + + public enum Type { + A, AAAA, CNAME, MX, NS, PTR, SOA, SPF, SRV, TXT, UNRECOGNIZED; + + public static Type fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().from(this); + } + + public final static class Builder { + private String name; + private Type type; + private Optional ttl = Optional.absent(); + private ImmutableList.Builder items = ImmutableList. builder(); + + /** + * @see ResourceRecordSet#getName() + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @see ResourceRecordSet#getType() + */ + public Builder type(Type type) { + this.type = type; + return this; + } + + /** + * @see ResourceRecordSet#getTTL() + */ + public Builder ttl(Integer ttl) { + this.ttl = Optional.fromNullable(ttl); + return this; + } + + public Builder add(String item) { + this.items.add(item); + return this; + } + + public Builder addAll(Iterable items) { + this.items.addAll(items); + return this; + } + + public ResourceRecordSet build() { + return new ResourceRecordSet(name, type, ttl, items.build()); + } + + public Builder from(ResourceRecordSet in) { + return this.name(in.name).type(in.type).ttl(in.ttl.orNull()).addAll(in.items); + } + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSetIterable.java b/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSetIterable.java new file mode 100644 index 0000000000..0e7448a4e2 --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/domain/ResourceRecordSetIterable.java @@ -0,0 +1,196 @@ +/* + * 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.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Iterator; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.route53.domain.ResourceRecordSet.Type; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; + +/** + * + * @author Adrian Cole + */ +public class ResourceRecordSetIterable extends IterableWithMarker { + + private final Iterable items; + private final Optional nextRecord; + + private ResourceRecordSetIterable(Iterable items, @Nullable NextRecord nextRecord) { + this.items = checkNotNull(items, "items"); + this.nextRecord = Optional.fromNullable(nextRecord); + } + + /** + * present when the list is not truncated + */ + public Optional nextRecord() { + return nextRecord; + } + + @SuppressWarnings("unchecked") + @Override + public Optional nextMarker() { + return Optional.class.cast(nextRecord); + } + + @Override + public Iterator iterator() { + return items.iterator(); + } + + @Override + public int hashCode() { + return Objects.hashCode(items, nextRecord); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + ResourceRecordSetIterable that = ResourceRecordSetIterable.class.cast(obj); + return equal(this.items, that.items) && equal(this.nextRecord, that.nextRecord); + } + + @Override + public String toString() { + return toStringHelper("").omitNullValues().add("items", items).add("nextRecord", nextRecord.orNull()).toString(); + } + + /** + * If the results were truncated, this holds the position of the next item. + */ + public static class NextRecord { + public static NextRecord nameAndType(String name, Type type) { + return new NextRecord(name, type, null); + } + + public static NextRecord nameTypeAndIdentifier(String name, Type type, String identifier) { + return new NextRecord(name, type, identifier); + } + + private final String name; + private final Type type; + private final Optional identifier; + + private NextRecord(String name, Type type, String identifier) { + this.name = checkNotNull(name, "name"); + this.type = checkNotNull(type, "type for %s", name); + this.identifier = Optional.fromNullable(identifier); + } + + /** + * If the results were truncated, the name of the next record in the list. + */ + public String getName() { + return name; + } + + /** + * the type of the next record in the list. + */ + public Type getType() { + return type; + } + + /** + * Weighted and latency resource record sets only. + */ + public Optional getIdentifier() { + return identifier; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, type, identifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + NextRecord other = NextRecord.class.cast(obj); + return equal(this.name, other.name) && equal(this.type, other.type) + && equal(this.identifier, other.identifier); + } + + @Override + public String toString() { + return toStringHelper("").omitNullValues().add("name", name).add("type", type) + .add("identifier", identifier.orNull()).toString(); + } + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + + private ImmutableList.Builder items = ImmutableList. builder(); + private String nextRecordName; + private Type nextRecordType; + private String nextRecordIdentifier; + + public Builder add(ResourceRecordSet item) { + this.items.add(item); + return this; + } + + public Builder addAll(Iterable items) { + this.items.addAll(items); + return this; + } + + public Builder nextRecordName(String nextRecordName) { + this.nextRecordName = nextRecordName; + return this; + } + + public Builder nextRecordType(Type nextRecordType) { + this.nextRecordType = nextRecordType; + return this; + } + + public Builder nextRecordIdentifier(String nextRecordIdentifier) { + this.nextRecordIdentifier = nextRecordIdentifier; + return this; + } + + public ResourceRecordSetIterable build() { + NextRecord nextRecord = nextRecordName != null ? new NextRecord(nextRecordName, nextRecordType, + nextRecordIdentifier) : null; + return new ResourceRecordSetIterable(items.build(), nextRecord); + } + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java b/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java new file mode 100644 index 0000000000..cd24e2b751 --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java @@ -0,0 +1,54 @@ +/** + * 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 java.util.concurrent.TimeUnit; + +import org.jclouds.collect.PagedIterable; +import org.jclouds.concurrent.Timeout; +import org.jclouds.route53.domain.ResourceRecordSet; +import org.jclouds.route53.domain.ResourceRecordSetIterable; +import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord; + +/** + * @see ResourceRecordSetAsyncApi + * @see + * @author Adrian Cole + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface ResourceRecordSetApi { + + /** + * returns all resource record sets in order. + */ + PagedIterable list(); + + /** + * retrieves up to 100 resource record sets in order. + */ + ResourceRecordSetIterable listFirstPage(); + + /** + * retrieves up to 100 resource record sets in order, starting at {@code nextRecord} + */ + ResourceRecordSetIterable listAt(NextRecord nextRecord); + +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java b/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java new file mode 100644 index 0000000000..cf0d87aa6a --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java @@ -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.route53.features; + +import javax.inject.Named; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import org.jclouds.collect.PagedIterable; +import org.jclouds.rest.annotations.BinderParam; +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.binders.BindNextRecord; +import org.jclouds.route53.domain.ResourceRecordSet; +import org.jclouds.route53.domain.ResourceRecordSetIterable; +import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord; +import org.jclouds.route53.filters.RestAuthentication; +import org.jclouds.route53.functions.ResourceRecordSetsToPagedIterable; +import org.jclouds.route53.xml.ListResourceRecordSetsResponseHandler; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * @see ResourceRecordSetApi + * @see + * @author Adrian Cole + */ +@RequestFilters(RestAuthentication.class) +@VirtualHost +@Path("/{jclouds.api-version}/hostedzone/{zoneId}") +public interface ResourceRecordSetAsyncApi { + + /** + * @see ResourceRecordSetApi#list() + */ + @Named("ListResourceRecordSets") + @GET + @Path("/rrset") + @XMLResponseParser(ListResourceRecordSetsResponseHandler.class) + @Transform(ResourceRecordSetsToPagedIterable.class) + ListenableFuture> list(); + + /** + * @see ResourceRecordSetApi#listFirstPage + */ + @Named("ListResourceRecordSets") + @GET + @Path("/rrset") + @XMLResponseParser(ListResourceRecordSetsResponseHandler.class) + ListenableFuture listFirstPage(); + + /** + * @see ResourceRecordSetApi#listAt(NextRecord) + */ + @Named("ListResourceRecordSets") + @GET + @Path("/rrset") + @XMLResponseParser(ListResourceRecordSetsResponseHandler.class) + ListenableFuture listAt(@BinderParam(BindNextRecord.class) NextRecord nextRecord); +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/features/ZoneApi.java b/labs/route53/src/main/java/org/jclouds/route53/features/ZoneApi.java index 8bf5bf7bdd..a7a5a3246c 100644 --- a/labs/route53/src/main/java/org/jclouds/route53/features/ZoneApi.java +++ b/labs/route53/src/main/java/org/jclouds/route53/features/ZoneApi.java @@ -65,24 +65,19 @@ public interface ZoneApi { NewZone createWithReferenceAndComment(String name, String callerReference, String comment); /** - * Lists the zones that have the specified path prefix. If there are none, - * the action returns an empty list. + * The action retrieves a specified number of zones in order. * *
- * You can paginate the results using the {@link ListZonesOptions parameter} + * You can paginate the results using the + * {@link ListZonesOptions parameter} * * @param options * the options describing the zones query - * - * @return the response object */ IterableWithMarker 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 + * returns all zones in order. */ PagedIterable list(); diff --git a/labs/route53/src/main/java/org/jclouds/route53/functions/ResourceRecordSetsToPagedIterable.java b/labs/route53/src/main/java/org/jclouds/route53/functions/ResourceRecordSetsToPagedIterable.java new file mode 100644 index 0000000000..2f4fd295f9 --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/functions/ResourceRecordSetsToPagedIterable.java @@ -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.ResourceRecordSet; +import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord; +import org.jclouds.route53.features.ResourceRecordSetApi; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Beta +public class ResourceRecordSetsToPagedIterable extends + CallerArg0ToPagedIterable { + + private final Route53Api api; + + @Inject + protected ResourceRecordSetsToPagedIterable(Route53Api api) { + this.api = checkNotNull(api, "api"); + } + + @Override + protected Function> markerToNextForCallingArg0(String zoneId) { + final ResourceRecordSetApi resourceRecordSetApi = api.getResourceRecordSetApiForZone(zoneId); + return new Function>() { + + @Override + public IterableWithMarker apply(Object input) { + return resourceRecordSetApi.listAt(NextRecord.class.cast(input)); + } + + @Override + public String toString() { + return "listResourceRecordSets()"; + } + }; + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/xml/ListResourceRecordSetsResponseHandler.java b/labs/route53/src/main/java/org/jclouds/route53/xml/ListResourceRecordSetsResponseHandler.java new file mode 100644 index 0000000000..246c4c18c1 --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/xml/ListResourceRecordSetsResponseHandler.java @@ -0,0 +1,101 @@ +/** + * 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 static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.route53.domain.ResourceRecordSet.Type; +import org.jclouds.route53.domain.ResourceRecordSetIterable; +import org.jclouds.route53.domain.ResourceRecordSetIterable.Builder; +import org.xml.sax.Attributes; + +import com.google.inject.Inject; + +/** + * @see
+ * + * @author Adrian Cole + */ +public class ListResourceRecordSetsResponseHandler extends + ParseSax.HandlerForGeneratedRequestWithResult { + + private final ResourceRecordSetHandler resourceRecordSetHandler; + + private StringBuilder currentText = new StringBuilder(); + private Builder builder = ResourceRecordSetIterable.builder(); + + private boolean inResourceRecordSets; + + @Inject + public ListResourceRecordSetsResponseHandler(ResourceRecordSetHandler resourceRecordSetHandler) { + this.resourceRecordSetHandler = resourceRecordSetHandler; + } + + @Override + public ResourceRecordSetIterable getResult() { + try { + return builder.build(); + } finally { + builder = ResourceRecordSetIterable.builder(); + } + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) { + if (equalsOrSuffix(qName, "ResourceRecordSets")) { + inResourceRecordSets = true; + } + if (inResourceRecordSets) { + resourceRecordSetHandler.startElement(url, name, qName, attributes); + } + } + + @Override + public void endElement(String uri, String name, String qName) { + if (inResourceRecordSets) { + if (qName.equals("ResourceRecordSets")) { + inResourceRecordSets = false; + } else if (qName.equals("ResourceRecordSet")) { + builder.add(resourceRecordSetHandler.getResult()); + } else { + resourceRecordSetHandler.endElement(uri, name, qName); + } + } else if (qName.equals("NextRecordName")) { + builder.nextRecordName(currentOrNull(currentText)); + } else if (qName.equals("NextRecordType")) { + builder.nextRecordType(Type.valueOf(currentOrNull(currentText))); + } else if (qName.equals("NextRecordIdentifier")) { + builder.nextRecordIdentifier(currentOrNull(currentText)); + } + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + if (inResourceRecordSets) { + resourceRecordSetHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } +} diff --git a/labs/route53/src/main/java/org/jclouds/route53/xml/ResourceRecordSetHandler.java b/labs/route53/src/main/java/org/jclouds/route53/xml/ResourceRecordSetHandler.java new file mode 100644 index 0000000000..763c4ca9ae --- /dev/null +++ b/labs/route53/src/main/java/org/jclouds/route53/xml/ResourceRecordSetHandler.java @@ -0,0 +1,68 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.route53.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.route53.domain.ResourceRecordSet; +import org.jclouds.route53.domain.ResourceRecordSet.Type; +import org.xml.sax.Attributes; + +/** + * + * @author Adrian Cole + */ +public class ResourceRecordSetHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private StringBuilder currentText = new StringBuilder(); + private ResourceRecordSet.Builder builder = ResourceRecordSet.builder(); + + @Override + public ResourceRecordSet getResult() { + try { + return builder.build(); + } finally { + builder = ResourceRecordSet.builder(); + } + } + + @Override + public void startElement(String url, String name, String qName, Attributes attributes) { + } + + @Override + public void endElement(String uri, String name, String qName) { + if (qName.equals("Name")) { + builder.name(currentOrNull(currentText)); + } else if (qName.equals("Type")) { + builder.type(Type.valueOf(currentOrNull(currentText))); + } else if (qName.equals("TTL")) { + builder.ttl(Integer.parseInt(currentOrNull(currentText))); + } else if (qName.equals("Value")) { + builder.add(currentOrNull(currentText)); + } + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/labs/route53/src/test/java/org/jclouds/route53/Route53ApiExpectTest.java b/labs/route53/src/test/java/org/jclouds/route53/Route53ApiExpectTest.java index 0168398a68..e79b0d0004 100644 --- a/labs/route53/src/test/java/org/jclouds/route53/Route53ApiExpectTest.java +++ b/labs/route53/src/test/java/org/jclouds/route53/Route53ApiExpectTest.java @@ -49,8 +49,6 @@ public class Route53ApiExpectTest extends BaseRoute53ApiExpectTest { 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")); diff --git a/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiExpectTest.java b/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiExpectTest.java new file mode 100644 index 0000000000..9950bd8fec --- /dev/null +++ b/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiExpectTest.java @@ -0,0 +1,88 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.testng.Assert.assertEquals; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.route53.Route53Api; +import org.jclouds.route53.domain.ResourceRecordSet.Type; +import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord; +import org.jclouds.route53.internal.BaseRoute53ApiExpectTest; +import org.jclouds.route53.parse.ListResourceRecordSetsResponseTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ResourceRecordSetApiExpectTest") +public class ResourceRecordSetApiExpectTest extends BaseRoute53ApiExpectTest { + + HttpRequest list = HttpRequest.builder().method("GET") + .endpoint("https://route53.amazonaws.com/2012-02-29/hostedzone/Z1PA6795UKMFR9/rrset") + .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("/rrsets.xml", "text/xml")).build(); + + public void testListWhenResponseIs2xx() { + Route53Api success = requestSendsResponse(list, listResponse); + assertEquals(success.getResourceRecordSetApiForZone("Z1PA6795UKMFR9").list().get(0).toString(), new ListResourceRecordSetsResponseTest().expected() + .toString()); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testListWhenResponseIs404() { + Route53Api fail = requestSendsResponse(list, notFound); + assertEquals(fail.getResourceRecordSetApiForZone("Z1PA6795UKMFR9").list().get(0).toImmutableSet(), ImmutableSet.of()); + } + + HttpRequest listAt = HttpRequest.builder().method("GET") + .endpoint("https://route53.amazonaws.com/2012-02-29/hostedzone/Z1PA6795UKMFR9/rrset?name=testdoc2.example.com&type=NS") + .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 testListAtWhenResponseIs2xx() { + Route53Api apiWhenAtExist = requestSendsResponse(listAt, listResponse); + NextRecord next = NextRecord.nameAndType("testdoc2.example.com", Type.NS); + assertEquals(apiWhenAtExist.getResourceRecordSetApiForZone("Z1PA6795UKMFR9").listAt(next).toString(), + new ListResourceRecordSetsResponseTest().expected().toString()); + } + + public void testList2PagesWhenResponseIs2xx() { + HttpResponse noMore = HttpResponse.builder().statusCode(200) + .payload(payloadFromStringWithContentType("", "text/xml")).build(); + + Route53Api success = requestsSendResponses(list, listResponse, listAt, noMore); + assertEquals(success.getResourceRecordSetApiForZone("Z1PA6795UKMFR9").list().concat().toImmutableSet(), new ListResourceRecordSetsResponseTest().expected() + .toImmutableSet()); + } +} diff --git a/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiLiveTest.java b/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiLiveTest.java new file mode 100644 index 0000000000..3b403e22bd --- /dev/null +++ b/labs/route53/src/test/java/org/jclouds/route53/features/ResourceRecordSetApiLiveTest.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.route53.features; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; + +import java.util.List; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.route53.domain.ResourceRecordSet; +import org.jclouds.route53.domain.Zone; +import org.jclouds.route53.internal.BaseRoute53ApiLiveTest; +import org.testng.SkipException; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "ResourceRecordSetApiLiveTest") +public class ResourceRecordSetApiLiveTest extends BaseRoute53ApiLiveTest { + + private void checkResourceRecordSet(ResourceRecordSet resourceRecordSet) { + checkNotNull(resourceRecordSet.getName(), "Id cannot be null for a ResourceRecordSet %s", resourceRecordSet); + checkNotNull(resourceRecordSet.getType(), "Type cannot be null for a ResourceRecordSet %s", resourceRecordSet); + checkNotNull(resourceRecordSet.getTTL(), + "While TTL can be null for a ResourceRecordSet, its Optional wrapper cannot %s", resourceRecordSet); + } + + @Test + protected void testListResourceRecordSets() { + IterableWithMarker zones = context.getApi().getZoneApi().list().get(0); + if (zones.isEmpty()) + throw new SkipException("no zones in context: " + context); + + Zone zone = zones.first().get(); + List records = api(zone.getId()).list().concat().toImmutableList(); + assertEquals(zone.getResourceRecordSetCount(), records.size()); + + for (ResourceRecordSet resourceRecordSet : records) { + checkResourceRecordSet(resourceRecordSet); + } + } + + protected ResourceRecordSetApi api(String zoneId) { + return context.getApi().getResourceRecordSetApiForZone(zoneId); + } +} diff --git a/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiExpectTest.java b/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiExpectTest.java index f9d8ec7cbb..4f8a5f9653 100644 --- a/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiExpectTest.java +++ b/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiExpectTest.java @@ -93,8 +93,6 @@ public class ZoneApiExpectTest extends BaseRoute53ApiExpectTest { assertEquals(success.getZoneApi().get("Z1XTHCPEFRWV1X").toString(), new GetHostedZoneResponseTest().expected() .toString()); } - - HttpResponse notFound = HttpResponse.builder().statusCode(404).build(); public void testGetWhenResponseIs404() { Route53Api fail = requestSendsResponse(get, notFound); diff --git a/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiLiveTest.java b/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiLiveTest.java index 25ce038169..e29924bb38 100644 --- a/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiLiveTest.java +++ b/labs/route53/src/test/java/org/jclouds/route53/features/ZoneApiLiveTest.java @@ -41,7 +41,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; /** * @author Adrian Cole @@ -63,7 +62,7 @@ public class ZoneApiLiveTest extends BaseRoute53ApiLiveTest { private void checkZone(Zone zone) { checkNotNull(zone.getId(), "Id cannot be null for a Zone %s", zone); - checkNotNull(zone.getName(), "Id cannot be null for a Zone %s", zone); + checkNotNull(zone.getName(), "Name cannot be null for a Zone %s", zone); checkNotNull(zone.getCallerReference(), "CallerReference cannot be null for a Zone %s", zone); checkNotNull(zone.getComment(), "While Comment can be null for a Zone, its Optional wrapper cannot %s", zone); } @@ -76,7 +75,7 @@ public class ZoneApiLiveTest extends BaseRoute53ApiLiveTest { checkZone(zone); } - if (Iterables.size(response) > 0) { + if (response.size() > 0) { Zone zone = response.iterator().next(); assertEquals(api().get(zone.getId()).getZone(), zone); } diff --git a/labs/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiExpectTest.java b/labs/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiExpectTest.java index f7796801cc..ca538ba739 100644 --- a/labs/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiExpectTest.java +++ b/labs/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiExpectTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.route53.internal; +import org.jclouds.http.HttpResponse; import org.jclouds.route53.Route53Api; /** @@ -25,5 +26,5 @@ import org.jclouds.route53.Route53Api; * @author Adrian Cole */ public class BaseRoute53ApiExpectTest extends BaseRoute53ExpectTest { - + protected HttpResponse notFound = HttpResponse.builder().statusCode(404).build(); } diff --git a/labs/route53/src/test/java/org/jclouds/route53/options/ListZonesOptionsTest.java b/labs/route53/src/test/java/org/jclouds/route53/options/ListZonesOptionsTest.java index 765f58c6b0..9270443341 100644 --- a/labs/route53/src/test/java/org/jclouds/route53/options/ListZonesOptionsTest.java +++ b/labs/route53/src/test/java/org/jclouds/route53/options/ListZonesOptionsTest.java @@ -31,7 +31,7 @@ import com.google.common.collect.ImmutableSet; * * @author Adrian Cole */ -@Test(groups = "maxItems", testName = "ListZonesOptionsTest") +@Test(groups = "unit", testName = "ListZonesOptionsTest") public class ListZonesOptionsTest { public void testMarker() { diff --git a/labs/route53/src/test/java/org/jclouds/route53/parse/ListResourceRecordSetsResponseTest.java b/labs/route53/src/test/java/org/jclouds/route53/parse/ListResourceRecordSetsResponseTest.java new file mode 100644 index 0000000000..4006c1b665 --- /dev/null +++ b/labs/route53/src/test/java/org/jclouds/route53/parse/ListResourceRecordSetsResponseTest.java @@ -0,0 +1,72 @@ +/** + * 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.ResourceRecordSet; +import org.jclouds.route53.domain.ResourceRecordSet.Type; +import org.jclouds.route53.domain.ResourceRecordSetIterable; +import org.jclouds.route53.xml.ListResourceRecordSetsResponseHandler; +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 = "ListResourceRecordSetsResponseTest") +public class ListResourceRecordSetsResponseTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/rrsets.xml"); + + ResourceRecordSetIterable expected = expected(); + + ListResourceRecordSetsResponseHandler handler = injector.getInstance(ListResourceRecordSetsResponseHandler.class); + ResourceRecordSetIterable result = factory.create(handler).parse(is); + + assertEquals(result.toString(), expected.toString()); + + } + + public ResourceRecordSetIterable expected() { + return ResourceRecordSetIterable.builder() + .add(ResourceRecordSet.builder() + .name("example.com.") + .type(Type.SOA) + .ttl(900) + .add("ns-2048.awsdns-64.net. hostmaster.awsdns.com. 1 7200 900 1209600 86400") + .build()) + .add(ResourceRecordSet.builder() + .name("example.com.") + .type(Type.NS) + .ttl(172800) + .add("ns-2048.awsdns-64.com.") + .add("ns-2049.awsdns-65.net.") + .add("ns-2050.awsdns-66.org.") + .add("ns-2051.awsdns-67.co.uk.") + .build()) + .nextRecordName("testdoc2.example.com") + .nextRecordType(Type.NS).build(); + } +} diff --git a/labs/route53/src/test/resources/rrsets.xml b/labs/route53/src/test/resources/rrsets.xml new file mode 100644 index 0000000000..02de2f52c4 --- /dev/null +++ b/labs/route53/src/test/resources/rrsets.xml @@ -0,0 +1,39 @@ + + + + + example.com. + SOA + 900 + + + ns-2048.awsdns-64.net. hostmaster.awsdns.com. 1 7200 900 1209600 86400 + + + + + example.com. + NS + 172800 + + + ns-2048.awsdns-64.com. + + + ns-2049.awsdns-65.net. + + + ns-2050.awsdns-66.org. + + + ns-2051.awsdns-67.co.uk. + + + + + true + 3 + testdoc2.example.com + NS + \ No newline at end of file