diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeApi.java index 93153d8d12..acf788e50f 100644 --- a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeApi.java +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeApi.java @@ -21,6 +21,7 @@ package org.jclouds.googlecompute; import com.google.common.annotations.Beta; import org.jclouds.googlecompute.features.DiskApi; import org.jclouds.googlecompute.features.FirewallApi; +import org.jclouds.googlecompute.features.ImageApi; import org.jclouds.googlecompute.features.KernelApi; import org.jclouds.googlecompute.features.MachineTypeApi; import org.jclouds.googlecompute.features.NetworkApi; @@ -61,6 +62,15 @@ public interface GoogleComputeApi { @Path("/projects/{project}") FirewallApi getFirewallApiForProject(@PathParam("project") String projectName); + /** + * Provides synchronous access to Image features + * + * @param projectName the name of the project + */ + @Delegate + @Path("/projects/{project}") + ImageApi getImageApiForProject(@PathParam("project") String projectName); + /** * Provides synchronous access to Kernel features * diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java index 39fb0d7513..5b7c68de10 100644 --- a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java @@ -21,6 +21,7 @@ package org.jclouds.googlecompute; import com.google.common.annotations.Beta; import org.jclouds.googlecompute.features.DiskAsyncApi; import org.jclouds.googlecompute.features.FirewallAsyncApi; +import org.jclouds.googlecompute.features.ImageAsyncApi; import org.jclouds.googlecompute.features.KernelAsyncApi; import org.jclouds.googlecompute.features.MachineTypeAsyncApi; import org.jclouds.googlecompute.features.NetworkAsyncApi; @@ -61,11 +62,22 @@ public interface GoogleComputeAsyncApi { @Path("/projects/{project}") FirewallAsyncApi getFirewallApiForProject(@PathParam("project") String projectName); + /** + * Provides asynchronous access to Image features + * + * @param projectName the name of the project + */ + @Delegate + @Path("/projects/{project}") + ImageAsyncApi getImageApiForProject(@PathParam("project") String projectName); + /** * Provides asynchronous access to Kernel features * * @param projectName the name of the project */ + @Delegate + @Path("/projects/{project}") KernelAsyncApi getKernelApiForProject(@PathParam("project") String projectName); /** diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java index 77577c7616..44a8a59936 100644 --- a/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java @@ -34,6 +34,8 @@ import org.jclouds.googlecompute.features.DiskApi; import org.jclouds.googlecompute.features.DiskAsyncApi; import org.jclouds.googlecompute.features.FirewallApi; import org.jclouds.googlecompute.features.FirewallAsyncApi; +import org.jclouds.googlecompute.features.ImageApi; +import org.jclouds.googlecompute.features.ImageAsyncApi; import org.jclouds.googlecompute.features.KernelApi; import org.jclouds.googlecompute.features.KernelAsyncApi; import org.jclouds.googlecompute.features.MachineTypeApi; @@ -76,6 +78,7 @@ public class GoogleComputeRestClientModule extends RestClientModule, Class> DELEGATE_MAP = ImmutableMap., Class>builder() .put(DiskApi.class, DiskAsyncApi.class) .put(FirewallApi.class, FirewallAsyncApi.class) + .put(ImageApi.class, ImageAsyncApi.class) .put(KernelApi.class, KernelAsyncApi.class) .put(MachineTypeApi.class, MachineTypeAsyncApi.class) .put(NetworkApi.class, NetworkAsyncApi.class) diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Image.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Image.java new file mode 100644 index 0000000000..2634b4a973 --- /dev/null +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Image.java @@ -0,0 +1,291 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.domain; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; +import com.google.common.base.Optional; + +import java.beans.ConstructorProperties; +import java.net.URI; +import java.util.Date; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Optional.fromNullable; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Represents a disk image to use on an instance. + * + * @author David Alves + * @see + */ +@Beta +public final class Image extends Resource { + + private final String sourceType; + private final Optional preferredKernel; + private final RawDisk rawDisk; + + @ConstructorProperties({ + "id", "creationTimestamp", "selfLink", "name", "description", "sourceType", "preferredKernel", + "rawDisk" + }) + protected Image(String id, Date creationTimestamp, URI selfLink, String name, String description, + String sourceType, URI preferredKernel, RawDisk rawDisk) { + super(Kind.IMAGE, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), + checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description)); + this.sourceType = checkNotNull(sourceType, "sourceType of %s", name); + this.preferredKernel = fromNullable(preferredKernel); + this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name); ; + } + + /** + * @return must be RAW; provided by the client when the disk image is created. + */ + public String getSourceType() { + return sourceType; + } + + /** + * @return An optional URL of the preferred kernel for use with this disk image. + */ + public Optional getPreferredKernel() { + return preferredKernel; + } + + /** + * @return the raw disk image parameters. + */ + public RawDisk getRawDisk() { + return rawDisk; + } + + /** + * {@inheritDoc} + */ + protected Objects.ToStringHelper string() { + return super.string() + .omitNullValues() + .add("sourceType", sourceType) + .add("preferredKernel", preferredKernel.orNull()) + .add("rawDisk", rawDisk); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return string().toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().fromImage(this); + } + + public static final class Builder extends Resource.Builder { + + private String sourceType; + private URI preferredKernel; + private RawDisk rawDisk; + + /** + * @see Image#getSourceType() + */ + public Builder sourceType(String sourceType) { + this.sourceType = checkNotNull(sourceType, "sourceType"); + return this; + } + + /** + * @see Image#getPreferredKernel() + */ + public Builder preferredKernel(URI preferredKernel) { + this.preferredKernel = preferredKernel; + return this; + } + + /** + * @see Image#getRawDisk() + */ + public Builder rawDisk(RawDisk rawDisk) { + this.rawDisk = checkNotNull(rawDisk); + return this; + } + + @Override + protected Builder self() { + return this; + } + + public Image build() { + return new Image(super.id, super.creationTimestamp, super.selfLink, super.name, + super.description, sourceType, preferredKernel, rawDisk); + } + + public Builder fromImage(Image in) { + return super.fromResource(in) + .sourceType(in.getSourceType()) + .preferredKernel(in.getPreferredKernel().orNull()) + .rawDisk(in.getRawDisk()); + } + + } + + /** + * A raw disk image, usually the base for an image. + * + * @author David Alves + * @see + */ + public static class RawDisk { + + private final String source; + private final String containerType; + private final Optional sha1Checksum; + + @ConstructorProperties({ + "source", "containerType", "sha1Checksum" + }) + private RawDisk(String source, String containerType, String sha1Checksum) { + this.source = checkNotNull(source, "source"); + this.containerType = checkNotNull(containerType, "containerType"); + this.sha1Checksum = fromNullable(sha1Checksum); + } + + /** + * @return the full Google Cloud Storage URL where the disk image is stored; provided by the client when the disk + * image is created. + */ + public String getSource() { + return source; + } + + /** + * @return the format used to encode and transmit the block device. + */ + public String getContainerType() { + return containerType; + } + + /** + * @return an optional SHA1 checksum of the disk image before unpackaging; provided by the client when the disk + * image is created. + */ + public Optional getSha1Checksum() { + return sha1Checksum; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(source, containerType, sha1Checksum); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + RawDisk that = RawDisk.class.cast(obj); + return equal(this.source, that.source) + && equal(this.containerType, that.containerType) + && equal(this.sha1Checksum, that.sha1Checksum); + } + + /** + * {@inheritDoc} + */ + protected Objects.ToStringHelper string() { + return toStringHelper(this) + .omitNullValues() + .add("source", source) + .add("containerType", containerType) + .add("sha1Checksum", sha1Checksum.orNull()); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return string().toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromImageRawDisk(this); + } + + public static class Builder { + + private String source; + private String containerType; + private String sha1Checksum; + + /** + * @see org.jclouds.googlecompute.domain.Image.RawDisk#getSource() + */ + public Builder source(String source) { + this.source = checkNotNull(source); + return this; + } + + /** + * @see org.jclouds.googlecompute.domain.Image.RawDisk#getContainerType() + */ + public Builder containerType(String containerType) { + this.containerType = checkNotNull(containerType); + return this; + } + + /** + * @see org.jclouds.googlecompute.domain.Image.RawDisk#getSha1Checksum() + */ + public Builder sha1Checksum(String sha1Checksum) { + this.sha1Checksum = sha1Checksum; + return this; + } + + public RawDisk build() { + return new RawDisk(source, containerType, sha1Checksum); + } + + public Builder fromImageRawDisk(RawDisk rawDisk) { + return new Builder().source(rawDisk.getSource()) + .containerType(rawDisk.getContainerType()) + .sha1Checksum(rawDisk.getSha1Checksum().orNull()); + } + } + } +} diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageApi.java new file mode 100644 index 0000000000..5f57b83d54 --- /dev/null +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageApi.java @@ -0,0 +1,93 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.features; + +import org.jclouds.collect.PagedIterable; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.domain.ListPage; +import org.jclouds.googlecompute.domain.Operation; +import org.jclouds.googlecompute.options.ListOptions; +import org.jclouds.javax.annotation.Nullable; + +/** + * Provides synchronous access to Images via their REST API. + *

+ * + * @author David Alves + * @see ImageAsyncApi + * @see + */ +public interface ImageApi { + + /** + * Returns the specified image resource. + * + * @param imageName name of the image resource to return. + * @return an Image resource + */ + Image get(String imageName); + + /** + * @see ImageApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions) + */ + public ListPage listFirstPage(); + + /** + * @see ImageApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions) + */ + public ListPage listAtMarker(@Nullable String marker); + + /** + * Deletes the specified image resource. + * + * @param imageName name of the image resource to delete. + * @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. If the image did not exist the result is null. + */ + Operation delete(String imageName); + + /** + * Retrieves the list of image resources available to the specified project. + * By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not + * been set. + * + * + * @param marker marks the beginning of the next list page + * @param listOptions listing options + * @return a page of the list + * @see ListOptions + * @see org.jclouds.googlecompute.domain.ListPage + */ + ListPage listAtMarker(String marker, @Nullable ListOptions listOptions); + + /** + * @see ImageApi#list(org.jclouds.googlecompute.options.ListOptions) + */ + public PagedIterable list(); + + /** + * A paged version of ImageApi#list() + * + * @return a Paged, Fluent Iterable that is able to fetch additional pages when required + * @see PagedIterable + * @see ImageApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions) + */ + PagedIterable list(@Nullable ListOptions listOptions); +} diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageAsyncApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageAsyncApi.java new file mode 100644 index 0000000000..38b3d8f25b --- /dev/null +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/ImageAsyncApi.java @@ -0,0 +1,139 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.features; + +import com.google.common.util.concurrent.ListenableFuture; +import org.jclouds.collect.PagedIterable; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.domain.ListPage; +import org.jclouds.googlecompute.domain.Operation; +import org.jclouds.googlecompute.functions.internal.ParseImages; +import org.jclouds.googlecompute.options.ListOptions; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.oauth.v2.config.OAuthScopes; +import org.jclouds.oauth.v2.filters.OAuthAuthenticator; +import org.jclouds.rest.annotations.Fallback; +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 javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import static org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404; +import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404; +import static org.jclouds.Fallbacks.NullOnNotFoundOr404; +import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE; +import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE; + +/** + * Provides asynchronous access to Images via their REST API. + * + * @author David Alves + * @see ImageApi + */ +@SkipEncoding({'/', '='}) +@RequestFilters(OAuthAuthenticator.class) +public interface ImageAsyncApi { + + /** + * @see ImageApi#get(String) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images/{image}") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @Fallback(NullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("image") String imageName); + + /** + * @see ImageApi#delete(String) + */ + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images/{image}") + @OAuthScopes(COMPUTE_SCOPE) + @Fallback(NullOnNotFoundOr404.class) + ListenableFuture delete(@PathParam("image") String imageName); + + /** + * @see ImageApi#listFirstPage() + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @ResponseParser(ParseImages.class) + @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listFirstPage(); + + /** + * @see ImageApi#listAtMarker(String) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @ResponseParser(ParseImages.class) + @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listAtMarker(@QueryParam("pageToken") @Nullable String marker); + + /** + * @see ImageApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @ResponseParser(ParseImages.class) + @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class) + ListenableFuture> listAtMarker(@QueryParam("pageToken") @Nullable String marker, + ListOptions options); + + /** + * @see ImageApi#listAtMarker(String) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @ResponseParser(ParseImages.class) + @Transform(ParseImages.ToPagedIterable.class) + @Fallback(EmptyPagedIterableOnNotFoundOr404.class) + ListenableFuture> list(); + + /** + * @see ImageApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @OAuthScopes(COMPUTE_READONLY_SCOPE) + @ResponseParser(ParseImages.class) + @Transform(ParseImages.ToPagedIterable.class) + @Fallback(EmptyPagedIterableOnNotFoundOr404.class) + ListenableFuture> list(ListOptions options); +} diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseImages.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseImages.java new file mode 100644 index 0000000000..54f54be0ba --- /dev/null +++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseImages.java @@ -0,0 +1,67 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.functions.internal; + +import com.google.common.base.Function; +import com.google.inject.TypeLiteral; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.googlecompute.GoogleComputeApi; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.domain.ListPage; +import org.jclouds.googlecompute.options.ListOptions; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.json.Json; + +import javax.inject.Inject; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * @author David Alves + */ +public class ParseImages extends ParseJson> { + + @Inject + public ParseImages(Json json) { + super(json, new TypeLiteral>() {}); + } + + public static class ToPagedIterable extends BaseToPagedIterable { + + private final GoogleComputeApi api; + + @Inject + protected ToPagedIterable(GoogleComputeApi api) { + this.api = checkNotNull(api, "api"); + } + + @Override + protected Function> fetchNextPage(final String projectName, + final ListOptions options) { + return new Function>() { + + @Override + public IterableWithMarker apply(Object input) { + return api.getImageApiForProject(projectName).listAtMarker(input.toString(), options); + } + }; + } + } +} diff --git a/labs/google-compute/src/test/java/org/jclouds/googlecompute/PageSystemExpectTest.java b/labs/google-compute/src/test/java/org/jclouds/googlecompute/PageSystemExpectTest.java new file mode 100644 index 0000000000..b726310c06 --- /dev/null +++ b/labs/google-compute/src/test/java/org/jclouds/googlecompute/PageSystemExpectTest.java @@ -0,0 +1,119 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute; + +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.features.ImageApi; +import org.jclouds.googlecompute.internal.BaseGoogleComputeApiExpectTest; +import org.jclouds.googlecompute.options.ListOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE; +import static org.testng.Assert.assertSame; + +/** + * A test specifically for the paging system. The code used is common to all list() methods so we're using Images + * but it could be anything else. + * + * @author David Alves + */ +@Test(groups = "unit") +public class PageSystemExpectTest extends BaseGoogleComputeApiExpectTest { + + public void testGetSinglePage() { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse operationResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_list_single_page.json")).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject"); + + PagedIterable images = imageApi.list(); + + // expect one page + assertSame(images.size(), 1); + // with three images + assertSame(images.concat().size(), 3); + } + + public void testGetMultiplePages() { + HttpRequest list1 = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images?maxResults=3") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpRequest list2 = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images?pageToken" + + "=CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx&maxResults=3") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpRequest list3 = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images?pageToken" + + "=CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2&maxResults=3") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse list1response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_list_multiple_page_1.json")).build(); + + HttpResponse list2Response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_list_multiple_page_2.json")).build(); + + HttpResponse list3Response = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_list_single_page.json")).build(); + + + ImageApi imageApi = orderedRequestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, list1, list1response, list2, list2Response, list3, list3Response) + .getImageApiForProject("myproject"); + + PagedIterable images = imageApi.list(new ListOptions.Builder().maxResults(3)); + + int imageCounter = 0; + for (IterableWithMarker page : images) { + for (Image image : page) { + imageCounter++; + } + } + assertSame(imageCounter, 9); + } + +} diff --git a/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiExpectTest.java b/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiExpectTest.java new file mode 100644 index 0000000000..0d3c4c2c83 --- /dev/null +++ b/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiExpectTest.java @@ -0,0 +1,149 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.features; + +import org.jclouds.googlecompute.internal.BaseGoogleComputeApiExpectTest; +import org.jclouds.googlecompute.parse.ParseImageListTest; +import org.jclouds.googlecompute.parse.ParseImageTest; +import org.jclouds.googlecompute.parse.ParseOperationTest; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE; +import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.AssertJUnit.assertNull; + +/** + * @author David Alves + */ +@Test(groups = "unit") +public class ImageApiExpectTest extends BaseGoogleComputeApiExpectTest { + + public void testGetImageResponseIs2xx() throws Exception { + HttpRequest get = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse operationResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_get.json")).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, get, operationResponse).getImageApiForProject("google"); + + assertEquals(imageApi.get("centos-6-2-v20120326"), + new ParseImageTest().expected()); + } + + public void testGetImageResponseIs4xx() throws Exception { + HttpRequest get = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, get, operationResponse).getImageApiForProject("google"); + + assertNull(imageApi.get("centos-6-2-v20120326")); + } + + public void testDeleteImageResponseIs2xx() { + HttpRequest delete = HttpRequest + .builder() + .method("DELETE") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse deleteResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/operation.json")).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE), + TOKEN_RESPONSE, delete, deleteResponse).getImageApiForProject("myproject"); + + assertEquals(imageApi.delete("centos-6-2-v20120326"), + new ParseOperationTest().expected()); + } + + public void testDeleteImageResponseIs4xx() { + HttpRequest delete = HttpRequest + .builder() + .method("DELETE") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE), + TOKEN_RESPONSE, delete, deleteResponse).getImageApiForProject("myproject"); + + assertNull(imageApi.delete("centos-6-2-v20120326")); + } + + public void testListImagesResponseIs2xx() { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse operationResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/image_list.json")).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject"); + + assertEquals(imageApi.listFirstPage().toString(), + new ParseImageListTest().expected().toString()); + } + + public void testListImagesResponseIs4xx() { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint("https://www.googleapis" + + ".com/compute/v1beta13/projects/myproject/images") + .addHeader("Accept", "application/json") + .addHeader("Authorization", "Bearer " + TOKEN).build(); + + HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build(); + + ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE), + TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject"); + + assertTrue(imageApi.list().concat().isEmpty()); + } +} diff --git a/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiLiveTest.java b/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiLiveTest.java new file mode 100644 index 0000000000..4f60864914 --- /dev/null +++ b/labs/google-compute/src/test/java/org/jclouds/googlecompute/features/ImageApiLiveTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.features; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import org.jclouds.collect.IterableWithMarker; +import org.jclouds.collect.PagedIterable; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.internal.BaseGoogleComputeApiLiveTest; +import org.jclouds.googlecompute.options.ListOptions; +import org.testng.annotations.Test; + +import java.util.Iterator; +import java.util.List; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +/** + * TODO figure out how to test insert and delete as this requires an image .tar.gz to be present in GCS + * + * @author David Alves + */ +public class ImageApiLiveTest extends BaseGoogleComputeApiLiveTest { + + private Image image; + + private ImageApi api() { + return context.getApi().getImageApiForProject("google"); + } + + @Test(groups = "live") + public void testListImage() { + + PagedIterable images = api().list(new ListOptions.Builder().maxResults(1)); + + Iterator> pageIterator = images.iterator(); + assertTrue(pageIterator.hasNext()); + + IterableWithMarker singlePageIterator = pageIterator.next(); + List imageAsList = Lists.newArrayList(singlePageIterator); + + assertSame(imageAsList.size(), 1); + + this.image = Iterables.getOnlyElement(imageAsList); + } + + + @Test(groups = "live", dependsOnMethods = "testListImage") + public void testGetImage() { + Image image = api().get(this.image.getName()); + assertNotNull(image); + assertImageEquals(image, this.image); + } + + private void assertImageEquals(Image result, Image expected) { + assertEquals(result.getName(), expected.getName()); + } + +} + diff --git a/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageListTest.java b/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageListTest.java new file mode 100644 index 0000000000..6350c67b88 --- /dev/null +++ b/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageListTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.parse; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.domain.ListPage; +import org.jclouds.googlecompute.domain.Resource; +import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import java.net.URI; + +/** + * @author David Alves + */ +@Test(groups = "unit") +public class ParseImageListTest extends BaseGoogleComputeParseTest> { + + @Override + public String resource() { + return "/image_list.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public ListPage expected() { + return ListPage.builder() + .kind(Resource.Kind.IMAGE_LIST) + .id("projects/google/images") + .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/images")) + .items(ImmutableSet.of(Image.builder() + .id("12941197498378735318") + .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-07-16T22:16:13.468")) + .selfLink(URI.create("https://www.googleapis" + + ".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326")) + .name("centos-6-2-v20120326") + .description("DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000") + .sourceType("RAW") + .preferredKernel(URI.create("https://www.googleapis" + + ".com/compute/v1beta13/projects/google/kernels/gce-20120326")) + .rawDisk( + Image.RawDisk.builder() + .source("") + .containerType("TAR") + .build() + ).build() + + )) + .build(); + } +} \ No newline at end of file diff --git a/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageTest.java b/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageTest.java new file mode 100644 index 0000000000..4f25eb18d0 --- /dev/null +++ b/labs/google-compute/src/test/java/org/jclouds/googlecompute/parse/ParseImageTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.googlecompute.parse; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.googlecompute.domain.Image; +import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import java.net.URI; + +/** + * @author David Alves + */ +@Test(groups = "unit") +public class ParseImageTest extends BaseGoogleComputeParseTest { + + @Override + public String resource() { + return "/image_get.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Image expected() { + return Image.builder() + .id("12941197498378735318") + .creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-07-16T22:16:13.468")) + .selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2" + + "-v20120326")) + .name("centos-6-2-v20120326") + .description("DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000") + .sourceType("RAW") + .preferredKernel(URI.create("https://www.googleapis" + + ".com/compute/v1beta13/projects/google/kernels/gce-20120326")) + .rawDisk( + Image.RawDisk.builder() + .source("") + .containerType("TAR") + .build() + ).build(); + } +} diff --git a/labs/google-compute/src/test/resources/image_get.json b/labs/google-compute/src/test/resources/image_get.json new file mode 100644 index 0000000000..79d358e9bc --- /dev/null +++ b/labs/google-compute/src/test/resources/image_get.json @@ -0,0 +1,14 @@ +{ + "kind": "compute#image", + "id": "12941197498378735318", + "creationTimestamp": "2012-07-16T22:16:13.468", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326", + "name": "centos-6-2-v20120326", + "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326", + "rawDisk": { + "source": "", + "containerType": "TAR" + } +} \ No newline at end of file diff --git a/labs/google-compute/src/test/resources/image_insert.json b/labs/google-compute/src/test/resources/image_insert.json new file mode 100644 index 0000000000..787ffde56d --- /dev/null +++ b/labs/google-compute/src/test/resources/image_insert.json @@ -0,0 +1 @@ +{"sourceType":"RAW","rawDisk":{"source":"https://storage.googleapis.com/mybuket/myimage.image.tar.gz","containerType":"TAR"},"kind":"compute#image","name":"myimage"} \ No newline at end of file diff --git a/labs/google-compute/src/test/resources/image_list.json b/labs/google-compute/src/test/resources/image_list.json new file mode 100644 index 0000000000..6095b29b9a --- /dev/null +++ b/labs/google-compute/src/test/resources/image_list.json @@ -0,0 +1,21 @@ +{ + "kind": "compute#imageList", + "id": "projects/google/images", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images", + "items": [ + { + "kind": "compute#image", + "id": "12941197498378735318", + "creationTimestamp": "2012-07-16T22:16:13.468", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326", + "name": "centos-6-2-v20120326", + "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + } + ] +} \ No newline at end of file diff --git a/labs/google-compute/src/test/resources/image_list_multiple_page_1.json b/labs/google-compute/src/test/resources/image_list_multiple_page_1.json new file mode 100644 index 0000000000..afb794c1c0 --- /dev/null +++ b/labs/google-compute/src/test/resources/image_list_multiple_page_1.json @@ -0,0 +1,50 @@ +{ + "kind": "compute#imageList", + "id": "projects/google/images", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images", + "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx", + "items": [ + { + "kind": "compute#image", + "id": "12941197498378735318", + "creationTimestamp": "2012-07-16T15:16:13.468-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120326", + "name": "centos-6-2-v20120326", + "description": "DEPRECATED. CentOS 6.2 image; Created Mon, 26 Mar 2012 21:19:09 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "12894486577628239762", + "creationTimestamp": "2012-05-21T13:15:37.215-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120503", + "name": "centos-6-2-v20120503", + "description": "CentOS 6.2; Created Wed, 09 May 2012 11:55:54 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120326", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "12917726455664967299", + "creationTimestamp": "2012-06-18T11:05:30.664-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120611", + "name": "centos-6-2-v20120611", + "description": "CentOS 6.2; Created Mon, 11 Jun 2012 13:15:44 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120611", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + } + ] +} \ No newline at end of file diff --git a/labs/google-compute/src/test/resources/image_list_multiple_page_2.json b/labs/google-compute/src/test/resources/image_list_multiple_page_2.json new file mode 100644 index 0000000000..71529d5ed6 --- /dev/null +++ b/labs/google-compute/src/test/resources/image_list_multiple_page_2.json @@ -0,0 +1,50 @@ +{ + "kind": "compute#imageList", + "id": "projects/google/images", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images", + "nextPageToken": "CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2", + "items": [ + { + "kind": "compute#image", + "id": "12920641029336858796", + "creationTimestamp": "2012-06-21T22:59:56.392-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-2-v20120621", + "name": "centos-6-2-v20120621", + "description": "CentOS 6.2; Created Thu, 21 Jun 2012 14:22:21 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20120621", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "12994279803511049620", + "creationTimestamp": "2012-09-18T08:52:47.584-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-v20120912", + "name": "centos-6-v20120912", + "description": "CentOS 6; Created Wed, 12 Sep 2012 00:00:00 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20120912", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "13037720516378381209", + "creationTimestamp": "2012-11-09T11:40:41.079-08:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/centos-6-v20121106", + "name": "centos-6-v20121106", + "description": "SCSI-enabled CentOS 6; Created Tue, 06 Nov 2012 00:00:00 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + } + ] +} \ No newline at end of file diff --git a/labs/google-compute/src/test/resources/image_list_single_page.json b/labs/google-compute/src/test/resources/image_list_single_page.json new file mode 100644 index 0000000000..b28f9a6087 --- /dev/null +++ b/labs/google-compute/src/test/resources/image_list_single_page.json @@ -0,0 +1,49 @@ +{ + "kind": "compute#imageList", + "id": "projects/google/images", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images", + "items": [ + { + "kind": "compute#image", + "id": "13037722963789596520", + "creationTimestamp": "2012-11-09T11:43:28.749-08:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-10-04-v20121106", + "name": "gcel-10-04-v20121106", + "description": "SCSI-enabled GCEL 10.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "13037721421359523565", + "creationTimestamp": "2012-11-09T11:40:51.994-08:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106", + "name": "gcel-12-04-v20121106", + "description": "SCSI-enabled GCEL 12.04 LTS; Created Tue, 06 Nov 2012 00:00:00 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-v20121106", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + }, + { + "kind": "compute#image", + "id": "12941198995845323366", + "creationTimestamp": "2012-07-16T15:18:50.405-07:00", + "selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/images/ubuntu-10-04-v20110728", + "name": "ubuntu-10-04-v20110728", + "description": "DEPRECATED. GCEL 10.04 LTS; Created Thu, 28 Jul 2011 16:45:51 +0000", + "sourceType": "RAW", + "preferredKernel": "https://www.googleapis.com/compute/v1beta13/projects/google/kernels/gce-20110728", + "rawDisk": { + "source": "", + "containerType": "TAR" + } + } + ] +} \ No newline at end of file