JCLOUDS-649: Added image creation from pd and made Image rawDisk Optional<T>

This commit is contained in:
Daniel Broudy 2014-10-15 10:33:27 -07:00
parent dab34c6e21
commit 324f443856
7 changed files with 124 additions and 7 deletions

View File

@ -39,7 +39,7 @@ import com.google.common.base.Optional;
public final class Image extends Resource {
private final String sourceType;
private final RawDisk rawDisk;
private final Optional<RawDisk> rawDisk;
private final Optional<Deprecated> deprecated;
@ConstructorProperties({
@ -50,7 +50,7 @@ public final class Image extends Resource {
String sourceType, RawDisk rawDisk, Deprecated deprecated) {
super(Kind.IMAGE, id, creationTimestamp, selfLink, name, description);
this.sourceType = checkNotNull(sourceType, "sourceType of %s", name);
this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name);
this.rawDisk = fromNullable(rawDisk);
this.deprecated = fromNullable(deprecated);
}
@ -64,7 +64,7 @@ public final class Image extends Resource {
/**
* @return the raw disk image parameters.
*/
public RawDisk getRawDisk() {
public Optional<RawDisk> getRawDisk() {
return rawDisk;
}
@ -146,7 +146,7 @@ public final class Image extends Resource {
public Builder fromImage(Image in) {
return super.fromResource(in)
.sourceType(in.getSourceType())
.rawDisk(in.getRawDisk())
.rawDisk(in.getRawDisk().orNull())
.deprecated(in.getDeprecated().orNull());
}
@ -188,7 +188,7 @@ public final class Image extends Resource {
}
/**
* @return an optional SHA1 checksum of the disk image before unpackaging; provided by the client when the disk
* @return an optional SHA1 checksum of the disk image before unpacking; provided by the client when the disk
* image is created.
*/
public Optional<String> getSha1Checksum() {

View File

@ -23,8 +23,10 @@ import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
@ -41,10 +43,13 @@ import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Images via their REST API.
@ -164,4 +169,21 @@ public interface ImageApi {
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Image> list(ListOptions options);
/**
* Creates an image resource in the specified project from the provided persistent disk.
*
* @param imageName the name of the created image
* @param sourceDisk fully qualified URL for the persistent disk to create the image from
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Images:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/global/images")
@OAuthScopes(COMPUTE_SCOPE)
@MapBinder(BindToJsonPayload.class)
Operation createImageFromPD(@PayloadParam("name") String imageName, @PayloadParam("sourceDisk") String sourceDisk);
}

View File

@ -23,7 +23,6 @@ import java.util.List;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
@ -43,7 +42,6 @@ public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
@Test(groups = "live")
public void testInsertDisk() {
Project project = api.getProjectApi().get(userProject.get());
assertZoneOperationDoneSucessfully(api().createInZone(DISK_NAME, sizeGb, DEFAULT_ZONE_NAME), TIME_WAIT);
}

View File

@ -28,6 +28,7 @@ import org.jclouds.googlecomputeengine.parse.ParseImageTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
@Test(groups = "unit")
@ -156,4 +157,47 @@ public class ImageApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
assertTrue(imageApi.list().concat().isEmpty());
}
public void testCreateImageFromPdResponseIs2xx(){
HttpRequest createImage = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis" +
".com/compute/v1/projects/myproject/global/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResource("/image_insert_from_pd.json"))
.build();
HttpResponse createImageResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, createImage, createImageResponse).getImageApiForProject("myproject");
assertEquals(imageApi.createImageFromPD("my-image", "https://www.googleapis.com/" +
"compute/v1/projects/myproject/zones/us-central1-a/disks/mydisk"),
new ParseOperationTest().expected());
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testCreateImageFromPdResponseIs4xx() {
HttpRequest createImage = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis" +
".com/compute/v1/projects/myproject/global/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResource("/image_insert_from_pd.json"))
.build();
HttpResponse createImageResponse = HttpResponse.builder().statusCode(404).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, createImage, createImageResponse).getImageApiForProject("myproject");
imageApi.createImageFromPD("my-image", "https://www.googleapis.com/" +
"compute/v1/projects/myproject/zones/us-central1-a/disks/mydisk");
}
}

View File

@ -21,11 +21,13 @@ import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
@ -36,12 +38,26 @@ import com.google.common.collect.Lists;
public class ImageApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
public static final String DISK_NAME = "image-api-live-test-disk";
public static final int TIME_WAIT = 300;
public static final int sizeGb = 10;
public static final String IMAGE_NAME = "image-api-live-test-image";
private Image image;
private URI diskURI;
private ImageApi api() {
return api.getImageApiForProject("centos-cloud");
}
private ImageApi imageApi(){
return api.getImageApiForProject(userProject.get());
}
private DiskApi diskApi() {
return api.getDiskApiForProject(userProject.get());
}
@Test(groups = "live")
public void testListImage() {
@ -70,5 +86,35 @@ public class ImageApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
assertEquals(result.getName(), expected.getName());
}
@Test(groups = "live")
public void testInsertDisk() {
assertZoneOperationDoneSucessfully(diskApi().createInZone(DISK_NAME, sizeGb, DEFAULT_ZONE_NAME), TIME_WAIT);
Disk disk = diskApi().getInZone(DEFAULT_ZONE_NAME, DISK_NAME);
diskURI = disk.getSelfLink();
}
@Test(groups = "live", dependsOnMethods = "testInsertDisk")
public void testCreateImageFromPD(){
assertGlobalOperationDoneSucessfully(imageApi().createImageFromPD(IMAGE_NAME, diskURI.toString()), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testCreateImageFromPD")
public void testGetCreatedImage(){
Image image = imageApi().get(IMAGE_NAME);
assertImageEquals(image);
}
@Test(groups = "live", dependsOnMethods = "testGetCreatedImage")
public void testCleanup(){
assertGlobalOperationDoneSucessfully(imageApi().delete(IMAGE_NAME), TIME_WAIT);
assertZoneOperationDoneSucessfully(diskApi().deleteInZone(DEFAULT_ZONE_NAME, DISK_NAME), TIME_WAIT);
}
private void assertImageEquals(Image result) {
assertEquals(result.getName(), IMAGE_NAME);
assertEquals(result.getSourceType(), "RAW");
assertEquals(result.getSelfLink(), getImageUrl(userProject.get(), IMAGE_NAME) );
}
}

View File

@ -58,6 +58,8 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
protected static final String GATEWAY_API_URL_SUFFIX = "/global/gateways/";
protected static final String DEFAULT_GATEWAY_NAME = "default-internet-gateway";
protected static final String IMAGE_API_URL_SUFFIX = "/global/images/";
protected static final String GOOGLE_PROJECT = "google";
protected Supplier<String> userProject;
@ -136,6 +138,10 @@ public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleCo
return URI.create(API_URL_PREFIX + project + GATEWAY_API_URL_SUFFIX + gateway);
}
protected URI getImageUrl(String project, String image){
return URI.create(API_URL_PREFIX + project + IMAGE_API_URL_SUFFIX + image);
}
protected URI getDefaultMachineTypeUrl(String project) {
return getMachineTypeUrl(project, DEFAULT_MACHINE_TYPE_NAME);
}

View File

@ -0,0 +1 @@
{"name":"my-image","sourceDisk":"https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/disks/mydisk"}