diff --git a/labs/ultradns-ws/pom.xml b/labs/ultradns-ws/pom.xml index 08803989c0..22daff8369 100644 --- a/labs/ultradns-ws/pom.xml +++ b/labs/ultradns-ws/pom.xml @@ -87,6 +87,8 @@ test + + 1 ${test.ultradns-ws.endpoint} ${test.ultradns-ws.api-version} diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSExceptions.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSExceptions.java new file mode 100644 index 0000000000..2d964b99e8 --- /dev/null +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSExceptions.java @@ -0,0 +1,39 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"), you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * +http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.ultradns.ws; + +/** + * Exceptions likely to be encountered when using {@link UltraDNSWSApi} + * + * @author Adrian Cole + */ +public interface UltraDNSWSExceptions { + + /** + * The Zone or other resource already exists + */ + public static class ResourceAlreadyExistsException extends IllegalStateException { + private static final long serialVersionUID = 1L; + + public ResourceAlreadyExistsException(String message, Throwable cause) { + super(message, cause); + } + } +} \ No newline at end of file diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java index 372f5b803c..d44c1cfcb5 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java @@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Objects; import com.google.common.base.Optional; +import com.google.common.primitives.UnsignedInteger; /** * @@ -32,17 +33,17 @@ public final class Zone { private final String id; private final String name; private final Type type; - private final int typeCode; + private final UnsignedInteger typeCode; private final String accountId; private final String ownerId; private final DNSSECStatus dnssecStatus; private final Optional primarySrc; - private Zone(String id, String name, Type type, int typeCode, String accountId, String ownerId, + private Zone(String id, String name, Type type, UnsignedInteger typeCode, String accountId, String ownerId, DNSSECStatus dnssecStatus, Optional primarySrc) { this.id = checkNotNull(id, "id"); - this.name = checkNotNull(name, "name"); - this.typeCode = typeCode; + this.name = checkNotNull(name, "name for %s", id); + this.typeCode = checkNotNull(typeCode, "typeCode for %s", name); this.type = checkNotNull(type, "type for %s", name); this.accountId = checkNotNull(accountId, "accountId for %s", name); this.ownerId = checkNotNull(ownerId, "ownerId for %s", name); @@ -74,7 +75,7 @@ public final class Zone { /** * The type of the zone */ - public int getTypeCode() { + public UnsignedInteger getTypeCode() { return typeCode; } @@ -135,13 +136,13 @@ public final class Zone { PRIMARY(1), SECONDARY(2), ALIAS(3), UNRECOGNIZED(-1); - private final int code; + private final UnsignedInteger code; Type(int code) { - this.code = code; + this.code = UnsignedInteger.fromIntBits(code); } - public int getCode() { + public UnsignedInteger getCode() { return code; } @@ -151,11 +152,11 @@ public final class Zone { } public static Type fromValue(String type) { - return fromValue(Integer.parseInt(checkNotNull(type, "type"))); + return fromValue(UnsignedInteger.valueOf(checkNotNull(type, "type"))); } - public static Type fromValue(int code) { - switch (code) { + public static Type fromValue(UnsignedInteger code) { + switch (code.intValue()) { case 1: return PRIMARY; case 2: @@ -193,7 +194,7 @@ public final class Zone { private String id; private String name; private Type type; - private int typeCode = -1; + private UnsignedInteger typeCode; private String accountId; private String ownerId; private DNSSECStatus dnssecStatus; @@ -226,12 +227,19 @@ public final class Zone { /** * @see Zone#getTypeCode() */ - public Builder typeCode(int typeCode) { + public Builder typeCode(UnsignedInteger typeCode) { this.typeCode = typeCode; this.type = Type.fromValue(typeCode); return this; } + /** + * @see ZoneProperties#getTypeCode() + */ + public Builder typeCode(int typeCode) { + return typeCode(UnsignedInteger.fromIntBits(typeCode)); + } + /** * @see Zone#getAccountId() */ diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java index 87a8485e3b..a05cf0ee59 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java @@ -25,6 +25,7 @@ import java.util.Date; import org.jclouds.ultradns.ws.domain.Zone.Type; import com.google.common.base.Objects; +import com.google.common.primitives.UnsignedInteger; /** * @@ -34,13 +35,13 @@ public final class ZoneProperties { private final String name; private final Type type; - private final int typeCode; + private final UnsignedInteger typeCode; private final Date modified; private final int resourceRecordCount; - private ZoneProperties(String name, Type type, int typeCode, Date modified, int resourceRecordCount) { + private ZoneProperties(String name, Type type, UnsignedInteger typeCode, Date modified, int resourceRecordCount) { this.name = checkNotNull(name, "name"); - this.typeCode = typeCode; + this.typeCode = checkNotNull(typeCode, "typeCode for %s", name); this.type = checkNotNull(type, "type for %s", name); this.modified = checkNotNull(modified, "modified for %s", name); this.resourceRecordCount = checkNotNull(resourceRecordCount, "resourceRecordCount for %s", name); @@ -63,7 +64,7 @@ public final class ZoneProperties { /** * The type of the zone */ - public int getTypeCode() { + public UnsignedInteger getTypeCode() { return typeCode; } @@ -113,7 +114,7 @@ public final class ZoneProperties { public final static class Builder { private String name; private Type type; - private int typeCode = -1; + private UnsignedInteger typeCode; private Date modified; private int resourceRecordCount; @@ -136,12 +137,19 @@ public final class ZoneProperties { /** * @see ZoneProperties#getTypeCode() */ - public Builder typeCode(int typeCode) { + public Builder typeCode(UnsignedInteger typeCode) { this.typeCode = typeCode; this.type = Type.fromValue(typeCode); return this; } + /** + * @see ZoneProperties#getTypeCode() + */ + public Builder typeCode(int typeCode) { + return typeCode(UnsignedInteger.fromIntBits(typeCode)); + } + /** * @see ZoneProperties#getModified() */ diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java index efb4b15d54..a2260ce829 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java @@ -20,6 +20,7 @@ package org.jclouds.ultradns.ws.features; import org.jclouds.javax.annotation.Nullable; import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException; import org.jclouds.ultradns.ws.domain.Zone; import org.jclouds.ultradns.ws.domain.Zone.Type; import org.jclouds.ultradns.ws.domain.ZoneProperties; @@ -32,11 +33,23 @@ import com.google.common.collect.FluentIterable; */ public interface ZoneApi { + /** + * creates a primary zone and its supporting records (SOA, NS and A). The + * user who issues this request becomes the owner of this zone. + * + * @param name + * the fully qualified name of the new zone. + * @param accountId + * the account to create the zone in + */ + void createInAccount(String name, String accountId) throws ResourceAlreadyExistsException; + /** * Retrieves information about the specified zone * * @param name - * Name of the zone to get information about. + * the fully-qualified name, including the trailing dot, of the + * zone to get information about. * @return null if not found */ @Nullable @@ -57,4 +70,14 @@ public interface ZoneApi { * if the account doesn't exist */ FluentIterable listByAccountAndType(String accountId, Type type) throws ResourceNotFoundException; + + /** + * deletes a zone and all its resource records + * + * @param name + * the fully-qualified name, including the trailing dot, of the + * zone you want to delete. + * @return null if not found + */ + void delete(String name); } diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java index a831f1363a..3da2d0a7ab 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java @@ -22,6 +22,7 @@ import javax.inject.Named; import javax.ws.rs.POST; import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Payload; @@ -29,6 +30,7 @@ import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException; import org.jclouds.ultradns.ws.domain.Zone; import org.jclouds.ultradns.ws.domain.Zone.Type; import org.jclouds.ultradns.ws.domain.ZoneProperties; @@ -49,6 +51,15 @@ import com.google.common.util.concurrent.ListenableFuture; @VirtualHost public interface ZoneAsyncApi { + /** + * @see ZoneApi#createInAccount(String, String + */ + @Named("createPrimaryZone") + @POST + @Payload("{accountId}{zoneName}false") + ListenableFuture createInAccount(@PayloadParam("zoneName") String name, + @PayloadParam("accountId") String accountId) throws ResourceAlreadyExistsException; + /** * @see ZoneApi#get(String) */ @@ -78,4 +89,13 @@ public interface ZoneAsyncApi { @Payload("{accountId}{zoneType}") ListenableFuture> listByAccountAndType(@PayloadParam("accountId") String accountId, @PayloadParam("zoneType") Type type) throws ResourceNotFoundException; + + /** + * @see ZoneApi#delete(String) + */ + @Named("deleteZone") + @POST + @Payload("{zoneName}") + @Fallback(VoidOnNotFoundOr404.class) + ListenableFuture delete(@PayloadParam("zoneName") String name); } diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandler.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandler.java index 1d62d5e1b1..ab56bad5c3 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandler.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandler.java @@ -32,6 +32,7 @@ import org.jclouds.http.HttpResponseException; import org.jclouds.http.functions.ParseSax.Factory; import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.ultradns.ws.UltraDNSWSError; +import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException; import org.jclouds.ultradns.ws.UltraDNSWSResponseException; import org.jclouds.ultradns.ws.xml.UltraWSExceptionHandler; @@ -79,6 +80,8 @@ public class UltraDNSWSErrorHandler implements HttpErrorHandler { case 1801: case 2401: return new ResourceNotFoundException(exception.getError().getDescription(), exception); + case 1802: + return new ResourceAlreadyExistsException(exception.getError().getDescription(), exception); } return exception; } diff --git a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ZoneHandler.java b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ZoneHandler.java index 3cac2f282f..43ee32f23b 100644 --- a/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ZoneHandler.java +++ b/labs/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ZoneHandler.java @@ -29,6 +29,8 @@ import org.jclouds.ultradns.ws.domain.Zone; import org.jclouds.ultradns.ws.domain.Zone.DNSSECStatus; import org.xml.sax.Attributes; +import com.google.common.primitives.UnsignedInteger; + /** * * @author Adrian Cole @@ -53,7 +55,7 @@ public class ZoneHandler extends ParseSax.HandlerForGeneratedRequestWithResult 0, "TypeCode must be positive for a Zone " + zone); + checkNotNull(zone.getTypeCode(), "TypeCode cannot be null for a Zone %s", zone); assertEquals(zone.getTypeCode(), zone.getType().getCode()); checkNotNull(zone.getAccountId(), "AccountId cannot be null for a Zone %s", zone); assertEquals(zone.getAccountId(), account.getId()); @@ -90,7 +95,8 @@ public class ZoneApiLiveTest extends BaseUltraDNSWSApiLiveTest { assertEquals(zoneProperties.getType(), zone.getType()); assertEquals(zoneProperties.getTypeCode(), zone.getTypeCode()); checkNotNull(zoneProperties.getModified(), "Modified cannot be null for a Zone %s", zone); - assertTrue(zoneProperties.getResourceRecordCount() >= 0, "ResourceRecordCount must be positive or zero for a Zone " + zone); + assertTrue(zoneProperties.getResourceRecordCount() >= 0, + "ResourceRecordCount must be positive or zero for a Zone " + zone); } } @@ -99,6 +105,42 @@ public class ZoneApiLiveTest extends BaseUltraDNSWSApiLiveTest { assertNull(api().get("AAAAAAAAAAAAAAAA")); } + @Test + public void testDeleteZoneWhenNotFound() { + api().delete("AAAAAAAAAAAAAAAA"); + } + + @Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Account not found in the system. ID: AAAAAAAAAAAAAAAA") + public void testCreateZoneBadAccountId() { + api().createInAccount(name, "AAAAAAAAAAAAAAAA"); + } + + String name = System.getProperty("user.name").replace('.', '-') + ".zone.ultradnstest.jclouds.org."; + + @Test + public void testCreateAndDeleteZone() { + try { + api().createInAccount(name, account.getId()); + ZoneProperties newZone = api().get(name); + getAnonymousLogger().info("created zone: " + newZone); + + try { + api().createInAccount(name, account.getId()); + fail(); + } catch (ResourceAlreadyExistsException e) { + + } + + assertEquals(newZone.getName(), name); + assertEquals(newZone.getType(), Type.PRIMARY); + assertEquals(newZone.getTypeCode(), Type.PRIMARY.getCode()); + checkNotNull(newZone.getModified(), "Modified cannot be null for a Zone %s", newZone); + assertEquals(newZone.getResourceRecordCount(), 5); + } finally { + api().delete(name); + } + } + protected ZoneApi api() { return context.getApi().getZoneApi(); } diff --git a/labs/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandlerTest.java b/labs/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandlerTest.java index ffe58682b0..c84c7b279c 100644 --- a/labs/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandlerTest.java +++ b/labs/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/handlers/UltraDNSWSErrorHandlerTest.java @@ -31,6 +31,7 @@ import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.config.SaxParserModule; import org.jclouds.io.Payload; import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException; import org.jclouds.ultradns.ws.UltraDNSWSResponseException; import org.testng.annotations.Test; @@ -111,6 +112,28 @@ public class UltraDNSWSErrorHandlerTest { assertEquals(exception.getError().getCode(), 1801); } + @Test + public void testCode1802SetsResourceAlreadyExistsException() throws IOException { + HttpRequest request = HttpRequest.builder().method("POST") + .endpoint("https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01") + .addHeader("Host", "ultra-api.ultradns.com:8443") + .payload(payloadFromResource("/create_zone.xml")).build(); + HttpCommand command = new HttpCommand(request); + HttpResponse response = HttpResponse.builder().message("Server Error").statusCode(500) + .payload(payloadFromResource("/zone_already_exists.xml")).build(); + + function.handleError(command, response); + + assertEquals(command.getException().getClass(), ResourceAlreadyExistsException.class); + assertEquals(command.getException().getMessage(), "Zone already exists in the system."); + + UltraDNSWSResponseException exception = UltraDNSWSResponseException.class.cast(command.getException().getCause()); + + assertEquals(exception.getMessage(), "Error 1802: Zone already exists in the system."); + assertEquals(exception.getError().getDescription(), "Zone already exists in the system."); + assertEquals(exception.getError().getCode(), 1802); + } + private Payload payloadFromResource(String resource) { try { return payloadFromStringWithContentType(toStringAndClose(getClass().getResourceAsStream(resource)), diff --git a/labs/ultradns-ws/src/test/resources/create_zone.xml b/labs/ultradns-ws/src/test/resources/create_zone.xml new file mode 100644 index 0000000000..d44b6122d3 --- /dev/null +++ b/labs/ultradns-ws/src/test/resources/create_zone.xml @@ -0,0 +1 @@ +identitycredentialAAAAAAAAAAAAAAAAjclouds.org.false \ No newline at end of file diff --git a/labs/ultradns-ws/src/test/resources/delete_zone.xml b/labs/ultradns-ws/src/test/resources/delete_zone.xml new file mode 100644 index 0000000000..77e29d0e07 --- /dev/null +++ b/labs/ultradns-ws/src/test/resources/delete_zone.xml @@ -0,0 +1 @@ +identitycredentialjclouds.org. \ No newline at end of file diff --git a/labs/ultradns-ws/src/test/resources/zone_already_exists.xml b/labs/ultradns-ws/src/test/resources/zone_already_exists.xml new file mode 100644 index 0000000000..a046b5e752 --- /dev/null +++ b/labs/ultradns-ws/src/test/resources/zone_already_exists.xml @@ -0,0 +1 @@ +soap:ServerFault occurred while processing.1802Zone already exists in the system. \ No newline at end of file diff --git a/labs/ultradns-ws/src/test/resources/zone_created.xml b/labs/ultradns-ws/src/test/resources/zone_created.xml new file mode 100644 index 0000000000..61f5586abd --- /dev/null +++ b/labs/ultradns-ws/src/test/resources/zone_created.xml @@ -0,0 +1,8 @@ + + + + Successful + + + \ No newline at end of file diff --git a/labs/ultradns-ws/src/test/resources/zone_deleted.xml b/labs/ultradns-ws/src/test/resources/zone_deleted.xml new file mode 100644 index 0000000000..f01a861289 --- /dev/null +++ b/labs/ultradns-ws/src/test/resources/zone_deleted.xml @@ -0,0 +1 @@ +Successful \ No newline at end of file