JCLOUDS-455: Add get() method to KeyPairApi

This commit is contained in:
Jeremy Daggett 2014-06-02 10:23:46 -07:00 committed by Jeremy Daggett
parent 5dbec6fb66
commit 7bb001beed
6 changed files with 101 additions and 41 deletions

View File

@ -24,7 +24,7 @@ import com.google.common.annotations.Beta;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Provides synchronous access to Security Groups. * Provides synchronous access to the OpenStack Nova Key Pair Extension API.
* <p/> * <p/>
* *
* @see KeyPairAsyncApi * @see KeyPairAsyncApi
@ -35,30 +35,44 @@ import com.google.common.collect.FluentIterable;
public interface KeyPairApi { public interface KeyPairApi {
/** /**
* List all Key Pairs. * Lists all Key Pairs.
* *
* @return all Key Pairs * @return all Key Pairs
*/ */
FluentIterable<? extends KeyPair> list(); FluentIterable<KeyPair> list();
/** /**
* Create a Key Pair. * Creates a {@link KeyPair}.
* *
* @return a Key Pair * @return the created {@link KeyPair}.
*/ */
KeyPair create(String name); KeyPair create(String name);
/** /**
* Create a Key Pair with a public key. * Creates a {@link KeyPair} with a public key.
* *
* @return a Key Pair with a public key. * @return the created {@link KeyPair}.
*/ */
KeyPair createWithPublicKey(String name, String publicKey); KeyPair createWithPublicKey(String name, String publicKey);
/** /**
* Delete a Key Pairs. * Gets a specific {@link KeyPair} by name.
* *
* @return * @param name
* the name of the {@link KeyPair}
*
* @return the specified {@link KeyPair}, otherwise null.
*/
KeyPair get(String name);
/**
* Deletes a {@link KeyPair}.
*
* @param name
* the name of the {@link KeyPair}
*
* @return {@code true} if the {@link KeyPair} was deleted, otherwise {@code false}.
*/ */
boolean delete(String name); boolean delete(String name);

View File

@ -28,6 +28,8 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404; import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.nova.v2_0.binders.BindKeyPairToJsonPayload; import org.jclouds.openstack.nova.v2_0.binders.BindKeyPairToJsonPayload;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
@ -47,17 +49,10 @@ import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
* Provides asynchronous access to Key Pairs via the REST API. * Provides asynchronous access to the OpenStack Nova Key Pair Extension API.
* <p/> * <p/>
* *
* @see KeyPairApi * @see KeyPairApi
* @author Jeremy Daggett
* @see ExtensionAsyncApi
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/ */
@Beta @Beta
@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS) @Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
@ -70,7 +65,7 @@ public interface KeyPairAsyncApi {
@ResponseParser(ParseKeyPairs.class) @ResponseParser(ParseKeyPairs.class)
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Fallback(EmptyFluentIterableOnNotFoundOr404.class) @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
ListenableFuture<? extends FluentIterable<? extends KeyPair>> list(); ListenableFuture<FluentIterable<KeyPair>> list();
@Named("keypair:create") @Named("keypair:create")
@POST @POST
@ -79,7 +74,16 @@ public interface KeyPairAsyncApi {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"keypair\":%7B\"name\":\"{name}\"%7D%7D") @Payload("%7B\"keypair\":%7B\"name\":\"{name}\"%7D%7D")
ListenableFuture<? extends KeyPair> create(@PayloadParam("name") String name); ListenableFuture<KeyPair> create(@PayloadParam("name") String name);
@Named("keypair:get")
@GET
@Path("/os-keypairs/{name}")
@SelectJson("keypair")
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
ListenableFuture<KeyPair> get(@PathParam("name") String name);
@Named("keypair:create") @Named("keypair:create")
@POST @POST
@ -88,7 +92,7 @@ public interface KeyPairAsyncApi {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@MapBinder(BindKeyPairToJsonPayload.class) @MapBinder(BindKeyPairToJsonPayload.class)
ListenableFuture<? extends KeyPair> createWithPublicKey(@PayloadParam("name") String name, ListenableFuture<KeyPair> createWithPublicKey(@PayloadParam("name") String name,
@PayloadParam("public_key") String publicKey); @PayloadParam("public_key") String publicKey);
@Named("keypair:delete") @Named("keypair:delete")

View File

@ -18,6 +18,7 @@ package org.jclouds.openstack.nova.v2_0.extensions;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNull;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
@ -86,7 +87,7 @@ public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
.build(); .build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200) HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_created.json")).build(); .payload(payloadFromResource("/keypair_details.json")).build();
NovaApi apiWhenServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, create, createResponse); responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, create, createResponse);
@ -109,7 +110,7 @@ public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
"application/json")).build(); "application/json")).build();
HttpResponse createResponse = HttpResponse.builder().statusCode(200) HttpResponse createResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_created.json")).build(); .payload(payloadFromResource("/keypair_details.json")).build();
NovaApi apiWhenServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, NovaApi apiWhenServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, create, createResponse); responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, create, createResponse);
@ -139,4 +140,38 @@ public class KeyPairApiExpectTest extends BaseNovaApiExpectTest {
assertTrue(apiWhenServersExist.getKeyPairExtensionForZone("az-1.region-a.geo-1").get().delete("testkeypair")); assertTrue(apiWhenServersExist.getKeyPairExtensionForZone("az-1.region-a.geo-1").get().delete("testkeypair"));
} }
public void testGetKeyPairWhenResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-keypairs/testkeypair")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
HttpResponse getResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/keypair_details.json")).build();
NovaApi apiWhenKeyPairExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, get, getResponse);
assertEquals(apiWhenKeyPairExists.getKeyPairExtensionForZone("az-1.region-a.geo-1").get().get("testkeypair"),
new ParseKeyPairTest().expected());
}
public void testGetKeyPairWhenResponseIs404() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-keypairs/testkeypair")
.addHeader("Accept", "application/json")
.addHeader("X-Auth-Token", authToken).build();
HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
NovaApi apiWhenNoKeyPairExists = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, get, getResponse);
assertNull(apiWhenNoKeyPairExists.getKeyPairExtensionForZone("az-1.region-a.geo-1").get().get("testkeypair"));
}
} }

