You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2016/01/21 01:03:26 UTC
[02/19] jclouds git commit: JCLOUDS-613: Implement the DigitalOcean
v2 API
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
new file mode 100644
index 0000000..73c7451
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiLiveTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.features;
+
+import static org.testng.Assert.assertTrue;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+import org.testng.util.Strings;
+
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "RegionApiLiveTest")
+public class RegionApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListRegions() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All regions must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some regions to be returned");
+ }
+
+ public void testListRegionsOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1)).allMatch(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All regions must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some regions to be returned");
+ }
+
+ private RegionApi api() {
+ return api.regionApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
new file mode 100644
index 0000000..8c8c326
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/RegionApiMockTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "RegionApiMockTest", singleThreaded = true)
+public class RegionApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListRegions() throws InterruptedException {
+ server.enqueue(jsonResponse("/regions-first.json"));
+ server.enqueue(jsonResponse("/regions-last.json"));
+
+ Iterable<Region> regions = api.regionApi().list().concat();
+
+ assertEquals(size(regions), 10); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/regions");
+ assertSent(server, "GET", "/regions?page=2&per_page=5");
+ }
+
+ public void testListRegionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Region> regions = api.regionApi().list().concat();
+
+ assertTrue(isEmpty(regions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/regions");
+ }
+
+ public void testListRegionsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/regions-first.json"));
+
+ Iterable<Region> regions = api.regionApi().list(page(1).perPage(5));
+
+ assertEquals(size(regions), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/regions?page=1&per_page=5");
+ }
+
+ public void testListRegionsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Region> regions = api.regionApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(regions));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/regions?page=1&per_page=5");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
new file mode 100644
index 0000000..a9a8566
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiLiveTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.features;
+
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jclouds.digitalocean2.domain.Size;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiLiveTest;
+import org.testng.annotations.Test;
+import org.testng.util.Strings;
+
+import com.google.common.base.Predicate;
+
+@Test(groups = "live", testName = "SizeApiLiveTest")
+public class SizeApiLiveTest extends BaseDigitalOcean2ApiLiveTest {
+
+ public void testListSizes() {
+ final AtomicInteger found = new AtomicInteger(0);
+ // DigitalOcean return 25 records per page by default. Inspect at most 2 pages
+ assertTrue(api().list().concat().limit(50).allMatch(new Predicate<Size>() {
+ @Override
+ public boolean apply(Size input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All sizes must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some sizes to be returned");
+ }
+
+ public void testListSizesOnePage() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(page(1)).allMatch(new Predicate<Size>() {
+ @Override
+ public boolean apply(Size input) {
+ found.incrementAndGet();
+ return !Strings.isNullOrEmpty(input.slug());
+ }
+ }), "All sizes must have the 'slug' field populated");
+ assertTrue(found.get() > 0, "Expected some sizes to be returned");
+ }
+
+ private SizeApi api() {
+ return api.sizeApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
new file mode 100644
index 0000000..7403518
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/features/SizeApiMockTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.features;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.Builder.page;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.digitalocean2.domain.Size;
+import org.jclouds.digitalocean2.internal.BaseDigitalOcean2ApiMockTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit", testName = "SizeApiMockTest", singleThreaded = true)
+public class SizeApiMockTest extends BaseDigitalOcean2ApiMockTest {
+
+ public void testListSizes() throws InterruptedException {
+ server.enqueue(jsonResponse("/sizes-first.json"));
+ server.enqueue(jsonResponse("/sizes-last.json"));
+
+ Iterable<Size> sizes = api.sizeApi().list().concat();
+
+ assertEquals(size(sizes), 9); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+
+ assertSent(server, "GET", "/sizes");
+ assertSent(server, "GET", "/sizes?page=2&per_page=5");
+ }
+
+ public void testListSizesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Size> sizes = api.sizeApi().list().concat();
+
+ assertTrue(isEmpty(sizes));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/sizes");
+ }
+
+ public void testListSizesWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/sizes-first.json"));
+
+ Iterable<Size> sizes = api.sizeApi().list(page(1).perPage(5));
+
+ assertEquals(size(sizes), 5);
+ assertEquals(server.getRequestCount(), 1);
+
+ assertSent(server, "GET", "/sizes?page=1&per_page=5");
+ }
+
+ public void testListSizesWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+
+ Iterable<Size> sizes = api.sizeApi().list(page(1).perPage(5));
+
+ assertTrue(isEmpty(sizes));
+
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "/sizes?page=1&per_page=5");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToImageListOptionsTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToImageListOptionsTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToImageListOptionsTest.java
new file mode 100644
index 0000000..22985fa
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToImageListOptionsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.functions;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.PRIVATE_PARAM;
+import static org.jclouds.digitalocean2.domain.options.ImageListOptions.TYPE_PARAM;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.PAGE_PARAM;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.PER_PAGE_PARAM;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+
+import java.net.URI;
+
+import org.jclouds.digitalocean2.domain.options.ImageListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Multimap;
+
+@Test(groups = "unit", testName = "LinkToImageListOptionsTest")
+public class LinkToImageListOptionsTest {
+
+ public void testNoOptions() {
+ LinkToImageListOptions function = new LinkToImageListOptions();
+
+ ImageListOptions options = function.apply(URI.create("https://api.digitalocean.com/v2/images"));
+ assertNotNull(options);
+
+ Multimap<String, String> params = options.buildQueryParameters();
+ assertFalse(params.containsKey(PAGE_PARAM));
+ assertFalse(params.containsKey(PER_PAGE_PARAM));
+ assertFalse(params.containsKey(TYPE_PARAM));
+ assertFalse(params.containsKey(PRIVATE_PARAM));
+ }
+
+ public void testWithOptions() {
+ LinkToImageListOptions function = new LinkToImageListOptions();
+
+ ImageListOptions options = function.apply(URI
+ .create("https://api.digitalocean.com/v2/images?page=1&per_page=5&type=distribution&private=true"));
+ assertNotNull(options);
+
+ Multimap<String, String> params = options.buildQueryParameters();
+ assertEquals(getOnlyElement(params.get(PAGE_PARAM)), "1");
+ assertEquals(getOnlyElement(params.get(PER_PAGE_PARAM)), "5");
+ assertEquals(getOnlyElement(params.get(TYPE_PARAM)), "distribution");
+ assertEquals(getOnlyElement(params.get(PRIVATE_PARAM)), "true");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToListOptionsTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToListOptionsTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToListOptionsTest.java
new file mode 100644
index 0000000..2bb3544
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/functions/LinkToListOptionsTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.functions;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.PAGE_PARAM;
+import static org.jclouds.digitalocean2.domain.options.ListOptions.PER_PAGE_PARAM;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+
+import java.net.URI;
+
+import org.jclouds.digitalocean2.domain.options.ListOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Multimap;
+
+@Test(groups = "unit", testName = "LinkToListOptionsTest")
+public class LinkToListOptionsTest {
+
+ public void testNoOptions() {
+ LinkToListOptions function = new LinkToListOptions();
+
+ ListOptions options = function.apply(URI.create("https://api.digitalocean.com/v2/actions"));
+ assertNotNull(options);
+
+ Multimap<String, String> params = options.buildQueryParameters();
+ assertFalse(params.containsKey(PAGE_PARAM));
+ assertFalse(params.containsKey(PER_PAGE_PARAM));
+ }
+
+ public void testWithOptions() {
+ LinkToListOptions function = new LinkToListOptions();
+
+ ListOptions options = function.apply(URI.create("https://api.digitalocean.com/v2/actions?page=2&per_page=5"));
+ assertNotNull(options);
+
+ Multimap<String, String> params = options.buildQueryParameters();
+ assertEquals(getOnlyElement(params.get(PAGE_PARAM)), "2");
+ assertEquals(getOnlyElement(params.get(PER_PAGE_PARAM)), "5");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiLiveTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiLiveTest.java
new file mode 100644
index 0000000..18f97c6
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiLiveTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.internal;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.testng.Assert.assertEquals;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.compute.config.ComputeServiceProperties;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.digitalocean2.DigitalOcean2Api;
+import org.jclouds.digitalocean2.domain.Action;
+import org.jclouds.digitalocean2.domain.Image;
+import org.jclouds.digitalocean2.domain.Region;
+import org.jclouds.digitalocean2.domain.Size;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+
+public class BaseDigitalOcean2ApiLiveTest extends BaseApiLiveTest<DigitalOcean2Api> {
+
+ protected Predicate<Integer> actionCompleted;
+ protected Predicate<AtomicReference<NodeMetadata>> nodeRunning;
+ protected Predicate<Integer> nodeTerminated;
+ protected Predicate<Integer> dropletOff;
+
+ public BaseDigitalOcean2ApiLiveTest() {
+ provider = "digitalocean2";
+ }
+
+ @Override protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ props.put(ComputeServiceProperties.POLL_INITIAL_PERIOD, 1000);
+ props.put(ComputeServiceProperties.POLL_MAX_PERIOD, 10000);
+ return props;
+ }
+
+ @Override protected DigitalOcean2Api create(Properties props, Iterable<Module> modules) {
+ Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
+ actionCompleted = injector.getInstance(Key.get(new TypeLiteral<Predicate<Integer>>(){}));
+ nodeTerminated = injector.getInstance(Key.get(new TypeLiteral<Predicate<Integer>>(){},
+ Names.named(TIMEOUT_NODE_TERMINATED)));
+ return injector.getInstance(DigitalOcean2Api.class);
+ }
+
+ protected void assertActionCompleted(int actionId) {
+ checkState(actionCompleted.apply(actionId), "Timeout waiting for action: %s", actionId);
+ Action action = api.actionApi().get(actionId);
+ assertEquals(action.status(), Action.Status.COMPLETED);
+ }
+
+ protected void assertNodeTerminated(int dropletId) {
+ assertEquals(nodeTerminated.apply(dropletId), true, String.format("Timeout waiting for dropletId: %s", dropletId));
+ }
+
+ protected Region firstAvailableRegion() {
+ return api.regionApi().list().concat().firstMatch(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region input) {
+ return input.available();
+ }
+ }).get();
+ }
+
+ protected Size cheapestSizeInRegion(final Region region) {
+ return sizesByPrice().min(api.sizeApi().list().concat().filter(new Predicate<Size>() {
+ @Override
+ public boolean apply(Size input) {
+ return input.available() && input.regions().contains(region.slug());
+ }
+ }));
+ }
+
+ protected Image ubuntuImageInRegion(final Region region) {
+ return api.imageApi().list().concat().firstMatch(new Predicate<Image>() {
+ @Override
+ public boolean apply(Image input) {
+ return "Ubuntu".equalsIgnoreCase(input.distribution()) && !isNullOrEmpty(input.slug())
+ && input.regions().contains(region.slug());
+ }
+ }).get();
+ }
+
+ protected static Ordering<Size> sizesByPrice() {
+ return new Ordering<Size>() {
+ @Override
+ public int compare(Size left, Size right) {
+ return ComparisonChain.start()
+ .compare(left.priceHourly(), right.priceHourly())
+ .compare(left.priceMonthly(), right.priceMonthly())
+ .result();
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiMockTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiMockTest.java
new file mode 100644
index 0000000..78550a5
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/internal/BaseDigitalOcean2ApiMockTest.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.internal;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.digitalocean2.DigitalOcean2Api;
+import org.jclouds.digitalocean2.DigitalOcean2ProviderMetadata;
+import org.jclouds.json.Json;
+import org.jclouds.rest.ApiContext;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.Resources;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.JsonParser;
+import com.google.inject.Module;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import com.squareup.okhttp.mockwebserver.RecordedRequest;
+
+public class BaseDigitalOcean2ApiMockTest {
+
+ private static final String MOCK_BEARER_TOKEN = "c5401990f0c24135e8d6b5d260603fc71696d4738da9aa04a720229a01a2521d";
+ private static final String DEFAULT_ENDPOINT = new DigitalOcean2ProviderMetadata().getEndpoint();
+
+ private final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor()));
+
+ protected MockWebServer server;
+ protected DigitalOcean2Api api;
+ private Json json;
+
+ // So that we can ignore formatting.
+ private final JsonParser parser = new JsonParser();
+
+
+ @BeforeMethod
+ public void start() throws IOException {
+ server = new MockWebServer();
+ server.play();
+ ApiContext<DigitalOcean2Api> ctx = ContextBuilder.newBuilder("digitalocean2")
+ .credentials("", MOCK_BEARER_TOKEN)
+ .endpoint(url(""))
+ .modules(modules)
+ .build();
+ json = ctx.utils().injector().getInstance(Json.class);
+ api = ctx.getApi();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void stop() throws IOException {
+ server.shutdown();
+ api.close();
+ }
+
+ protected String url(String path) {
+ return server.getUrl(path).toString();
+ }
+
+ protected MockResponse jsonResponse(String resource) {
+ return new MockResponse().addHeader("Content-Type", "application/json").setBody(stringFromResource(resource));
+ }
+
+ protected MockResponse response404() {
+ return new MockResponse().setStatus("HTTP/1.1 404 Not Found");
+ }
+
+ protected MockResponse response204() {
+ return new MockResponse().setStatus("HTTP/1.1 204 No Content");
+ }
+
+ protected String stringFromResource(String resourceName) {
+ try {
+ return Resources.toString(getClass().getResource(resourceName), Charsets.UTF_8)
+ .replace(DEFAULT_ENDPOINT, url(""));
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ protected <T> T onlyObjectFromResource(String resourceName, TypeToken<Map<String, T>> type) {
+ // Assume JSON objects passed here will be in the form: { "entity": { ... } }
+ String text = stringFromResource(resourceName);
+ Map<String, T> object = json.fromJson(text, type.getType());
+ checkArgument(!object.isEmpty(), "The given json does not contain any object: %s", text);
+ checkArgument(object.keySet().size() == 1, "The given json does not contain more than one object: %s", text);
+ return object.get(getOnlyElement(object.keySet()));
+ }
+
+ protected <T> T objectFromResource(String resourceName, Class<T> type) {
+ String text = stringFromResource(resourceName);
+ return json.fromJson(text, type);
+ }
+
+ protected RecordedRequest assertSent(MockWebServer server, String method, String path) throws InterruptedException {
+ RecordedRequest request = server.takeRequest();
+ assertEquals(request.getMethod(), method);
+ assertEquals(request.getPath(), path);
+ assertEquals(request.getHeader("Accept"), "application/json");
+ assertEquals(request.getHeader("Authorization"), "Bearer " + MOCK_BEARER_TOKEN);
+ return request;
+ }
+
+ protected RecordedRequest assertSent(MockWebServer server, String method, String path, String json)
+ throws InterruptedException {
+ RecordedRequest request = assertSent(server, method, path);
+ assertEquals(request.getHeader("Content-Type"), "application/json");
+ assertEquals(parser.parse(new String(request.getBody(), Charsets.UTF_8)), parser.parse(json));
+ return request;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/DSAKeysTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/DSAKeysTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/DSAKeysTest.java
new file mode 100644
index 0000000..91f3c96
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/DSAKeysTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.ssh;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+import org.jclouds.util.Strings2;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for the {@link DSAKeys} class.
+ */
+@Test(groups = "unit", testName = "DSAKeysTest")
+public class DSAKeysTest {
+
+ private static final String expectedFingerPrint = "2a:54:bb:8e:ba:44:96:c8:6c:9c:40:34:3c:4d:38:e4";
+
+ @Test
+ public void testCanReadRsaAndCompareFingerprintOnPublicRSAKey() throws IOException {
+ String dsa = Strings2.toStringAndClose(getClass().getResourceAsStream("/ssh-dsa.pub"));
+ String fingerPrint = DSAKeys.fingerprintPublicKey(dsa);
+ assertEquals(fingerPrint, expectedFingerPrint);
+ }
+
+ @Test
+ public void testEncodeAsOpenSSH() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
+ String dsa = Strings2.toStringAndClose(getClass().getResourceAsStream("/ssh-dsa.pub"));
+ DSAPublicKeySpec spec = DSAKeys.publicKeySpecFromOpenSSH(dsa);
+ DSAPublicKey key = (DSAPublicKey) KeyFactory.getInstance("DSA").generatePublic(spec);
+
+ assertEquals(DSAKeys.encodeAsOpenSSH(key), dsa);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/ECDSAKeysTest.java
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/ECDSAKeysTest.java b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/ECDSAKeysTest.java
new file mode 100644
index 0000000..2053ac7
--- /dev/null
+++ b/providers/digitalocean2/src/test/java/org/jclouds/digitalocean2/ssh/ECDSAKeysTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.digitalocean2.ssh;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+import org.jclouds.util.Strings2;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for the {@link ECDSAKeysTest} class.
+ */
+@Test(groups = "unit", testName = "ECDSAKeysTest")
+public class ECDSAKeysTest {
+
+ private static final String expectedFingerPrint = "0e:9f:aa:cc:3e:79:5d:1e:f9:19:58:08:dc:c4:5e:1c";
+
+ @Test
+ public void testCanReadRsaAndCompareFingerprintOnPublicECDSAKey() throws IOException {
+ String ecdsa = Strings2.toStringAndClose(getClass().getResourceAsStream("/ssh-ecdsa.pub"));
+ String fingerPrint = ECDSAKeys.fingerprintPublicKey(ecdsa);
+ assertEquals(fingerPrint, expectedFingerPrint);
+ }
+
+ @Test
+ public void testEncodeAsOpenSSH() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
+ String ecdsa = Strings2.toStringAndClose(getClass().getResourceAsStream("/ssh-ecdsa.pub"));
+ ECPublicKeySpec spec = ECDSAKeys.publicKeySpecFromOpenSSH(ecdsa);
+ ECPublicKey key = (ECPublicKey) KeyFactory.getInstance("EC").generatePublic(spec);
+
+ assertTrue(ecdsa.startsWith(ECDSAKeys.encodeAsOpenSSH(key)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/action.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/action.json b/providers/digitalocean2/src/test/resources/action.json
new file mode 100644
index 0000000..0202ca0
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/action.json
@@ -0,0 +1,33 @@
+{
+ "action": {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "completed",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "destroy"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/actions-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/actions-first.json b/providers/digitalocean2/src/test/resources/actions-first.json
new file mode 100644
index 0000000..c19fde3
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/actions-first.json
@@ -0,0 +1,168 @@
+{
+ "actions" : [
+ {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "completed",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "destroy"
+ },
+ {
+ "started_at" : "2015-05-19T15:07:55Z",
+ "region" : {
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true,
+ "slug" : "nyc1",
+ "name" : "New York 1"
+ },
+ "status" : "completed",
+ "resource_type" : "droplet",
+ "region_slug" : "nyc1",
+ "id" : 50899364,
+ "resource_id" : 5346565,
+ "completed_at" : "2015-05-19T15:08:04Z",
+ "type" : "destroy"
+ },
+ {
+ "completed_at" : "2015-05-19T13:39:59Z",
+ "type" : "create",
+ "region" : {
+ "name" : "New York 1",
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true,
+ "slug" : "nyc1"
+ },
+ "started_at" : "2015-05-19T13:39:12Z",
+ "resource_type" : "droplet",
+ "status" : "completed",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50892713
+ },
+ {
+ "resource_id" : 5346565,
+ "region_slug" : "nyc1",
+ "id" : 50888077,
+ "status" : "completed",
+ "resource_type" : "droplet",
+ "region" : {
+ "name" : "New York 1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true,
+ "slug" : "nyc1",
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T12:37:23Z",
+ "type" : "create",
+ "completed_at" : "2015-05-19T12:38:13Z"
+ },
+ {
+ "completed_at" : "2015-05-19T11:33:00Z",
+ "type" : "destroy",
+ "status" : "completed",
+ "resource_type" : "droplet",
+ "started_at" : "2015-05-19T11:32:55Z",
+ "region" : {
+ "available" : true,
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "slug" : "nyc1",
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "name" : "New York 1"
+ },
+ "region_slug" : "nyc1",
+ "id" : 50884032,
+ "resource_id" : 5344505
+ }
+ ],
+ "links" : {
+ "pages" : {
+ "last" : "https://api.digitalocean.com/v2/actions?page=2&per_page=5",
+ "next" : "https://api.digitalocean.com/v2/actions?page=2&per_page=5"
+ }
+ },
+ "meta" : {
+ "total" : 8
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/actions-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/actions-last.json b/providers/digitalocean2/src/test/resources/actions-last.json
new file mode 100644
index 0000000..5d86e7a
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/actions-last.json
@@ -0,0 +1,106 @@
+{
+ "meta" : {
+ "total" : 8
+ },
+ "links" : {
+ "pages" : {
+ "first" : "https://api.digitalocean.com/v2/actions?page=1&per_page=5",
+ "prev" : "https://api.digitalocean.com/v2/actions?page=1&per_page=5"
+ }
+ },
+ "actions" : [
+ {
+ "region" : {
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "available" : true,
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "slug" : "nyc1",
+ "name" : "New York 1"
+ },
+ "started_at" : "2014-01-18T22:39:08Z",
+ "type" : "create",
+ "resource_type" : "droplet",
+ "id" : 14115951,
+ "completed_at" : "2014-01-18T22:41:14Z",
+ "region_slug" : "nyc1",
+ "resource_id" : 1010699,
+ "status" : "completed"
+ },
+ {
+ "started_at" : "2014-01-18T22:39:06Z",
+ "type" : "create",
+ "resource_type" : "droplet",
+ "region" : {
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "slug" : "nyc1",
+ "name" : "New York 1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true
+ },
+ "resource_id" : 1010697,
+ "region_slug" : "nyc1",
+ "status" : "completed",
+ "id" : 14115948,
+ "completed_at" : "2014-01-18T22:40:43Z"
+ },
+ {
+ "region_slug" : "nyc1",
+ "resource_id" : 1010698,
+ "status" : "completed",
+ "id" : 14115949,
+ "completed_at" : "2014-01-18T22:44:08Z",
+ "type" : "create",
+ "started_at" : "2014-01-18T22:39:06Z",
+ "resource_type" : "droplet",
+ "region" : {
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ],
+ "slug" : "nyc1",
+ "name" : "New York 1",
+ "available" : true,
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ]
+ }
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/backups-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/backups-first.json b/providers/digitalocean2/src/test/resources/backups-first.json
new file mode 100644
index 0000000..f1083f1
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/backups-first.json
@@ -0,0 +1,26 @@
+{
+ "backups": [
+ {
+ "id": 7622989,
+ "name": "example.com 2014-11-14",
+ "distribution": "Ubuntu",
+ "slug": null,
+ "public": false,
+ "regions": [
+ "nyc3"
+ ],
+ "created_at": "2014-11-14T16:07:38Z",
+ "type": "snapshot",
+ "min_disk_size": 20
+ }
+ ],
+ "links" : {
+ "pages" : {
+ "last" : "https://api.digitalocean.com/v2/droplets/3067509/backups?page=2",
+ "next" : "https://api.digitalocean.com/v2/droplets/3067509/backups?page=2"
+ }
+ },
+ "meta": {
+ "total": 2
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/backups-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/backups-last.json b/providers/digitalocean2/src/test/resources/backups-last.json
new file mode 100644
index 0000000..c927c19
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/backups-last.json
@@ -0,0 +1,26 @@
+{
+ "backups": [
+ {
+ "id": 76229890,
+ "name": "example.com 2014-11-14",
+ "distribution": "Ubuntu",
+ "slug": null,
+ "public": false,
+ "regions": [
+ "nyc3"
+ ],
+ "created_at": "2014-11-14T16:07:38Z",
+ "type": "snapshot",
+ "min_disk_size": 20
+ }
+ ],
+ "links" : {
+ "pages" : {
+ "first" : "https://api.digitalocean.com/v2/droplets/3067509/backups?page=1",
+ "prev" : "https://api.digitalocean.com/v2/droplets/3067509/backups?page=1"
+ }
+ },
+ "meta": {
+ "total": 2
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/droplet-create-req.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/droplet-create-req.json b/providers/digitalocean2/src/test/resources/droplet-create-req.json
new file mode 100644
index 0000000..3ed5273
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/droplet-create-req.json
@@ -0,0 +1,12 @@
+{
+ "name": "digitalocean2-s-d5e",
+ "region": "sfo1",
+ "size": "512mb",
+ "image": "6374124",
+ "ssh_keys": [
+ 421192
+ ],
+ "backups": false,
+ "ipv6": false,
+ "private_networking": false
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/droplet-create-res.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/droplet-create-res.json b/providers/digitalocean2/src/test/resources/droplet-create-res.json
new file mode 100644
index 0000000..a7d37a5
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/droplet-create-res.json
@@ -0,0 +1,35 @@
+{
+ "droplet": {
+ "id": 2987224,
+ "name": "digitalocean2-s-d5e",
+ "memory": 512,
+ "vcpus": 1,
+ "disk": 20,
+ "locked": true,
+ "status": "new",
+ "kernel": {
+ "id": 70,
+ "name": "Ubuntu 10.04 x64 vmlinuz-2.6.32-41-server",
+ "version": "2.6.32-41-server"
+ },
+ "created_at": "2014-10-27T19:33:34Z",
+ "features": [
+ "virtio"
+ ],
+ "backup_ids": [],
+ "snapshot_ids": [],
+ "image": {},
+ "size_slug": "512mb",
+ "networks": {},
+ "region": {}
+ },
+ "links": {
+ "actions": [
+ {
+ "id": 35383956,
+ "rel": "create",
+ "href": "https://api.digitalocean.com/v2/actions/35383956"
+ }
+ ]
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/droplet.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/droplet.json b/providers/digitalocean2/src/test/resources/droplet.json
new file mode 100644
index 0000000..fb995c5
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/droplet.json
@@ -0,0 +1,105 @@
+{
+ "droplet" :
+ {
+ "created_at" : "2015-05-25T15:50:48Z",
+ "region" : {
+ "name" : "New York 1",
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true
+ },
+ "id" : 5425561,
+ "disk" : 20,
+ "networks" : {
+ "v6" : [],
+ "v4" : [
+ {
+ "type" : "public",
+ "ip_address" : "162.243.167.46",
+ "netmask" : "255.255.255.0",
+ "gateway" : "162.243.167.1"
+ }
+ ]
+ },
+ "backup_ids" : [],
+ "image" : {
+ "slug" : "ubuntu-14-10-x32",
+ "public" : true,
+ "created_at" : "2015-01-08T18:41:22Z",
+ "distribution" : "Ubuntu",
+ "id" : 9801951,
+ "type" : "snapshot",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "name" : "14.10 x32",
+ "min_disk_size" : 20
+ },
+ "vcpus" : 1,
+ "next_backup_window" : {
+ "end" : "2015-06-01T23:00:00Z",
+ "start" : "2015-06-01T00:00:00Z"
+ },
+ "locked" : false,
+ "snapshot_ids" : [],
+ "kernel" : {
+ "name" : "Ubuntu 14.10 x32 vmlinuz-3.16.0-28-generic",
+ "id" : 2926,
+ "version" : "3.16.0-28-generic"
+ },
+ "status" : "active",
+ "features" : [
+ "backups",
+ "virtio"
+ ],
+ "size" : {
+ "price_hourly" : 0.00744,
+ "slug" : "512mb",
+ "disk" : 20,
+ "available" : true,
+ "transfer" : 1,
+ "price_monthly" : 5,
+ "regions" : [
+ "nyc1",
+ "sgp1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "ams2",
+ "fra1"
+ ],
+ "memory" : 512,
+ "vcpus" : 1
+ },
+ "name" : "test1",
+ "size_slug" : "512mb",
+ "memory" : 512
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/droplets-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/droplets-first.json b/providers/digitalocean2/src/test/resources/droplets-first.json
new file mode 100644
index 0000000..5493f7f
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/droplets-first.json
@@ -0,0 +1,115 @@
+{
+ "links" : {
+ "pages" : {
+ "next" : "https://api.digitalocean.com/v2/droplets/5425561?page=2&per_page=1",
+ "last" : "https://api.digitalocean.com/v2/droplets/5425561?page=2&per_page=1"
+ }
+ },
+ "meta" : {
+ "total" : 2
+ },
+ "droplets" : [
+ {
+ "created_at" : "2015-05-25T15:50:48Z",
+ "region" : {
+ "name" : "New York 1",
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true
+ },
+ "id" : 5425561,
+ "disk" : 20,
+ "networks" : {
+ "v6" : [],
+ "v4" : [
+ {
+ "type" : "public",
+ "ip_address" : "162.243.167.46",
+ "netmask" : "255.255.255.0",
+ "gateway" : "162.243.167.1"
+ }
+ ]
+ },
+ "backup_ids" : [],
+ "image" : {
+ "slug" : "ubuntu-14-10-x32",
+ "public" : true,
+ "created_at" : "2015-01-08T18:41:22Z",
+ "distribution" : "Ubuntu",
+ "id" : 9801951,
+ "type" : "snapshot",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "name" : "14.10 x32",
+ "min_disk_size" : 20
+ },
+ "vcpus" : 1,
+ "next_backup_window" : {
+ "end" : "2015-06-01T23:00:00Z",
+ "start" : "2015-06-01T00:00:00Z"
+ },
+ "locked" : false,
+ "snapshot_ids" : [],
+ "kernel" : {
+ "name" : "Ubuntu 14.10 x32 vmlinuz-3.16.0-28-generic",
+ "id" : 2926,
+ "version" : "3.16.0-28-generic"
+ },
+ "status" : "active",
+ "features" : [
+ "backups",
+ "virtio"
+ ],
+ "size" : {
+ "price_hourly" : 0.00744,
+ "slug" : "512mb",
+ "disk" : 20,
+ "available" : true,
+ "transfer" : 1,
+ "price_monthly" : 5,
+ "regions" : [
+ "nyc1",
+ "sgp1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "ams2",
+ "fra1"
+ ],
+ "memory" : 512,
+ "vcpus" : 1
+ },
+ "name" : "test1",
+ "size_slug" : "512mb",
+ "memory" : 512
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/droplets-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/droplets-last.json b/providers/digitalocean2/src/test/resources/droplets-last.json
new file mode 100644
index 0000000..beeb654
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/droplets-last.json
@@ -0,0 +1,115 @@
+{
+ "links" : {
+ "pages" : {
+ "first" : "https://api.digitalocean.com/v2/droplets/5425561?page=2&per_page=1",
+ "prev" : "https://api.digitalocean.com/v2/droplets/5425561?page=2&per_page=1"
+ }
+ },
+ "meta" : {
+ "total" : 2
+ },
+ "droplets" : [
+ {
+ "created_at" : "2015-05-25T15:50:48Z",
+ "region" : {
+ "name" : "New York 1",
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true
+ },
+ "id" : 5425561,
+ "disk" : 20,
+ "networks" : {
+ "v6" : [],
+ "v4" : [
+ {
+ "type" : "public",
+ "ip_address" : "162.243.167.46",
+ "netmask" : "255.255.255.0",
+ "gateway" : "162.243.167.1"
+ }
+ ]
+ },
+ "backup_ids" : [],
+ "image" : {
+ "slug" : "ubuntu-14-10-x32",
+ "public" : true,
+ "created_at" : "2015-01-08T18:41:22Z",
+ "distribution" : "Ubuntu",
+ "id" : 9801951,
+ "type" : "snapshot",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "name" : "14.10 x32",
+ "min_disk_size" : 20
+ },
+ "vcpus" : 1,
+ "next_backup_window" : {
+ "end" : "2015-06-01T23:00:00Z",
+ "start" : "2015-06-01T00:00:00Z"
+ },
+ "locked" : false,
+ "snapshot_ids" : [],
+ "kernel" : {
+ "name" : "Ubuntu 14.10 x32 vmlinuz-3.16.0-28-generic",
+ "id" : 2926,
+ "version" : "3.16.0-28-generic"
+ },
+ "status" : "active",
+ "features" : [
+ "backups",
+ "virtio"
+ ],
+ "size" : {
+ "price_hourly" : 0.00744,
+ "slug" : "512mb",
+ "disk" : 20,
+ "available" : true,
+ "transfer" : 1,
+ "price_monthly" : 5,
+ "regions" : [
+ "nyc1",
+ "sgp1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "ams2",
+ "fra1"
+ ],
+ "memory" : 512,
+ "vcpus" : 1
+ },
+ "name" : "test1",
+ "size_slug" : "512mb",
+ "memory" : 512
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/image.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/image.json b/providers/digitalocean2/src/test/resources/image.json
new file mode 100644
index 0000000..e66fda9
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/image.json
@@ -0,0 +1,24 @@
+{
+ "image" : {
+ "type" : "snapshot",
+ "id" : 11732785,
+ "name" : "Maintenance Mode",
+ "min_disk_size" : 20,
+ "distribution" : "Debian",
+ "created_at" : "2015-05-05T21:21:25Z",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "slug" : null,
+ "public" : true
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/images-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/images-first.json b/providers/digitalocean2/src/test/resources/images-first.json
new file mode 100644
index 0000000..7d98cf9
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/images-first.json
@@ -0,0 +1,108 @@
+{
+ "meta" : {
+ "total" : 54
+ },
+ "links" : {
+ "pages" : {
+ "next" : "https://api.digitalocean.com/v2/images?page=2&per_page=5&type=distribution",
+ "last" : "https://api.digitalocean.com/v2/images?page=11&per_page=5&type=distribution"
+ }
+ },
+ "images" : [
+ {
+ "type" : "snapshot",
+ "id" : 11732785,
+ "name" : "Maintenance Mode",
+ "min_disk_size" : 20,
+ "distribution" : "Debian",
+ "created_at" : "2015-05-05T21:21:25Z",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "slug" : null,
+ "public" : true
+ },
+ {
+ "type" : "snapshot",
+ "id" : 11833262,
+ "distribution" : "CoreOS",
+ "created_at" : "2015-05-12T17:41:36Z",
+ "regions" : [
+ "nyc1",
+ "sfo1",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "public" : true,
+ "slug" : "coreos-stable",
+ "name" : "647.0.0 (stable)",
+ "min_disk_size" : 20
+ },
+ {
+ "min_disk_size" : 20,
+ "name" : "668.3.0 (beta)",
+ "created_at" : "2015-05-18T18:14:12Z",
+ "public" : true,
+ "regions" : [
+ "nyc1",
+ "sfo1",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "slug" : "coreos-beta",
+ "distribution" : "CoreOS",
+ "id" : 11919888,
+ "type" : "snapshot"
+ },
+ {
+ "type" : "snapshot",
+ "id" : 11919908,
+ "distribution" : "CoreOS",
+ "created_at" : "2015-05-18T18:20:08Z",
+ "public" : true,
+ "regions" : [
+ "nyc1",
+ "sfo1",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "slug" : "coreos-alpha",
+ "name" : "681.0.0 (alpha)",
+ "min_disk_size" : 20
+ },
+ {
+ "min_disk_size" : 30,
+ "name" : "vum-easter-move",
+ "slug" : null,
+ "regions" : [
+ "ams1"
+ ],
+ "public" : true,
+ "created_at" : "2015-04-10T07:31:20Z",
+ "distribution" : "Debian",
+ "id" : 11385199,
+ "type" : "snapshot"
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/images-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/images-last.json b/providers/digitalocean2/src/test/resources/images-last.json
new file mode 100644
index 0000000..89642fe
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/images-last.json
@@ -0,0 +1,123 @@
+{
+ "meta" : {
+ "total" : 54
+ },
+ "links" : {
+ "pages" : {
+ "prev" : "https://api.digitalocean.com/v2/images?page=1&per_page=5&type=distribution",
+ "first" : "https://api.digitalocean.com/v2/images?page=1&per_page=5&type=distribution"
+ }
+ },
+ "images" : [
+ {
+ "distribution" : "Fedora",
+ "min_disk_size" : 20,
+ "id" : 6370882,
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "name" : "20 x64",
+ "type" : "snapshot",
+ "slug" : "fedora-20-x64",
+ "public" : true,
+ "created_at" : "2014-09-26T15:29:01Z"
+ },
+ {
+ "name" : "20 x32",
+ "type" : "snapshot",
+ "distribution" : "Fedora",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "id" : 6370885,
+ "min_disk_size" : 20,
+ "created_at" : "2014-09-26T15:29:18Z",
+ "public" : true,
+ "slug" : "fedora-20-x32"
+ },
+ {
+ "created_at" : "2014-09-26T16:40:18Z",
+ "slug" : "centos-5-8-x64",
+ "public" : true,
+ "type" : "snapshot",
+ "name" : "5.10 x64",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "min_disk_size" : 20,
+ "id" : 6372321,
+ "distribution" : "CentOS"
+ },
+ {
+ "public" : true,
+ "slug" : "centos-5-8-x32",
+ "created_at" : "2014-09-26T16:45:29Z",
+ "id" : 6372425,
+ "min_disk_size" : 20,
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "distribution" : "CentOS",
+ "type" : "snapshot",
+ "name" : "5.10 x32"
+ },
+ {
+ "created_at" : "2014-09-26T16:56:00Z",
+ "public" : true,
+ "slug" : "debian-6-0-x64",
+ "type" : "snapshot",
+ "name" : "6.0 x64",
+ "regions" : [
+ "nyc1",
+ "ams1",
+ "sfo1",
+ "nyc2",
+ "ams2",
+ "sgp1",
+ "lon1",
+ "nyc3",
+ "ams3",
+ "fra1"
+ ],
+ "min_disk_size" : 20,
+ "id" : 6372581,
+ "distribution" : "Debian"
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/kernels-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/kernels-first.json b/providers/digitalocean2/src/test/resources/kernels-first.json
new file mode 100644
index 0000000..3ec05e0
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/kernels-first.json
@@ -0,0 +1,38 @@
+{
+ "links" : {
+ "pages" : {
+ "next" : "https://api.digitalocean.com/v2/droplets/5425561/kernels?page=2",
+ "last" : "https://api.digitalocean.com/v2/droplets/5425561/kernels?page=2"
+ }
+ },
+ "meta" : {
+ "total" : 10
+ },
+ "kernels" : [
+ {
+ "id" : 231,
+ "version" : "3.8.0-25-generic",
+ "name" : "DO-recovery-static-fsck"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-41-generic-pae",
+ "version" : "2.6.32-41-generic-pae",
+ "id" : 61
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-56-generic-pae",
+ "id" : 946,
+ "version" : "2.6.32-56-generic-pae"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-57-generic-pae",
+ "id" : 987,
+ "version" : "2.6.32-57-generic-pae"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-58-generic-pae",
+ "id" : 1269,
+ "version" : "2.6.32-58-generic-pae"
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/kernels-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/kernels-last.json b/providers/digitalocean2/src/test/resources/kernels-last.json
new file mode 100644
index 0000000..ca6c4f6
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/kernels-last.json
@@ -0,0 +1,38 @@
+{
+ "links" : {
+ "pages" : {
+ "first" : "https://api.digitalocean.com/v2/droplets/5425561/kernels?page=2",
+ "prev" : "https://api.digitalocean.com/v2/droplets/5425561/kernels?page=2"
+ }
+ },
+ "meta" : {
+ "total" : 10
+ },
+ "kernels" : [
+ {
+ "id" : 2311,
+ "version" : "3.8.0-25-generic",
+ "name" : "DO-recovery-static-fsck"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-41-generic-pae",
+ "version" : "2.6.32-41-generic-pae",
+ "id" : 6111
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-56-generic-pae",
+ "id" : 94611,
+ "version" : "2.6.32-56-generic-pae"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-57-generic-pae",
+ "id" : 98711,
+ "version" : "2.6.32-57-generic-pae"
+ },
+ {
+ "name" : "Ubuntu 10.04 x32 vmlinuz-2.6.32-58-generic-pae",
+ "id" : 1269,
+ "version" : "2.6.32-58-generic-pae"
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/key.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/key.json b/providers/digitalocean2/src/test/resources/key.json
new file mode 100644
index 0000000..db77937
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/key.json
@@ -0,0 +1,8 @@
+{
+ "ssh_key" : {
+ "id" : 767051,
+ "name" : "ubuntu-1204-64bit-338",
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCIshoBsRRK73Kwq9zlKauwNWClpaR99TpAxjtP5DcL3EMCTCDepaNPMHhPYO1rogRyjZrc2nsJ1ImCbZ3eEGFjspyhIyPk1NbYkAFsoSV7eBtqy1V7ddZ8t1ZsDexigAA5GnXZSWL4O0oVyZpBTrkzhZ49lbWUq8ch3Hhulvml1BR4nTx92ZcYIFFr1S7NEtua9xhKvRvUcSmgL/0A8deOBgkc85y5ADcEIt+nrlrOtIOW/agX0VPXNFjRxYW7MCkRGoDObOYEaT/mj7PyKk0kimmemxAH5wd6aOI4C82TmHjQmXTwXZgpVlrsdbxomOGDDGNSy7HoQLI/xMRvEf+9",
+ "fingerprint" : "1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90"
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/keys-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/keys-first.json b/providers/digitalocean2/src/test/resources/keys-first.json
new file mode 100644
index 0000000..93cbdd7
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/keys-first.json
@@ -0,0 +1,43 @@
+{
+ "meta" : {
+ "total" : 17
+ },
+ "ssh_keys" : [
+ {
+ "id" : 767051,
+ "name" : "ubuntu-1204-64bit-338",
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCIshoBsRRK73Kwq9zlKauwNWClpaR99TpAxjtP5DcL3EMCTCDepaNPMHhPYO1rogRyjZrc2nsJ1ImCbZ3eEGFjspyhIyPk1NbYkAFsoSV7eBtqy1V7ddZ8t1ZsDexigAA5GnXZSWL4O0oVyZpBTrkzhZ49lbWUq8ch3Hhulvml1BR4nTx92ZcYIFFr1S7NEtua9xhKvRvUcSmgL/0A8deOBgkc85y5ADcEIt+nrlrOtIOW/agX0VPXNFjRxYW7MCkRGoDObOYEaT/mj7PyKk0kimmemxAH5wd6aOI4C82TmHjQmXTwXZgpVlrsdbxomOGDDGNSy7HoQLI/xMRvEf+9",
+ "fingerprint" : "1a:cc:9b:88:c8:4f:b8:77:96:15:d2:0c:95:86:ff:90"
+ },
+ {
+ "id" : 767067,
+ "name" : "ubuntu-1204-64bit-ea4",
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdkjezVub0t+lSNSQYbO+Kcd/SoOJBCYgETqroI+ysHpPjRRNTYp3XSqSB0O3snnXM1GRfjPFatYFBUO9ajsb8cq0pzDPEIh3+cn+ZEoQ5WPg8OpaU6zVt2fPZNwqE2FCWEr2naH2yj2qV7Wzd1T9xYRfFdQ19YU1HuUhs16zvF6cO4BJH0YX2HLtZkxtOHonSbBx78/hBoV1NgSKlzlHVj9rhqmJO0fcEBeia4y/6G/65n8Z3hrM3zwyoN/eBKV7ngeJ70VU8tcP/QK9anB6hx4lOOSnWro2j3GKDwjSADL2vbOGl4OS6kM2y+6I04A6UAUkMu7KWCSr1Zf0zC45N",
+ "fingerprint" : "8f:81:51:d2:91:09:25:8f:c2:9c:b2:c3:6f:67:55:77"
+ },
+ {
+ "name" : "ubuntu-1204-64bit-jdk8-850",
+ "id" : 767363,
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD0zjvxYEyNYsVd7lfYXJxLON98OTgdMizD14XYCHwhVdJkS5ht9h+6dpiWbgatVgb/xyB63N2EeW+yZvQGlohWFytd1HvX7C8LFVtS/h4nrFJxtEYc2QXRl+WRRys6ekxYy6cwf/WV8nQPitUIPQru7vKR8bRpMPDBh+2Va/k7ApLd83AM9UYwXgCxDC7wlL/ttdJCV40buwPVvbOot97+qFPyg600/s6MGMX5448VifeBEEZG/qjzHj4SSGpQn+12O0dFLpYxOruzLLBpu2QxwvIqj1Nsm2ij6seMh0J8a5rQPl3ssPYrDCi8QGhL2NyzDSmT/9tYMLOlhBj7x3zN",
+ "fingerprint" : "1c:17:a2:c2:00:42:89:63:23:79:01:d7:b8:e6:a6:b4"
+ },
+ {
+ "name" : "ubuntu-1204-64bit-jdk8-ead",
+ "id" : 767375,
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCTMLrMCDSPF3BBeDjzSIYtVi8ACkxrvG4VT58sI+XjpeE9c3KGekqXqeTKZFwLxRllgbox8j610ABvcdAstBBSooSYmuDjT2nFotiTcw+5iHUe4A8BHG3HSlqXfuPlBCZ9bE4MdDBTPXqaDjiuvUqWdjpUihZeX2W2OtznDXDMFtn846Df0hD2V7ixHqVVQRXgflSfIoajEY5MlVG/Iuh3cjPpoJZ/IN/FcQnHjNe1FdJM8fC7kF+yY8sEE+u10KlfR1Y9WTdJSIiz5QDdlR4RTPXYyb9wyctD/sxCJ3xAgfZOG7Ey8eZF0+0MSbxkUGQll/xLuaP2aA5owIfMkEoj",
+ "fingerprint" : "a1:4d:20:c8:25:ce:2f:fa:43:8d:21:6f:65:77:c9:c4"
+ },
+ {
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCj9vCuDlTrQd+9WqlsQxWLg7VO2oVwq960CyW9C7rEro07wPGDdiOQornhyy7KiSL0mqYzFT5j0vTICSYeiGXIO/4SFPekz7vRN1yjO2GKaPokl/eYnbt1ABqB41jL0YX4ySwTm11O8A5yqWMouyxiGlSr13p61S2LTim5r5Z2C+4dKWHduloxnyCJJsh/56ZquS/ERgcrZusis9ybIP3aP+5DbXmyokGU83qGuNqSjZXaWc7MGFRTZzzzR9dQsbMvTgPwpyFXtSruIC+u7ca8oJ0b7+9WCAj2g/GXzbv/dsiJyJkEOtx6k1NN8n02PmL3o50vM1GGAjBFUN65JghD",
+ "name" : "ubuntu-1204-64bit-jdk8-ce2",
+ "id" : 767390,
+ "fingerprint" : "7f:bc:1c:af:e5:51:b6:1b:f0:bd:93:de:60:1a:e9:25"
+ }
+ ],
+ "links" : {
+ "pages" : {
+ "next" : "https://api.digitalocean.com/v2/account/keys?page=2&per_page=5",
+ "last" : "https://api.digitalocean.com/v2/account/keys?page=2&per_page=5"
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/keys-last.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/keys-last.json b/providers/digitalocean2/src/test/resources/keys-last.json
new file mode 100644
index 0000000..becbed1
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/keys-last.json
@@ -0,0 +1,25 @@
+{
+ "meta" : {
+ "total" : 7
+ },
+ "ssh_keys" : [
+ {
+ "fingerprint" : "a1:df:a0:64:e4:36:10:6b:de:8d:e6:65:55:17:8f:31",
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCHcVV1Rb5+/sCDF0eZ9Hw8vrHF+HYxptZRaNmnWsjzjeupeIiFgq6W1gRrDKB6pjA1t8R0b1xlcfb0361B5fRuwkeQTr2ALior6cipTgUUHT4UKcZMah7n09/YMPj2I7vzxjdX07PyB1z4OkL7FT3zBrsDTaR+ZngeFAVG59WmCj6vD2EqoZ2PeiEKETZOvQnZ3MEGiU5sYX9odIh5mjO5Jg1Q7oLjFzBbmMQ0oo/gkte8nBybHlD20iq1kzvmoSV4ECbTIa48yr8cgsX0d4M29YV9v2WCBfqaSRTRGVhfsalu9sgeSTHZ7F68g1wEkPXOzE3ZCUlZsKpskiYmCcTP",
+ "name" : "ubuntu-1204-64bit-jdk8-77a",
+ "id" : 799690
+ },
+ {
+ "name" : "ubuntu-1204-64bit-jdk8-a14",
+ "public_key" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeU4rK0wlk8YOOAWd9GURgJzOlgNkLEarq/y9RMXKq1zUW9Jf5J4UuztZm6HsSpAbiBfwL/QYBsFEhfDUZiW0B5p6CL0cR93vgUhGVgoi+v5Nl3KDEgMDryja48CdmzkCB3KoX4aRGRkahx6chrFByM5laEyGJETnDl0s4VyxZH07FGgQYqdWj8jg99stIvZ8Ktzlq5RMXPYePEA03vzzc5JrTEtdhuiy/wjxY8piq1j40uch6JEfcEzfPdkWY7LZt5KlOtrYoVFVmu+Mp3QSknhZPyMMZW5GOEtcr1IGtOEBCL3gJWz0E/H4e4Itt+3L2bNpNfHJmISJRXsNanuyn",
+ "fingerprint" : "f3:34:8d:dc:26:31:90:2b:55:f0:d4:77:d4:17:1e:f2",
+ "id" : 802469
+ }
+ ],
+ "links" : {
+ "pages" : {
+ "first" : "https://api.digitalocean.com/v2/account/keys?page=1&per_page=5",
+ "prev" : "https://api.digitalocean.com/v2/account/keys?page=1&per_page=5"
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/logback-test.xml b/providers/digitalocean2/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..4cac342
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/logback-test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<configuration scan="false">
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+ <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds-wire.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+ <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/jclouds-compute.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.jclouds">
+ <level value="DEBUG" />
+ <appender-ref ref="FILE" />
+ </logger>
+ <logger name="jclouds.compute">
+ <level value="DEBUG" />
+ <appender-ref ref="COMPUTEFILE" />
+ </logger>
+ <logger name="jclouds.wire">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+ <logger name="jclouds.headers">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+
+ <root>
+ <level value="INFO" />
+ </root>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/power-cycle.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/power-cycle.json b/providers/digitalocean2/src/test/resources/power-cycle.json
new file mode 100644
index 0000000..7af5963
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/power-cycle.json
@@ -0,0 +1,33 @@
+{
+ "action": {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "in-progress",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "power_cycle"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/power-off.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/power-off.json b/providers/digitalocean2/src/test/resources/power-off.json
new file mode 100644
index 0000000..7affe0a
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/power-off.json
@@ -0,0 +1,33 @@
+{
+ "action": {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "in-progress",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "power_off"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/power-on.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/power-on.json b/providers/digitalocean2/src/test/resources/power-on.json
new file mode 100644
index 0000000..32e6e83
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/power-on.json
@@ -0,0 +1,33 @@
+{
+ "action": {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "in-progress",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "power_on"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/reboot.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/reboot.json b/providers/digitalocean2/src/test/resources/reboot.json
new file mode 100644
index 0000000..799500a
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/reboot.json
@@ -0,0 +1,33 @@
+{
+ "action": {
+ "region" : {
+ "name" : "New York 1",
+ "available" : true,
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "sizes" : [
+ "512mb",
+ "8gb",
+ "16gb",
+ "32gb",
+ "48gb",
+ "64gb",
+ "1gb",
+ "2gb",
+ "4gb"
+ ]
+ },
+ "started_at" : "2015-05-19T15:17:55Z",
+ "status" : "in-progress",
+ "resource_type" : "droplet",
+ "resource_id" : 5347489,
+ "region_slug" : "nyc1",
+ "id" : 50900149,
+ "completed_at" : "2015-05-19T15:18:01Z",
+ "type" : "reboot"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/057be8df/providers/digitalocean2/src/test/resources/regions-first.json
----------------------------------------------------------------------
diff --git a/providers/digitalocean2/src/test/resources/regions-first.json b/providers/digitalocean2/src/test/resources/regions-first.json
new file mode 100644
index 0000000..5be4b3f
--- /dev/null
+++ b/providers/digitalocean2/src/test/resources/regions-first.json
@@ -0,0 +1,111 @@
+{
+ "links" : {
+ "pages" : {
+ "next" : "https://api.digitalocean.com/v2/regions?page=2&per_page=5",
+ "last" : "https://api.digitalocean.com/v2/regions?page=2&per_page=5"
+ }
+ },
+ "meta" : {
+ "total" : 10
+ },
+ "regions" : [
+ {
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "name" : "New York 1",
+ "slug" : "nyc1",
+ "features" : [
+ "virtio",
+ "backups",
+ "metadata"
+ ],
+ "available" : true
+ },
+ {
+ "slug" : "ams1",
+ "name" : "Amsterdam 1",
+ "available" : false,
+ "features" : [
+ "virtio",
+ "backups"
+ ],
+ "sizes" : []
+ },
+ {
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "name" : "San Francisco 1",
+ "slug" : "sfo1",
+ "features" : [
+ "virtio",
+ "private_networking",
+ "backups",
+ "ipv6",
+ "metadata"
+ ],
+ "available" : true
+ },
+ {
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ],
+ "available" : true,
+ "features" : [
+ "virtio",
+ "private_networking",
+ "backups"
+ ],
+ "name" : "New York 2",
+ "slug" : "nyc2"
+ },
+ {
+ "features" : [
+ "virtio",
+ "private_networking",
+ "backups",
+ "ipv6",
+ "metadata"
+ ],
+ "available" : true,
+ "slug" : "ams2",
+ "name" : "Amsterdam 2",
+ "sizes" : [
+ "32gb",
+ "16gb",
+ "2gb",
+ "1gb",
+ "4gb",
+ "8gb",
+ "512mb",
+ "64gb",
+ "48gb"
+ ]
+ }
+ ]
+}
\ No newline at end of file