From f2231c64eb0600e2aa71313538f972e3a9b375f5 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Thu, 31 Mar 2016 08:48:05 +0200 Subject: [PATCH] Add ImageInfo and related non-functional classes - Add public builder and factory methods to DeprecationStatus - Add setters/getters for DeprecationStatus timestamps as String - Add ImageId, configuration classes and ImageInfo class --- .../gcloud/compute/DeprecationStatus.java | 271 ++++++++++-- .../compute/DiskImageConfiguration.java | 161 +++++++ .../gcloud/compute/ImageConfiguration.java | 190 ++++++++ .../com/google/gcloud/compute/ImageId.java | 145 ++++++ .../com/google/gcloud/compute/ImageInfo.java | 416 ++++++++++++++++++ .../compute/StorageImageConfiguration.java | 201 +++++++++ .../gcloud/compute/DeprecationStatusTest.java | 121 ++++- .../compute/DiskImageConfigurationTest.java | 112 +++++ .../google/gcloud/compute/DiskTypeTest.java | 6 +- .../google/gcloud/compute/ImageIdTest.java | 79 ++++ .../google/gcloud/compute/ImageInfoTest.java | 175 ++++++++ .../gcloud/compute/MachineTypeTest.java | 6 +- .../com/google/gcloud/compute/RegionTest.java | 7 +- .../gcloud/compute/SerializationTest.java | 15 +- .../StorageImageConfigurationTest.java | 108 +++++ .../com/google/gcloud/compute/ZoneTest.java | 7 +- 16 files changed, 1944 insertions(+), 76 deletions(-) create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/DiskImageConfiguration.java create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageConfiguration.java create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageId.java create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageInfo.java create mode 100644 gcloud-java-compute/src/main/java/com/google/gcloud/compute/StorageImageConfiguration.java create mode 100644 gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskImageConfigurationTest.java create mode 100644 gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageIdTest.java create mode 100644 gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageInfoTest.java create mode 100644 gcloud-java-compute/src/test/java/com/google/gcloud/compute/StorageImageConfigurationTest.java diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DeprecationStatus.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DeprecationStatus.java index c80071dde10a..896aeebe096f 100644 --- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DeprecationStatus.java +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DeprecationStatus.java @@ -16,6 +16,8 @@ package com.google.gcloud.compute; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.base.Function; import com.google.common.base.MoreObjects; @@ -28,16 +30,17 @@ /** * The deprecation status associated to a Google Compute Engine resource. * - * @param The Google Compute Engine resource to which the deprecation status refers to. + * @param The Google Compute Engine resource identity to which the deprecation status refers */ public final class DeprecationStatus implements Serializable { private static final long serialVersionUID = -2695077634793679794L; private static final DateTimeFormatter TIMESTAMP_FORMATTER = ISODateTimeFormat.dateTime(); + private static final DateTimeFormatter TIMESTAMP_PARSER = ISODateTimeFormat.dateTimeParser(); - private final Long deleted; - private final Long deprecated; - private final Long obsolete; + private final String deleted; + private final String deprecated; + private final String obsolete; private final T replacement; private final Status status; @@ -64,38 +67,203 @@ public enum Status { DELETED } - DeprecationStatus(Long deleted, Long deprecated, Long obsolete, T replacement, Status status) { - this.deleted = deleted; - this.deprecated = deprecated; - this.obsolete = obsolete; - this.replacement = replacement; - this.status = status; + /** + * A builder for {@code DeprecationStatus} objects. + * + * @param The Google Compute Engine resource identity to which the deprecation status refers + */ + public static final class Builder { + + private String deleted; + private String deprecated; + private String obsolete; + private T replacement; + private Status status; + + Builder() {} + + Builder(DeprecationStatus deprecationStatus) { + this.deleted = deprecationStatus.deleted; + this.deprecated = deprecationStatus.deprecated; + this.obsolete = deprecationStatus.obsolete; + this.replacement = deprecationStatus.replacement; + this.status = deprecationStatus.status; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#DELETED}. Timestamp should be in RFC3339 format. + * + * @see RFC3339 + */ + // todo(mziccard): remove this method if #732 is closed + public Builder deleted(String deleted) { + this.deleted = deleted; + return this; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#DEPRECATED}. Timestamp should be in RFC3339 format. + * + * @see RFC3339 + */ + // todo(mziccard): remove this method if #732 is closed + public Builder deprecated(String deprecated) { + this.deprecated = deprecated; + return this; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#OBSOLETE}. Timestamp should be in RFC3339 format. + * + * @see RFC3339 + */ + // todo(mziccard): remove this method if #732 is closed + public Builder obsolete(String obsolete) { + this.obsolete = obsolete; + return this; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#DELETED}. In milliseconds since epoch. + */ + public Builder deleted(long deleted) { + this.deleted = TIMESTAMP_FORMATTER.print(deleted); + return this; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#DEPRECATED}. In milliseconds since epoch. + */ + public Builder deprecated(long deprecated) { + this.deprecated = TIMESTAMP_FORMATTER.print(deprecated); + return this; + } + + /** + * Sets the timestamp on or after which the deprecation state of this resource will be changed + * to {@link Status#OBSOLETE}. In milliseconds since epoch. + */ + public Builder obsolete(long obsolete) { + this.obsolete = TIMESTAMP_FORMATTER.print(obsolete); + return this; + } + + /** + * Sets the identity of the suggested replacement for a deprecated resource. The suggested + * replacement resource must be the same kind of resource as the deprecated resource. + */ + public Builder replacement(T replacement) { + this.replacement = replacement; + return this; + } + + /** + * Sets the status of the deprecated resource. + */ + public Builder status(Status status) { + this.status = checkNotNull(status); + return this; + } + + /** + * Creates a {@code DeprecationStatus} object. + */ + public DeprecationStatus build() { + return new DeprecationStatus(this); + } + } + + DeprecationStatus(Builder builder) { + this.deleted = builder.deleted; + this.deprecated = builder.deprecated; + this.obsolete = builder.obsolete; + this.replacement = builder.replacement; + this.status = checkNotNull(builder.status); } /** * Returns the timestamp on or after which the deprecation state of this resource will be changed - * to {@link Status#DELETED}. In milliseconds since epoch. + * to {@link Status#DELETED}. Returns {@code null} if not set. This value should be in RFC3339 + * format. + * + * @see RFC3339 */ - public Long deleted() { + // todo(mziccard): remove this method if #732 is closed + public String deleted() { return deleted; } /** * Returns the timestamp on or after which the deprecation state of this resource will be changed - * to {@link Status#DEPRECATED}. In milliseconds since epoch. + * to {@link Status#DEPRECATED}. Returns {@code null} if not set. This value should be in RFC3339 + * format. + * + * @see RFC3339 */ - public Long deprecated() { + // todo(mziccard): remove this method if #732 is closed + public String deprecated() { return deprecated; } /** * Returns the timestamp on or after which the deprecation state of this resource will be changed - * to {@link Status#OBSOLETE}. In milliseconds since epoch. + * to {@link Status#OBSOLETE}. Returns {@code null} if not set. This value should be in RFC3339 + * format. + * + * @see RFC3339 */ - public Long obsolete() { + // todo(mziccard): remove this method if #732 is closed + public String obsolete() { return obsolete; } + /** + * Returns the timestamp (in milliseconds since epoch) on or after which the deprecation state of + * this resource will be changed to {@link Status#DELETED}. Returns {@code null} if not set. + * + * @throws IllegalStateException if {@link #deleted()} is not a valid date, time or datetime + */ + public Long deletedMillis() { + try { + return deleted != null ? TIMESTAMP_PARSER.parseMillis(deleted) : null; + } catch (IllegalArgumentException ex) { + throw new IllegalStateException(ex.getMessage(), ex); + } + } + + /** + * Returns the timestamp (in milliseconds since epoch) on or after which the deprecation state of + * this resource will be changed to {@link Status#DEPRECATED}. Returns {@code null} if not set. + * + * @throws IllegalStateException if {@link #deprecated()} is not a valid date, time or datetime + */ + public Long deprecatedMillis() { + try { + return deprecated != null ? TIMESTAMP_PARSER.parseMillis(deprecated) : null; + } catch (IllegalArgumentException ex) { + throw new IllegalStateException(ex.getMessage(), ex); + } + } + + /** + * Returns the timestamp (in milliseconds since epoch) on or after which the deprecation state of + * this resource will be changed to {@link Status#OBSOLETE}. Returns {@code null} if not set. + * + * @throws IllegalStateException if {@link #obsolete()} is not a valid date, time or datetime + */ + public Long obsoleteMillis() { + try { + return obsolete != null ? TIMESTAMP_PARSER.parseMillis(obsolete) : null; + } catch (IllegalArgumentException ex) { + throw new IllegalStateException(ex.getMessage(), ex); + } + } + /** * Returns the identity of the suggested replacement for a deprecated resource. The suggested * replacement resource must be the same kind of resource as the deprecated resource. @@ -111,6 +279,13 @@ public Status status() { return status; } + /** + * Returns a builder for the {@code DeprecationStatus} object. + */ + public Builder toBuilder() { + return new Builder<>(this); + } + @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -136,37 +311,49 @@ public boolean equals(Object obj) { com.google.api.services.compute.model.DeprecationStatus toPb() { com.google.api.services.compute.model.DeprecationStatus deprecationStatusPb = new com.google.api.services.compute.model.DeprecationStatus(); - if (deleted != null) { - deprecationStatusPb.setDeleted(TIMESTAMP_FORMATTER.print(deleted)); - } - if (deprecated != null) { - deprecationStatusPb.setDeprecated(TIMESTAMP_FORMATTER.print(deprecated)); - } - if (obsolete != null) { - deprecationStatusPb.setObsolete(TIMESTAMP_FORMATTER.print(obsolete)); - } - if (replacement != null) { - deprecationStatusPb.setReplacement(replacement.selfLink()); - } - if (status() != null) { - deprecationStatusPb.setState(status.name()); - } + deprecationStatusPb.setDeleted(deleted); + deprecationStatusPb.setDeprecated(deprecated); + deprecationStatusPb.setObsolete(obsolete); + deprecationStatusPb.setReplacement(replacement.selfLink()); + deprecationStatusPb.setState(status.name()); return deprecationStatusPb; } + /** + * Returns the builder for a {@code DeprecationStatus} object given the status. + */ + public static Builder builder(Status status) { + return new Builder().status(status); + } + + /** + * Returns the builder for a {@code DeprecationStatus} object given the status and replacement's + * identity. + */ + public static Builder builder(Status status, T replacement) { + return new Builder().status(status).replacement(replacement); + } + + /** + * Returns a {@code DeprecationStatus} object given the status and replacement's identity. + */ + public static DeprecationStatus of(Status status, T replacement) { + return builder(status, replacement).build(); + } + static DeprecationStatus fromPb( com.google.api.services.compute.model.DeprecationStatus deprecationStatusPb, Function fromUrl) { - return new DeprecationStatus<>( - deprecationStatusPb.getDeleted() != null - ? TIMESTAMP_FORMATTER.parseMillis(deprecationStatusPb.getDeleted()) : null, - deprecationStatusPb.getDeprecated() != null - ? TIMESTAMP_FORMATTER.parseMillis(deprecationStatusPb.getDeprecated()) : null, - deprecationStatusPb.getObsolete() != null - ? TIMESTAMP_FORMATTER.parseMillis(deprecationStatusPb.getObsolete()) : null, - deprecationStatusPb.getReplacement() != null - ? fromUrl.apply(deprecationStatusPb.getReplacement()) : null, - deprecationStatusPb.getState() != null - ? Status.valueOf(deprecationStatusPb.getState()) : null); + Builder builder = new Builder<>(); + builder.deleted(deprecationStatusPb.getDeleted()); + builder.deprecated(deprecationStatusPb.getDeprecated()); + builder.obsolete(deprecationStatusPb.getObsolete()); + if (deprecationStatusPb.getReplacement() != null) { + builder.replacement(fromUrl.apply(deprecationStatusPb.getReplacement())); + } + if (deprecationStatusPb.getState() != null) { + builder.status(Status.valueOf(deprecationStatusPb.getState())); + } + return builder.build(); } } diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DiskImageConfiguration.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DiskImageConfiguration.java new file mode 100644 index 000000000000..b8b0857b3963 --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/DiskImageConfiguration.java @@ -0,0 +1,161 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.compute.model.Image; +import com.google.common.base.MoreObjects; + +import java.util.Objects; + +/** + * A Google Compute Engine disk image configuration. This class can be used to create images from an + * existing Google Compute Engine disk. + */ +public class DiskImageConfiguration extends ImageConfiguration { + + private static final long serialVersionUID = 2716403667042981170L; + + private final DiskId sourceDisk; + private final String sourceDiskId; + + /** + * A builder for {@code DiskImageConfiguration} objects. + */ + public static final class Builder + extends ImageConfiguration.Builder { + + private DiskId sourceDisk; + private String sourceDiskId; + + private Builder() { + super(Type.DISK); + } + + private Builder(DiskImageConfiguration imageConfiguration) { + super(Type.DISK, imageConfiguration); + this.sourceDisk = imageConfiguration.sourceDisk; + this.sourceDiskId = imageConfiguration.sourceDiskId; + } + + private Builder(Image imagePb) { + super(Type.DISK, imagePb); + this.sourceDisk = DiskId.fromUrl(imagePb.getSourceDisk()); + this.sourceDiskId = imagePb.getSourceDiskId(); + } + + /** + * Sets the identity of the source disk used to create the image. + */ + public Builder sourceDisk(DiskId sourceDisk) { + this.sourceDisk = checkNotNull(sourceDisk); + return this; + } + + Builder sourceDiskId(String sourceDiskId) { + this.sourceDiskId = sourceDiskId; + return this; + } + + /** + * Creates a {@code DiskImageConfiguration} object. + */ + @Override + public DiskImageConfiguration build() { + return new DiskImageConfiguration(this); + } + } + + private DiskImageConfiguration(Builder builder) { + super(builder); + this.sourceDisk = checkNotNull(builder.sourceDisk); + this.sourceDiskId = builder.sourceDiskId; + } + + /** + * Returns the identity of the source disk used to create this image. + */ + public DiskId sourceDisk() { + return sourceDisk; + } + + /** + * Returns the id of the disk used to create this image. This value may be used to determine + * whether the image was taken from the current or a previous instance of a given disk name. + */ + public String sourceDiskId() { + return sourceDiskId; + } + + @Override + public Builder toBuilder() { + return new Builder(this); + } + + @Override + MoreObjects.ToStringHelper toStringHelper() { + return super.toStringHelper() + .add("sourceDisk", sourceDisk) + .add("sourceDiskId", sourceDiskId); + } + + @Override + public final int hashCode() { + return Objects.hash(baseHashCode(), sourceDisk, sourceDiskId); + } + + @Override + public final boolean equals(Object obj) { + return obj instanceof DiskImageConfiguration && baseEquals((DiskImageConfiguration) obj); + } + + @Override + DiskImageConfiguration setProjectId(String projectId) { + if (sourceDisk.project() != null) { + return this; + } + return toBuilder().sourceDisk(sourceDisk.setProjectId(projectId)).build(); + } + + @Override + Image toPb() { + Image imagePb = super.toPb(); + imagePb.setSourceDisk(sourceDisk.selfLink()); + imagePb.setSourceDiskId(sourceDiskId); + return imagePb; + } + + /** + * Creates a builder for a {@code DiskImageConfiguration} given the source disk identity. + */ + public static Builder builder(DiskId sourceDisk) { + return new Builder().sourceDisk(sourceDisk); + } + + /** + * Creates a {@code DiskImageConfiguration} object given the source disk identity. + */ + public static DiskImageConfiguration of(DiskId sourceId) { + return builder(sourceId).build(); + } + + @SuppressWarnings("unchecked") + static DiskImageConfiguration fromPb(Image imagePb) { + return new Builder(imagePb).build(); + } +} diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageConfiguration.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageConfiguration.java new file mode 100644 index 000000000000..aa6379b12f4f --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageConfiguration.java @@ -0,0 +1,190 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import com.google.api.services.compute.model.Image; +import com.google.common.base.MoreObjects; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Base class for Google Compute Engine image configuration. Use {@link DiskImageConfiguration} to + * create an image from an existing Google Compute Engine disk. Use + * {@link StorageImageConfiguration} to create an image from a file stored in Google Cloud Storage. + */ +public abstract class ImageConfiguration implements Serializable { + + private static final long serialVersionUID = -9154332316597745316L; + + private final Type type; + private final SourceType sourceType; + private final Long archiveSizeBytes; + + /** + * Type of a Google Compute Engine image. + */ + public enum Type { + /** + * A Google Compute Engine image created from a Google Compute Engine disk. + */ + DISK, + + /** + * A Google Compute Engine image created from a file saved in Google Cloud Storage. + */ + STORAGE + } + + /** + * Image source type. The only admissible value is {@code RAW}. + */ + public enum SourceType { + RAW + } + + /** + * Base builder for image configurations. + * + * @param the image configuration class + * @param the image configuration builder + */ + public abstract static class Builder> { + + private Type type; + private SourceType sourceType; + private Long archiveSizeBytes; + + Builder(Type type) { + this.type = type; + } + + Builder(Type type, ImageConfiguration imageConfiguration) { + this.type = type; + this.sourceType = imageConfiguration.sourceType; + this.archiveSizeBytes = imageConfiguration.archiveSizeBytes; + } + + Builder(Type type, Image imagePb) { + this.type = type; + if (imagePb.getSourceType() != null) { + this.sourceType = SourceType.valueOf(imagePb.getSourceType()); + } + this.archiveSizeBytes = imagePb.getArchiveSizeBytes(); + } + + @SuppressWarnings("unchecked") + B self() { + return (B) this; + } + + B type(Type type) { + this.type = type; + return self(); + } + + B sourceType(SourceType sourceType) { + this.sourceType = sourceType; + return self(); + } + + B archiveSizeBytes(Long archiveSizeBytes) { + this.archiveSizeBytes = archiveSizeBytes; + return self(); + } + + /** + * Creates a configuration object. + */ + public abstract T build(); + } + + ImageConfiguration(Builder builder) { + this.type = builder.type; + this.sourceType = builder.sourceType; + this.archiveSizeBytes = builder.archiveSizeBytes; + } + + /** + * Returns the image's type. This method returns {@link Type#DISK} if this image was created from + * an existing disk. This method returns {@link Type#STORAGE} if this image was created from a + * file in Google Cloud Storage. + */ + public Type type() { + return type; + } + + /** + * Returns the source type of the disk. The default and only value is {@link SourceType#RAW}. + */ + public SourceType sourceType() { + return sourceType; + } + + /** + * Returns the size of the image archive stored in Google Cloud Storage (in bytes). + */ + public Long archiveSizeBytes() { + return archiveSizeBytes; + } + + /** + * Returns a builder for the object. + */ + public abstract Builder toBuilder(); + + MoreObjects.ToStringHelper toStringHelper() { + return MoreObjects.toStringHelper(this) + .add("type", type) + .add("sourceType", sourceType) + .add("archiveSizeBytes", archiveSizeBytes); + } + + @Override + public String toString() { + return toStringHelper().toString(); + } + + final int baseHashCode() { + return Objects.hash(type, sourceType, archiveSizeBytes); + } + + final boolean baseEquals(ImageConfiguration imageConfiguration) { + return imageConfiguration != null + && getClass().equals(imageConfiguration.getClass()) + && Objects.equals(toPb(), imageConfiguration.toPb()); + } + + abstract ImageConfiguration setProjectId(String projectId); + + Image toPb() { + Image imagePb = new Image(); + if (sourceType != null) { + imagePb.setSourceType(sourceType.name()); + } + imagePb.setArchiveSizeBytes(archiveSizeBytes); + return imagePb; + } + + @SuppressWarnings("unchecked") + static T fromPb(Image imagePb) { + if (imagePb.getSourceDisk() != null) { + return (T) DiskImageConfiguration.fromPb(imagePb); + } + return (T) StorageImageConfiguration.fromPb(imagePb); + } +} diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageId.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageId.java new file mode 100644 index 000000000000..eacea6402cba --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageId.java @@ -0,0 +1,145 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Identity for a Google Compute Engine image. + */ +public final class ImageId extends ResourceId { + + static final Function FROM_URL_FUNCTION = new Function() { + @Override + public ImageId apply(String pb) { + return ImageId.fromUrl(pb); + } + }; + static final Function TO_URL_FUNCTION = new Function() { + @Override + public String apply(ImageId imageId) { + return imageId.selfLink(); + } + }; + + private static final String REGEX = ResourceId.REGEX + "global/images/([^/]+)"; + private static final Pattern PATTERN = Pattern.compile(REGEX); + private static final long serialVersionUID = 6434553917859414341L; + + private final String image; + + private ImageId(String project, String image) { + super(project); + this.image = checkNotNull(image); + } + + /** + * Returns the name of the image. The name must be 1-63 characters long and comply with RFC1035. + * Specifically, the name must match the regular expression {@code [a-z]([-a-z0-9]*[a-z0-9])?} + * which means the first character must be a lowercase letter, and all following characters must + * be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. + * + * @see RFC1035 + */ + public String image() { + return image; + } + + @Override + public String selfLink() { + return super.selfLink() + "/global/images/" + image; + } + + @Override + MoreObjects.ToStringHelper toStringHelper() { + return super.toStringHelper().add("image", image); + } + + @Override + public int hashCode() { + return Objects.hash(baseHashCode(), image); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ImageId)) { + return false; + } + ImageId other = (ImageId) obj; + return baseEquals(other) && Objects.equals(image, other.image); + } + + @Override + ImageId setProjectId(String projectId) { + if (project() != null) { + return this; + } + return ImageId.of(projectId, image); + } + + /** + * Returns an image identity given the image name. The image name must be 1-63 characters long and + * comply with RFC1035. Specifically, the name must match the regular expression + * {@code [a-z]([-a-z0-9]*[a-z0-9])?} which means the first character must be a lowercase letter, + * and all following characters must be a dash, lowercase letter, or digit, except the last + * character, which cannot be a dash. + * + * @see RFC1035 + */ + public static ImageId of(String image) { + return new ImageId(null, image); + } + + /** + * Returns an image identity given project and image names. The image name must be 1-63 characters + * long and comply with RFC1035. Specifically, the name must match the regular expression + * {@code [a-z]([-a-z0-9]*[a-z0-9])?} which means the first character must be a lowercase letter, + * and all following characters must be a dash, lowercase letter, or digit, except the last + * character, which cannot be a dash. + * + * @see RFC1035 + */ + public static ImageId of(String project, String image) { + return new ImageId(project, image); + } + + /** + * Returns {@code true} if the provided string matches the expected format of an image URL. + * Returns {@code false} otherwise. + */ + static boolean matchesUrl(String url) { + return PATTERN.matcher(url).matches(); + } + + static ImageId fromUrl(String url) { + Matcher matcher = PATTERN.matcher(url); + if (!matcher.matches()) { + throw new IllegalArgumentException(url + " is not a valid image URL"); + } + return ImageId.of(matcher.group(1), matcher.group(2)); + } +} diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageInfo.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageInfo.java new file mode 100644 index 000000000000..c243154cec4e --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ImageInfo.java @@ -0,0 +1,416 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.compute.model.Image; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import java.io.Serializable; +import java.math.BigInteger; +import java.util.List; +import java.util.Objects; + +/** + * A Google Compute Engine Image. An image contains a boot loader, an operating system and a root + * file system that is necessary for starting an instance. Compute Engine offers publicly-available + * images of certain operating systems that you can use, or you can create a custom image. A custom + * image is an image created from one of your virtual machine instances that contains your specific + * instance configurations. Use {@link DiskImageConfiguration} to create an image from an existing + * disk. Use {@link StorageImageConfiguration} to create an image from a file stored in Google + * Cloud Storage. + * + * @see Images + */ +public class ImageInfo implements Serializable { + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public ImageInfo apply(Image pb) { + return ImageInfo.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public Image apply(ImageInfo image) { + return image.toPb(); + } + }; + + private static final long serialVersionUID = -1061916352807358977L; + private static final DateTimeFormatter TIMESTAMP_FORMATTER = ISODateTimeFormat.dateTime(); + + private final String id; + private final ImageId imageId; + private final Long creationTimestamp; + private final String description; + private final ImageConfiguration configuration; + private final Status status; + private final Long diskSizeGb; + private final List licenses; + private final DeprecationStatus deprecationStatus; + + /** + * The status of a Google Compute Engine Image. An image can be used to create other disks only + * after it has been successfully created and its status is set to {@code READY}. + */ + public enum Status { + /** + * Image creation failed. The image can not be used. + */ + FAILED, + + /** + * Image creation is pending. The image is not ready to be used yet. + */ + PENDING, + + /** + * Image has been created and is ready for use. + */ + READY + } + + /** + * A builder for {@code ImageInfo} objects. + */ + public abstract static class Builder { + + abstract Builder id(String id); + + abstract Builder creationTimestamp(Long creationTimestamp); + + /** + * Sets the image identity. + */ + public abstract Builder imageId(ImageId imageId); + + /** + * Sets an optional textual description of the image. + */ + public abstract Builder description(String description); + + /** + * Sets the image configuration. Use {@link DiskImageConfiguration} to create an image from an + * existing disk. Use {@link StorageImageConfiguration} to create an image from a file stored in + * Google Cloud Storage. + */ + public abstract Builder configuration(ImageConfiguration configuration); + + abstract Builder status(Status status); + + abstract Builder diskSizeGb(Long diskSizeGb); + + abstract Builder licenses(List licenses); + + abstract Builder deprecationStatus(DeprecationStatus deprecationStatus); + + /** + * Creates a {@code ImageInfo} object. + */ + public abstract ImageInfo build(); + } + + static final class BuilderImpl extends Builder { + + private String id; + private Long creationTimestamp; + private ImageId imageId; + private String description; + private ImageConfiguration configuration; + private Status status; + private Long diskSizeGb; + private List licenses; + private DeprecationStatus deprecationStatus; + + BuilderImpl() {} + + BuilderImpl(ImageInfo imageInfo) { + this.id = imageInfo.id; + this.creationTimestamp = imageInfo.creationTimestamp; + this.imageId = imageInfo.imageId; + this.description = imageInfo.description; + this.configuration = imageInfo.configuration; + this.status = imageInfo.status; + this.diskSizeGb = imageInfo.diskSizeGb; + this.licenses = imageInfo.licenses; + this.deprecationStatus = imageInfo.deprecationStatus; + } + + BuilderImpl(Image imagePb) { + if (imagePb.getId() != null) { + this.id = imagePb.getId().toString(); + } + if (imagePb.getCreationTimestamp() != null) { + this.creationTimestamp = TIMESTAMP_FORMATTER.parseMillis(imagePb.getCreationTimestamp()); + } + this.imageId = ImageId.fromUrl(imagePb.getSelfLink()); + this.description = imagePb.getDescription(); + this.configuration = ImageConfiguration.fromPb(imagePb); + if (imagePb.getStatus() != null) { + this.status = Status.valueOf(imagePb.getStatus()); + } + this.diskSizeGb = imagePb.getDiskSizeGb(); + if (imagePb.getLicenses() != null) { + this.licenses = Lists.transform(imagePb.getLicenses(), LicenseId.FROM_URL_FUNCTION); + } + if (imagePb.getDeprecated() != null) { + this.deprecationStatus = + DeprecationStatus.fromPb(imagePb.getDeprecated(), ImageId.FROM_URL_FUNCTION); + } + } + + @Override + BuilderImpl id(String id) { + this.id = id; + return this; + } + + @Override + BuilderImpl creationTimestamp(Long creationTimestamp) { + this.creationTimestamp = creationTimestamp; + return this; + } + + @Override + public BuilderImpl imageId(ImageId imageId) { + this.imageId = checkNotNull(imageId); + return this; + } + + @Override + public BuilderImpl description(String description) { + this.description = description; + return this; + } + + @Override + public BuilderImpl configuration(ImageConfiguration configuration) { + this.configuration = checkNotNull(configuration); + return this; + } + + @Override + BuilderImpl status(Status status) { + this.status = status; + return this; + } + + @Override + BuilderImpl diskSizeGb(Long diskSizeGb) { + this.diskSizeGb = diskSizeGb; + return this; + } + + @Override + BuilderImpl licenses(List licenses) { + this.licenses = licenses != null ? ImmutableList.copyOf(licenses) : null; + return this; + } + + @Override + BuilderImpl deprecationStatus(DeprecationStatus deprecationStatus) { + this.deprecationStatus = deprecationStatus; + return this; + } + + @Override + public ImageInfo build() { + return new ImageInfo(this); + } + } + + ImageInfo(BuilderImpl builder) { + this.id = builder.id; + this.creationTimestamp = builder.creationTimestamp; + this.imageId = checkNotNull(builder.imageId); + this.description = builder.description; + this.configuration = checkNotNull(builder.configuration); + this.status = builder.status; + this.diskSizeGb = builder.diskSizeGb; + this.licenses = builder.licenses; + this.deprecationStatus = builder.deprecationStatus; + } + + /** + * Returns the unique identifier for the image; defined by the service. + */ + public String id() { + return id; + } + + /** + * Returns the creation timestamp in milliseconds since epoch. + */ + public Long creationTimestamp() { + return creationTimestamp; + } + + /** + * Returns the image identity. + */ + public ImageId imageId() { + return imageId; + } + + /** + * Returns a textual description of the image. + */ + public String description() { + return description; + } + + /** + * Returns the image configuration. This method returns an instance of + * {@link DiskImageConfiguration} if the the image was created from a Google Compute Engine disk. + * This method returns an instance of {@link StorageImageConfiguration} if the image was created + * from a file stored in Google Cloud Storage. + */ + @SuppressWarnings("unchecked") + public T configuration() { + return (T) configuration; + } + + /** + * Returns all applicable publicly visible licenses. + */ + public List licenses() { + return licenses; + } + + /** + * Returns the status of the image. An image can be used to create other disks only after it has + * been successfully created and its status is set to {@link Status#READY}. + */ + public Status status() { + return status; + } + + /** + * Returns the size of the image when restored onto a persistent disk (in GB). + */ + public Long diskSizeGb() { + return diskSizeGb; + } + + /** + * Returns the deprecation status of the image. If {@link DeprecationStatus#status()} is either + * {@link DeprecationStatus.Status#DELETED} or {@link DeprecationStatus.Status#OBSOLETE} the + * image must not be used. Returns {@code null} if the image is not deprecated. + */ + public DeprecationStatus deprecationStatus() { + return deprecationStatus; + } + + /** + * Returns a builder for the current image. + */ + public Builder toBuilder() { + return new BuilderImpl(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .add("creationTimestamp", creationTimestamp) + .add("imageId", imageId) + .add("description", description) + .add("configuration", configuration) + .add("status", status) + .add("diskSizeGb", diskSizeGb) + .add("licenses", licenses) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(id, creationTimestamp, imageId, description, configuration, status, + diskSizeGb, licenses); + } + + @Override + public boolean equals(Object obj) { + return obj != null + && obj.getClass().equals(ImageInfo.class) + && Objects.equals(toPb(), ((ImageInfo) obj).toPb()); + } + + ImageInfo setProjectId(String projectId) { + return toBuilder() + .imageId(imageId.setProjectId(projectId)) + .configuration(configuration.setProjectId(projectId)) + .build(); + } + + Image toPb() { + Image imagePb = configuration.toPb(); + if (id != null) { + imagePb.setId(new BigInteger(id)); + } + if (creationTimestamp != null) { + imagePb.setCreationTimestamp(TIMESTAMP_FORMATTER.print(creationTimestamp)); + } + imagePb.setName(imageId.image()); + imagePb.setDescription(description); + imagePb.setSelfLink(imageId.selfLink()); + if (status != null) { + imagePb.setStatus(status.name()); + } + imagePb.setDiskSizeGb(diskSizeGb); + if (licenses != null) { + imagePb.setLicenses(Lists.transform(licenses, LicenseId.TO_URL_FUNCTION)); + } + if (deprecationStatus != null) { + imagePb.setDeprecated(deprecationStatus.toPb()); + } + return imagePb; + } + + /** + * Returns a builder for an {@code ImageInfo} object given the image identity and an image + * configuration. Use {@link DiskImageConfiguration} to create an image from an existing disk. Use + * {@link StorageImageConfiguration} to create an image from a file stored in Google Cloud + * Storage. + */ + public static Builder builder(ImageId imageId, ImageConfiguration configuration) { + return new BuilderImpl().imageId(imageId).configuration(configuration); + } + + /** + * Returns an {@code ImageInfo} object given the image identity and an image configuration. Use + * {@link DiskImageConfiguration} to create an image from an existing disk. Use + * {@link StorageImageConfiguration} to create an image from a file stored in Google Cloud + * Storage. + */ + public static ImageInfo of(ImageId imageId, ImageConfiguration configuration) { + return builder(imageId, configuration).build(); + } + + static ImageInfo fromPb(Image imagePb) { + return new BuilderImpl(imagePb).build(); + } +} diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/StorageImageConfiguration.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/StorageImageConfiguration.java new file mode 100644 index 000000000000..a09be89aefe6 --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/StorageImageConfiguration.java @@ -0,0 +1,201 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.services.compute.model.Image; +import com.google.common.base.MoreObjects; + +import java.util.Objects; + +/** + * A Google Compute Engine image configuration used to create images from a Google Cloud Storage + * URL where the disk image is stored. + */ +public class StorageImageConfiguration extends ImageConfiguration { + + private static final long serialVersionUID = 8160447986545005880L; + + private final ContainerType containerType; + private final String sha1; + private final String source; + + /** + * The format used to encode and transmit the block device. The only supported value is + * {@code TAR}. This is just a container and transmission format, not a runtime format. + */ + public enum ContainerType { + TAR + } + + /** + * A builder for {@code StorageImageConfiguration} objects. + */ + public static final class Builder + extends ImageConfiguration.Builder { + + private ContainerType containerType; + private String sha1; + private String source; + + private Builder() { + super(Type.STORAGE); + } + + private Builder(StorageImageConfiguration imageConfiguration) { + super(Type.STORAGE, imageConfiguration); + this.containerType = imageConfiguration.containerType; + this.sha1 = imageConfiguration.sha1; + this.source = imageConfiguration.source; + } + + private Builder(Image imagePb) { + super(Type.STORAGE, imagePb); + if (imagePb.getRawDisk().getContainerType() != null) { + this.containerType = ContainerType.valueOf(imagePb.getRawDisk().getContainerType()); + } + this.sha1 = imagePb.getRawDisk().getSha1Checksum(); + this.source = imagePb.getRawDisk().getSource(); + } + + /** + * Sets the format used to encode and transmit the block device. The only supported value is + * {@code TAR}. This is just a container and transmission format, not a runtime format. + */ + public Builder containerType(ContainerType containerType) { + this.containerType = containerType; + return this; + } + + /** + * Sets the SHA1 checksum of the disk image before unpackaging. + */ + public Builder sha1(String sha1) { + this.sha1 = sha1; + return this; + } + + /** + * Sets the full Google Cloud Storage URL where the disk image is stored (e.g. + * {@code gs://bucket/file}). + */ + public Builder source(String source) { + this.source = checkNotNull(source); + return this; + } + + /** + * Creates a {@code StorageImageConfiguration} object. + */ + @Override + public StorageImageConfiguration build() { + return new StorageImageConfiguration(this); + } + } + + private StorageImageConfiguration(Builder builder) { + super(builder); + this.source = checkNotNull(builder.source); + this.containerType = builder.containerType; + this.sha1 = builder.sha1; + } + + /** + * Returns the format used to encode and transmit the block device. This is just a container and + * transmission format, not a runtime format. + */ + public ContainerType containerType() { + return containerType; + } + + /** + * Returns the SHA1 checksum of the disk image before unpackaging. + */ + public String sha1() { + return sha1; + } + + /** + * Returns the full Google Cloud Storage URL where the disk image is stored (e.g. + * {@code gs://bucket/file}). + */ + public String source() { + return source; + } + + @Override + public Builder toBuilder() { + return new Builder(this); + } + + @Override + MoreObjects.ToStringHelper toStringHelper() { + return super.toStringHelper() + .add("source", source) + .add("containerType", containerType) + .add("sha1", sha1); + } + + @Override + public final int hashCode() { + return Objects.hash(baseHashCode(), source, containerType, sha1); + } + + @Override + public final boolean equals(Object obj) { + return obj instanceof StorageImageConfiguration && baseEquals((StorageImageConfiguration) obj); + } + + @Override + StorageImageConfiguration setProjectId(String projectId) { + return this; + } + + @Override + Image toPb() { + Image.RawDisk rawDiskPb = new Image.RawDisk(); + rawDiskPb.setSource(source); + rawDiskPb.setSha1Checksum(sha1); + if (containerType != null) { + rawDiskPb.setContainerType(containerType.name()); + } + Image imagePb = super.toPb(); + return imagePb.setRawDisk(rawDiskPb); + } + + /** + * Creates a {@code StorageImageConfiguration} builder given the full Google Cloud Storage URL + * where the disk image is stored. + */ + public static Builder builder(String source) { + return new Builder().source(source); + } + + /** + * Creates a {@code StorageImageConfiguration} object given the full Google Cloud Storage URL + * where the disk image is stored. + */ + public static StorageImageConfiguration of(String source) { + return builder(source).build(); + } + + @SuppressWarnings("unchecked") + static StorageImageConfiguration fromPb(Image imagePb) { + return new Builder(imagePb).build(); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DeprecationStatusTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DeprecationStatusTest.java index e8d29669da7b..389d470bd300 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DeprecationStatusTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DeprecationStatusTest.java @@ -17,39 +17,137 @@ package com.google.gcloud.compute; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import com.google.gcloud.compute.DeprecationStatus.Status; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; import org.junit.Test; public class DeprecationStatusTest { - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; + private static final DateTimeFormatter TIMESTAMP_FORMATTER = ISODateTimeFormat.dateTime(); + private static final Long DELETED_MILLIS = 1453293540000L; + private static final Long DEPRECATED_MILLIS = 1453293420000L; + private static final Long OBSOLETE_MILLIS = 1453293480000L; + private static final String DELETED = TIMESTAMP_FORMATTER.print(DELETED_MILLIS); + private static final String DEPRECATED = TIMESTAMP_FORMATTER.print(DEPRECATED_MILLIS); + private static final String OBSOLETE = TIMESTAMP_FORMATTER.print(OBSOLETE_MILLIS); private static final DiskTypeId DISK_TYPE_ID = DiskTypeId.of("project", "zone", "diskType"); private static final MachineTypeId MACHINE_TYPE_ID = MachineTypeId.of("project", "zone", "machineType"); private static final Status STATUS = Status.DELETED; private static final DeprecationStatus DISK_TYPE_STATUS = - new DeprecationStatus<>(DELETED, DEPRECATED, OBSOLETE, DISK_TYPE_ID, STATUS); + DeprecationStatus.builder(STATUS) + .replacement(DISK_TYPE_ID) + .deprecated(DEPRECATED) + .obsolete(OBSOLETE) + .deleted(DELETED) + .build(); + private static final DeprecationStatus DISK_TYPE_STATUS_MILLIS = + DeprecationStatus.builder(STATUS) + .replacement(DISK_TYPE_ID) + .deprecated(DEPRECATED_MILLIS) + .obsolete(OBSOLETE_MILLIS) + .deleted(DELETED_MILLIS) + .build(); private static final DeprecationStatus MACHINE_TYPE_STATUS = - new DeprecationStatus<>(DELETED, DEPRECATED, OBSOLETE, MACHINE_TYPE_ID, STATUS); + DeprecationStatus.builder(STATUS, MACHINE_TYPE_ID) + .deprecated(DEPRECATED) + .obsolete(OBSOLETE) + .deleted(DELETED) + .build(); @Test - public void testConstructor() { + public void testBuilder() { + compareDeprecationStatus(DISK_TYPE_STATUS, DISK_TYPE_STATUS_MILLIS); assertEquals(DELETED, DISK_TYPE_STATUS.deleted()); assertEquals(DEPRECATED, DISK_TYPE_STATUS.deprecated()); assertEquals(OBSOLETE, DISK_TYPE_STATUS.obsolete()); assertEquals(DISK_TYPE_ID, DISK_TYPE_STATUS.replacement()); + assertEquals(DEPRECATED_MILLIS, DISK_TYPE_STATUS.deprecatedMillis()); + assertEquals(DELETED_MILLIS, DISK_TYPE_STATUS.deletedMillis()); + assertEquals(OBSOLETE_MILLIS, DISK_TYPE_STATUS.obsoleteMillis()); + assertEquals(STATUS, DISK_TYPE_STATUS.status()); + assertEquals(DELETED, DISK_TYPE_STATUS_MILLIS.deleted()); + assertEquals(DEPRECATED, DISK_TYPE_STATUS_MILLIS.deprecated()); + assertEquals(OBSOLETE, DISK_TYPE_STATUS_MILLIS.obsolete()); + assertEquals(DISK_TYPE_ID, DISK_TYPE_STATUS_MILLIS.replacement()); + assertEquals(DEPRECATED_MILLIS, DISK_TYPE_STATUS_MILLIS.deprecatedMillis()); + assertEquals(DELETED_MILLIS, DISK_TYPE_STATUS_MILLIS.deletedMillis()); + assertEquals(OBSOLETE_MILLIS, DISK_TYPE_STATUS_MILLIS.obsoleteMillis()); assertEquals(STATUS, DISK_TYPE_STATUS.status()); assertEquals(DELETED, MACHINE_TYPE_STATUS.deleted()); assertEquals(DEPRECATED, MACHINE_TYPE_STATUS.deprecated()); assertEquals(OBSOLETE, MACHINE_TYPE_STATUS.obsolete()); + assertEquals(DEPRECATED_MILLIS, MACHINE_TYPE_STATUS.deprecatedMillis()); + assertEquals(DELETED_MILLIS, MACHINE_TYPE_STATUS.deletedMillis()); + assertEquals(OBSOLETE_MILLIS, MACHINE_TYPE_STATUS.obsoleteMillis()); assertEquals(MACHINE_TYPE_ID, MACHINE_TYPE_STATUS.replacement()); assertEquals(STATUS, MACHINE_TYPE_STATUS.status()); } + @Test + public void testGettersIllegalArgument() { + DeprecationStatus deprecationStatus = + DeprecationStatus.builder(STATUS, MACHINE_TYPE_ID) + .deprecated("deprecated") + .obsolete("obsolete") + .deleted("delete") + .build(); + assertEquals("deprecated", deprecationStatus.deprecated()); + try { + deprecationStatus.deprecatedMillis(); + fail("Expected IllegalArgumentException"); + } catch (IllegalStateException ex) { + // never reached + } + assertEquals("obsolete", deprecationStatus.obsolete()); + try { + deprecationStatus.obsoleteMillis(); + fail("Expected IllegalArgumentException"); + } catch (IllegalStateException ex) { + // never reached + } + assertEquals("delete", deprecationStatus.deleted()); + try { + deprecationStatus.deletedMillis(); + fail("Expected IllegalArgumentException"); + } catch (IllegalStateException ex) { + // never reached + } + } + + @Test + public void testToBuilder() { + compareDeprecationStatus(DISK_TYPE_STATUS, DISK_TYPE_STATUS.toBuilder().build()); + compareDeprecationStatus(MACHINE_TYPE_STATUS, MACHINE_TYPE_STATUS.toBuilder().build()); + DeprecationStatus deprecationStatus = DISK_TYPE_STATUS.toBuilder() + .deleted(DEPRECATED) + .build(); + assertEquals(DEPRECATED, deprecationStatus.deleted()); + deprecationStatus = deprecationStatus.toBuilder().deleted(DELETED).build(); + compareDeprecationStatus(DISK_TYPE_STATUS, deprecationStatus); + } + + @Test + public void testToBuilderIncomplete() { + DeprecationStatus diskStatus = DeprecationStatus.of(STATUS, DISK_TYPE_ID); + assertEquals(diskStatus, diskStatus.toBuilder().build()); + } + + @Test + public void testOf() { + DeprecationStatus diskStatus = DeprecationStatus.of(STATUS, DISK_TYPE_ID); + assertNull(diskStatus.deleted()); + assertNull(diskStatus.deprecated()); + assertNull(diskStatus.obsolete()); + assertEquals(DISK_TYPE_ID, diskStatus.replacement()); + assertEquals(STATUS, diskStatus.status()); + } + @Test public void testToAndFromPb() { DeprecationStatus diskStatus = @@ -58,12 +156,16 @@ public void testToAndFromPb() { DeprecationStatus machineStatus = DeprecationStatus.fromPb(MACHINE_TYPE_STATUS.toPb(), MachineTypeId.FROM_URL_FUNCTION); compareDeprecationStatus(MACHINE_TYPE_STATUS, machineStatus); - diskStatus = new DeprecationStatus<>(null, DEPRECATED, null, DISK_TYPE_ID, STATUS); + diskStatus = DeprecationStatus.builder(STATUS, DISK_TYPE_ID).deprecated(DEPRECATED).build(); assertEquals(diskStatus, DeprecationStatus.fromPb(diskStatus.toPb(), DiskTypeId.FROM_URL_FUNCTION)); - machineStatus = new DeprecationStatus<>(null, DEPRECATED, null, MACHINE_TYPE_ID, STATUS); + machineStatus = + DeprecationStatus.builder(STATUS, MACHINE_TYPE_ID).deprecated(DEPRECATED).build(); assertEquals(machineStatus, DeprecationStatus.fromPb(machineStatus.toPb(), MachineTypeId.FROM_URL_FUNCTION)); + diskStatus = DeprecationStatus.of(STATUS, DISK_TYPE_ID); + assertEquals(diskStatus, + DeprecationStatus.fromPb(diskStatus.toPb(), DiskTypeId.FROM_URL_FUNCTION)); } private void compareDeprecationStatus(DeprecationStatus expected, DeprecationStatus value) { @@ -71,6 +173,9 @@ private void compareDeprecationStatus(DeprecationStatus expected, DeprecationSta assertEquals(expected.deleted(), value.deleted()); assertEquals(expected.deprecated(), value.deprecated()); assertEquals(expected.obsolete(), value.obsolete()); + assertEquals(expected.deletedMillis(), value.deletedMillis()); + assertEquals(expected.deprecatedMillis(), value.deprecatedMillis()); + assertEquals(expected.obsoleteMillis(), value.obsoleteMillis()); assertEquals(expected.replacement(), value.replacement()); assertEquals(expected.status(), value.status()); assertEquals(expected.hashCode(), value.hashCode()); diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskImageConfigurationTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskImageConfigurationTest.java new file mode 100644 index 000000000000..df1e8bf62a4c --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskImageConfigurationTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import com.google.gcloud.compute.ImageConfiguration.SourceType; +import com.google.gcloud.compute.ImageConfiguration.Type; + +import org.junit.Test; + +public class DiskImageConfigurationTest { + + private static final DiskId SOURCE_DISK = DiskId.of("project", "zone", "disk"); + private static final String SOURCE_DISK_ID = "diskId"; + private static final Long ARCHIVE_SIZE_BYTES = 42L; + private static final SourceType SOURCE_TYPE = SourceType.RAW; + private static final DiskImageConfiguration CONFIGURATION = + DiskImageConfiguration.builder(SOURCE_DISK) + .sourceDiskId(SOURCE_DISK_ID) + .sourceType(SOURCE_TYPE) + .archiveSizeBytes(ARCHIVE_SIZE_BYTES) + .build(); + + @Test + public void testToBuilder() { + compareDiskImageConfiguration(CONFIGURATION, CONFIGURATION.toBuilder().build()); + DiskId newDisk = DiskId.of("newProject", "newZone", "newDisk"); + String newDiskId = "newDiskId"; + DiskImageConfiguration configuration = CONFIGURATION.toBuilder() + .sourceDisk(newDisk) + .sourceDiskId(newDiskId) + .build(); + assertEquals(newDisk, configuration.sourceDisk()); + assertEquals(newDiskId, configuration.sourceDiskId()); + configuration = configuration.toBuilder() + .sourceDiskId(SOURCE_DISK_ID) + .sourceDisk(SOURCE_DISK) + .build(); + compareDiskImageConfiguration(CONFIGURATION, configuration); + } + + @Test + public void testToBuilderIncomplete() { + DiskImageConfiguration configuration = DiskImageConfiguration.of(SOURCE_DISK); + compareDiskImageConfiguration(configuration, configuration.toBuilder().build()); + } + + @Test + public void testBuilder() { + assertEquals(SOURCE_TYPE, CONFIGURATION.sourceType()); + assertEquals(SOURCE_DISK, CONFIGURATION.sourceDisk()); + assertEquals(SOURCE_DISK_ID, CONFIGURATION.sourceDiskId()); + assertEquals(ARCHIVE_SIZE_BYTES, CONFIGURATION.archiveSizeBytes()); + assertEquals(Type.DISK, CONFIGURATION.type()); + } + + @Test + public void testToAndFromPb() { + assertTrue(ImageConfiguration.fromPb(CONFIGURATION.toPb()) instanceof DiskImageConfiguration); + compareDiskImageConfiguration(CONFIGURATION, + ImageConfiguration.fromPb(CONFIGURATION.toPb())); + DiskImageConfiguration configuration = DiskImageConfiguration.of(SOURCE_DISK); + compareDiskImageConfiguration(configuration, + DiskImageConfiguration.fromPb(configuration.toPb())); + } + + @Test + public void testOf() { + DiskImageConfiguration configuration = DiskImageConfiguration.of(SOURCE_DISK); + assertEquals(Type.DISK, configuration.type()); + assertNull(configuration.sourceDiskId()); + assertNull(configuration.sourceType()); + assertNull(configuration.archiveSizeBytes()); + assertEquals(SOURCE_DISK, configuration.sourceDisk()); + } + + @Test + public void testSetProjectId() { + DiskImageConfiguration configuration = CONFIGURATION.toBuilder() + .sourceDisk(DiskId.of("zone", "disk")) + .build(); + compareDiskImageConfiguration(CONFIGURATION, configuration.setProjectId("project")); + } + + private void compareDiskImageConfiguration(DiskImageConfiguration expected, + DiskImageConfiguration value) { + assertEquals(expected, value); + assertEquals(expected.type(), value.type()); + assertEquals(expected.archiveSizeBytes(), value.archiveSizeBytes()); + assertEquals(expected.sourceDisk(), value.sourceDisk()); + assertEquals(expected.sourceDiskId(), value.sourceDiskId()); + assertEquals(expected.sourceType(), value.sourceType()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskTypeTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskTypeTest.java index 9e97b8d1becd..4cbb8351270c 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskTypeTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/DiskTypeTest.java @@ -28,12 +28,8 @@ public class DiskTypeTest { private static final String VALID_DISK_SIZE = "10GB-10TB"; private static final Long DEFAULT_DISK_SIZE_GB = 10L; private static final DiskTypeId DISK_TYPE_ID = DiskTypeId.of("project", "zone", "diskType"); - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; - private static final DeprecationStatus.Status STATUS = DeprecationStatus.Status.DELETED; private static final DeprecationStatus DEPRECATION_STATUS = - new DeprecationStatus<>(DELETED, DEPRECATED, OBSOLETE, DISK_TYPE_ID, STATUS); + DeprecationStatus.of(DeprecationStatus.Status.DELETED, DISK_TYPE_ID); private static final DiskType DISK_TYPE = DiskType.builder() .id(ID) .diskTypeId(DISK_TYPE_ID) diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageIdTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageIdTest.java new file mode 100644 index 000000000000..0a11b7fe60f6 --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageIdTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class ImageIdTest { + + private static final String PROJECT = "project"; + private static final String NAME = "image"; + private static final String URL = + "https://www.googleapis.com/compute/v1/projects/project/global/images/image"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testOf() { + ImageId imageId = ImageId.of(PROJECT, NAME); + assertEquals(PROJECT, imageId.project()); + assertEquals(NAME, imageId.image()); + assertEquals(URL, imageId.selfLink()); + imageId = ImageId.of(NAME); + assertNull(imageId.project()); + assertEquals(NAME, imageId.image()); + } + + @Test + public void testToAndFromUrl() { + ImageId imageId = ImageId.of(PROJECT, NAME); + compareImageId(imageId, ImageId.fromUrl(imageId.selfLink())); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("notMatchingUrl is not a valid image URL"); + ImageId.fromUrl("notMatchingUrl"); + } + + @Test + public void testSetProjectId() { + ImageId imageId = ImageId.of(PROJECT, NAME); + assertSame(imageId, imageId.setProjectId(PROJECT)); + compareImageId(imageId, ImageId.of(NAME).setProjectId(PROJECT)); + } + + @Test + public void testMatchesUrl() { + assertTrue(ImageId.matchesUrl(ImageId.of(PROJECT, NAME).selfLink())); + assertFalse(ImageId.matchesUrl("notMatchingUrl")); + } + + private void compareImageId(ImageId expected, ImageId value) { + assertEquals(expected, value); + assertEquals(expected.project(), expected.project()); + assertEquals(expected.image(), expected.image()); + assertEquals(expected.selfLink(), expected.selfLink()); + assertEquals(expected.hashCode(), expected.hashCode()); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageInfoTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageInfoTest.java new file mode 100644 index 000000000000..db6e092b5587 --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ImageInfoTest.java @@ -0,0 +1,175 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.google.common.collect.ImmutableList; +import com.google.gcloud.compute.ImageConfiguration.SourceType; + +import org.junit.Test; + +import java.util.List; + +public class ImageInfoTest { + + private static final ImageId IMAGE_ID = ImageId.of("project", "image"); + private static final String ID = "42"; + private static final Long CREATION_TIMESTAMP = 1453293540000L; + private static final String DESCRIPTION = "description"; + private static final ImageInfo.Status STATUS = ImageInfo.Status.READY; + private static final List LICENSES = ImmutableList.of( + LicenseId.of("project", "license1"), LicenseId.of("project", "license2")); + private static final Long DISK_SIZE_GB = 42L; + private static final String STORAGE_SOURCE = "source"; + private static final Long ARCHIVE_SIZE_BYTES = 24L; + private static final String SHA1_CHECKSUM = "checksum"; + private static final DiskId SOURCE_DISK = DiskId.of("project", "zone", "disk"); + private static final String SOURCE_DISK_ID = "diskId"; + private static final SourceType SOURCE_TYPE = SourceType.RAW; + private static final StorageImageConfiguration STORAGE_CONFIGURATION = + StorageImageConfiguration.builder(STORAGE_SOURCE) + .archiveSizeBytes(ARCHIVE_SIZE_BYTES) + .containerType(StorageImageConfiguration.ContainerType.TAR) + .sha1(SHA1_CHECKSUM) + .sourceType(SOURCE_TYPE) + .build(); + private static final DiskImageConfiguration DISK_CONFIGURATION = + DiskImageConfiguration.builder(SOURCE_DISK) + .archiveSizeBytes(ARCHIVE_SIZE_BYTES) + .sourceDiskId(SOURCE_DISK_ID) + .sourceType(SOURCE_TYPE) + .build(); + private static final DeprecationStatus DEPRECATION_STATUS = + DeprecationStatus.of(DeprecationStatus.Status.DELETED, IMAGE_ID); + private static final ImageInfo STORAGE_IMAGE = ImageInfo.builder(IMAGE_ID, STORAGE_CONFIGURATION) + .id(ID) + .creationTimestamp(CREATION_TIMESTAMP) + .description(DESCRIPTION) + .status(STATUS) + .diskSizeGb(DISK_SIZE_GB) + .licenses(LICENSES) + .deprecationStatus(DEPRECATION_STATUS) + .build(); + private static final ImageInfo DISK_IMAGE = ImageInfo.builder(IMAGE_ID, DISK_CONFIGURATION) + .id(ID) + .creationTimestamp(CREATION_TIMESTAMP) + .description(DESCRIPTION) + .status(STATUS) + .diskSizeGb(DISK_SIZE_GB) + .licenses(LICENSES) + .deprecationStatus(DEPRECATION_STATUS) + .build(); + + @Test + public void testToBuilder() { + compareImageInfo(STORAGE_IMAGE, STORAGE_IMAGE.toBuilder().build()); + compareImageInfo(DISK_IMAGE, DISK_IMAGE.toBuilder().build()); + ImageInfo imageInfo = STORAGE_IMAGE.toBuilder().description("newDescription").build(); + assertEquals("newDescription", imageInfo.description()); + imageInfo = imageInfo.toBuilder().description("description").build(); + compareImageInfo(STORAGE_IMAGE, imageInfo); + } + + @Test + public void testToBuilderIncomplete() { + ImageInfo imageInfo = ImageInfo.of(IMAGE_ID, STORAGE_CONFIGURATION); + assertEquals(imageInfo, imageInfo.toBuilder().build()); + imageInfo = ImageInfo.of(IMAGE_ID, DISK_CONFIGURATION); + assertEquals(imageInfo, imageInfo.toBuilder().build()); + } + + @Test + public void testBuilder() { + assertEquals(ID, STORAGE_IMAGE.id()); + assertEquals(IMAGE_ID, STORAGE_IMAGE.imageId()); + assertEquals(CREATION_TIMESTAMP, STORAGE_IMAGE.creationTimestamp()); + assertEquals(DESCRIPTION, STORAGE_IMAGE.description()); + assertEquals(STORAGE_CONFIGURATION, STORAGE_IMAGE.configuration()); + assertEquals(STATUS, STORAGE_IMAGE.status()); + assertEquals(DISK_SIZE_GB, STORAGE_IMAGE.diskSizeGb()); + assertEquals(LICENSES, STORAGE_IMAGE.licenses()); + assertEquals(DEPRECATION_STATUS, STORAGE_IMAGE.deprecationStatus()); + assertEquals(ID, DISK_IMAGE.id()); + assertEquals(IMAGE_ID, DISK_IMAGE.imageId()); + assertEquals(CREATION_TIMESTAMP, DISK_IMAGE.creationTimestamp()); + assertEquals(DESCRIPTION, DISK_IMAGE.description()); + assertEquals(DISK_CONFIGURATION, DISK_IMAGE.configuration()); + assertEquals(STATUS, DISK_IMAGE.status()); + assertEquals(DISK_SIZE_GB, DISK_IMAGE.diskSizeGb()); + assertEquals(LICENSES, DISK_IMAGE.licenses()); + assertEquals(DEPRECATION_STATUS, DISK_IMAGE.deprecationStatus()); + } + + @Test + public void testOf() { + ImageInfo imageInfo = ImageInfo.of(IMAGE_ID, STORAGE_CONFIGURATION); + assertEquals(IMAGE_ID, imageInfo.imageId()); + assertEquals(STORAGE_CONFIGURATION, imageInfo.configuration()); + assertNull(imageInfo.id()); + assertNull(imageInfo.creationTimestamp()); + assertNull(imageInfo.description()); + assertNull(imageInfo.status()); + assertNull(imageInfo.diskSizeGb()); + assertNull(imageInfo.licenses()); + assertNull(imageInfo.deprecationStatus()); + imageInfo = ImageInfo.of(IMAGE_ID, DISK_CONFIGURATION); + assertEquals(IMAGE_ID, imageInfo.imageId()); + assertEquals(DISK_CONFIGURATION, imageInfo.configuration()); + assertNull(imageInfo.id()); + assertNull(imageInfo.creationTimestamp()); + assertNull(imageInfo.description()); + assertNull(imageInfo.status()); + assertNull(imageInfo.diskSizeGb()); + assertNull(imageInfo.licenses()); + assertNull(imageInfo.deprecationStatus()); + } + + @Test + public void testToAndFromPb() { + compareImageInfo(STORAGE_IMAGE, ImageInfo.fromPb(STORAGE_IMAGE.toPb())); + compareImageInfo(DISK_IMAGE, ImageInfo.fromPb(DISK_IMAGE.toPb())); + ImageInfo imageInfo = ImageInfo.of(IMAGE_ID, StorageImageConfiguration.of(STORAGE_SOURCE)); + compareImageInfo(imageInfo, ImageInfo.fromPb(imageInfo.toPb())); + imageInfo = ImageInfo.of(IMAGE_ID, DiskImageConfiguration.of(SOURCE_DISK)); + compareImageInfo(imageInfo, ImageInfo.fromPb(imageInfo.toPb())); + } + + @Test + public void testSetProjectId() { + ImageInfo imageInfo = DISK_IMAGE.toBuilder() + .imageId(ImageId.of("image")) + .configuration(DISK_CONFIGURATION.toBuilder().sourceDisk(DiskId.of("zone", "disk")).build()) + .build(); + compareImageInfo(DISK_IMAGE, imageInfo.setProjectId("project")); + } + + public void compareImageInfo(ImageInfo expected, ImageInfo value) { + assertEquals(expected, value); + assertEquals(expected.id(), value.id()); + assertEquals(expected.imageId(), value.imageId()); + assertEquals(expected.creationTimestamp(), value.creationTimestamp()); + assertEquals(expected.description(), value.description()); + assertEquals(expected.configuration(), value.configuration()); + assertEquals(expected.status(), value.status()); + assertEquals(expected.diskSizeGb(), value.diskSizeGb()); + assertEquals(expected.licenses(), value.licenses()); + assertEquals(expected.deprecationStatus(), value.deprecationStatus()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/MachineTypeTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/MachineTypeTest.java index 969b370ddce8..6b0f78dff00a 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/MachineTypeTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/MachineTypeTest.java @@ -35,12 +35,8 @@ public class MachineTypeTest { private static final List SCRATCH_DISKS = ImmutableList.of(3); private static final Integer MAXIMUM_PERSISTENT_DISKS = 4; private static final Long MAXIMUM_PERSISTENT_DISKS_SIZE_GB = 5L; - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; - private static final DeprecationStatus.Status STATUS = DeprecationStatus.Status.DELETED; private static final DeprecationStatus DEPRECATION_STATUS = - new DeprecationStatus<>(DELETED, DEPRECATED, OBSOLETE, MACHINE_TYPE_ID, STATUS); + DeprecationStatus.of(DeprecationStatus.Status.DELETED, MACHINE_TYPE_ID); private static final MachineType MACHINE_TYPE = MachineType.builder() .id(ID) .machineTypeId(MACHINE_TYPE_ID) diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/RegionTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/RegionTest.java index fb0250366a5e..07701b1d2248 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/RegionTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/RegionTest.java @@ -39,11 +39,8 @@ public class RegionTest { private static final Region.Quota QUOTA2 = new Region.Quota("METRIC2", 4, 3); private static final List QUOTAS = ImmutableList.of(QUOTA1, QUOTA2); - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; - private static final DeprecationStatus DEPRECATION_STATUS = new DeprecationStatus<>( - DELETED, DEPRECATED, OBSOLETE, REGION_ID, DeprecationStatus.Status.DELETED); + private static final DeprecationStatus DEPRECATION_STATUS = + DeprecationStatus.of(DeprecationStatus.Status.DELETED, REGION_ID); private static final Region REGION = Region.builder() .regionId(REGION_ID) .id(ID) diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java index ab15ca5dc6a9..b533ae9c6ae7 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/SerializationTest.java @@ -105,12 +105,8 @@ public class SerializationTest { .maintenanceWindows(WINDOWS) .region(REGION_ID) .build(); - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; private static final DeprecationStatus DEPRECATION_STATUS = - new DeprecationStatus<>(DELETED, DEPRECATED, OBSOLETE, MACHINE_TYPE_ID, - DeprecationStatus.Status.DELETED); + DeprecationStatus.of(DeprecationStatus.Status.DELETED, MACHINE_TYPE_ID); private static final LicenseId LICENSE_ID = LicenseId.of("project", "license"); private static final Boolean CHARGES_USE_FEE = true; private static final License LICENSE = new License(LICENSE_ID, CHARGES_USE_FEE); @@ -152,6 +148,12 @@ public class SerializationTest { private static final SnapshotInfo SNAPSHOT_INFO = SnapshotInfo.of(SNAPSHOT_ID, DISK_ID); private static final Snapshot SNAPSHOT = new Snapshot.Builder(COMPUTE, SNAPSHOT_ID, DISK_ID).build(); + private static final ImageId IMAGE_ID = ImageId.of("project", "image"); + private static final DiskImageConfiguration DISK_IMAGE_CONFIGURATION = + DiskImageConfiguration.of(DISK_ID); + private static final StorageImageConfiguration RAW_IMAGE_CONFIGURATION = + StorageImageConfiguration.of("gs:/bucket/file"); + private static final ImageInfo IMAGE_INFO = ImageInfo.of(IMAGE_ID, DISK_IMAGE_CONFIGURATION); private static final Compute.DiskTypeOption DISK_TYPE_OPTION = Compute.DiskTypeOption.fields(); private static final Compute.DiskTypeFilter DISK_TYPE_FILTER = @@ -222,7 +224,8 @@ public void testModelAndRequests() throws Exception { REGION_OPERATION_ID, ZONE_OPERATION_ID, GLOBAL_OPERATION, REGION_OPERATION, ZONE_OPERATION, INSTANCE_ID, REGION_FORWARDING_RULE_ID, GLOBAL_FORWARDING_RULE_ID, GLOBAL_ADDRESS_ID, REGION_ADDRESS_ID, INSTANCE_USAGE, GLOBAL_FORWARDING_USAGE, REGION_FORWARDING_USAGE, - ADDRESS_INFO, ADDRESS, DISK_ID, SNAPSHOT_ID, SNAPSHOT_INFO, SNAPSHOT, DISK_TYPE_OPTION, + ADDRESS_INFO, ADDRESS, DISK_ID, SNAPSHOT_ID, SNAPSHOT_INFO, SNAPSHOT, IMAGE_ID, + DISK_IMAGE_CONFIGURATION, RAW_IMAGE_CONFIGURATION, IMAGE_INFO, DISK_TYPE_OPTION, DISK_TYPE_FILTER, DISK_TYPE_LIST_OPTION, DISK_TYPE_AGGREGATED_LIST_OPTION, MACHINE_TYPE_OPTION, MACHINE_TYPE_FILTER, MACHINE_TYPE_LIST_OPTION, MACHINE_TYPE_AGGREGATED_LIST_OPTION, REGION_OPTION, REGION_FILTER, REGION_LIST_OPTION, diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/StorageImageConfigurationTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/StorageImageConfigurationTest.java new file mode 100644 index 000000000000..dc05686a478f --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/StorageImageConfigurationTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.compute; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import com.google.gcloud.compute.ImageConfiguration.SourceType; +import com.google.gcloud.compute.StorageImageConfiguration.ContainerType; +import com.google.gcloud.compute.ImageConfiguration.Type; + +import org.junit.Test; + +public class StorageImageConfigurationTest { + + private static final String SOURCE = "source"; + private static final SourceType SOURCE_TYPE = SourceType.RAW; + private static final ContainerType CONTAINER_TYPE = ContainerType.TAR; + private static final Long ARCHIVE_SIZE_BYTES = 42L; + private static final String SHA1 = "sha1"; + private static final StorageImageConfiguration CONFIGURATION = + StorageImageConfiguration.builder(SOURCE) + .sourceType(SOURCE_TYPE) + .containerType(CONTAINER_TYPE) + .archiveSizeBytes(ARCHIVE_SIZE_BYTES) + .sha1(SHA1) + .build(); + + @Test + public void testToBuilder() { + compareRawImageConfiguration(CONFIGURATION, CONFIGURATION.toBuilder().build()); + String newSource = "newSource"; + StorageImageConfiguration configuration = CONFIGURATION.toBuilder().source(newSource).build(); + assertEquals(newSource, configuration.source()); + configuration = configuration.toBuilder().source(SOURCE).build(); + compareRawImageConfiguration(CONFIGURATION, configuration); + } + + @Test + public void testToBuilderIncomplete() { + StorageImageConfiguration configuration = StorageImageConfiguration.of(SOURCE); + compareRawImageConfiguration(configuration, configuration.toBuilder().build()); + } + + @Test + public void testBuilder() { + assertEquals(SOURCE_TYPE, CONFIGURATION.sourceType()); + assertEquals(SOURCE, CONFIGURATION.source()); + assertEquals(CONTAINER_TYPE, CONFIGURATION.containerType()); + assertEquals(ARCHIVE_SIZE_BYTES, CONFIGURATION.archiveSizeBytes()); + assertEquals(SHA1, CONFIGURATION.sha1()); + assertEquals(Type.STORAGE, CONFIGURATION.type()); + } + + @Test + public void testToAndFromPb() { + assertTrue(ImageConfiguration.fromPb(CONFIGURATION.toPb()) instanceof StorageImageConfiguration); + compareRawImageConfiguration(CONFIGURATION, + ImageConfiguration.fromPb(CONFIGURATION.toPb())); + StorageImageConfiguration configuration = StorageImageConfiguration.of(SOURCE); + compareRawImageConfiguration(configuration, + StorageImageConfiguration.fromPb(configuration.toPb())); + } + + @Test + public void testOf() { + StorageImageConfiguration configuration = StorageImageConfiguration.of(SOURCE); + assertEquals(Type.STORAGE, configuration.type()); + assertNull(configuration.sourceType()); + assertEquals(SOURCE, configuration.source()); + assertNull(configuration.containerType()); + assertNull(configuration.archiveSizeBytes()); + assertNull(configuration.sha1()); + } + + @Test + public void testSetProjectId() { + assertSame(CONFIGURATION, CONFIGURATION.setProjectId("project")); + } + + private void compareRawImageConfiguration(StorageImageConfiguration expected, + StorageImageConfiguration value) { + assertEquals(expected, value); + assertEquals(expected.type(), value.type()); + assertEquals(expected.source(), value.source()); + assertEquals(expected.sourceType(), value.sourceType()); + assertEquals(expected.containerType(), value.containerType()); + assertEquals(expected.archiveSizeBytes(), value.archiveSizeBytes()); + assertEquals(expected.sha1(), value.sha1()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ZoneTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ZoneTest.java index d686054b8cf6..1224c607a567 100644 --- a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ZoneTest.java +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/ZoneTest.java @@ -40,11 +40,8 @@ public class ZoneTest { private static final MaintenanceWindow WINDOW2 = new MaintenanceWindow("NAME2", "DESCRIPTION2", BEGIN_TIME, END_TIME); private static final List WINDOWS = ImmutableList.of(WINDOW1, WINDOW2); - private static final Long DELETED = 1453293540000L; - private static final Long DEPRECATED = 1453293420000L; - private static final Long OBSOLETE = 1453293480000L; - private static final DeprecationStatus DEPRECATION_STATUS = new DeprecationStatus<>( - DELETED, DEPRECATED, OBSOLETE, ZONE_ID, DeprecationStatus.Status.DELETED); + private static final DeprecationStatus DEPRECATION_STATUS = + DeprecationStatus.of(DeprecationStatus.Status.DELETED, ZONE_ID); private static final Zone ZONE = Zone.builder() .zoneId(ZONE_ID) .id(ID)