diff --git a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java index 1e4d16f7bb..6774568b70 100644 --- a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java +++ b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/domain/IpDetails.java @@ -26,7 +26,7 @@ import java.util.Arrays; import java.util.List; /** - * Represents detailed information about an available IP address. + * Represents detailed information about an IP address. */ public class IpDetails { diff --git a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java index 220f75952b..51154c292c 100644 --- a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java +++ b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpAsyncClient.java @@ -18,14 +18,7 @@ */ package org.jclouds.glesys.features; -import java.util.Set; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.MediaType; - +import com.google.common.util.concurrent.ListenableFuture; import org.jclouds.glesys.domain.IpDetails; import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.rest.annotations.ExceptionParser; @@ -34,13 +27,16 @@ import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import com.google.common.util.concurrent.ListenableFuture; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import java.util.Set; /** * Provides asynchronous access to IP Addresses via their REST API. *

* - * @author Adrian Cole + * @author Adrian Cole, Mattias Holmqvist + * * @see ServerClient * @see */ @@ -48,6 +44,41 @@ import com.google.common.util.concurrent.ListenableFuture; public interface IpAsyncClient { + /** + * @see IpClient#take + */ + @POST + @Path("/ip/take/format/json") + ListenableFuture take(@FormParam("ipaddress") String ipAddress); + + + /** + * @see IpClient#release + */ + @POST + @Path("/ip/release/format/json") + ListenableFuture release(@FormParam("ipaddress") String ipAddress); + + /** + * @see IpClient#add + */ + @POST + @Path("/ip/add/format/json") + ListenableFuture add(@FormParam("serverid") String serverId, + @FormParam("ipaddress") String ipAddress); + + + /** + * @see IpClient#remove + * + * TODO: add optional release_ip parameter + */ + @POST + @Path("/ip/remove/format/json") + ListenableFuture remove(@FormParam("ipaddress") String ipAddress, + @FormParam("serverid") String serverId); + + /** * @see IpClient#listFree */ diff --git a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java index 394c32d195..e7a8778f64 100644 --- a/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java +++ b/sandbox-providers/glesys/src/main/java/org/jclouds/glesys/features/IpClient.java @@ -28,13 +28,50 @@ import java.util.concurrent.TimeUnit; * Provides synchronous access to IP Addresses. *

* - * @author Adrian Cole + * @author Adrian Cole, Mattias Holmqvist * @see IpAsyncClient * @see */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) public interface IpClient { + /** + * Take a free IP address and add it to this account. You can list free IP addresses with the function listFree(). + * Once your free IP on this account you can add it to a server with the add() function. + * + * @param ipAddress + * @return + */ + void take(String ipAddress); + + /** + * Return an unused IP address to the pool of free ips. If the IP address is allocated to a server, + * it must first be removed by calling remove(ipAddress) before it can be released. + * + * @param ipAddress the IP address to be released + */ + void release(String ipAddress); + + /** + * Add an IP address to an server. The IP has to be free, but reserved to this account. You are able to list such addresses + * with listOwn() and reserve an address for this account by using take(). To find free ips you can use ip/listfree + * ip to an Xen-server you have to configure the server yourself, unless the ip was added during the c + * server (server/create). You can get detailed information such as gateway and netmask using the ip + * + * @param serverId the server to add the IP address to + * @param ipAddress the IP address to remove + */ + void add(String serverId, String ipAddress); + + /** + * Remove an IP address from a server. This does not release it back to GleSYS pool of free ips. The address will be + * kept on the account so that you can use it for other servers or the same server at a later time. To completely remove + * the IP address from this account, use the function release(). + * + * @param ipAddress the IP address to remove + * @param serverId the server to remove the IP address from + */ + void remove(String ipAddress, String serverId); /** * Get a set of all IP addresses that are available and not used on any account or server. @@ -51,9 +88,8 @@ public interface IpClient { * on different platforms. * * @param ipAddress the ip address - * @return details about the given IP saddress + * @return details about the given IP address */ IpDetails getIpDetails(String ipAddress); - } \ No newline at end of file diff --git a/sandbox-providers/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java b/sandbox-providers/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java index 810f53d972..7e7fddb932 100644 --- a/sandbox-providers/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java +++ b/sandbox-providers/glesys/src/test/java/org/jclouds/glesys/features/IpClientExpectTest.java @@ -18,23 +18,28 @@ */ package org.jclouds.glesys.features; -import static org.testng.Assert.assertEquals; - -import java.net.URI; - +import com.google.common.collect.ImmutableMultimap; import org.jclouds.glesys.GleSYSClient; import org.jclouds.glesys.domain.IpDetails; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; import org.jclouds.rest.BaseRestClientExpectTest; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMultimap; +import java.net.URI; +import java.util.Set; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; +import static org.jclouds.io.Payloads.newUrlEncodedFormPayload; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; +import static org.testng.collections.Sets.newHashSet; /** - * * Allows us to test a client via its side effects. - * + * * @author Adrian Cole */ @Test(groups = "unit", testName = "IpClientExpectTest") @@ -46,28 +51,199 @@ public class IpClientExpectTest extends BaseRestClientExpectTest { public void testGetIpDetailsWhenResponseIs2xx() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( - ImmutableMultimap. builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_get_details.json")).build()) - .getIpClient(); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( + ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_get_details.json")).build()) + .getIpClient(); assertEquals(client.getIpDetails("31.192.227.37"), IpDetails.builder().datacenter("Falkenberg").ipversion("4") - .platform("OpenVZ").ptr("31-192-227-37-static.serverhotell.net.").build()); + .platform("OpenVZ").ptr("31-192-227-37-static.serverhotell.net.").build()); } public void testGetIpDetailsWhenResponseIs4xxReturnsNull() { IpClient client = requestSendsResponse( - HttpRequest.builder().method("GET").endpoint( - URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( - ImmutableMultimap. builder().put("Accept", "application/json").put( - "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), - HttpResponse.builder().statusCode(404).build()).getIpClient(); + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/details/ipaddress/31.192.227.37/format/json")).headers( + ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(404).build()).getIpClient(); assertEquals(client.getIpDetails("31.192.227.37"), null); } + + public void testTakeWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/take/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_take.json")).build()) + .getIpClient(); + + client.take("46.21.105.186"); + } + + public void testTakeWhenResponseIs4xxThrowsResponseException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/take/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); + + try { + client.take("46.21.105.186"); + fail(); + } catch (HttpResponseException e) { + // Expected + } + } + + public void testReleaseWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/release/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_release.json")).build()) + .getIpClient(); + + client.release("46.21.105.186"); + } + + public void testReleaseWhenResponseIs4xxThrowsResponseException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/release/format/json")) + .headers(ImmutableMultimap.builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder().put("ipaddress", "46.21.105.186").build() + )).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); + + try { + client.release("46.21.105.186"); + fail(); + } catch (HttpResponseException e) { + // Expected + } + } + + public void testListFreeWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listfree/ipversion/4/datacenter/Falkenberg/platform/OpenVZ/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/ip_list_free.json")).build()) + .getIpClient(); + + Set expectedIps = newHashSet(); + expectedIps.addAll(asList("31.192.226.131", "31.192.226.133")); + assertEquals(client.listFree("4", "Falkenberg", "OpenVZ"), expectedIps); + } + + public void testListFreeWhenResponseIs404ReturnsEmptySet() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("GET").endpoint( + URI.create("https://api.glesys.com/ip/listfree/ipversion/4/datacenter/Falkenberg/platform/OpenVZ/format/json")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(), + HttpResponse.builder().statusCode(404).build()) + .getIpClient(); + + assertEquals(client.listFree("4", "Falkenberg", "OpenVZ"), emptySet()); + } + + public void testAddWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/add/format/json")) + .headers(ImmutableMultimap.builder().put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("serverid", "vz1946889") + .put("ipaddress", "31.192.227.37").build())).build(), + HttpResponse.builder().statusCode(200).build()) + .getIpClient(); + + client.add("vz1946889", "31.192.227.37"); + } + + public void testAddWhenResponseIs4xxThrowsHttpException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/add/format/json")) + .headers(ImmutableMultimap.builder().put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("serverid", "vz1946889") + .put("ipaddress", "31.192.227.37").build())).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); + + try { + client.add("vz1946889", "31.192.227.37"); + fail(); + } catch (HttpResponseException e) { + // Expected + } + } + + public void testRemoveWhenResponseIs2xx() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(200).build()) + .getIpClient(); + + client.remove("31.192.227.37", "vz1946889"); + } + + public void testRemoveWhenResponseIs4xxThrowsHttpException() { + IpClient client = requestSendsResponse( + HttpRequest.builder().method("POST").endpoint( + URI.create("https://api.glesys.com/ip/remove/format/json")) + .headers(ImmutableMultimap.builder().put( + "Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(newUrlEncodedFormPayload( + ImmutableMultimap.builder() + .put("ipaddress", "31.192.227.37") + .put("serverid", "vz1946889").build())).build(), + HttpResponse.builder().statusCode(400).build()) + .getIpClient(); + + try { + client.remove("31.192.227.37", "vz1946889"); + fail(); + } catch (HttpResponseException e) { + // Expected + } + } + } \ No newline at end of file diff --git a/sandbox-providers/glesys/src/test/resources/ip_release.json b/sandbox-providers/glesys/src/test/resources/ip_release.json new file mode 100644 index 0000000000..1367493276 --- /dev/null +++ b/sandbox-providers/glesys/src/test/resources/ip_release.json @@ -0,0 +1 @@ +{"response":{"status":{"code":"200","text":"OK"},"debug":{"input":{"ipaddress":"31.192.227.37"}}}} \ No newline at end of file diff --git a/sandbox-providers/glesys/src/test/resources/ip_take.json b/sandbox-providers/glesys/src/test/resources/ip_take.json new file mode 100644 index 0000000000..e0d9e408ca --- /dev/null +++ b/sandbox-providers/glesys/src/test/resources/ip_take.json @@ -0,0 +1 @@ +{"response":{"status":{"code":"200","text":"OK"},"debug":{"input":{"ipaddress":"46.21.105.186"}}}} \ No newline at end of file