View File

@ -16,6 +16,7 @@
*/ */
package org.jclouds.openstack.nova.v2_0.extensions; package org.jclouds.openstack.nova.v2_0.extensions;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
@ -25,13 +26,14 @@ import org.testng.annotations.Test;
import com.google.common.collect.FluentIterable; import com.google.common.collect.FluentIterable;
/** /**
* Tests behavior of {@code KeyPairApi} * Tests live behavior of {@code KeyPairApi}
*
* @author Michael Arnold
*/ */
@Test(groups = "live", testName = "KeyPairApiLiveTest") @Test(groups = "live", testName = "KeyPairApiLiveTest")
public class KeyPairApiLiveTest extends BaseNovaApiLiveTest { public class KeyPairApiLiveTest extends BaseNovaApiLiveTest {
final String KEYPAIR_NAME = "testkp";
final String PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCrrBREFxz3002l1HuXz0+UOdJQ/mOYD5DiJwwB/TOybwIKQJPOxJWA9gBoo4k9dthTKBTaEYbzrll7iZcp59E80S6mNiAr3mUgi+x5Y8uyXeJ2Ws+h6peVyFVUu9epkwpcTd1GVfdcVWsTajwDz9+lxCDhl0RZKDFoT0scTxbj/w== nova@nv-aw2az2-api0002";
public void testListKeyPairs() throws Exception { public void testListKeyPairs() throws Exception {
for (String zoneId : api.getConfiguredZones()) { for (String zoneId : api.getConfiguredZones()) {
KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get(); KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get();
@ -40,16 +42,20 @@ public class KeyPairApiLiveTest extends BaseNovaApiLiveTest {
} }
} }
public void testCreateAndDeleteKeyPair() throws Exception { public void testCreateAndGetAndDeleteKeyPair() throws Exception {
final String KEYPAIR_NAME = "testkp";
for (String zoneId : api.getConfiguredZones()) { for (String zoneId : api.getConfiguredZones()) {
KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get(); KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get();
KeyPair keyPair = null; KeyPair createdKeyPair = null;
try { try {
keyPair = keyPairApi.create(KEYPAIR_NAME); createdKeyPair = keyPairApi.create(KEYPAIR_NAME);
assertNotNull(keyPair); assertNotNull(createdKeyPair);
KeyPair keyPair = keyPairApi.get(KEYPAIR_NAME);
assertEquals(keyPair.getName(), createdKeyPair.getName());
assertEquals(keyPair.getFingerprint(), createdKeyPair.getFingerprint());
assertEquals(keyPair.getPublicKey(), createdKeyPair.getPublicKey());
} finally { } finally {
if (keyPair != null) { if (createdKeyPair != null) {
keyPairApi.delete(KEYPAIR_NAME); keyPairApi.delete(KEYPAIR_NAME);
} }
} }
@ -57,17 +63,19 @@ public class KeyPairApiLiveTest extends BaseNovaApiLiveTest {
} }
public void testCreateAndDeleteKeyPairWithPublicKey() throws Exception { public void testCreateAndDeleteKeyPairWithPublicKey() throws Exception {
final String KEYPAIR_NAME = "testkp";
final String PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCrrBREFxz3002l1HuXz0+UOdJQ/mOYD5DiJwwB/TOybwIKQJPOxJWA9gBoo4k9dthTKBTaEYbzrll7iZcp59E80S6mNiAr3mUgi+x5Y8uyXeJ2Ws+h6peVyFVUu9epkwpcTd1GVfdcVWsTajwDz9+lxCDhl0RZKDFoT0scTxbj/w== nova@nv-aw2az2-api0002";
for (String zoneId : api.getConfiguredZones()) { for (String zoneId : api.getConfiguredZones()) {
KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get(); KeyPairApi keyPairApi = api.getKeyPairExtensionForZone(zoneId).get();
KeyPair keyPair = null; KeyPair createdKeyPair = null;
try { try {
keyPair = keyPairApi.createWithPublicKey(KEYPAIR_NAME, PUBLIC_KEY); createdKeyPair = keyPairApi.createWithPublicKey(KEYPAIR_NAME, PUBLIC_KEY);
assertNotNull(keyPair); assertNotNull(createdKeyPair);
KeyPair keyPair = keyPairApi.get(KEYPAIR_NAME);
assertEquals(keyPair.getName(), createdKeyPair.getName());
assertEquals(keyPair.getFingerprint(), createdKeyPair.getFingerprint());
assertEquals(keyPair.getPublicKey(), createdKeyPair.getPublicKey());
} finally { } finally {
if (keyPair != null) { if (createdKeyPair != null) {
keyPairApi.delete(KEYPAIR_NAME); keyPairApi.delete(KEYPAIR_NAME);
} }
} }

View File

@ -30,15 +30,14 @@ import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
* * Tests parsing of a {@link KeyPair}.
* @author Michael Arnold
*/ */
@Test(groups = "unit", testName = "ParseKeyPairTest") @Test(groups = "unit", testName = "ParseKeyPairTest")
public class ParseKeyPairTest extends BaseItemParserTest<KeyPair> { public class ParseKeyPairTest extends BaseItemParserTest<KeyPair> {
@Override @Override
public String resource() { public String resource() {
return "/keypair_created.json"; return "/keypair_details.json";
} }
@Override @Override