From d9572151ae76121e241505079dce5a0e2bab2f75 Mon Sep 17 00:00:00 2001 From: adriancole Date: Sun, 24 Mar 2013 16:01:01 -0700 Subject: [PATCH] update pool record support in ultradns --- .../ws/binders/UpdatePoolRecordToXML.java | 62 +++++ .../ultradns/ws/domain/UpdatePoolRecord.java | 232 ++++++++++++++++++ .../ws/features/TrafficControllerPoolApi.java | 17 +- .../TrafficControllerPoolAsyncApi.java | 12 + .../TrafficControllerPoolApiExpectTest.java | 29 +++ .../TrafficControllerPoolApiLiveTest.java | 25 ++ .../src/test/resources/poolrecord_updated.xml | 1 + .../src/test/resources/update_poolrecord.xml | 1 + 8 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/binders/UpdatePoolRecordToXML.java create mode 100644 providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java create mode 100644 providers/ultradns-ws/src/test/resources/poolrecord_updated.xml create mode 100644 providers/ultradns-ws/src/test/resources/update_poolrecord.xml diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/binders/UpdatePoolRecordToXML.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/binders/UpdatePoolRecordToXML.java new file mode 100644 index 0000000000..670a9ca06c --- /dev/null +++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/binders/UpdatePoolRecordToXML.java @@ -0,0 +1,62 @@ +/** + * 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.binders; + +import static java.lang.String.format; + +import java.util.Map; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.MapBinder; +import org.jclouds.ultradns.ws.domain.UpdatePoolRecord; + +/** + * + * @author Adrian Cole + */ +public class UpdatePoolRecordToXML implements MapBinder { + private static final String HEADER = "%s"; + private static final String FOOTER = ""; + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Map postParams) { + + StringBuilder xml = new StringBuilder(); + xml.append(format(HEADER, postParams.get("poolRecordID"))); + + UpdatePoolRecord update = UpdatePoolRecord.class.cast(postParams.get("update")); + + xml.append("").append(update.getPointsTo()).append(""); + xml.append("").append(update.getPriority()).append(""); + xml.append("").append(update.getFailOverDelay()).append(""); + xml.append("").append(update.getTTL()).append(""); + xml.append("").append(update.getWeight()).append(""); + xml.append("").append(update.getMode()).append(""); + xml.append("").append(update.getThreshold()).append(""); + + xml.append(FOOTER); + return (R) request.toBuilder().payload(xml.toString()).build(); + } + + @Override + public R bindToRequest(R request, Object input) { + throw new UnsupportedOperationException("use map form"); + } +} diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java new file mode 100644 index 0000000000..a7883b4e30 --- /dev/null +++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java @@ -0,0 +1,232 @@ +/** + * 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.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Objects; + +/** + * holds updates for a record + * + * @author Adrian Cole + */ +public final class UpdatePoolRecord { + + /** + * @param spec what to prime updates from + * @param pointsTo new value to point to. + */ + public static UpdatePoolRecord pointingTo(PoolRecordSpec spec, String pointsTo) { + return new Builder().from(spec).pointsTo(pointsTo).build(); + } + + private final String pointsTo; + private final String mode; + private final int priority; + private final int weight; + private final int failOverDelay; + private final int threshold; + private final int ttl; + + private UpdatePoolRecord(String pointsTo, String mode, int priority, int weight, int failOverDelay, int threshold, + int ttl) { + this.pointsTo = checkNotNull(pointsTo, "pointsTo"); + this.mode = checkNotNull(mode, "mode for %s", pointsTo); + this.priority = priority; + this.weight = weight; + checkArgument(weight >= 0, "weight of %s must be unsigned", pointsTo); + this.failOverDelay = failOverDelay; + checkArgument(failOverDelay >= 0, "failOverDelay of %s must be unsigned", pointsTo); + this.threshold = threshold; + checkArgument(threshold >= 0, "threshold of %s must be unsigned", pointsTo); + this.ttl = ttl; + checkArgument(ttl >= 0, "ttl of %s must be unsigned", pointsTo); + } + + /** + * correlates to {@link TrafficControllerPoolRecord#getPointsTo()} + */ + public String getPointsTo() { + return pointsTo; + } + + /** + * correlates to {@link PoolRecordSpec#getState()} + */ + public String getMode() { + return mode; + } + + /** + * correlates to {@link PoolRecordSpec#getPriority()} + */ + public int getPriority() { + return priority; + } + + /** + * correlates to {@link PoolRecordSpec#getWeight()} + */ + public int getWeight() { + return weight; + } + + /** + * correlates to {@link PoolRecordSpec#getFailOverDelay()} + */ + public int getFailOverDelay() { + return failOverDelay; + } + + /** + * correlates to {@link PoolRecordSpec#getThreshold()} + */ + public int getThreshold() { + return threshold; + } + + /** + * correlates to {@link PoolRecordSpec#getTTL()} + */ + public int getTTL() { + return ttl; + } + + @Override + public int hashCode() { + return Objects.hashCode(pointsTo, mode, priority, weight, failOverDelay, threshold, ttl); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UpdatePoolRecord that = UpdatePoolRecord.class.cast(obj); + return equal(this.pointsTo, that.pointsTo) && equal(this.mode, that.mode) && equal(this.priority, that.priority) + && equal(this.weight, that.weight) && equal(this.failOverDelay, that.failOverDelay) + && equal(this.threshold, that.threshold) && equal(this.ttl, that.ttl); + } + + @Override + public String toString() { + return toStringHelper(this).add("pointsTo", pointsTo).add("mode", mode).add("priority", priority) + .add("weight", weight).add("failOverDelay", failOverDelay).add("threshold", threshold).add("ttl", ttl) + .toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().from(this); + } + + public final static class Builder { + private String pointsTo; + private String mode; + private int priority; + private int weight; + private int failOverDelay; + private int threshold; + private int ttl; + + /** + * @see UpdatePoolRecord#getPointsTo() + */ + public Builder pointsTo(String pointsTo) { + this.pointsTo = pointsTo; + return this; + } + + /** + * @see UpdatePoolRecord#getMode() + */ + public Builder mode(String mode) { + this.mode = mode; + return this; + } + + /** + * @see UpdatePoolRecord#getPriority() + */ + public Builder priority(int priority) { + this.priority = priority; + return this; + } + + /** + * @see UpdatePoolRecord#getWeight() + */ + public Builder weight(int weight) { + this.weight = weight; + return this; + } + + /** + * @see UpdatePoolRecord#getFailOverDelay() + */ + public Builder failOverDelay(int failOverDelay) { + this.failOverDelay = failOverDelay; + return this; + } + + /** + * @see UpdatePoolRecord#getThreshold() + */ + public Builder threshold(int threshold) { + this.threshold = threshold; + return this; + } + + /** + * @see UpdatePoolRecord#getTTL() + */ + public Builder ttl(int ttl) { + this.ttl = ttl; + return this; + } + + public UpdatePoolRecord build() { + return new UpdatePoolRecord(pointsTo, mode, priority, weight, failOverDelay, threshold, ttl); + } + + public Builder from(PoolRecordSpec in) { + return this.mode(in.getState()).weight(in.getWeight()).failOverDelay(in.getFailOverDelay()) + .threshold(in.getThreshold()).ttl(in.getTTL()); + } + + public Builder from(TrafficControllerPoolRecord in) { + return this.weight(in.getWeight()).pointsTo(in.getPointsTo()).priority(in.getPriority()); + } + + public Builder from(UpdatePoolRecord in) { + return this.pointsTo(in.pointsTo).mode(in.mode).priority(in.priority).weight(in.weight) + .failOverDelay(in.failOverDelay).threshold(in.threshold).ttl(in.ttl); + } + } +} diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java index da0c80f14e..1509528eea 100644 --- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java +++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java @@ -25,6 +25,7 @@ import org.jclouds.ultradns.ws.domain.PoolRecordSpec; import org.jclouds.ultradns.ws.domain.ResourceRecord; import org.jclouds.ultradns.ws.domain.TrafficControllerPool; import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord; +import org.jclouds.ultradns.ws.domain.UpdatePoolRecord; import com.google.common.collect.FluentIterable; @@ -102,12 +103,26 @@ public interface TrafficControllerPoolApi { * Retrieves information about the specified pool record * * @param poolRecordID - * {@see TrafficControllerPoolRecord#getId()} + * {@link TrafficControllerPoolRecord#getId()} * @return null if not found */ @Nullable PoolRecordSpec getRecordSpec(String poolRecordID); + /** + * This request updates an existing pool record. + * + * @param poolRecordID + * {@link TrafficControllerPoolRecord#getId()} + * @param update + * what to update, usually primed via + * {@link UpdatePoolRecord#pointingTo(PoolRecordSpec, String)} or + * {@link org.jclouds.ultradns.ws.domain.UpdatePoolRecord.Builder#from(PoolRecordSpec)} + * @throws ResourceNotFoundException + * if the record doesn't exist + */ + void updateRecord(String poolRecordID, UpdatePoolRecord update) throws ResourceNotFoundException; + /** * deletes a specific pooled resource record * diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java index 6127b3495c..c20cc7f72f 100644 --- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java +++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java @@ -25,15 +25,18 @@ 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.MapBinder; import org.jclouds.rest.annotations.Payload; 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.binders.UpdatePoolRecordToXML; import org.jclouds.ultradns.ws.domain.PoolRecordSpec; import org.jclouds.ultradns.ws.domain.TrafficControllerPool; import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord; +import org.jclouds.ultradns.ws.domain.UpdatePoolRecord; import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth; import org.jclouds.ultradns.ws.xml.AttributeHandler; import org.jclouds.ultradns.ws.xml.PoolRecordSpecHandler; @@ -122,6 +125,15 @@ public interface TrafficControllerPoolAsyncApi { @Fallback(NullOnNotFoundOr404.class) ListenableFuture getRecordSpec(@PayloadParam("poolRecordId") String poolRecordID); + /** + * @see TrafficControllerPoolApi#getRecordSpec(String) + */ + @Named("updatePoolRecord>") + @POST + @MapBinder(UpdatePoolRecordToXML.class) + ListenableFuture updateRecord(@PayloadParam("poolRecordID") String poolRecordID, + @PayloadParam("update") UpdatePoolRecord update) throws ResourceNotFoundException; + /** * @see TrafficControllerPoolApi#deleteRecord(String) */ diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiExpectTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiExpectTest.java index fc8833bbc8..583a562739 100644 --- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiExpectTest.java +++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiExpectTest.java @@ -23,8 +23,10 @@ import static org.testng.Assert.assertNull; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.ultradns.ws.UltraDNSWSApi; import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException; +import org.jclouds.ultradns.ws.domain.UpdatePoolRecord; import org.jclouds.ultradns.ws.internal.BaseUltraDNSWSApiExpectTest; import org.jclouds.ultradns.ws.parse.GetPoolRecordSpecResponseTest; import org.jclouds.ultradns.ws.parse.GetTCLoadBalancingPoolsByZoneResponseTest; @@ -172,6 +174,33 @@ public class TrafficControllerPoolApiExpectTest extends BaseUltraDNSWSApiExpectT assertNull(notFound.getTrafficControllerPoolApiForZone("jclouds.org.").getRecordSpec("04053D8E57C7931F")); } + UpdatePoolRecord update = UpdatePoolRecord.builder() + .pointsTo("www.baz.com.") + .mode("Normal") + .weight(98) + .failOverDelay(0) + .threshold(1) + .ttl(200).build(); + + HttpRequest updateRecord = HttpRequest.builder().method("POST") + .endpoint("https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01") + .addHeader("Host", "ultra-api.ultradns.com:8443") + .payload(payloadFromResourceWithContentType("/update_poolrecord.xml", "application/xml")).build(); + + HttpResponse updateRecordResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/poolrecord_updated.xml", "application/xml")).build(); + + public void testUpdateRecordWhenResponseIs2xx() { + UltraDNSWSApi success = requestSendsResponse(updateRecord, updateRecordResponse); + success.getTrafficControllerPoolApiForZone("jclouds.org.").updateRecord("04053D8E57C7931F", update); + } + + @Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Pool Record does not exist.") + public void testUpdateRecordWhenResponseNotFound() { + UltraDNSWSApi notFound = requestSendsResponse(updateRecord, recordDoesntExist); + notFound.getTrafficControllerPoolApiForZone("jclouds.org.").updateRecord("04053D8E57C7931F", update); + } + HttpRequest deleteRecord = HttpRequest.builder().method("POST") .endpoint("https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01") .addHeader("Host", "ultra-api.ultradns.com:8443") diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java index 11d1fb1cd2..c173d4c4a3 100644 --- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java +++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java @@ -35,6 +35,7 @@ import org.jclouds.ultradns.ws.domain.PoolRecordSpec; import org.jclouds.ultradns.ws.domain.TrafficControllerPool; import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord; import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord.Status; +import org.jclouds.ultradns.ws.domain.UpdatePoolRecord; import org.jclouds.ultradns.ws.domain.Zone; import org.jclouds.ultradns.ws.internal.BaseUltraDNSWSApiLiveTest; import org.testng.annotations.AfterClass; @@ -152,6 +153,12 @@ public class TrafficControllerPoolApiLiveTest extends BaseUltraDNSWSApiLiveTest assertNull(api(zoneName).getRecordSpec("06063D9C54C5AE09")); } + @Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Pool Record does not exist.") + public void testUpdateRecordWhenNotFound() { + api(zoneName).updateRecord("06063D9C54C5AE09", + UpdatePoolRecord.builder().pointsTo("www.foo.com.").mode("Normal").build()); + } + String hostname = "www.tcpool." + zoneName; String poolId; @@ -223,6 +230,24 @@ public class TrafficControllerPoolApiLiveTest extends BaseUltraDNSWSApiLiveTest } @Test(dependsOnMethods = "addCNAMERecordsToPool") + public void testUpdateRecord() { + PoolRecordSpec spec = api(zoneName).getRecordSpec(cname2); + UpdatePoolRecord update = UpdatePoolRecord.builder().from(spec) + .pointsTo("www.baz.com.") + .weight(98) + .ttl(200).build(); + + api(zoneName).updateRecord(cname2, update); + + TrafficControllerPoolRecord record = getRecordById(cname2).get(); + assertEquals(record.getPointsTo(), "www.baz.com."); + + spec = api(zoneName).getRecordSpec(cname2); + assertEquals(spec.getWeight(), 98); + assertEquals(spec.getTTL(), 200); + } + + @Test(dependsOnMethods = "testUpdateRecord") public void testDeleteRecord() { api(zoneName).deleteRecord(cname1); assertFalse(getRecordById(cname1).isPresent()); diff --git a/providers/ultradns-ws/src/test/resources/poolrecord_updated.xml b/providers/ultradns-ws/src/test/resources/poolrecord_updated.xml new file mode 100644 index 0000000000..64d564f58e --- /dev/null +++ b/providers/ultradns-ws/src/test/resources/poolrecord_updated.xml @@ -0,0 +1 @@ +Successful \ No newline at end of file diff --git a/providers/ultradns-ws/src/test/resources/update_poolrecord.xml b/providers/ultradns-ws/src/test/resources/update_poolrecord.xml new file mode 100644 index 0000000000..3b33d73e1d --- /dev/null +++ b/providers/ultradns-ws/src/test/resources/update_poolrecord.xml @@ -0,0 +1 @@ +identitycredential04053D8E57C7931Fwww.baz.com.0020098Normal1 \ No newline at end of file