diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java index ee0c327da8dc..907f581fcca6 100644 --- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java @@ -2339,7 +2339,7 @@ Operation deprecate(ImageId image, DeprecationStatus deprecationStatus, * * @throws ComputeException upon failure */ - Page listSubnetworks(String project, SubnetworkListOption... options); + Page listSubnetworks(String region, SubnetworkListOption... options); /** * Lists subnetworks for all regions. diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/InstanceInfo.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/InstanceInfo.java new file mode 100644 index 000000000000..b26d0994e7af --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/InstanceInfo.java @@ -0,0 +1,1282 @@ +/* + * 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.Instance; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import java.io.Serializable; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A Google Compute Engine VM Instance. An instance is a virtual machine (VM) hosted on Google's + * infrastructure. Instances can run Linux and Windows Server images provided by Google, or any + * customized versions of these images. You can also build and run images of other operating + * systems. Google Compute Engine also lets you choose the machine properties of your instances, + * such as the number of virtual CPUs and the amount of memory + * + *

By default, each Compute Engine instance has a small root persistent disk that contains the + * operating system. When your applications require additional storage space, you can add one or + * more additional disks to your instance. + * + *

Instances communicate with other instances in the same network through a local area network. + * Instances communicate with the rest of the world through the Internet. A network lives in a + * project and is isolated from other networks in the project. A project can have up to five + * different networks. + * + * @see Virtual Machine Instances + */ +public class InstanceInfo implements Serializable { + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public InstanceInfo apply(Instance pb) { + return InstanceInfo.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public Instance apply(InstanceInfo instance) { + return instance.toPb(); + } + }; + + private static final long serialVersionUID = -6601223112628977168L; + private static final DateTimeFormatter TIMESTAMP_FORMATTER = ISODateTimeFormat.dateTime(); + + private final String id; + private final InstanceId instanceId; + private final Long creationTimestamp; + private final String description; + private final Status status; + private final String statusMessage; + private final Tags tags; + private final MachineTypeId machineType; + private final Boolean canIpForward; + private final List networkInterfaces; + private final List attachedDisks; + private final Metadata metadata; + private final List serviceAccounts; + private final SchedulingOptions schedulingOptions; + private final String cpuPlatform; + + /** + * The status of the instance. + */ + public enum Status { + /** + * Indicates that resources are being reserved for the instance. The instance isn't running yet. + */ + PROVISIONING, + + /** + * Indicates that resources have been acquired and the instance is being prepared for launch. + */ + STAGING, + + /** + * Indicates that the instance is booting up or running. You should be able to {@code ssh} into + * the instance soon, though not immediately, after it enters this state. + */ + RUNNING, + + /** + * Indicates that the instance is being stopped either due to a failure, or the instance being + * shut down. This is a temporary status and the instance will move to {@code TERMINATED}. + */ + STOPPING, + + /** + * Indicates that the instance was shut down or encountered a failure, either through the API or + * from inside the guest. You can choose to restart the instance or delete it. + */ + TERMINATED + } + + /** + * A list of tags for a Google Compute Engine Instance; with associated fingerprint. Tags are used + * to identify valid sources or targets for network firewalls and are specified by the client + * during instance creation. Each tag within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public static final class Tags implements Serializable { + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public Tags apply(com.google.api.services.compute.model.Tags pb) { + return Tags.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.compute.model.Tags apply(Tags tags) { + return tags.toPb(); + } + }; + + private static final long serialVersionUID = 5627093820497225322L; + + private final List values; + private final String fingerprint; + + /** + * A builder for {@code Tags} objects. + */ + public static final class Builder { + + private List values; + private String fingerprint; + + private Builder() { + values = Lists.newArrayList(); + } + + private Builder(Tags tags) { + this.values = tags.values != null ? Lists.newArrayList(tags.values) + : Lists.newArrayList(); + this.fingerprint = tags.fingerprint; + } + + /** + * Sets a list of tags to apply to an instance. Tags are used to identify valid sources or + * targets for network firewalls. Each tag within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public Builder values(Iterable values) { + this.values = Lists.newArrayList(values); + return this; + } + + /** + * Sets a list of tags to apply to an instance. Tags are used to identify valid sources or + * targets for network firewalls. Each tag within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public Builder values(String... values) { + this.values = Lists.newArrayList(Arrays.asList(checkNotNull(values))); + return this; + } + + /** + * Adds a tag to the list of tags. Tags are used to identify valid sources or targets for + * network firewalls. The tag must comply with RFC1035. + * + * @see RFC1035 + */ + public Builder add(String tag) { + this.values.add(tag); + return this; + } + + /** + * Sets the fingerprint for the tags. This value is needed to update instance's tags. + */ + public Builder fingerprint(String fingerprint) { + this.fingerprint = fingerprint; + return this; + } + + /** + * Creates a {@code Tags} object. + */ + public Tags build() { + return new Tags(this); + } + } + + private Tags(Builder builder) { + this.values = ImmutableList.copyOf(builder.values); + this.fingerprint = builder.fingerprint; + } + + /** + * Returns a list of tags to apply to an instance. Tags are used to identify valid sources or + * targets for network firewalls. Each tag within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public List values() { + return values; + } + + /** + * Returns the fingerprint for the tags. This value is needed to update instance's tags. + */ + public String fingerprint() { + return fingerprint; + } + + /** + * Returns a builder for the current instance tags. + */ + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("values", values) + .add("fingerprint", fingerprint) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(values, fingerprint); + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof Tags && Objects.equals(toPb(), ((Tags) obj).toPb()); + } + + com.google.api.services.compute.model.Tags toPb() { + com.google.api.services.compute.model.Tags tagsPb = + new com.google.api.services.compute.model.Tags(); + tagsPb.setFingerprint(fingerprint); + tagsPb.setItems(values); + return tagsPb; + } + + /** + * Returns a builder for a {@code Tags} object given the tags to apply to the instance. Each tag + * within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public static Builder builder(Iterable values) { + return new Builder().values(values); + } + + /** + * Returns a builder for a {@code Tags} object given the tags to apply to the instance. Each tag + * within the list must comply with RFC1035. + * + * @see RFC1035 + */ + public static Builder builder(String... values) { + return new Builder().values(values); + } + + /** + * Returns a {@code Tags} object given the tags to apply to the instance. Each tag within the + * list must comply with RFC1035. + * + * @see RFC1035 + */ + public static Tags of(Iterable values) { + return builder(values).build(); + } + + /** + * Returns a {@code Tags} object given the tags to apply to the instance. Each tag within the + * list must comply with RFC1035. + * + * @see RFC1035 + */ + public static Tags of(String... values) { + return builder(values).build(); + } + + static Tags fromPb(com.google.api.services.compute.model.Tags tagsPb) { + Builder builder = + builder(tagsPb.getItems() != null ? tagsPb.getItems() : ImmutableList.of()); + return builder.fingerprint(tagsPb.getFingerprint()).build(); + } + } + + /** + * Metadata for Google Compute Engine Instance as ket/value pairs. This includes custom metadata + * and predefined keys. + * + * @see Metadata + */ + public static final class Metadata implements Serializable { + + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public Metadata apply(com.google.api.services.compute.model.Metadata pb) { + return Metadata.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.compute.model.Metadata apply(Metadata metadata) { + return metadata.toPb(); + } + }; + + private static final long serialVersionUID = -945038809838910107L; + + private final Map values; + private final String fingerprint; + + /** + * A builder for {@code Metadata} objects. + */ + public static final class Builder { + + private Map values; + private String fingerprint; + + Builder() { + values = Maps.newHashMap(); + } + + Builder(Metadata metadata) { + this.values = metadata.values != null ? Maps.newHashMap(metadata.values) + : Maps.newHashMap(); + this.fingerprint = metadata.fingerprint; + } + + /** + * Sets the metadata for the instance as key/value pairs. The total size of all keys and + * values must be less than 512 KB. Keys must conform to the following regexp: + * {@code [a-zA-Z0-9-_]+}, and be less than 128 bytes in length. This is reflected as part of + * a URL in the metadata server. Additionally, to avoid ambiguity, keys must not conflict with + * any other metadata keys for the project. Values must be less than or equal to 32768 bytes. + */ + public Builder values(Map values) { + this.values = Maps.newHashMap(checkNotNull(values)); + return this; + } + + /** + * Adds a key/value pair to the instance metadata. The total size of all keys and values must + * be less than 512 KB. Keys must conform to the following regexp: {@code [a-zA-Z0-9-_]+}, and + * be less than 128 bytes in length. This is reflected as part of a URL in the metadata + * server. Additionally, to avoid ambiguity, keys must not conflict with any other metadata + * keys for the project. Values must be less than or equal to 32768 bytes. + */ + public Builder add(String key, String value) { + this.values.put(key, value); + return this; + } + + /** + * Sets the fingerprint for the metadata. This value can be used to update instance's + * metadata. + */ + public Builder fingerprint(String fingerprint) { + this.fingerprint = fingerprint; + return this; + } + + /** + * Creates a {@code Metadata} object. + */ + public Metadata build() { + return new Metadata(this); + } + } + + private Metadata(Builder builder) { + this.values = ImmutableMap.copyOf(builder.values); + this.fingerprint = builder.fingerprint; + } + + /** + * Returns instance's metadata as key/value pairs. + */ + public Map values() { + return values; + } + + /** + * Returns the fingerprint for the metadata. This value can be used to update instance's + * metadata. + */ + public String fingerprint() { + return fingerprint; + } + + /** + * Returns a builder for the current instance metadata. + */ + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("values", values) + .add("fingerprint", fingerprint) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(values, fingerprint); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj instanceof Metadata + && Objects.equals(toPb(), ((Metadata) obj).toPb()); + } + + com.google.api.services.compute.model.Metadata toPb() { + com.google.api.services.compute.model.Metadata metadataPb = + new com.google.api.services.compute.model.Metadata(); + metadataPb.setFingerprint(fingerprint); + List itemsPb = + Lists.newArrayListWithCapacity(values.size()); + for (Map.Entry entry : values.entrySet()) { + itemsPb.add(new com.google.api.services.compute.model.Metadata.Items() + .setKey(entry.getKey()).setValue(entry.getValue())); + } + metadataPb.setItems(itemsPb); + metadataPb.setFingerprint(fingerprint); + return metadataPb; + } + + /** + * Returns a builder for a {@code Metadata} object. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Returns a {@code Metadata} object given the the metadata as a map. The total size of all keys + * and values must be less than 512 KB. Keys must conform to the following regexp: + * {@code [a-zA-Z0-9-_]+}, and be less than 128 bytes in length. This is reflected as part of a + * URL in the metadata server. Additionally, to avoid ambiguity, keys must not conflict with any + * other metadata keys for the project. Values must be less than or equal to 32768 bytes. + */ + public static Metadata of(Map values) { + return builder().values(values).build(); + } + + static Metadata fromPb(com.google.api.services.compute.model.Metadata metadataPb) { + Builder builder = builder(); + if (metadataPb.getItems() != null) { + Map metadataValues = + Maps.newHashMapWithExpectedSize(metadataPb.getItems().size()); + for (com.google.api.services.compute.model.Metadata.Items item : metadataPb.getItems()) { + metadataValues.put(item.getKey(), item.getValue()); + } + builder.values(metadataValues); + } + return builder.fingerprint(metadataPb.getFingerprint()).build(); + } + } + + /** + * A service account, with its specified scopes, authorized for this instance. + * + * @see Authenticating from Google + * Compute Engine + */ + public static final class ServiceAccount implements Serializable { + + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public ServiceAccount apply(com.google.api.services.compute.model.ServiceAccount pb) { + return ServiceAccount.fromPb(pb); + } + }; + static final Function + TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.compute.model.ServiceAccount apply( + ServiceAccount metadata) { + return metadata.toPb(); + } + }; + + private static final long serialVersionUID = 4199610694227857331L; + + private final String email; + private final List scopes; + + private ServiceAccount(String email, List scopes) { + this.email = email; + this.scopes = ImmutableList.copyOf(scopes); + } + + /** + * Returns the email address of the service account. + */ + public String email() { + return email; + } + + /** + * Returns the list of scopes to be made available for this service account. + */ + public List scopes() { + return scopes; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("email", email) + .add("scopes", scopes) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(email, scopes); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj instanceof ServiceAccount + && Objects.equals(toPb(), ((ServiceAccount) obj).toPb()); + } + + com.google.api.services.compute.model.ServiceAccount toPb() { + com.google.api.services.compute.model.ServiceAccount serviceAccountPb = + new com.google.api.services.compute.model.ServiceAccount(); + serviceAccountPb.setEmail(email); + serviceAccountPb.setScopes(scopes); + return serviceAccountPb; + } + + /** + * Returns a {@code ServiceAccount} object for the provided email and scopes. + */ + public static ServiceAccount of(String email, List scopes) { + return new ServiceAccount(email, scopes); + } + + /** + * Returns a {@code ServiceAccount} object for the provided email and scopes. + */ + public static ServiceAccount of(String email, String... scopes) { + return of(email, Arrays.asList(scopes)); + } + + static ServiceAccount fromPb(com.google.api.services.compute.model.ServiceAccount accountPb) { + return new ServiceAccount(accountPb.getEmail(), accountPb.getScopes()); + } + } + + /** + * A Google Compute Engine instance scheduling options. When there are system events that might + * cause your instances to be disrupted, Google Compute Engine automatically manages the + * scheduling decisions for your instances. Use {@code SchedulingOptions.preemptible()} to create + * a preemptible instance. Use {@code SchedulingOptions.standard()} to configure scheduling + * options for a standard instance. + * + * @see + * Setting Instance Scheduling Options + */ + public static final class SchedulingOptions implements Serializable { + + private static final long serialVersionUID = 4199610694227857331L; + + private final boolean automaticRestart; + private final Maintenance maintenance; + private final boolean isPreemptible; + + /** + * Defines the maintenance behavior for this instance. + */ + public enum Maintenance { + /** + * The default behavior for standard instances. + */ + MIGRATE, + + /** + * The default and only possible behavior for preemptible instances. + */ + TERMINATE + } + + private SchedulingOptions(Boolean automaticRestart, Maintenance maintenance, + Boolean isPreemptible) { + this.automaticRestart = automaticRestart; + this.maintenance = maintenance; + this.isPreemptible = isPreemptible; + } + + /** + * Returns whether the instance should be automatically restarted if it is terminated by Compute + * Engine (not terminated by a user). + */ + public Boolean automaticRestart() { + return automaticRestart; + } + + /** + * Returns the maintenance behavior for the instance. + */ + public Maintenance maintenance() { + return maintenance; + } + + /** + * Returns {@code true} if the instance is preemptible, {@code false} otherwhise. + * + * @see Preemptible + * Instance + */ + public boolean isPreemptible() { + return isPreemptible; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("automaticRestart", automaticRestart) + .add("maintenance", maintenance) + .add("isPreemptible", isPreemptible) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(automaticRestart, maintenance, isPreemptible); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj instanceof SchedulingOptions + && Objects.equals(toPb(), ((SchedulingOptions) obj).toPb()); + } + + com.google.api.services.compute.model.Scheduling toPb() { + com.google.api.services.compute.model.Scheduling schedulingPb = + new com.google.api.services.compute.model.Scheduling(); + schedulingPb.setAutomaticRestart(automaticRestart); + schedulingPb.setPreemptible(isPreemptible); + if (maintenance != null) { + schedulingPb.setOnHostMaintenance(maintenance.name()); + } + return schedulingPb; + } + + /** + * Returns a {@code SchedulingOptions} object for a preemptible instance. + * + * @see Preemptible + * Instance + */ + public static SchedulingOptions preemptible() { + return new SchedulingOptions(false, Maintenance.TERMINATE, true); + } + + /** + * Returns a {@code SchedulingOptions} object for a standard instance. + * + * @param automaticRestart specifies whether the instance should be automatically restarted if + * it is terminated by Compute Engine (not terminated by a user) + * @param maintenance defines the maintenance behavior for the instance + */ + public static SchedulingOptions standard(boolean automaticRestart, Maintenance maintenance) { + return new SchedulingOptions(automaticRestart, maintenance, false); + } + + static SchedulingOptions fromPb(com.google.api.services.compute.model.Scheduling schedPb) { + Maintenance maintenance = null; + if (schedPb.getOnHostMaintenance() != null) { + maintenance = Maintenance.valueOf(schedPb.getOnHostMaintenance()); + } + return new SchedulingOptions(schedPb.getAutomaticRestart(), maintenance, + schedPb.getPreemptible()); + } + } + + /** + * A builder for {@code InstanceInfo} objects. + */ + public abstract static class Builder { + + abstract Builder id(String id); + + /** + * Sets the identity of the virtual machine instance. + */ + public abstract Builder instanceId(InstanceId instanceId); + + abstract Builder creationTimestamp(Long creationTimestamp); + + /** + * Sets an optional description of this Google Compute Engine instance. + */ + public abstract Builder description(String description); + + abstract Builder status(Status status); + + abstract Builder statusMessage(String statusMessage); + + /** + * Sets the tags to apply to this instance. Tags are used to identify valid sources or targets + * for network firewalls. + */ + public abstract Builder tags(Tags tags); + + /** + * Sets the machine type identity. + */ + public abstract Builder machineType(MachineTypeId machineType); + + /** + * Sets whether to allow this instance to send and receive packets with non-matching destination + * or source IPs. This is required if you plan to use this instance to forward routes. + * + * @see Enabling IP + * Forwarding + */ + public abstract Builder canIpForward(Boolean canIpForward); + + /** + * Sets a list of network interfaces. This specifies how this instance is configured to interact + * with other network services, such as connecting to the internet. At the moment, instances + * only support one network interface. + */ + public abstract Builder networkInterfaces(List networkInterfaces); + + /** + * Sets a list of network interfaces. This specifies how this instance is configured to interact + * with other network services, such as connecting to the internet. At the moment, instances + * only support one network interface. + */ + public abstract Builder networkInterfaces(NetworkInterface... networkInterfaces); + + /** + * Sets a list of disks to attach to the instance. One boot disk must be provided (i.e. an + * attached disk such that {@link AttachedDisk.AttachedDiskConfiguration#boot()} returns + * {@code true}). + */ + public abstract Builder attachedDisks(List attachedDisks); + + /** + * Sets a list of disks to attach to the instance. One boot disk must be provided. + */ + public abstract Builder attachedDisks(AttachedDisk... attachedDisks); + + /** + * Sets the instance metadata. + */ + public abstract Builder metadata(Metadata metadata); + + /** + * Sets a list of service accounts, with their specified scopes, authorized for this instance. + * Service accounts generate access tokens that can be accessed through the metadata server and + * used to authenticate applications on the instance. + * + * @see Authenticating from + * Google Compute Engine + */ + public abstract Builder serviceAccounts(List serviceAccounts); + + /** + * Sets the scheduling options for the instance. + */ + public abstract Builder schedulingOptions(SchedulingOptions schedulingOptions); + + abstract Builder cpuPlatform(String cpuPlatform); + + /** + * Creates an {@code InstanceInfo} object. + */ + public abstract InstanceInfo build(); + } + + public static final class BuilderImpl extends Builder { + + private String id; + private InstanceId instanceId; + private Long creationTimestamp; + private String description; + private Status status; + private String statusMessage; + private Tags tags; + private MachineTypeId machineType; + private Boolean canIpForward; + private List networkInterfaces; + private List attachedDisks; + private Metadata metadata; + private List serviceAccounts; + private SchedulingOptions schedulingOptions; + private String cpuPlatform; + + BuilderImpl(InstanceId instanceId) { + this.instanceId = checkNotNull(instanceId); + } + + BuilderImpl(InstanceInfo instance) { + this.id = instance.id; + this.instanceId = instance.instanceId; + this.creationTimestamp = instance.creationTimestamp; + this.description = instance.description; + this.status = instance.status; + this.statusMessage = instance.statusMessage; + this.tags = instance.tags; + this.machineType = instance.machineType; + this.canIpForward = instance.canIpForward; + this.networkInterfaces = instance.networkInterfaces; + this.attachedDisks = instance.attachedDisks; + this.metadata = instance.metadata; + this.serviceAccounts = instance.serviceAccounts; + this.schedulingOptions = instance.schedulingOptions; + this.cpuPlatform = instance.cpuPlatform; + } + + BuilderImpl(Instance instancePb) { + if (instancePb.getId() != null) { + this.id = instancePb.getId().toString(); + } + this.instanceId = InstanceId.fromUrl(instancePb.getSelfLink()); + if (instancePb.getCreationTimestamp() != null) { + this.creationTimestamp = TIMESTAMP_FORMATTER.parseMillis(instancePb.getCreationTimestamp()); + } + this.description = instancePb.getDescription(); + if (instancePb.getStatus() != null) { + this.status = Status.valueOf(instancePb.getStatus()); + } + this.statusMessage = instancePb.getStatusMessage(); + if (instancePb.getTags() != null) { + this.tags = Tags.fromPb(instancePb.getTags()); + } + if (instancePb.getMachineType() != null) { + this.machineType = MachineTypeId.fromUrl(instancePb.getMachineType()); + } + this.canIpForward = instancePb.getCanIpForward(); + if (instancePb.getNetworkInterfaces() != null) { + this.networkInterfaces = + Lists.transform(instancePb.getNetworkInterfaces(), NetworkInterface.FROM_PB_FUNCTION); + } + if (instancePb.getDisks() != null) { + this.attachedDisks = Lists.transform(instancePb.getDisks(), AttachedDisk.FROM_PB_FUNCTION); + } + if (instancePb.getMetadata() != null) { + this.metadata = Metadata.fromPb(instancePb.getMetadata()); + } + if (instancePb.getServiceAccounts() != null) { + this.serviceAccounts = + Lists.transform(instancePb.getServiceAccounts(), ServiceAccount.FROM_PB_FUNCTION); + } + if (instancePb.getScheduling() != null) { + this.schedulingOptions = SchedulingOptions.fromPb(instancePb.getScheduling()); + } + this.cpuPlatform = instancePb.getCpuPlatform(); + } + + @Override + Builder id(String id) { + this.id = id; + return this; + } + + @Override + public Builder instanceId(InstanceId instanceId) { + this.instanceId = checkNotNull(instanceId); + return this; + } + + @Override + Builder creationTimestamp(Long creationTimestamp) { + this.creationTimestamp = creationTimestamp; + return this; + } + + @Override + public Builder description(String description) { + this.description = description; + return this; + } + + @Override + Builder status(Status status) { + this.status = status; + return this; + } + + @Override + Builder statusMessage(String statusMessage) { + this.statusMessage = statusMessage; + return this; + } + + @Override + public Builder tags(Tags tags) { + this.tags = tags; + return this; + } + + @Override + public Builder machineType(MachineTypeId machineType) { + this.machineType = checkNotNull(machineType); + return this; + } + + @Override + public Builder canIpForward(Boolean canIpForward) { + this.canIpForward = canIpForward; + return this; + } + + @Override + public Builder networkInterfaces(List networkInterfaces) { + this.networkInterfaces = ImmutableList.copyOf(checkNotNull(networkInterfaces)); + return this; + } + + @Override + public Builder networkInterfaces(NetworkInterface... networkInterfaces) { + this.networkInterfaces = Arrays.asList(networkInterfaces); + return this; + } + + @Override + public Builder attachedDisks(List attachedDisks) { + this.attachedDisks = ImmutableList.copyOf(checkNotNull(attachedDisks)); + return this; + } + + @Override + public Builder attachedDisks(AttachedDisk... attachedDisks) { + this.attachedDisks = Arrays.asList(attachedDisks); + return this; + } + + @Override + public Builder metadata(Metadata metadata) { + this.metadata = metadata; + return this; + } + + @Override + public Builder serviceAccounts(List serviceAccounts) { + this.serviceAccounts = ImmutableList.copyOf(checkNotNull(serviceAccounts)); + return this; + } + + @Override + public Builder schedulingOptions(SchedulingOptions schedulingOptions) { + this.schedulingOptions = schedulingOptions; + return this; + } + + @Override + Builder cpuPlatform(String cpuPlatform) { + this.cpuPlatform = cpuPlatform; + return this; + } + + @Override + public InstanceInfo build() { + checkNotNull(attachedDisks); + checkNotNull(networkInterfaces); + return new InstanceInfo(this); + } + } + + InstanceInfo(BuilderImpl builder) { + this.id = builder.id; + this.instanceId = builder.instanceId; + this.creationTimestamp = builder.creationTimestamp; + this.description = builder.description; + this.status = builder.status; + this.statusMessage = builder.statusMessage; + this.tags = builder.tags; + this.machineType = builder.machineType; + this.canIpForward = builder.canIpForward; + this.networkInterfaces = builder.networkInterfaces; + this.attachedDisks = builder.attachedDisks; + this.metadata = builder.metadata; + this.serviceAccounts = builder.serviceAccounts; + this.schedulingOptions = builder.schedulingOptions; + this.cpuPlatform = builder.cpuPlatform; + } + + /** + * Returns the unique identifier for the instance; defined by the service. + */ + public String id() { + return id; + } + + /** + * Returns the instance identity. + */ + public InstanceId instanceId() { + return instanceId; + } + + /** + * Returns the creation timestamp in milliseconds since epoch. + */ + public Long creationTimestamp() { + return creationTimestamp; + } + + /** + * Returns a textual description of the instance. + */ + public String description() { + return description; + } + + /** + * Returns the status of the instance. + */ + public Status status() { + return status; + } + + /** + * Returns an optional, human-readable explanation of the status. + */ + public String statusMessage() { + return statusMessage; + } + + /** + * Returns the tags of this instance. Tags are used to identify valid sources or targets for + * network firewalls. + */ + public Tags tags() { + return tags; + } + + /** + * Returns the machine type identity. + */ + public MachineTypeId machineType() { + return machineType; + } + + /** + * Returns whether to allow this instance to send and receive packets with non-matching + * destination or source IPs. This is required if you plan to use this instance to forward routes. + * + * @see Enabling IP + * Forwarding + */ + public Boolean canIpForward() { + return canIpForward; + } + + /** + * Returns a list of network interfaces. This specifies how this instance is configured to + * interact with other network services, such as connecting to the internet. + */ + public List networkInterfaces() { + return networkInterfaces; + } + + /** + * Returns a list of disks attached to the instance. + */ + public List attachedDisks() { + return attachedDisks; + } + + /** + * Returns the instance metadata. + */ + public Metadata metadata() { + return metadata; + } + + /** + * Returns a list of service accounts, with their specified scopes, authorized for this instance. + * Service accounts generate access tokens that can be accessed through the metadata server and + * used to authenticate applications on the instance. + * + * @see Authenticating from + * Google Compute Engine + */ + public List serviceAccounts() { + return serviceAccounts; + } + + /** + * Returns the scheduling options for the instance. + */ + public SchedulingOptions schedulingOptions() { + return schedulingOptions; + } + + /** + * Returns the CPU platform used by this instance. + */ + public String cpuPlatform() { + return cpuPlatform; + } + + /** + * Returns a builder for the current instance. + */ + public Builder toBuilder() { + return new BuilderImpl(this); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .add("instanceId", instanceId) + .add("creationTimestamp", creationTimestamp) + .add("description", description) + .add("status", status) + .add("statusMessage", statusMessage) + .add("tags", tags) + .add("machineType", machineType) + .add("canIpForward", canIpForward) + .add("networkInterfaces", networkInterfaces) + .add("attachedDisks", attachedDisks) + .add("metadata", metadata) + .add("serviceAccounts", serviceAccounts) + .add("schedulingOptions", schedulingOptions) + .add("cpuPlatform", cpuPlatform) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(id, instanceId, creationTimestamp, description, status, statusMessage, tags, + machineType, canIpForward, networkInterfaces, attachedDisks, metadata, serviceAccounts, + schedulingOptions, cpuPlatform); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InstanceInfo + && Objects.equals(toPb(), ((InstanceInfo) obj).toPb()); + } + + InstanceInfo setProjectId(final String projectId) { + Builder builder = toBuilder(); + builder.networkInterfaces(Lists.transform(networkInterfaces, + new Function() { + @Override + public NetworkInterface apply(NetworkInterface networkInterface) { + return networkInterface.setProjectId(projectId); + } + })); + builder.attachedDisks(Lists.transform(attachedDisks, + new Function() { + @Override + public AttachedDisk apply(AttachedDisk attachedDisk) { + return attachedDisk.setProjectId(projectId); + } + })); + return builder.instanceId(instanceId.setProjectId(projectId)) + .machineType(machineType.setProjectId(projectId)) + .build(); + } + + Instance toPb() { + Instance instancePb = new Instance(); + if (id != null) { + instancePb.setId(new BigInteger(id)); + } + if (creationTimestamp != null) { + instancePb.setCreationTimestamp(TIMESTAMP_FORMATTER.print(creationTimestamp)); + } + instancePb.setName(instanceId.instance()); + instancePb.setDescription(description); + instancePb.setSelfLink(instanceId.selfLink()); + instancePb.setZone(instanceId.zoneId().selfLink()); + if (status != null) { + instancePb.setStatus(status.name()); + } + instancePb.setStatusMessage(statusMessage); + if (tags != null) { + instancePb.setTags(tags.toPb()); + } + if (machineType != null) { + instancePb.setMachineType(machineType.selfLink()); + } + instancePb.setCanIpForward(canIpForward); + if (networkInterfaces != null) { + instancePb.setNetworkInterfaces( + Lists.transform(networkInterfaces, NetworkInterface.TO_PB_FUNCTION)); + } + if (attachedDisks != null) { + instancePb.setDisks(Lists.transform(attachedDisks, AttachedDisk.TO_PB_FUNCTION)); + } + if (metadata != null) { + instancePb.setMetadata(metadata.toPb()); + } + if (serviceAccounts != null) { + instancePb.setServiceAccounts( + Lists.transform(serviceAccounts, ServiceAccount.TO_PB_FUNCTION)); + } + if (schedulingOptions != null) { + instancePb.setScheduling(schedulingOptions.toPb()); + } + instancePb.setCpuPlatform(cpuPlatform); + return instancePb; + } + + /** + * Returns a builder for an {@code InstanceInfo} object given the instance identity and the + * machine type. + */ + public static Builder builder(InstanceId instanceId, MachineTypeId machineType) { + return new BuilderImpl(instanceId).machineType(machineType); + } + + /** + * Returns an {@code InstanceInfo} object given the instance identity, the machine type, a disk + * to attach to the instance and a network interface. {@code disk} must be a boot disk (i.e. + * {@link AttachedDisk.AttachedDiskConfiguration#boot()} returns {@code true}). + */ + public static InstanceInfo of(InstanceId instanceId, MachineTypeId machineType, AttachedDisk disk, + NetworkInterface networkInterface) { + return builder(instanceId, machineType) + .attachedDisks(ImmutableList.of(disk)) + .networkInterfaces(ImmutableList.of(networkInterface)) + .build(); + } + + static InstanceInfo fromPb(Instance instancePb) { + return new BuilderImpl(instancePb).build(); + } +} diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInfo.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInfo.java index 1e1d4f4bf907..d3e1cddcd6be 100644 --- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInfo.java +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/NetworkInfo.java @@ -35,6 +35,9 @@ * networks, use firewall rules to restrict access to instances, and create static routes to forward * traffic to specific destinations. * + *

