diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java index 88fc8067f1..2e6c7b2918 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java @@ -18,6 +18,8 @@ */ package org.jclouds.openstack.glance.v1_0.config; +import java.util.Map; + import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; @@ -26,11 +28,15 @@ import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.openstack.glance.v1_0.GlanceAsyncClient; import org.jclouds.openstack.glance.v1_0.GlanceClient; +import org.jclouds.openstack.glance.v1_0.features.ImageAsyncClient; +import org.jclouds.openstack.glance.v1_0.features.ImageClient; import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler; import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; +import com.google.common.collect.ImmutableMap; + /** * Configures the Glance connection. * @@ -39,6 +45,14 @@ import org.jclouds.rest.config.RestClientModule; @ConfiguresRestClient public class GlanceRestClientModule extends RestClientModule { + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder() + .put(ImageClient.class, ImageAsyncClient.class) + .build(); + + public GlanceRestClientModule() { + super(DELEGATE_MAP); + } + @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ContainerFormat.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ContainerFormat.java new file mode 100644 index 0000000000..d18b60b5e8 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ContainerFormat.java @@ -0,0 +1,83 @@ +/** + * 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.openstack.glance.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * The container format refers to whether the virtual machine image is in a file format that also + * contains metadata about the actual virtual machine. + * + *

Note

+ * + * Note that the container format string is not currently used by Glance or other OpenStack + * components, so it is safe to simply specify {@link #BARE} as the container format if you are + * unsure. + * + * @author Adrian Cole + * @see + */ +public enum ContainerFormat { + /** + * This indicates there is no container or metadata envelope for the image + */ + BARE, + + /** + * This is the OVF container format + */ + OVF, + + /** + * This indicates what is stored in Glance is an Amazon kernel image + */ + AKI, + + /** + * This indicates what is stored in Glance is an Amazon ramdisk image + */ + ARI, + + /** + * This indicates what is stored in Glance is an Amazon machine image + */ + AMI, + + /** + * Type unknown to jclouds + */ + UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static ContainerFormat fromValue(String containerFormat) { + try { + return valueOf(checkNotNull(containerFormat, "containerFormat").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } +} \ No newline at end of file diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/DiskFormat.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/DiskFormat.java new file mode 100644 index 0000000000..afc01bec55 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/DiskFormat.java @@ -0,0 +1,95 @@ +/** + * 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.openstack.glance.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * The disk format of a virtual machine image is the format of the underlying disk image. Virtual + * appliance vendors have different formats for laying out the information contained in a virtual + * machine disk image. + * + * @author Adrian Cole + * @see + */ +public enum DiskFormat { + /** + * This is an unstructured disk image format + */ + RAW, + /** + * This is the VHD disk format, a common disk format used by virtual machine monitors from + * VMWare, Xen, Microsoft, VirtualBox, and others + */ + VHD, + /** + * Another common disk format supported by many common virtual machine monitors + */ + VMDK, + /** + * A disk format supported by VirtualBox virtual machine monitor and the QEMU emulator + */ + VDI, + /** + * An archive format for the data contents of an optical disc (e.g. CDROM). + */ + ISO, + /** + * A disk format supported by the QEMU emulator that can expand dynamically and supports Copy on + * Write + */ + QCOW2, + + /** + * This indicates what is stored in Glance is an Amazon kernel image + */ + AKI, + + /** + * This indicates what is stored in Glance is an Amazon ramdisk image + */ + ARI, + + /** + * This indicates what is stored in Glance is an Amazon machine image + */ + AMI, + + /** + * Type unknown to jclouds + */ + UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static DiskFormat fromValue(String diskFormat) { + try { + return valueOf(checkNotNull(diskFormat, "diskFormat").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } +} \ No newline at end of file diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/Image.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/Image.java new file mode 100644 index 0000000000..91b4db43f8 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/Image.java @@ -0,0 +1,191 @@ +/** + * 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.openstack.glance.v1_0.domain; + +import org.jclouds.openstack.domain.Resource; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.gson.annotations.SerializedName; + +/** + * An image the Glance server knows about + * + * @author Adrian Cole + * @see + * @see + */ +public class Image extends Resource { + public static enum Status { + + UNRECOGNIZED, ACTIVE, SAVING, QUEUED, KILLED, PENDING_DELETE, DELETED; + + public String value() { + return name(); + } + + public static Status fromValue(String v) { + try { + return valueOf(v.toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + + } + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromImage(this); + } + + public static abstract class Builder> extends Resource.Builder { + private Optional containerFormat = Optional.absent(); + private Optional diskFormat = Optional.absent(); + private Optional size = Optional.absent(); + private Optional checksum = Optional.absent(); + + /** + * @see Image#getContainerFormat() + */ + public T containerFormat(Optional containerFormat) { + this.containerFormat = containerFormat; + return self(); + } + + /** + * @see Image#getDiskFormat() + */ + public T diskFormat(Optional diskFormat) { + this.diskFormat = diskFormat; + return self(); + } + + /** + * @see Image#getSize() + */ + public T size(Optional size) { + this.size = size; + return self(); + } + + /** + * @see Image#getSize() + */ + public T checksum(Optional checksum) { + this.checksum = checksum; + return self(); + } + + /** + * @see Image#getContainerFormat() + */ + public T containerFormat(ContainerFormat containerFormat) { + return containerFormat(Optional.of(containerFormat)); + } + + /** + * @see Image#getDiskFormat() + */ + public T diskFormat(DiskFormat diskFormat) { + return diskFormat(Optional.of(diskFormat)); + } + + /** + * @see Image#getSize() + */ + public T size(long size) { + return size(Optional.of(size)); + } + + /** + * @see Image#getSize() + */ + public T checksum(String checksum) { + return checksum(Optional.of(checksum)); + } + + public Image build() { + return new Image(this); + } + + public T fromImage(Image in) { + return super.fromResource(in).containerFormat(in.getContainerFormat()).diskFormat(in.getDiskFormat()).size( + in.getSize()).checksum(in.getChecksum()); + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + protected Image() { + // we want serializers like Gson to work w/o using sun.misc.Unsafe, + // prohibited in GAE. This also implies fields are not final. + // see http://code.google.com/p/jclouds/issues/detail?id=925 + } + + // | container_format | varchar(20) | YES | | NULL | | + @SerializedName("container_format") + private Optional containerFormat = Optional.absent(); + // | disk_format | varchar(20) | YES | | NULL | | + @SerializedName("disk_format") + private Optional diskFormat = Optional.absent(); + // | size | bigint(20) | YES | | NULL | | + private Optional size = Optional.absent(); + // | checksum | varchar(32) | YES | | NULL | | + private Optional checksum = Optional.absent(); + + protected Image(Builder builder) { + super(builder); + this.containerFormat = builder.containerFormat; + this.diskFormat = builder.diskFormat; + this.size = builder.size; + this.checksum = builder.checksum; + } + + public Optional getContainerFormat() { + return this.containerFormat; + } + + public Optional getDiskFormat() { + return this.diskFormat; + } + + public Optional getSize() { + return this.size; + } + + public Optional getChecksum() { + return checksum; + } + + @Override + protected Objects.ToStringHelper string() { + return super.string().add("containerFormat", containerFormat).add("diskFormat", diskFormat).add("size", size) + .add("checksum", checksum); + } +} \ No newline at end of file diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ImageDetails.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ImageDetails.java new file mode 100644 index 0000000000..6504b68fe8 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/domain/ImageDetails.java @@ -0,0 +1,279 @@ +/** + * 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.openstack.glance.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Date; +import java.util.Map; + +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.gson.annotations.SerializedName; + +/** + * Detailed listing of an Image + * + * @author Adrian Cole + * @see + * @see + * @see + */ +public class ImageDetails extends Image { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromImageDetails(this); + } + + public static abstract class Builder> extends Image.Builder { + private long minDisk; + private long minRam; + private Optional location = Optional.absent(); + private Optional owner = Optional.absent(); + private Date updatedAt; + private Date createdAt; + private Optional deletedAt = Optional.absent(); + private Status status = Status.UNRECOGNIZED; + private boolean isPublic; + private Map properties = ImmutableMap.of(); + + /** + * @see ImageDetails#getMinDisk() + */ + public T minDisk(long minDisk) { + this.minDisk = minDisk; + return self(); + } + + /** + * @see ImageDetails#getMinRam() + */ + public T minRam(long minRam) { + this.minRam = minRam; + return self(); + } + + /** + * @see ImageDetails#getLocation() + */ + public T location(Optional location) { + this.location = location; + return self(); + } + + /** + * @see ImageDetails#getLocation() + */ + public T location(String location) { + return location(Optional.of(location)); + } + + /** + * @see ImageDetails#getOwner() + */ + public T owner(Optional owner) { + this.owner = owner; + return self(); + } + + /** + * @see ImageDetails#getOwner() + */ + public T owner(String owner) { + return owner(Optional.of(owner)); + } + + /** + * @see ImageDetails#getUpdatedAt() + */ + public T updatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + return self(); + } + + /** + * @see ImageDetails#getCreatedAt() + */ + public T createdAt(Date createdAt) { + this.createdAt = createdAt; + return self(); + } + + /** + * @see ImageDetails#getDeletedAt() + */ + public T deletedAt(Optional deletedAt) { + this.deletedAt = deletedAt; + return self(); + } + + /** + * @see ImageDetails#getDeletedAt() + */ + public T deletedAt(Date deletedAt) { + return deletedAt(Optional.of(deletedAt)); + } + + /** + * @see ImageDetails#getStatus() + */ + public T status(Status status) { + this.status = status; + return self(); + } + + /** + * @see ImageDetails#isPublic() + */ + public T isPublic(boolean isPublic) { + this.isPublic = isPublic; + return self(); + } + + /** + * @see ImageDetails#getProperties() + */ + public T properties(Map properties) { + this.properties = properties; + return self(); + } + + public ImageDetails build() { + return new ImageDetails(this); + } + + public T fromImageDetails(ImageDetails in) { + return super.fromImage(in).minDisk(in.getMinDisk()).minRam(in.getMinRam()).location(in.getLocation()) + .updatedAt(in.getUpdatedAt()).createdAt(in.getCreatedAt()).deletedAt(in.getDeletedAt()).status( + in.getStatus()).isPublic(in.isPublic()).properties(in.getProperties()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + protected ImageDetails() { + // we want serializers like Gson to work w/o using sun.misc.Unsafe, + // prohibited in GAE. This also implies fields are not final. + // see http://code.google.com/p/jclouds/issues/detail?id=925 + } + + // | min_disk | int(11) | YES | | NULL | | + @SerializedName("min_disk") + private long minDisk; + // | min_ram | int(11) | YES | | NULL | | + @SerializedName("min_ram") + private long minRam; + // | location | text | YES | | NULL | | + private Optional location = Optional.absent(); + // | owner | varchar(255) | YES | | NULL | | + private Optional owner = Optional.absent(); + // | updated_at | datetime | YES | | NULL | | + @SerializedName("updated_at") + private Date updatedAt; + // | created_at | datetime | NO | | NULL | | + @SerializedName("created_at") + private Date createdAt; + @SerializedName("deleted_at") + private Optional deletedAt = Optional.absent(); + // | status | varchar(30) | NO | | NULL | | + private Status status = Status.UNRECOGNIZED; + // | is_public | tinyint(1) | NO | | NULL | | + @SerializedName("is_public") + private boolean isPublic; + private Map properties = ImmutableMap.of(); + + protected ImageDetails(Builder builder) { + super(builder); + this.minDisk = builder.minDisk; + this.minRam = checkNotNull(builder.minRam, "minRam"); + this.location = checkNotNull(builder.location, "location"); + this.owner = checkNotNull(builder.owner, "owner"); + this.updatedAt = checkNotNull(builder.updatedAt, "updatedAt"); + this.createdAt = checkNotNull(builder.createdAt, "createdAt"); + this.deletedAt = checkNotNull(builder.deletedAt, "deletedAt"); + this.status = checkNotNull(builder.status, "status"); + this.isPublic = checkNotNull(builder.isPublic, "isPublic"); + this.properties = ImmutableMap.copyOf(builder.properties); + } + + /** + * Note this could be zero if unset + */ + public long getMinDisk() { + return this.minDisk; + } + + /** + * Note this could be zero if unset + */ + public long getMinRam() { + return this.minRam; + } + + public Status getStatus() { + return this.status; + } + + public Optional getLocation() { + return this.location; + } + + public Date getUpdatedAt() { + return this.updatedAt; + } + + public Date getCreatedAt() { + return this.createdAt; + } + + public Optional getDeletedAt() { + return this.deletedAt; + } + + public boolean isPublic() { + return this.isPublic; + } + + public Map getProperties() { + // in case this was assigned in gson + return ImmutableMap.copyOf(Maps.filterValues(this.properties, Predicates.notNull())); + } + + // hashCode/equals from super is ok + + @Override + protected ToStringHelper string() { + return super.string().add("minDisk", minDisk).add("minRam", minRam).add("location", location).add("deletedAt", + getDeletedAt()).add("updatedAt", updatedAt).add("createdAt", createdAt).add("status", status).add( + "location", location).add("owner", owner).add("isPublic", isPublic).add("properties", properties); + } + +} \ No newline at end of file diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java index 09879510f6..6d4d140a64 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java @@ -18,9 +18,29 @@ */ package org.jclouds.openstack.glance.v1_0.features; +import java.io.InputStream; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; +import org.jclouds.openstack.glance.v1_0.functions.ParseImageDetailsFromHeaders; +import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; /** * Image Services @@ -28,9 +48,52 @@ import org.jclouds.rest.annotations.SkipEncoding; * @see ImageClient * @author Adrian Cole * @see api doc + * @see api src */ @SkipEncoding( { '/', '=' }) @RequestFilters(AuthenticateRequest.class) public interface ImageAsyncClient { + /** + * @see ImageClient#list + */ + @GET + @SelectJson("images") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> list(); + + /** + * @see ImageClient#listInDetail + */ + @GET + @SelectJson("images") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/images/detail") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listInDetail(); + + /** + * @see ImageClient#show + */ + @HEAD + @Path("/images/{id}") + @ResponseParser(ParseImageDetailsFromHeaders.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture show(@PathParam("id") String id); + + /** + * @see ImageClient#getAsStream + */ + @GET + @Path("/images/{id}") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getAsStream(@PathParam("id") String id); + +// POST /images -- Store image data and return metadata about the +// newly-stored image +// PUT /images/ -- Update image metadata and/or upload image +// data for a previously-reserved image +// DELETE /images/ -- Delete the image with id } diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java index a99d41282b..4e50c938ba 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java @@ -18,9 +18,14 @@ */ package org.jclouds.openstack.glance.v1_0.features; +import java.io.InputStream; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; /** * Image Services @@ -31,5 +36,31 @@ import org.jclouds.concurrent.Timeout; */ @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) public interface ImageClient { - + /** + * Returns a set of brief metadata about images + */ + Set list(); + + /** + * Returns a set of detailed metadata about images + */ + Set listInDetail(); + + /** + * Return metadata about an image with id + */ + @Nullable + ImageDetails show(String id); + + /** + * Return image data for image with id + */ + @Nullable + InputStream getAsStream(String id); + +// POST /images -- Store image data and return metadata about the +// newly-stored image +// PUT /images/ -- Update image metadata and/or upload image +// data for a previously-reserved image +// DELETE /images/ -- Delete the image with id } diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeaders.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeaders.java new file mode 100644 index 0000000000..4edb1915b4 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeaders.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.openstack.glance.v1_0.functions; + +import javax.inject.Inject; + +import org.jclouds.date.DateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat; +import org.jclouds.openstack.glance.v1_0.domain.DiskFormat; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; + +import com.google.common.base.Function; + +/** + * This parses {@link ImageDetails} from HTTP headers. + * + * @author Adrian Cole + */ +public class ParseImageDetailsFromHeaders implements Function { + private final DateService dateService; + + @Inject + public ParseImageDetailsFromHeaders(DateService dateService) { + this.dateService = dateService; + } + + public ImageDetails apply(HttpResponse from) { + ImageDetails.Builder builder = ImageDetails.builder() + .id(from.getFirstHeaderOrNull("X-Image-Meta-Id")) + .name(from.getFirstHeaderOrNull("X-Image-Meta-Name")) + .checksum(from.getFirstHeaderOrNull("X-Image-Meta-Checksum")) + .containerFormat(ContainerFormat.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Container_format"))) + .diskFormat(DiskFormat.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Disk_format"))) + .size(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Size"))) + .minDisk(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Min_disk"))) + .minRam(Long.parseLong(from.getFirstHeaderOrNull("X-Image-Meta-Min_ram"))) + .isPublic(Boolean.parseBoolean(from.getFirstHeaderOrNull("X-Image-Meta-Is_public"))) + .createdAt(dateService.iso8601SecondsDateParse(from.getFirstHeaderOrNull("X-Image-Meta-Created_at"))) + .updatedAt(dateService.iso8601SecondsDateParse(from.getFirstHeaderOrNull("X-Image-Meta-Updated_at"))) + .owner(from.getFirstHeaderOrNull("X-Image-Meta-Owner")) + .status(Image.Status.fromValue(from.getFirstHeaderOrNull("X-Image-Meta-Status"))); + + String deletedAt = from.getFirstHeaderOrNull("X-Image-Meta-Deleted_at"); + if (deletedAt != null) + builder.deletedAt(dateService.iso8601SecondsDateParse(deletedAt)); + + return builder.build(); + } +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java index 9f165e7995..4796b15fad 100644 --- a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java @@ -18,13 +18,185 @@ */ package org.jclouds.openstack.glance.v1_0.features; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.openstack.glance.v1_0.GlanceClient; +import org.jclouds.openstack.glance.v1_0.functions.ParseImageDetailsFromHeadersTest; import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientExpectTest; +import org.jclouds.openstack.glance.v1_0.parse.ParseImagesInDetailTest; +import org.jclouds.openstack.glance.v1_0.parse.ParseImagesTest; +import org.jclouds.util.Strings2; import org.testng.annotations.Test; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + /** * @author Adrian Cole */ @Test(groups = "unit", testName = "ImageClientExpectTest") public class ImageClientExpectTest extends BaseGlanceClientExpectTest { + public void testListWhenResponseIs2xx() throws Exception { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images")) + .headers( + ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/images.json")).build(); + + GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, list, listResponse); + + assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1")); + + assertEquals(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").list().toString(), + new ParseImagesTest().expected().toString()); + } + + public void testListWhenReponseIs404IsEmpty() throws Exception { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images")) + .headers( + ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); + + GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, list, listResponse); + + assertTrue(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").list().isEmpty()); + } + + public void testListInDetailWhenResponseIs2xx() throws Exception { + HttpRequest listInDetail = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/detail")) + .headers( + ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse listInDetailResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/images_detail.json")).build(); + + GlanceClient clientWhenExistInDetail = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, listInDetail, listInDetailResponse); + + assertEquals(clientWhenExistInDetail.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1")); + + assertEquals(clientWhenExistInDetail.getImageClientForRegion("az-1.region-a.geo-1").listInDetail().toString(), + new ParseImagesInDetailTest().expected().toString()); + } + + public void testListInDetailWhenReponseIs404IsEmpty() throws Exception { + HttpRequest listInDetail = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/detail")) + .headers( + ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse listInDetailResponse = HttpResponse.builder().statusCode(404).build(); + + GlanceClient clientWhenNoExistInDetail = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, listInDetail, listInDetailResponse); + + assertTrue(clientWhenNoExistInDetail.getImageClientForRegion("az-1.region-a.geo-1").listInDetail().isEmpty()); + } + + public void testShowWhenResponseIs2xx() throws Exception { + HttpRequest show = HttpRequest + .builder() + .method("HEAD") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse showResponse = new ParseImageDetailsFromHeadersTest().response; + + GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, show, showResponse); + + assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1")); + + assertEquals(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").show("fcc451d0-f6e4-4824-ad8f-70ec12326d07").toString(), + new ParseImageDetailsFromHeadersTest().expected().toString()); + } + + public void testShowWhenReponseIs404IsNull() throws Exception { + HttpRequest show = HttpRequest + .builder() + .method("HEAD") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse showResponse = HttpResponse.builder().statusCode(404).build(); + + GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, show, showResponse); + + assertNull(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").show("fcc451d0-f6e4-4824-ad8f-70ec12326d07")); + } + + + public void testGetAsStreamWhenResponseIs2xx() throws Exception { + HttpRequest get = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse getResponse = HttpResponse.builder().statusCode(200).payload(Payloads.newStringPayload("foo")).build(); + + GlanceClient clientWhenExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, get, getResponse); + + assertEquals(clientWhenExist.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1")); + + assertEquals(Strings2.toStringAndClose(clientWhenExist.getImageClientForRegion("az-1.region-a.geo-1").getAsStream("fcc451d0-f6e4-4824-ad8f-70ec12326d07")), + "foo"); + } + + public void testGetAsStreamWhenReponseIs404IsNull() throws Exception { + HttpRequest get = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://glance.jclouds.org:9292/v1.0/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07")) + .headers( + ImmutableMultimap. builder() + .put("X-Auth-Token", authToken).build()).build(); + + HttpResponse getResponse = HttpResponse.builder().statusCode(404).build(); + + GlanceClient clientWhenNoExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, get, getResponse); + + assertNull(clientWhenNoExist.getImageClientForRegion("az-1.region-a.geo-1").getAsStream("fcc451d0-f6e4-4824-ad8f-70ec12326d07")); + } + } diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java index d4f88f3acb..88f03d3115 100644 --- a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java @@ -18,6 +18,12 @@ */ package org.jclouds.openstack.glance.v1_0.features; +import static org.testng.Assert.assertEquals; + +import java.util.Set; + +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientLiveTest; import org.testng.annotations.Test; @@ -27,4 +33,49 @@ import org.testng.annotations.Test; @Test(groups = "live", testName = "ImageClientLiveTest") public class ImageClientLiveTest extends BaseGlanceClientLiveTest { + @Test + public void testList() throws Exception { + for (String zoneId : glanceContext.getApi().getConfiguredRegions()) { + ImageClient client = glanceContext.getApi().getImageClientForRegion(zoneId); + Set response = client.list(); + assert null != response; + for (Image image : response) { + checkImage(image); + } + } + } + + private void checkImage(Image image) { + assert image.getId() != null : image; + assert image.getSize().isPresent() : image; + assert image.getChecksum().isPresent() : image; + assert image.getContainerFormat().isPresent() : image; + assert image.getContainerFormat().isPresent() : image; + } + + @Test + public void testListInDetail() throws Exception { + for (String zoneId : glanceContext.getApi().getConfiguredRegions()) { + ImageClient client = glanceContext.getApi().getImageClientForRegion(zoneId); + Set response = client.listInDetail(); + assert null != response; + for (ImageDetails image : response) { + checkImage(image); + ImageDetails newDetails = client.show(image.getId()); + checkImageDetails(newDetails); + checkImageDetailsEqual(image, newDetails); + } + } + } + + private void checkImageDetails(ImageDetails image) { + //TODO + } + + private void checkImageDetailsEqual(ImageDetails image, ImageDetails newDetails) { + assertEquals(newDetails.getId(), image.getId()); + assertEquals(newDetails.getName(), image.getName()); + assertEquals(newDetails.getLinks(), image.getLinks()); + } + } diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeadersTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeadersTest.java new file mode 100644 index 0000000000..e95c14e819 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/functions/ParseImageDetailsFromHeadersTest.java @@ -0,0 +1,85 @@ +/** + * 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.openstack.glance.v1_0.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat; +import org.jclouds.openstack.glance.v1_0.domain.DiskFormat; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseImageDetailsFromHeadersTest") +public class ParseImageDetailsFromHeadersTest { + + ParseImageDetailsFromHeaders fn = new ParseImageDetailsFromHeaders(new SimpleDateFormatDateService()); + + public HttpResponse response = HttpResponse.builder() + .message("HTTP/1.1 200 OK") + .statusCode(200) + .headers(ImmutableMultimap.builder() + .put("X-Image-Meta-Id", "fcc451d0-f6e4-4824-ad8f-70ec12326d07") + .put("X-Image-Meta-Deleted", "False") + .put("X-Image-Meta-Container_format", "bare") + .put("X-Image-Meta-Checksum", "233afa7b8809d840679b5f0d36d7350a") + .put("X-Image-Meta-Protected", "False") + .put("X-Image-Meta-Min_disk", "0") + .put("X-Image-Meta-Created_at", "2012-05-18T18:06:44") + .put("X-Image-Meta-Size", "65645798") + .put("X-Image-Meta-Status", "active") + .put("X-Image-Meta-Is_public", "True") + .put("X-Image-Meta-Min_ram", "0") + .put("X-Image-Meta-Owner", "5821675") + .put("X-Image-Meta-Updated_at", "2012-05-18T18:42:58") + .put("X-Image-Meta-Disk_format", "raw") + .put("X-Image-Meta-Name", "debian") + .put("Location", "http://HOST/v1/images/fcc451d0-f6e4-4824-ad8f-70ec12326d07") + .put("Etag", "233afa7b8809d840679b5f0d36d7350a") + .build()) + .build(); + + public void test() { + assertEquals(fn.apply(response).toString(), expected().toString()); + } + + public ImageDetails expected() { + return ImageDetails.builder() + .id("fcc451d0-f6e4-4824-ad8f-70ec12326d07") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .status(Image.Status.ACTIVE) + .owner("5821675") + .isPublic(true) + .createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:44")) + .updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:42:58")) + .build(); + } +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesInDetailTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesInDetailTest.java new file mode 100644 index 0000000000..bf1af868d3 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesInDetailTest.java @@ -0,0 +1,85 @@ +/** + * 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.openstack.glance.v1_0.parse; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseSetParserTest; +import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat; +import org.jclouds.openstack.glance.v1_0.domain.DiskFormat; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.openstack.glance.v1_0.domain.ImageDetails; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseImageDetailsListTest") +public class ParseImagesInDetailTest extends BaseSetParserTest { + + @Override + public String resource() { + return "/images_detail.json"; + } + + @Override + @SelectJson("images") + @Consumes(MediaType.APPLICATION_JSON) + public Set expected() { + return ImmutableSet.builder() + .add(ImageDetails + .builder() + .id("fcc451d0-f6e4-4824-ad8f-70ec12326d07") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .status(Image.Status.ACTIVE) + .owner("5821675") + .isPublic(true) + .createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:44")) + .updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-18T18:06:45")) + .build()) + .add(ImageDetails + .builder() + .id("f9fcb127-071d-4670-883e-eedb7efac183") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .status(Image.Status.ACTIVE) + .owner("5821675") + .isPublic(true) + .createdAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T15:04:47")) + .updatedAt(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-05-11T15:04:48")) + .build()) + .build(); + } + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesTest.java new file mode 100644 index 0000000000..7b66f84022 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/parse/ParseImagesTest.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.openstack.glance.v1_0.parse; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseSetParserTest; +import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat; +import org.jclouds.openstack.glance.v1_0.domain.DiskFormat; +import org.jclouds.openstack.glance.v1_0.domain.Image; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseImageListTest") +public class ParseImagesTest extends BaseSetParserTest { + + @Override + public String resource() { + return "/images.json"; + } + + @Override + @SelectJson("images") + @Consumes(MediaType.APPLICATION_JSON) + public Set expected() { + return ImmutableSet.builder() + .add(Image + .builder() + .id("f0209a30-25b8-4d9a-8e2f-dbc028e20b2b") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .build()) + .add(Image + .builder() + .id("fcc451d0-f6e4-4824-ad8f-70ec12326d07") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .build()) + .add(Image + .builder() + .id("f9fcb127-071d-4670-883e-eedb7efac183") + .name("debian") + .containerFormat(ContainerFormat.BARE) + .diskFormat(DiskFormat.RAW) + .checksum("233afa7b8809d840679b5f0d36d7350a") + .size(65645798l) + .build()) + .build(); + } +} diff --git a/labs/openstack-glance/src/test/resources/images.json b/labs/openstack-glance/src/test/resources/images.json new file mode 100644 index 0000000000..b731788379 --- /dev/null +++ b/labs/openstack-glance/src/test/resources/images.json @@ -0,0 +1,24 @@ + { + "images": [{ + "name": "debian", + "container_format": "bare", + "disk_format": "raw", + "checksum": "233afa7b8809d840679b5f0d36d7350a", + "id": "f0209a30-25b8-4d9a-8e2f-dbc028e20b2b", + "size": 65645798 + }, { + "name": "debian", + "container_format": "bare", + "disk_format": "raw", + "checksum": "233afa7b8809d840679b5f0d36d7350a", + "id": "fcc451d0-f6e4-4824-ad8f-70ec12326d07", + "size": 65645798 + }, { + "name": "debian", + "container_format": "bare", + "disk_format": "raw", + "checksum": "233afa7b8809d840679b5f0d36d7350a", + "id": "f9fcb127-071d-4670-883e-eedb7efac183", + "size": 65645798 + }] + } \ No newline at end of file diff --git a/labs/openstack-glance/src/test/resources/images_detail.json b/labs/openstack-glance/src/test/resources/images_detail.json new file mode 100644 index 0000000000..8c8c36d35d --- /dev/null +++ b/labs/openstack-glance/src/test/resources/images_detail.json @@ -0,0 +1,39 @@ +{ + "images": [{ + "status": "active", + "name": "debian", + "deleted": false, + "container_format": "bare", + "created_at": "2012-05-18T18:06:44", + "disk_format": "raw", + "updated_at": "2012-05-18T18:06:45", + "properties": {}, + "min_disk": 0, + "protected": false, + "id": "fcc451d0-f6e4-4824-ad8f-70ec12326d07", + "checksum": "233afa7b8809d840679b5f0d36d7350a", + "owner": "5821675", + "is_public": true, + "deleted_at": null, + "min_ram": 0, + "size": 65645798 + }, { + "status": "active", + "name": "debian", + "deleted": false, + "container_format": "bare", + "created_at": "2012-05-11T15:04:47", + "disk_format": "raw", + "updated_at": "2012-05-11T15:04:48", + "properties": {}, + "min_disk": 0, + "protected": false, + "id": "f9fcb127-071d-4670-883e-eedb7efac183", + "checksum": "233afa7b8809d840679b5f0d36d7350a", + "owner": "5821675", + "is_public": true, + "deleted_at": null, + "min_ram": 0, + "size": 65645798 + }] +} \ No newline at end of file