A network lives in a project and is isolated from other networks in the project. A project can + * have up to five different networks. + * * @see Using Networks and Firewalls */ public class NetworkInfo implements Serializable { diff --git a/gcloud-java-compute/src/test/java/com/google/gcloud/compute/InstanceInfoTest.java b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/InstanceInfoTest.java new file mode 100644 index 000000000000..604624d91c7f --- /dev/null +++ b/gcloud-java-compute/src/test/java/com/google/gcloud/compute/InstanceInfoTest.java @@ -0,0 +1,326 @@ +/* + * 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.assertTrue; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gcloud.compute.AttachedDisk.PersistentDiskConfiguration; +import com.google.gcloud.compute.InstanceInfo.Metadata; +import com.google.gcloud.compute.InstanceInfo.SchedulingOptions; +import com.google.gcloud.compute.InstanceInfo.SchedulingOptions.Maintenance; +import com.google.gcloud.compute.InstanceInfo.ServiceAccount; +import com.google.gcloud.compute.InstanceInfo.Tags; + +import org.junit.Test; + +import java.util.List; +import java.util.Map; + +public class InstanceInfoTest { + + private static final String ID = "42"; + private static final Long CREATION_TIMESTAMP = 1453293540000L; + private static final String DESCRIPTION = "description"; + private static final InstanceId INSTANCE_ID = InstanceId.of("project", "zone", "instance"); + private static final InstanceInfo.Status STATUS = InstanceInfo.Status.RUNNING; + private static final String STATUS_MESSAGE = "statusMessage"; + private static final Tags TAGS = Tags.of("tag1", "tag2"); + private static final MachineTypeId MACHINE_TYPE = MachineTypeId.of("project", "zone", "type"); + private static final Boolean CAN_IP_FORWARD = true; + private static final NetworkInterface NETWORK_INTERFACE = + NetworkInterface.of(NetworkId.of("project", "network")); + private static final List NETWORK_INTERFACES = + ImmutableList.of(NETWORK_INTERFACE); + private static final DiskId DISK_ID = DiskId.of("project", "zone", "disk"); + private static final AttachedDisk ATTACHED_DISK = + AttachedDisk.of(PersistentDiskConfiguration.of(DISK_ID)); + private static final List ATTACHED_DISKS = ImmutableList.of(ATTACHED_DISK); + private static final Metadata METADATA = Metadata.builder() + .add("key1", "value1") + .add("key2", "value2") + .build(); + private static final ServiceAccount SERVICE_ACCOUNT = + ServiceAccount.of("email", ImmutableList.of("scope1")); + private static final List SERVICE_ACCOUNTS = ImmutableList.of(SERVICE_ACCOUNT); + private static final SchedulingOptions SCHEDULING_OPTIONS = + SchedulingOptions.preemptible(); + private static final String CPU_PLATFORM = "cpuPlatform"; + private static final InstanceInfo INSTANCE_INFO = InstanceInfo.builder(INSTANCE_ID, MACHINE_TYPE) + .id(ID) + .creationTimestamp(CREATION_TIMESTAMP) + .description(DESCRIPTION) + .status(STATUS) + .statusMessage(STATUS_MESSAGE) + .tags(TAGS) + .canIpForward(CAN_IP_FORWARD) + .networkInterfaces(NETWORK_INTERFACES) + .attachedDisks(ATTACHED_DISKS) + .metadata(METADATA) + .serviceAccounts(SERVICE_ACCOUNTS) + .schedulingOptions(SCHEDULING_OPTIONS) + .cpuPlatform(CPU_PLATFORM) + .build(); + + @Test + public void testMetadataToBuilder() { + Metadata metadata = METADATA.toBuilder().fingerprint("newFingerprint").build(); + assertEquals("newFingerprint", metadata.fingerprint()); + comparevalues(METADATA, metadata.toBuilder().fingerprint(null).build()); + } + + @Test + public void testTagsToBuilder() { + Tags tags = TAGS.toBuilder().values("tag1").build(); + assertEquals(ImmutableList.of("tag1"), tags.values()); + compareTags(TAGS, tags.toBuilder().values("tag1", "tag2").build()); + } + + @Test + public void testToBuilder() { + compareInstanceInfo(INSTANCE_INFO, INSTANCE_INFO.toBuilder().build()); + InstanceInfo instance = INSTANCE_INFO.toBuilder().description("newDescription").build(); + assertEquals("newDescription", instance.description()); + instance = instance.toBuilder().description(DESCRIPTION).build(); + compareInstanceInfo(INSTANCE_INFO, instance); + } + + @Test + public void testToBuilderIncomplete() { + InstanceInfo instanceInfo = InstanceInfo.of(INSTANCE_ID, MACHINE_TYPE, ATTACHED_DISK, + NETWORK_INTERFACE); + assertEquals(instanceInfo, instanceInfo.toBuilder().build()); + } + + @Test + public void testMetadataBuilder() { + assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"), METADATA.values()); + assertNull(METADATA.fingerprint()); + Metadata metadata = Metadata.builder() + .values(ImmutableMap.of("key1", "value1", "key2", "value2")) + .build(); + assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"), metadata.values()); + assertNull(metadata.fingerprint()); + metadata = Metadata.builder() + .values(ImmutableMap.of("key1", "value1", "key2", "value2")) + .fingerprint("fingerprint") + .build(); + assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"), metadata.values()); + assertEquals("fingerprint", metadata.fingerprint()); + } + + @Test + public void testTagsBuilder() { + Tags tags = Tags.builder().values(ImmutableList.of("tag1", "tag2")).build(); + assertEquals(ImmutableList.of("tag1", "tag2"), tags.values()); + assertNull(tags.fingerprint()); + tags = Tags.builder().add("tag1").add("tag2").build(); + assertEquals(ImmutableList.of("tag1", "tag2"), tags.values()); + assertNull(tags.fingerprint()); + tags = Tags.builder().add("tag1").add("tag2").fingerprint("fingerprint").build(); + assertEquals(ImmutableList.of("tag1", "tag2"), tags.values()); + assertEquals("fingerprint", tags.fingerprint()); + } + + @Test + public void testBuilder() { + assertEquals(ID, INSTANCE_INFO.id()); + assertEquals(INSTANCE_ID, INSTANCE_INFO.instanceId()); + assertEquals(CREATION_TIMESTAMP, INSTANCE_INFO.creationTimestamp()); + assertEquals(DESCRIPTION, INSTANCE_INFO.description()); + assertEquals(STATUS, INSTANCE_INFO.status()); + assertEquals(STATUS_MESSAGE, INSTANCE_INFO.statusMessage()); + assertEquals(TAGS, INSTANCE_INFO.tags()); + assertEquals(MACHINE_TYPE, INSTANCE_INFO.machineType()); + assertEquals(CAN_IP_FORWARD, INSTANCE_INFO.canIpForward()); + assertEquals(NETWORK_INTERFACES, INSTANCE_INFO.networkInterfaces()); + assertEquals(ATTACHED_DISKS, INSTANCE_INFO.attachedDisks()); + assertEquals(METADATA, INSTANCE_INFO.metadata()); + assertEquals(SERVICE_ACCOUNTS, INSTANCE_INFO.serviceAccounts()); + assertEquals(SCHEDULING_OPTIONS, INSTANCE_INFO.schedulingOptions()); + assertEquals(CPU_PLATFORM, INSTANCE_INFO.cpuPlatform()); + InstanceInfo instanceInfo = InstanceInfo.builder(INSTANCE_ID, MACHINE_TYPE) + .id(ID) + .creationTimestamp(CREATION_TIMESTAMP) + .description(DESCRIPTION) + .status(STATUS) + .statusMessage(STATUS_MESSAGE) + .tags(TAGS) + .canIpForward(CAN_IP_FORWARD) + .networkInterfaces(NETWORK_INTERFACE) + .attachedDisks(ATTACHED_DISK) + .metadata(METADATA) + .serviceAccounts(SERVICE_ACCOUNTS) + .schedulingOptions(SCHEDULING_OPTIONS) + .cpuPlatform(CPU_PLATFORM) + .build(); + compareInstanceInfo(INSTANCE_INFO, instanceInfo); + } + + @Test + public void testMetadataOf() { + Map map = ImmutableMap.of("key1", "value1", "key2", "value2"); + comparevalues(METADATA, Metadata.of(map)); + } + + @Test + public void testTagsOf() { + compareTags(TAGS, Tags.of("tag1", "tag2")); + compareTags(TAGS, Tags.of(ImmutableList.of("tag1", "tag2"))); + } + + @Test + public void testServiceAccountOf() { + compareServiceAccount(SERVICE_ACCOUNT, ServiceAccount.of("email", ImmutableList.of("scope1"))); + compareServiceAccount(SERVICE_ACCOUNT, ServiceAccount.of("email", "scope1")); + } + + @Test + public void testSchedulingOptionsFactoryMethods() { + assertTrue(SCHEDULING_OPTIONS.isPreemptible()); + assertFalse(SCHEDULING_OPTIONS.automaticRestart()); + assertEquals(Maintenance.TERMINATE, SCHEDULING_OPTIONS.maintenance()); + SchedulingOptions schedulingOptions = SchedulingOptions.standard(true, Maintenance.MIGRATE); + assertFalse(schedulingOptions.isPreemptible()); + assertTrue(schedulingOptions.automaticRestart()); + assertEquals(Maintenance.MIGRATE, schedulingOptions.maintenance()); + } + + @Test + public void testOf() { + InstanceInfo instance = + InstanceInfo.of(INSTANCE_ID, MACHINE_TYPE, ATTACHED_DISK, NETWORK_INTERFACE); + assertNull(instance.id()); + assertEquals(INSTANCE_ID, instance.instanceId()); + assertNull(instance.creationTimestamp()); + assertNull(instance.description()); + assertNull(instance.status()); + assertNull(instance.statusMessage()); + assertNull(instance.tags()); + assertEquals(MACHINE_TYPE, instance.machineType()); + assertNull(instance.canIpForward()); + assertEquals(NETWORK_INTERFACES, instance.networkInterfaces()); + assertEquals(ATTACHED_DISKS, instance.attachedDisks()); + assertNull(instance.metadata()); + assertNull(instance.serviceAccounts()); + assertNull(instance.schedulingOptions()); + assertNull(instance.cpuPlatform()); + } + + @Test + public void testMetadataToAndFromPb() { + comparevalues(METADATA, Metadata.fromPb(METADATA.toPb())); + Metadata metadata = Metadata.builder() + .values(ImmutableMap.of("key1", "value1", "key2", "value2")) + .fingerprint("fingerprint") + .build(); + comparevalues(metadata, Metadata.fromPb(metadata.toPb())); + } + + @Test + public void testTagsToAndFromPb() { + compareTags(TAGS, Tags.fromPb(TAGS.toPb())); + Tags tags = Tags.builder().add("tag1").add("tag2").fingerprint("fingerprint").build(); + compareTags(tags, Tags.fromPb(tags.toPb())); + } + + @Test + public void testServiceAccountToAndFromPb() { + compareServiceAccount(SERVICE_ACCOUNT, ServiceAccount.fromPb(SERVICE_ACCOUNT.toPb())); + } + + @Test + public void testSchedulingOptionsToAndFromPb() { + compareSchedulingOptions(SCHEDULING_OPTIONS, + SchedulingOptions.fromPb(SCHEDULING_OPTIONS.toPb())); + SchedulingOptions schedulingOptions = SchedulingOptions.standard(true, Maintenance.MIGRATE); + compareSchedulingOptions(schedulingOptions, SchedulingOptions.fromPb(schedulingOptions.toPb())); + } + + @Test + public void testToAndFromPb() { + compareInstanceInfo(INSTANCE_INFO, InstanceInfo.fromPb(INSTANCE_INFO.toPb())); + InstanceInfo instance = + InstanceInfo.of(INSTANCE_ID, MACHINE_TYPE, ATTACHED_DISK, NETWORK_INTERFACE); + compareInstanceInfo(instance, InstanceInfo.fromPb(instance.toPb())); + } + + @Test + public void testSetProjectId() { + InstanceInfo instance = InstanceInfo.of( + InstanceId.of("zone", "instance"), + MachineTypeId.of("zone", "type"), + AttachedDisk.of(PersistentDiskConfiguration.of(DiskId.of("zone", "disk"))), + NetworkInterface.of(NetworkId.of("project", "network"))); + InstanceInfo instanceWithProject = + InstanceInfo.of(INSTANCE_ID, MACHINE_TYPE, ATTACHED_DISK, NETWORK_INTERFACE); + compareInstanceInfo(instanceWithProject, instance.setProjectId("project")); + } + + public void comparevalues(Metadata expected, Metadata value) { + assertEquals(expected, value); + assertEquals(expected.fingerprint(), value.fingerprint()); + assertEquals(expected.values(), value.values()); + assertEquals(expected.hashCode(), value.hashCode()); + } + + public void compareTags(Tags expected, Tags value) { + assertEquals(expected, value); + assertEquals(expected.fingerprint(), value.fingerprint()); + assertEquals(expected.values(), value.values()); + assertEquals(expected.hashCode(), value.hashCode()); + } + + public void compareServiceAccount(ServiceAccount expected, ServiceAccount value) { + assertEquals(expected, value); + assertEquals(expected.email(), value.email()); + assertEquals(expected.scopes(), value.scopes()); + assertEquals(expected.hashCode(), value.hashCode()); + } + + public void compareSchedulingOptions(SchedulingOptions expected, SchedulingOptions value) { + assertEquals(expected, value); + assertEquals(expected.isPreemptible(), value.isPreemptible()); + assertEquals(expected.maintenance(), value.maintenance()); + assertEquals(expected.automaticRestart(), value.automaticRestart()); + assertEquals(expected.hashCode(), value.hashCode()); + } + + public void compareInstanceInfo(InstanceInfo expected, InstanceInfo value) { + assertEquals(expected, value); + assertEquals(expected.id(), value.id()); + assertEquals(expected.instanceId(), value.instanceId()); + assertEquals(expected.creationTimestamp(), value.creationTimestamp()); + assertEquals(expected.description(), value.description()); + assertEquals(expected.status(), value.status()); + assertEquals(expected.statusMessage(), value.statusMessage()); + assertEquals(expected.tags(), value.tags()); + assertEquals(expected.machineType(), value.machineType()); + assertEquals(expected.canIpForward(), value.canIpForward()); + assertEquals(expected.networkInterfaces(), value.networkInterfaces()); + assertEquals(expected.attachedDisks(), value.attachedDisks()); + assertEquals(expected.metadata(), value.metadata()); + assertEquals(expected.serviceAccounts(), value.serviceAccounts()); + assertEquals(expected.schedulingOptions(), value.schedulingOptions()); + assertEquals(expected.cpuPlatform(), value.cpuPlatform()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} 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 73a572141b2a..e31280f94ec3 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 @@ -20,11 +20,16 @@ import static org.junit.Assert.assertNotSame; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.gcloud.AuthCredentials; import com.google.gcloud.RetryParams; import com.google.gcloud.compute.AttachedDisk.CreateDiskConfiguration; import com.google.gcloud.compute.AttachedDisk.PersistentDiskConfiguration; import com.google.gcloud.compute.AttachedDisk.ScratchDiskConfiguration; +import com.google.gcloud.compute.InstanceInfo.Metadata; +import com.google.gcloud.compute.InstanceInfo.SchedulingOptions; +import com.google.gcloud.compute.InstanceInfo.ServiceAccount; +import com.google.gcloud.compute.InstanceInfo.Tags; import com.google.gcloud.compute.NetworkInterface.AccessConfig; import org.junit.Test; @@ -186,6 +191,12 @@ public class SerializationTest { private static final ScratchDiskConfiguration SCRATCH_DISK_CONFIGURATION = ScratchDiskConfiguration.of(DISK_TYPE_ID); private static final AttachedDisk ATTACHED_DISK = AttachedDisk.of(CREATE_DISK_CONFIGURATION); + private static final Tags TAGS = Tags.of("tag1", "tag2"); + private static final Metadata METADATA = Metadata.of(ImmutableMap.of("key1", "val1")); + private static final ServiceAccount SERVICE_ACCOUNT = ServiceAccount.of("email"); + private static final SchedulingOptions SCHEDULING_OPTIONS = SchedulingOptions.preemptible(); + private static final InstanceInfo INSTANCE_INFO = + InstanceInfo.of(INSTANCE_ID, MACHINE_TYPE_ID, ATTACHED_DISK, NETWORK_INTERFACE); private static final Compute.DiskTypeOption DISK_TYPE_OPTION = Compute.DiskTypeOption.fields(); private static final Compute.DiskTypeFilter DISK_TYPE_FILTER = @@ -288,7 +299,8 @@ public void testModelAndRequests() throws Exception { DISK_INFO, DISK, SUBNETWORK_ID, NETWORK_ID, SUBNETWORK_INFO, SUBNETWORK, STANDARD_NETWORK_CONFIGURATION, SUBNET_NETWORK_CONFIGURATION, NETWORK_INFO, NETWORK, ACCESS_CONFIG, NETWORK_INTERFACE, CREATE_DISK_CONFIGURATION, PERSISTENT_DISK_CONFIGURATION, - SCRATCH_DISK_CONFIGURATION, ATTACHED_DISK, DISK_TYPE_OPTION, DISK_TYPE_FILTER, + SCRATCH_DISK_CONFIGURATION, ATTACHED_DISK, TAGS, METADATA, SERVICE_ACCOUNT, + SCHEDULING_OPTIONS, INSTANCE_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, ZONE_OPTION, ZONE_FILTER,