diff --git a/README.md b/README.md index b6c2473f9794..7525806d7850 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Java idiomatic client for [Google Cloud Platform][cloud-platform] services. This client supports the following Google Cloud Platform services: - [Google Cloud BigQuery] (#google-cloud-bigquery-alpha) (Alpha) +- [Google Cloud Compute] (#google-cloud-compute-alpha) (Alpha) - [Google Cloud Datastore] (#google-cloud-datastore) - [Google Cloud Resource Manager] (#google-cloud-resource-manager-alpha) (Alpha) - [Google Cloud Storage] (#google-cloud-storage) @@ -46,6 +47,8 @@ Example Applications - [`BigQueryExample`](./gcloud-java-examples/src/main/java/com/google/gcloud/examples/bigquery/BigQueryExample.java) - A simple command line interface providing some of Cloud BigQuery's functionality - Read more about using this application on the [`gcloud-java-examples` docs page](http://googlecloudplatform.github.io/gcloud-java/apidocs/?com/google/gcloud/examples/BigQueryExample.html). +- [`ComputeExample`](./gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/ComputeExample.java) - A simple command line interface providing some of Cloud Compute's functionality + - Read more about using this application on the [`gcloud-java-examples` docs page](http://googlecloudplatform.github.io/gcloud-java/apidocs/?com/google/gcloud/examples/compute/ComputeExample.html). - [`Bookshelf`](https://github.com/GoogleCloudPlatform/getting-started-java/tree/master/bookshelf) - An App Engine app that manages a virtual bookshelf. - This app uses `gcloud-java` to interface with Cloud Datastore and Cloud Storage. It also uses Cloud SQL, another Google Cloud Platform service. - [`DatastoreExample`](./gcloud-java-examples/src/main/java/com/google/gcloud/examples/datastore/DatastoreExample.java) - A simple command line interface for the Cloud Datastore @@ -161,6 +164,78 @@ if (loadJob.status().error() != null) { } ``` +Google Cloud Compute (Alpha) +---------------------- + +- [API Documentation][compute-api] +- [Official Documentation][cloud-compute-docs] + +#### Preview + +Here are two code snippets showing simple usage examples from within Compute/App Engine. Note that +you must [supply credentials](#authentication) and a project ID if running this snippet elsewhere. + +The first snippet shows how to create a snapshot from an existing disk. Complete source code can be +found at +[CreateSnapshot.java](./gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateSnapshot.java). + +```java +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.Disk; +import com.google.gcloud.compute.DiskId; +import com.google.gcloud.compute.Operation; +import com.google.gcloud.compute.Snapshot; + +Compute compute = ComputeOptions.defaultInstance().service(); +DiskId diskId = DiskId.of("us-central1-a", "disk-name"); +Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields()); +if (disk != null) { + String snapshotName = "disk-name-snapshot"; + Operation operation = disk.createSnapshot(snapshotName); + while (!operation.isDone()) { + Thread.sleep(1000L); + } + if (operation.errors() == null) { + // use snapshot + Snapshot snapshot = compute.getSnapshot("disk-name-snapshot"); + } +} +``` +The second snippet shows how to create a virtual machine instance. Complete source code can be found +at +[CreateInstance.java](./gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateInstance.java). +```java +import com.google.gcloud.compute.AttachedDisk; +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.ImageId; +import com.google.gcloud.compute.Instance; +import com.google.gcloud.compute.InstanceId; +import com.google.gcloud.compute.InstanceInfo; +import com.google.gcloud.compute.MachineTypeId; +import com.google.gcloud.compute.NetworkId; +import com.google.gcloud.compute.NetworkInterface; +import com.google.gcloud.compute.Operation; + +Compute compute = ComputeOptions.defaultInstance().service(); +ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329"); +NetworkId networkId = NetworkId.of("default"); +AttachedDisk attachedDisk = AttachedDisk.of(AttachedDisk.CreateDiskConfiguration.of(imageId)); +NetworkInterface networkInterface = NetworkInterface.of(networkId); +InstanceId instanceId = InstanceId.of("us-central1-a", "instance-name"); +MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1"); +Operation operation = + compute.create(InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface)); +while (!operation.isDone()) { + Thread.sleep(1000L); +} +if (operation.errors() == null) { + // use instance + Instance instance = compute.getInstance(instanceId); +} +``` + Google Cloud Datastore ---------------------- @@ -374,3 +449,7 @@ Apache 2.0 - See [LICENSE] for more information. [cloud-bigquery]: https://cloud.google.com/bigquery/ [cloud-bigquery-docs]: https://cloud.google.com/bigquery/docs/overview [bigquery-api]: http://googlecloudplatform.github.io/gcloud-java/apidocs/index.html?com/google/gcloud/bigquery/package-summary.html + +[cloud-compute]: https://cloud.google.com/compute/ +[cloud-compute-docs]: https://cloud.google.com/compute/docs/overview +[compute-api]: http://googlecloudplatform.github.io/gcloud-java/apidocs/index.html?com/google/gcloud/compute/package-summary.html diff --git a/gcloud-java-compute/README.md b/gcloud-java-compute/README.md index d1909f904095..2b9dbd63cc3d 100644 --- a/gcloud-java-compute/README.md +++ b/gcloud-java-compute/README.md @@ -1,17 +1,16 @@ Google Cloud Java Client for Compute (Alpha) ==================================== -Java idiomatic client for [Google Cloud Compute] (https://cloud.google.com/compute). +Java idiomatic client for [Google Cloud Compute](https://cloud.google.com/compute). [![Build Status](https://travis-ci.org/GoogleCloudPlatform/gcloud-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/gcloud-java) [![Coverage Status](https://coveralls.io/repos/GoogleCloudPlatform/gcloud-java/badge.svg?branch=master)](https://coveralls.io/r/GoogleCloudPlatform/gcloud-java?branch=master) - +[![Maven](https://img.shields.io/maven-central/v/com.google.cloud/gcloud-java-compute.svg)]( https://img.shields.io/maven-central/v/com.google.cloud/gcloud-java-compute.svg) [![Codacy Badge](https://api.codacy.com/project/badge/grade/9da006ad7c3a4fe1abd142e77c003917)](https://www.codacy.com/app/mziccard/gcloud-java) [![Dependency Status](https://www.versioneye.com/user/projects/56bd8ee72a29ed002d2b0969/badge.svg?style=flat)](https://www.versioneye.com/user/projects/56bd8ee72a29ed002d2b0969) -- [Homepage] (https://googlecloudplatform.github.io/gcloud-java/) - - +- [Homepage](https://googlecloudplatform.github.io/gcloud-java/) +- [API Documentation](http://googlecloudplatform.github.io/gcloud-java/apidocs/index.html?com/google/gcloud/compute/package-summary.html) > Note: This client is a work-in-progress, and may occasionally > make backwards-incompatible changes. @@ -27,7 +26,11 @@ If you are using SBT, add this to your dependencies Example Application ------------------- - + +[`ComputeExample`](../gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/ComputeExample.java) +is a simple command line interface that provides some of Google Cloud Compute Engine's +functionality. Read more about using the application on the +[`ComputeExample` docs page](http://googlecloudplatform.github.io/gcloud-java/apidocs/?com/google/gcloud/examples/compute/ComputeExample.html). Authentication -------------- @@ -51,7 +54,160 @@ with Google Cloud Compute using this Client Library. Getting Started --------------- - + +#### Prerequisites +For this tutorial, you will need a [Google Developers Console](https://console.developers.google.com/) +project with the Compute Engine API enabled. You will need to [enable billing](https://support.google.com/cloud/answer/6158867?hl=en) +to use Google Cloud DNS. [Follow these instructions](https://cloud.google.com/docs/authentication#preparation) +to get your project set up. You will also need to set up the local development environment by +[installing the Google Cloud SDK](https://cloud.google.com/sdk/) and running the following commands +in command line: `gcloud auth login` and `gcloud config set project [YOUR PROJECT ID]`. + +#### Installation and setup +You'll need to obtain the `gcloud-java-compute` library. See the [Quickstart](#quickstart) section +to add `gcloud-java-compute` as a dependency in your code. + +#### Creating an authorized service object +To make authenticated requests to Google Cloud Compute Engine, you must create a service object with +credentials. You can then make API calls by calling methods on the Compute service object. The +simplest way to authenticate is to use [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials). +These credentials are automatically inferred from your environment, so you only need the following +code to create your service object: + +```java +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; + +Compute compute = ComputeOptions.defaultInstance().service(); +``` + +For other authentication options, see the [Authentication](https://github.com/GoogleCloudPlatform/gcloud-java#authentication) +page. + +#### Creating a region IP address +An external region IP address can be associated to a Google Compute Engine instance to communicate +with instances in different regions or to communicate with the instance from ouside of Compute +Engine. In this code snippet, we will create a new external region address. + +Add the following imports at the top of your file: + +```java +import com.google.gcloud.compute.AddressInfo; +import com.google.gcloud.compute.Operation; +import com.google.gcloud.compute.RegionAddressId; +``` + +Then add the following code to create an address. Most Compute Engine calls return an `Operation` +object that can be used to wait for operation completion and to check whether operation failed or +succeeded: + +```java +RegionAddressId addressId = RegionAddressId.of("us-central1", "test-address"); +Operation operation = compute.create(AddressInfo.of(addressId)); +while (!operation.isDone()) { + Thread.sleep(1000L); +} +operation = operation.reload(); +if (operation.errors() == null) { + System.out.println("Address " + addressId + " was successfully created"); +} else { + // inspect operation.errors() + throw new RuntimeException("Address creation failed"); +} +``` + +#### Creating a persistent disk +A persistent disk can be used as primary storage for your virtual machine instances. Persistent +disks can be created empty, from a disk image or from a disk snapshot. Compute Engine offers +[publicly-available images](https://cloud.google.com/compute/docs/operating-systems/) of certain +operating systems that you can use. In this code snippet, we will create a new persistent disk from +a publicly-available image. + +Add the following imports at the top of your file: + +```java +import com.google.gcloud.compute.DiskInfo; +import com.google.gcloud.compute.DiskId; +import com.google.gcloud.compute.ImageDiskConfiguration; +import com.google.gcloud.compute.ImageId; +``` + +Then add the following code to create a disk and wait for disk creation to terminate. + +```java +ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329"); +DiskId diskId = DiskId.of("us-central1-a", "test-disk"); +ImageDiskConfiguration diskConfiguration = ImageDiskConfiguration.of(imageId); +DiskInfo disk = DiskInfo.of(diskId, diskConfiguration); +Operation operation = compute.create(disk); +while (!operation.isDone()) { + Thread.sleep(1000L); +} +operation = operation.reload(); +if (operation.errors() == null) { + System.out.println("Disk " + diskId + " was successfully created"); +} else { + // inspect operation.errors() + throw new RuntimeException("Disk creation failed"); +} +``` + +#### Creating a virtual machine instance +An Google Compute Engine instance is a virtual machine (VM) hosted on Google's infrastructure. An +instance can be created given it's identity, a machine type, one boot disk and a network interface. +In this code snippet, we will create a virtual machine instance in the default network using as a +boot disk the disk we have just created and assigning to it the just created IP address. + +Add the following imports at the top of your file: + +```java +import com.google.gcloud.compute.AttachedDisk; +import com.google.gcloud.compute.AttachedDisk.PersistentDiskConfiguration; +import com.google.gcloud.compute.InstanceId; +import com.google.gcloud.compute.InstanceInfo; +import com.google.gcloud.compute.MachineTypeId; +import com.google.gcloud.compute.NetworkConfiguration; +import com.google.gcloud.compute.NetworkConfiguration.AccessConfig; +import com.google.gcloud.compute.NetworkId; +import com.google.gcloud.compute.NetworkInterface; +``` + +Then add the following code to create an instance and wait for instance creation to terminate. + +```java +Address externalIp = compute.getAddress(addressId); +InstanceId instanceId = InstanceId.of("us-central1-a", "test-instance"); +NetworkId networkId = NetworkId.of("default"); +PersistentDiskConfiguration attachConfiguration = + PersistentDiskConfiguration.builder(diskId).boot(true).build(); +AttachedDisk attachedDisk = AttachedDisk.of("dev0", attachConfiguration); +NetworkInterface networkInterface = NetworkInterface.builder(networkId) + .accessConfigurations(AccessConfig.of(externalIp.address())) + .build(); +MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1"); +InstanceInfo instance = + InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface); +Operation operation = compute.create(instance); +while (!operation.isDone()) { + Thread.sleep(1000L); +} +operation = operation.reload(); +if (operation.errors() == null) { + System.out.println("Instance " + instanceId + " was successfully created"); +} else { + // inspect operation.errors() + throw new RuntimeException("Instance creation failed"); +} +``` + +#### Complete source code + +In +[CreateAddressDiskAndInstance.java](../gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateAddressDiskAndInstance.java) +we put together all the code shown above into one program. The program assumes that you are +running on Compute Engine or from your own desktop. To run the example on App Engine, simply move +the code from the main method to your application's servlet class and change the print statements to +display on your webpage. Troubleshooting --------------- @@ -73,7 +229,7 @@ See [TESTING] to read more about testing. Versioning ---------- -This library follows [Semantic Versioning] (http://semver.org/). +This library follows [Semantic Versioning](http://semver.org/). It is currently in major version zero (``0.y.z``), which means that anything may change at any time and the public API should not be considered diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/package-info.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/package-info.java new file mode 100644 index 000000000000..88dab612c599 --- /dev/null +++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/package-info.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +/** + * A client to Google Cloud Compute. + * + *

Here's a simple usage example for using gcloud-java from App/Compute Engine. This example + * shows how to create a snapshot from an existing disk. For the complete source code see + * + * CreateSnapshot.java. + *

 {@code
+ * Compute compute = ComputeOptions.defaultInstance().service();
+ * DiskId diskId = DiskId.of("us-central1-a", "disk-name");
+ * Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields());
+ * if (disk != null) {
+ *   String snapshotName = "disk-name-snapshot";
+ *   Operation operation = disk.createSnapshot(snapshotName);
+ *   while (!operation.isDone()) {
+ *     Thread.sleep(1000L);
+ *   }
+ *   if (operation.errors() == null) {
+ *     // use snapshot
+ *     Snapshot snapshot = compute.getSnapshot("disk-name-snapshot");
+ *   }
+ * }}
+ *

This second example shows how to create a virtual machine instance. Complete source code can + * be found at + * + * CreateInstance.java. + *

 {@code
+ * Compute compute = ComputeOptions.defaultInstance().service();
+ * ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329");
+ * NetworkId networkId = NetworkId.of("default");
+ * AttachedDisk attachedDisk = AttachedDisk.of(AttachedDisk.CreateDiskConfiguration.of(imageId));
+ * NetworkInterface networkInterface = NetworkInterface.of(networkId);
+ * InstanceId instanceId = InstanceId.of("us-central1-a", "instance-name");
+ * MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1");
+ * Operation operation =
+ * compute.create(InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface));
+ * while (!operation.isDone()) {
+ *   Thread.sleep(1000L);
+ * }
+ * if (operation.errors() == null) {
+ *   // use instance
+ *   Instance instance = compute.getInstance(instanceId);
+ * }}
+ * + * @see Google Cloud Compute + */ +package com.google.gcloud.compute; diff --git a/gcloud-java-examples/README.md b/gcloud-java-examples/README.md index 59fbca11e219..53fc5f7d7f80 100644 --- a/gcloud-java-examples/README.md +++ b/gcloud-java-examples/README.md @@ -62,6 +62,18 @@ To run examples from your command line: mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.bigquery.BigQueryExample" -Dexec.args="query 'select * from new_dataset_id.new_table_id'" ``` + * Here's an example run of `ComputeExample`. + + Before running the example, go to the [Google Developers Console][developers-console] to ensure + that Compute API is enabled. + ``` + mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.compute.ComputeExample" -Dexec.args="create image-disk us-central1-a test-disk debian-cloud debian-8-jessie-v20160329" + mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.compute.ComputeExample" -Dexec.args="create instance us-central1-a test-instance n1-standard-1 test-disk default" + mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.compute.ComputeExample" -Dexec.args="add-access-config us-central1-a test-instance nic0 NAT" + mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.compute.ComputeExample" -Dexec.args="delete instance us-central1-a test-instance" + mvn exec:java -Dexec.mainClass="com.google.gcloud.examples.compute.ComputeExample" -Dexec.args="delete disk us-central1-a test-disk" + ``` + * Here's an example run of `DatastoreExample`. Be sure to change the placeholder project ID "your-project-id" with your own project ID. Also note that you have to enable the Google Cloud Datastore API on the [Google Developers Console][developers-console] before running the following commands. diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/ComputeExample.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/ComputeExample.java new file mode 100644 index 000000000000..afc2d6c049c2 --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/ComputeExample.java @@ -0,0 +1,2539 @@ +/* + * 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.examples.compute; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.gcloud.compute.Address; +import com.google.gcloud.compute.AddressId; +import com.google.gcloud.compute.AddressInfo; +import com.google.gcloud.compute.AttachedDisk; +import com.google.gcloud.compute.AttachedDisk.PersistentDiskConfiguration; +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.Disk; +import com.google.gcloud.compute.DiskConfiguration; +import com.google.gcloud.compute.DiskId; +import com.google.gcloud.compute.DiskImageConfiguration; +import com.google.gcloud.compute.DiskInfo; +import com.google.gcloud.compute.DiskType; +import com.google.gcloud.compute.DiskTypeId; +import com.google.gcloud.compute.GlobalAddressId; +import com.google.gcloud.compute.GlobalOperationId; +import com.google.gcloud.compute.Image; +import com.google.gcloud.compute.ImageDiskConfiguration; +import com.google.gcloud.compute.ImageId; +import com.google.gcloud.compute.ImageInfo; +import com.google.gcloud.compute.Instance; +import com.google.gcloud.compute.InstanceId; +import com.google.gcloud.compute.InstanceInfo; +import com.google.gcloud.compute.LicenseId; +import com.google.gcloud.compute.MachineType; +import com.google.gcloud.compute.MachineTypeId; +import com.google.gcloud.compute.Network; +import com.google.gcloud.compute.NetworkId; +import com.google.gcloud.compute.NetworkInfo; +import com.google.gcloud.compute.NetworkInterface; +import com.google.gcloud.compute.NetworkInterface.AccessConfig; +import com.google.gcloud.compute.Operation; +import com.google.gcloud.compute.Region; +import com.google.gcloud.compute.RegionAddressId; +import com.google.gcloud.compute.RegionId; +import com.google.gcloud.compute.RegionOperationId; +import com.google.gcloud.compute.SchedulingOptions; +import com.google.gcloud.compute.SchedulingOptions.Maintenance; +import com.google.gcloud.compute.Snapshot; +import com.google.gcloud.compute.SnapshotDiskConfiguration; +import com.google.gcloud.compute.SnapshotId; +import com.google.gcloud.compute.SnapshotInfo; +import com.google.gcloud.compute.StandardDiskConfiguration; +import com.google.gcloud.compute.StandardNetworkConfiguration; +import com.google.gcloud.compute.SubnetNetworkConfiguration; +import com.google.gcloud.compute.Subnetwork; +import com.google.gcloud.compute.SubnetworkId; +import com.google.gcloud.compute.SubnetworkInfo; +import com.google.gcloud.compute.Zone; +import com.google.gcloud.compute.ZoneId; +import com.google.gcloud.compute.ZoneOperationId; +import com.google.gcloud.compute.spi.ComputeRpc.Tuple; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * An example of using Google Compute. + * + *

This example demonstrates a simple/typical Compute usage. + * + *

Steps needed for running the example: + *

    + *
  1. login using gcloud SDK - {@code gcloud auth login}.
  2. + *
  3. compile using maven - {@code mvn compile}
  4. + *
  5. run using maven - + *
    {@code mvn exec:java -Dexec.mainClass="com.google.cloud.examples.compute.ComputeExample"
    + *  -Dexec.args="[]
    + * list networks |
    + * list region-operations  |
    + * list instances ? |
    + * list regions |
    + * list zones |
    + * list zone-operations  |
    + * list disks ? |
    + * list subnetworks ? |
    + * list machineTypes ? |
    + * list global-operations |
    + * list images |
    + * list diskTypes ? |
    + * list snapshots |
    + * list addresses ? |
    + * create subnet-network  true|false |
    + * create image-disk   ?  |
    + * create subnetwork     |
    + * create address ? 
    | + * create snapshot | + * create snapshot-disk | + * create image | + * create standard-network | + * create instance | + * create standard-disk ? | + * info region | + * info region-operation | + * info machineType | + * info snapshot | + * info disk | + * info image | + * info diskType | + * info network | + * info zone-operation | + * info subnetwork | + * info address ?
    | + * info instance | + * info license | + * info global-operation | + * info zone | + * delete region-operation | + * delete zone-operation | + * delete subnetwork | + * delete address ?
    | + * delete snapshot | + * delete disk | + * delete image | + * delete instance | + * delete global-operation | + * delete network | + * get-serial-port | + * set-machine-type | + * set-disk-auto-delete true|false | + * set-scheduling-options preemptible|(standard true|false MIGRATE|TERMINATE) | + * add-access-config ? | + * delete-access-config | + * attach-disk | + * detach-disk | + * start | + * stop | + * reset | + * set-tags * | + * set-metadata *"}
    + *
  6. + *
+ * + *

The first parameter is an optional {@code project_id} (logged-in project will be used if not + * supplied). Second parameter is a Compute operation and can be used to demonstrate its usage. For + * operations that apply to more than one entity (`list`, `create`, `info` and `delete`) the third + * parameter specifies the entity. + */ +public class ComputeExample { + + private static final Map CREATE_ACTIONS = new HashMap<>(); + private static final Map INFO_ACTIONS = new HashMap<>(); + private static final Map LIST_ACTIONS = new HashMap<>(); + private static final Map DELETE_ACTIONS = new HashMap<>(); + private static final Map ACTIONS = new HashMap<>(); + + static class Triple { + + private final X x; + private final Y y; + private final Z z; + + private Triple(X x, Y y, Z z) { + this.x = x; + this.y = y; + this.z = z; + } + + public static Triple of(X x, Y y, Z z) { + return new Triple<>(x, y, z); + } + + X x() { + return x; + } + + Y y() { + return y; + } + + Z z() { + return z; + } + } + + private abstract static class ComputeAction { + + abstract void run(Compute compute, T request) throws Exception; + + abstract T parse(String... args) throws Exception; + + protected String params() { + return ""; + } + } + + private static class ParentAction extends ComputeAction> { + + private final Map subActions; + + ParentAction(Map subActions) { + this.subActions = ImmutableMap.copyOf(subActions); + } + + @Override + @SuppressWarnings("unchecked") + void run(Compute compute, Tuple subaction) throws Exception { + subaction.x().run(compute, subaction.y()); + } + + @Override + Tuple parse(String... args) throws Exception { + if (args.length >= 1) { + ComputeAction action = subActions.get(args[0]); + if (action != null) { + Object actionArguments = action.parse(Arrays.copyOfRange(args, 1, args.length)); + return Tuple.of(action, actionArguments); + } else { + throw new IllegalArgumentException("Unrecognized entity '" + args[0] + "'."); + } + } + throw new IllegalArgumentException("Missing required entity."); + } + + @Override + public String params() { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : subActions.entrySet()) { + builder.append('\n').append(entry.getKey()); + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + builder.append(' ').append(param); + } + } + return builder.toString(); + } + } + + private abstract static class OptionalZoneAction extends ComputeAction { + @Override + ZoneId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return ZoneId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + return null; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return "?"; + } + } + + private abstract static class OptionalRegionAction extends ComputeAction { + @Override + RegionId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return RegionId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + return null; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return "?"; + } + } + + private abstract static class NoArgsAction extends ComputeAction { + @Override + Void parse(String... args) throws Exception { + if (args.length == 0) { + return null; + } + throw new IllegalArgumentException("This action takes no arguments."); + } + } + + /** + * This class demonstrates how to list Compute disk types. + * + * @see DiskTypes: + * list + * @see + * DiskTypes: aggregated list + */ + private static class ListDiskTypesAction extends OptionalZoneAction { + @Override + public void run(Compute compute, ZoneId zone) { + Iterator diskTypeIterator; + if (zone != null) { + diskTypeIterator = compute.listDiskTypes(zone.zone()).iterateAll(); + } else { + diskTypeIterator = compute.listDiskTypes().iterateAll(); + } + while (diskTypeIterator.hasNext()) { + System.out.println(diskTypeIterator.next()); + } + } + } + + /** + * This class demonstrates how to retrieve information on a Compute disk type. + * + * @see DiskTypes: + * get + */ + private static class DiskTypeInfoAction extends ComputeAction { + @Override + public void run(Compute compute, DiskTypeId diskType) { + System.out.println("Disk type info: " + compute.getDiskType(diskType)); + } + + @Override + DiskTypeId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return DiskTypeId.of(args[0], args[1]); + } else if (args.length < 2) { + message = "Missing required zone and disk type id."; + } else { + message = "Too many arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to list Compute machine types. + * + * @see + * MachineTypes: list + * @see + * MachineTypes: aggregated list + */ + private static class ListMachineTypesAction extends OptionalZoneAction { + @Override + public void run(Compute compute, ZoneId zone) { + Iterator machineTypeIterator; + if (zone != null) { + machineTypeIterator = compute.listMachineTypes(zone.zone()).iterateAll(); + } else { + machineTypeIterator = compute.listMachineTypes().iterateAll(); + } + while (machineTypeIterator.hasNext()) { + System.out.println(machineTypeIterator.next()); + } + } + } + + /** + * This class demonstrates how to retrieve information on a Compute machine type. + * + * @see + * MachineTypes: get + */ + private static class MachineTypeInfoAction extends ComputeAction { + @Override + public void run(Compute compute, MachineTypeId machineType) { + System.out.println("Machine type info: " + compute.getMachineType(machineType)); + } + + @Override + MachineTypeId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return MachineTypeId.of(args[0], args[1]); + } else if (args.length < 2) { + message = "Missing required zone and machine type id."; + } else { + message = "Too many arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to list Compute regions. + * + * @see Regions: + * list + */ + private static class ListRegionsAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator regionIterator = compute.listRegions().iterateAll(); + while (regionIterator.hasNext()) { + System.out.println(regionIterator.next()); + } + } + } + + /** + * This class demonstrates how to retrieve information on a Compute region. + * + * @see + * Regions: get + */ + private static class RegionInfoAction extends ComputeAction { + @Override + public void run(Compute compute, RegionId region) { + System.out.println("Region info: " + compute.getRegion(region.region())); + } + + @Override + RegionId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return RegionId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required region id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to list Compute zones. + * + * @see Zones: list + * + */ + private static class ListZonesAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator zoneIterator = compute.listZones().iterateAll(); + while (zoneIterator.hasNext()) { + System.out.println(zoneIterator.next()); + } + } + } + + /** + * This class demonstrates how to retrieve information on a Compute zone. + * + * @see Zones: get + */ + private static class ZoneInfoAction extends ComputeAction { + @Override + public void run(Compute compute, ZoneId zone) { + System.out.println("Zone info: " + compute.getZone(zone.zone())); + } + + @Override + ZoneId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return ZoneId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required zone id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute license. + * + * @see License: + * get + */ + private static class LicenseInfoAction extends ComputeAction { + @Override + public void run(Compute compute, LicenseId license) { + System.out.println("License info: " + compute.getLicense(license.license())); + } + + @Override + LicenseId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return LicenseId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required license id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to list Compute global operations. + * + * @see + * GLobalOperations: list + */ + private static class ListGlobalOperationsAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator operationIterator = compute.listGlobalOperations().iterateAll(); + while (operationIterator.hasNext()) { + System.out.println(operationIterator.next()); + } + } + } + + /** + * This class demonstrates how to list Compute zone operations. + * + * @see + * ZoneOperations: list + */ + private static class ListZoneOperationsAction extends ComputeAction { + @Override + public void run(Compute compute, ZoneId zone) { + Iterator operationIterator = compute.listZoneOperations(zone.zone()).iterateAll(); + while (operationIterator.hasNext()) { + System.out.println(operationIterator.next()); + } + } + + @Override + ZoneId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return ZoneId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required zone id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to list Compute region operations. + * + * @see + * RegionOperations: list + */ + private static class ListRegionOperationsAction extends ComputeAction { + @Override + public void run(Compute compute, RegionId region) { + Iterator operationIterator = + compute.listRegionOperations(region.region()).iterateAll(); + while (operationIterator.hasNext()) { + System.out.println(operationIterator.next()); + } + } + + @Override + RegionId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return RegionId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required region id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + private abstract static class GlobalOperationAction extends ComputeAction { + @Override + GlobalOperationId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return GlobalOperationId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required operation id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + private abstract static class ZoneOperationAction extends ComputeAction { + @Override + ZoneOperationId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return ZoneOperationId.of(args[0], (args[1])); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required zone and operation id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + private abstract static class RegionOperationAction extends ComputeAction { + @Override + RegionOperationId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return RegionOperationId.of(args[0], (args[1])); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required region and operation id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute global operation. + * + * @see + * GlobalOperations: get + */ + private static class GlobalOperationInfoAction extends GlobalOperationAction { + @Override + public void run(Compute compute, GlobalOperationId operation) { + System.out.println("Operation info: " + compute.getOperation(operation)); + } + } + + /** + * This class demonstrates how to retrieve information on a Compute zone operation. + * + * @see + * ZoneOperations: get + */ + private static class ZoneOperationInfoAction extends ZoneOperationAction { + @Override + public void run(Compute compute, ZoneOperationId operation) { + System.out.println("Operation info: " + compute.getOperation(operation)); + } + } + + /** + * This class demonstrates how to retrieve information on a Compute region operation. + * + * @see + * RegionOperations: get + */ + private static class RegionOperationInfoAction extends RegionOperationAction { + @Override + public void run(Compute compute, RegionOperationId operation) { + System.out.println("Operation info: " + compute.getOperation(operation)); + } + } + + /** + * This class demonstrates how to delete a Compute global operation. + * + * @see + * GlobalOperations: delete + */ + private static class DeleteGlobalOperationAction extends GlobalOperationAction { + @Override + public void run(Compute compute, GlobalOperationId operation) { + if (compute.deleteOperation(operation)) { + System.out.println("Operation " + operation + " was deleted"); + } else { + System.out.println("Operation " + operation + " not found"); + } + } + } + + /** + * This class demonstrates how to delete a Compute zone operation. + * + * @see + * ZoneOperations: delete + */ + private static class DeleteZoneOperationAction extends ZoneOperationAction { + @Override + public void run(Compute compute, ZoneOperationId operation) { + if (compute.deleteOperation(operation)) { + System.out.println("Operation " + operation + " was deleted"); + } else { + System.out.println("Operation " + operation + " not found"); + } + } + } + + /** + * This class demonstrates how to delete a Compute region operation. + * + * @see + * RegionOperations: delete + */ + private static class DeleteRegionOperationAction extends RegionOperationAction { + @Override + public void run(Compute compute, RegionOperationId operation) { + if (compute.deleteOperation(operation)) { + System.out.println("Operation " + operation + " was deleted"); + } else { + System.out.println("Operation " + operation + " not found"); + } + } + } + + /** + * This class demonstrates how to list Compute addresses. + * + * @see + * Addresses: list + * @see + * Addresses: aggerated list + */ + private static class ListAddressesAction extends OptionalRegionAction { + @Override + public void run(Compute compute, RegionId region) { + Iterator

addressIterator; + if (region != null) { + addressIterator = compute.listRegionAddresses(region.region()).iterateAll(); + } else { + addressIterator = compute.listAddresses().iterateAll(); + } + while (addressIterator.hasNext()) { + System.out.println(addressIterator.next()); + } + } + } + + private abstract static class AddressAction extends ComputeAction { + @Override + AddressId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return RegionAddressId.of(args[0], (args[1])); + } else if (args.length == 1) { + return GlobalAddressId.of(args[0]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required address id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return "?
"; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute address. + * + * @see + * Addresses: get + * @see + * Global Addresses: get + */ + private static class AddressInfoAction extends AddressAction { + @Override + public void run(Compute compute, AddressId address) { + System.out.println("Address info: " + compute.getAddress(address)); + } + } + + /** + * This class demonstrates how to delete a Compute address. + * + * @see + * Addresses: delete + * @see + * Global Addresses: delete + */ + private static class DeleteAddressAction extends AddressAction { + @Override + public void run(Compute compute, AddressId address) throws InterruptedException { + Operation operation = compute.deleteAddress(address); + if (operation == null) { + System.out.println("Address " + address + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Address " + address + " was deleted"); + } else { + System.out.println("Deletion of address " + address + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute address. + * + * @see + * Addresses: insert + * @see + * Global Addresses: insert + */ + private static class CreateAddressAction extends AddressAction { + @Override + public void run(Compute compute, AddressId address) throws InterruptedException { + Operation operation = compute.create(AddressInfo.of(address)); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Address " + address + " was created"); + } else { + System.out.println("Creation of address " + address + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to list Compute snapshots. + * + * @see + * Snapshots: list + */ + private static class ListSnapshotsAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator snapshotIterator = compute.listSnapshots().iterateAll(); + while (snapshotIterator.hasNext()) { + System.out.println(snapshotIterator.next()); + } + } + } + + private abstract static class SnapshotAction extends ComputeAction { + @Override + SnapshotId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return SnapshotId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required shapshot id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute snapshot. + * + * @see + * Snapshots: get + */ + private static class SnapshotInfoAction extends SnapshotAction { + @Override + public void run(Compute compute, SnapshotId snapshot) { + System.out.println("Snapshot info: " + compute.getSnapshot(snapshot.snapshot())); + } + } + + /** + * This class demonstrates how to delete a Compute snapshot. + * + * @see + * Snapshots: delete + */ + private static class DeleteSnapshotAction extends SnapshotAction { + @Override + public void run(Compute compute, SnapshotId snapshot) throws InterruptedException { + Operation operation = compute.deleteSnapshot(snapshot.snapshot()); + if (operation == null) { + System.out.println("Snapshot " + snapshot + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Snapshot " + snapshot + " was deleted"); + } else { + System.out.println("Deletion of snapshot " + snapshot + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute snapshot. + * + * @see + * Snapshots: insert + */ + private static class CreateSnapshotAction extends ComputeAction { + @Override + public void run(Compute compute, SnapshotInfo snapshot) throws InterruptedException { + Operation operation = compute.create(snapshot); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Snapshot " + snapshot.snapshotId() + " was created"); + } else { + System.out.println("Creation of snapshot " + snapshot.snapshotId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + SnapshotInfo parse(String... args) throws Exception { + String message; + if (args.length == 3) { + String snapshot = args[0]; + String zone = args[1]; + String disk = args[2]; + return SnapshotInfo.of(SnapshotId.of(snapshot), DiskId.of(zone, disk)); + } else if (args.length > 3) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to list Compute images. + * + * @see Images: list + * + */ + private static class ListImagesAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator imageIterator = compute.listImages().iterateAll(); + while (imageIterator.hasNext()) { + System.out.println(imageIterator.next()); + } + } + } + + private abstract static class ImageAction extends ComputeAction { + @Override + ImageId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return ImageId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required image id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute image. + * + * @see Images: get + * + */ + private static class ImageInfoAction extends ImageAction { + @Override + public void run(Compute compute, ImageId image) { + System.out.println("Image info: " + compute.getImage(image)); + } + } + + /** + * This class demonstrates how to delete a Compute image. + * + * @see Images: + * delete + */ + private static class DeleteImageAction extends ImageAction { + @Override + public void run(Compute compute, ImageId image) throws InterruptedException { + Operation operation = compute.deleteImage(image); + if (operation == null) { + System.out.println("Image " + image + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Image " + image + " was deleted"); + } else { + System.out.println("Deletion of image " + image + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute image. + * + * @see Images: + * insert + */ + private static class CreateImageAction extends ComputeAction { + @Override + public void run(Compute compute, ImageInfo image) throws InterruptedException { + Operation operation = compute.create(image); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Image " + image.imageId() + " was created"); + } else { + System.out.println("Creation of image " + image.imageId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + ImageInfo parse(String... args) throws Exception { + String message; + if (args.length == 3) { + String image = args[0]; + String zone = args[1]; + String disk = args[2]; + return ImageInfo.of(ImageId.of(image), DiskImageConfiguration.of(DiskId.of(zone, disk))); + } else if (args.length > 3) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + private abstract static class DiskAction extends ComputeAction { + @Override + DiskId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return DiskId.of(args[0], args[1]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required zone and disk id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute disk. + * + * @see + * Snapshots: get + */ + private static class DiskInfoAction extends DiskAction { + @Override + public void run(Compute compute, DiskId disk) { + System.out.println("Disk info: " + compute.getDisk(disk)); + } + } + + /** + * This class demonstrates how to delete a Compute disk. + * + * @see Disks: + * delete + */ + private static class DeleteDiskAction extends DiskAction { + @Override + public void run(Compute compute, DiskId disk) throws InterruptedException { + Operation operation = compute.deleteDisk(disk); + if (operation == null) { + System.out.println("Disk " + disk + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Disk " + disk + " was deleted"); + } else { + System.out.println("Deletion of disk " + disk + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to list Compute disks. + * + * @see Disks: list + * + */ + private static class ListDisksAction extends OptionalZoneAction { + @Override + public void run(Compute compute, ZoneId zone) { + Iterator diskIterator = compute.listDisks().iterateAll(); + while (diskIterator.hasNext()) { + System.out.println(diskIterator.next()); + } + } + } + + private abstract static class CreateDiskAction extends ComputeAction { + @Override + public void run(Compute compute, DiskInfo disk) throws InterruptedException { + Operation operation = compute.create(disk); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Disk " + disk.diskId() + " was created"); + } else { + System.out.println("Creation of disk " + disk.diskId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + static DiskId parseDiskId(String[] args) { + return DiskId.of(args[0], args[1]); + } + } + + /** + * This class demonstrates how to create a Compute disk given its type and size. + * + * @see Disks: + * insert + */ + private static class CreateStandardDiskAction extends CreateDiskAction { + @Override + DiskInfo parse(String... args) throws Exception { + if (args.length >= 3) { + DiskId diskId = parseDiskId(args); + String diskType = args[2]; + DiskConfiguration configuration; + if (args.length == 4) { + try { + configuration = StandardDiskConfiguration.of(DiskTypeId.of(diskId.zone(), diskType), + Integer.parseInt(args[3])); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Error parsing disk size parameter."); + } + } else if (args.length == 3) { + configuration = StandardDiskConfiguration.of(DiskTypeId.of(diskId.zone(), diskType)); + } else { + throw new IllegalArgumentException("Too many arguments."); + } + return DiskInfo.of(diskId, configuration); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " ?"; + } + } + + /** + * This class demonstrates how to create a Compute disk given a source snapshot. + * + * @see Disks: + * insert + */ + private static class CreateSnapshotDiskAction extends CreateDiskAction { + @Override + DiskInfo parse(String... args) throws Exception { + if (args.length == 3) { + DiskId diskId = parseDiskId(args); + return DiskInfo.of(diskId, SnapshotDiskConfiguration.of(SnapshotId.of(args[2]))); + } else if (args.length > 3) { + throw new IllegalArgumentException("Too many arguments."); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to create a Compute disk given a source image. + * + * @see Disks: + * insert + */ + private static class CreateImageDiskAction extends CreateDiskAction { + @Override + DiskInfo parse(String... args) throws Exception { + if (args.length == 3) { + DiskId diskId = parseDiskId(args); + return DiskInfo.of(diskId, ImageDiskConfiguration.of(ImageId.of(args[2]))); + } else if (args.length == 4) { + DiskId diskId = parseDiskId(args); + return DiskInfo.of(diskId, ImageDiskConfiguration.of(ImageId.of(args[2], args[3]))); + } else if (args.length > 4) { + throw new IllegalArgumentException("Too many arguments."); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " ? "; + } + } + + /** + * This class demonstrates how to list Compute networks. + * + * @see Networks: + * list + */ + private static class ListNetworksAction extends NoArgsAction { + @Override + public void run(Compute compute, Void arg) { + Iterator networkIterator = compute.listNetworks().iterateAll(); + while (networkIterator.hasNext()) { + System.out.println(networkIterator.next()); + } + } + } + + private abstract static class NetworkAction extends ComputeAction { + @Override + NetworkId parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return NetworkId.of(args[0]); + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required network id."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute network. + * + * @see Networks: + * get + */ + private static class NetworkInfoAction extends NetworkAction { + @Override + public void run(Compute compute, NetworkId network) { + System.out.println("Network info: " + compute.getNetwork(network.network())); + } + } + + /** + * This class demonstrates how to delete a Compute network. + * + * @see Networks: + * delete + */ + private static class DeleteNetworkAction extends NetworkAction { + @Override + public void run(Compute compute, NetworkId network) throws InterruptedException { + Operation operation = compute.deleteNetwork(network.network()); + if (operation == null) { + System.out.println("Network " + network + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Network " + network + " was deleted"); + } else { + System.out.println("Deletion of network " + network + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + private abstract static class CreateNetworkAction extends ComputeAction { + @Override + public void run(Compute compute, NetworkInfo network) throws InterruptedException { + Operation operation = compute.create(network); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Network " + network.networkId() + " was created"); + } else { + System.out.println("Creation of network " + network.networkId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute network with no subnetworks. + * + * @see Networks: + * insert + */ + private static class CreateStandardNetworkAction extends CreateNetworkAction { + @Override + NetworkInfo parse(String... args) throws Exception { + if (args.length == 2) { + return NetworkInfo.of(NetworkId.of(args[0]), StandardNetworkConfiguration.of(args[1])); + } else if (args.length > 2) { + throw new IllegalArgumentException("Too many arguments."); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to create a Compute network that supports the creation of + * subnetworks (either manual or automatic). + * + * @see Networks: + * insert + */ + private static class CreateSubnetNetworkAction extends CreateNetworkAction { + @Override + NetworkInfo parse(String... args) throws Exception { + if (args.length == 2) { + boolean autoCreateSubnetworks; + switch (args[1]) { + case "true": + autoCreateSubnetworks = true; + break; + case "false": + autoCreateSubnetworks = false; + break; + default: + throw new IllegalArgumentException( + "Couldn't parse autoCreateSubnetworks argument (must be either true or false)."); + } + return NetworkInfo.of(NetworkId.of(args[0]), + SubnetNetworkConfiguration.of(autoCreateSubnetworks)); + } else if (args.length > 2) { + throw new IllegalArgumentException("Too many arguments."); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " true|false"; + } + } + + /** + * This class demonstrates how to list Compute subnetworks. + * + * @see + * Subnetworks: list + */ + private static class ListSubnetworksAction extends OptionalRegionAction { + + @Override + public void run(Compute compute, RegionId region) { + Iterator subnetworkIterator; + if (region != null) { + subnetworkIterator = compute.listSubnetworks(region.region()).iterateAll(); + } else { + subnetworkIterator = compute.listSubnetworks().iterateAll(); + } + while (subnetworkIterator.hasNext()) { + System.out.println(subnetworkIterator.next()); + } + } + } + + private abstract static class SubnetworkAction extends ComputeAction { + @Override + SubnetworkId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return SubnetworkId.of(args[0], args[1]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required region and subnetwork."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute subnetwork. + * + * @see + * Subnetworks: get + */ + private static class SubnetworkInfoAction extends SubnetworkAction { + @Override + public void run(Compute compute, SubnetworkId subnetwork) { + System.out.println("Subnetwork info: " + compute.getSubnetwork(subnetwork)); + } + } + + /** + * This class demonstrates how to delete a Compute subnetwork. + * + * @see + * Subnetworks: delete + */ + private static class DeleteSubnetworkAction extends SubnetworkAction { + @Override + public void run(Compute compute, SubnetworkId subnetwork) throws InterruptedException { + Operation operation = compute.deleteSubnetwork(subnetwork); + if (operation == null) { + System.out.println("Subnetwork " + subnetwork + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Subnetwork " + subnetwork + " was deleted"); + } else { + System.out.println("Deletion of subnetwork " + subnetwork + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute subnetwork. + * + * @see + * Subnetworks: insert + */ + private static class CreateSubnetworkAction extends ComputeAction { + @Override + public void run(Compute compute, SubnetworkInfo subnetwork) throws InterruptedException { + Operation operation = compute.create(subnetwork); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Subnetwork " + subnetwork.subnetworkId() + " was created"); + } else { + System.out.println("Creation of subnetwork " + subnetwork.subnetworkId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + SubnetworkInfo parse(String... args) throws Exception { + String message; + if (args.length == 4) { + SubnetworkId subnetwork = SubnetworkId.of(args[0], args[1]); + return SubnetworkInfo.of(subnetwork, NetworkId.of(args[2]), args[3]); + } else if (args.length > 4) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to list Compute instances. + * + * @see Instances: + * list + */ + private static class ListInstancesAction extends OptionalZoneAction { + @Override + public void run(Compute compute, ZoneId zone) { + Iterator instanceIterator; + if (zone != null) { + instanceIterator = compute.listInstances(zone.zone()).iterateAll(); + } else { + instanceIterator = compute.listInstances().iterateAll(); + } + while (instanceIterator.hasNext()) { + System.out.println(instanceIterator.next()); + } + } + } + + private abstract static class InstanceAction extends ComputeAction { + @Override + InstanceId parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return InstanceId.of(args[0], args[1]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required zone and instance."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to retrieve information on a Compute instance. + * + * @see Instances: + * get + */ + private static class InstanceInfoAction extends InstanceAction { + @Override + public void run(Compute compute, InstanceId instance) { + System.out.println("Instance info: " + compute.getInstance(instance)); + } + } + + /** + * This class demonstrates how to delete a Compute instance. + * + * @see + * Instances: delete + */ + private static class DeleteInstanceAction extends InstanceAction { + @Override + public void run(Compute compute, InstanceId instance) throws InterruptedException { + Operation operation = compute.deleteInstance(instance); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instance + " was deleted"); + } else { + System.out.println("Deletion of instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to create a Compute instance. + * + * @see + * Instances: insert + */ + private static class CreateInstanceAction extends ComputeAction { + @Override + public void run(Compute compute, InstanceInfo instance) throws InterruptedException { + Operation operation = compute.create(instance); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instance.instanceId() + " was created"); + } else { + System.out.println("Creation of instance " + instance.instanceId() + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + InstanceInfo parse(String... args) throws Exception { + String message; + if (args.length == 5) { + String zone = args[0]; + String instance = args[1]; + InstanceId instanceId = InstanceId.of(zone, instance); + MachineTypeId machineTypeId = MachineTypeId.of(zone, args[2]); + DiskId diskId = DiskId.of(zone, args[3]); + AttachedDisk disk = + AttachedDisk.of(PersistentDiskConfiguration.builder(diskId).boot(true).build()); + NetworkInterface networkInterface = NetworkInterface.of(args[4]); + return InstanceInfo.of(instanceId, machineTypeId, disk, networkInterface); + } else if (args.length > 5) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to get the serial port output for a Compute instance. + * + * @see + * Instances: getSerialPortOutput + */ + private static class GetSerialPortAction extends ComputeAction> { + @Override + public void run(Compute compute, Tuple instanceAndPort) + throws InterruptedException { + InstanceId instance = instanceAndPort.x(); + Integer port = instanceAndPort.y(); + String serialPortOutput; + if (port != null) { + System.out.println("Getting serial port " + port + " output for instance " + instance); + serialPortOutput = compute.getSerialPortOutput(instance, port); + } else { + System.out.println("Getting serial port output for instance " + instance); + serialPortOutput = compute.getSerialPortOutput(instance); + } + System.out.println(serialPortOutput); + } + + @Override + Tuple parse(String... args) throws Exception { + if (args.length >= 2) { + InstanceId instanceId = InstanceId.of(args[0], args[1]); + Integer port = null; + if (args.length == 3) { + try { + port = Integer.parseInt(args[2]); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException( + "Error parsing portNumber parameter (must be a number)"); + } + } else if (args.length > 3) { + throw new IllegalArgumentException("Too many arguments."); + } + return Tuple.of(instanceId, port); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to add an access configuration to a Compute instance network + * interface. + * + * @see + * Instances: addAccessConfig + */ + private static class AddAccessConfigAction + extends ComputeAction> { + @Override + public void run(Compute compute, Triple interfaceAndConfig) + throws InterruptedException { + InstanceId instance = interfaceAndConfig.x(); + String networkInterface = interfaceAndConfig.y(); + AccessConfig accessConfig = interfaceAndConfig.z(); + Operation operation = compute.addAccessConfig(instance, networkInterface, accessConfig); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Access config added to network interface " + networkInterface + + " of instance " + instance); + } else { + System.out.println("Attempt to add access config to network interface " + networkInterface + + " of instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Triple parse(String... args) throws Exception { + String message; + if (args.length >= 4) { + InstanceId instance = InstanceId.of(args[0], args[1]); + String networkInterface = args[2]; + String accessConfig = args[3]; + if (args.length == 4) { + return Triple.of(instance, networkInterface, + AccessConfig.builder().name(accessConfig).build()); + } else if (args.length == 5) { + return Triple.of(instance, networkInterface, + AccessConfig.builder().name(accessConfig).natIp(args[4]).build()); + } else { + message = "Too many arguments."; + } + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " ?"; + } + } + + /** + * This class demonstrates how to delete an access configuration from a Compute instance network + * interface. + * + * @see + * Instances: deleteAccessConfig + */ + private static class DeleteAccessConfigAction extends + ComputeAction> { + @Override + public void run(Compute compute, Triple interfaceAndConfig) + throws InterruptedException { + InstanceId instance = interfaceAndConfig.x(); + String networkInterface = interfaceAndConfig.y(); + String accessConfig = interfaceAndConfig.z(); + Operation operation = compute.deleteAccessConfig(instance, networkInterface, accessConfig); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Access config deleted from network interface " + networkInterface + + " of instance " + instance); + } else { + System.out.println("Attempt to delete access config from network interface " + + networkInterface + " of instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Triple parse(String... args) throws Exception { + String message; + if (args.length == 4) { + InstanceId instance = InstanceId.of(args[0], args[1]); + String networkInterface = args[2]; + String accessConfig = args[3]; + return Triple.of(instance, networkInterface, accessConfig); + } else if (args.length > 4) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to attach a persistent disk to a Compute instance. + * + * @see + * Instances: attachDisk + */ + private static class AttachDiskAction + extends ComputeAction> { + @Override + public void run(Compute compute, Triple + instanceAndDisk) throws InterruptedException { + InstanceId instance = instanceAndDisk.x(); + String deviceName = instanceAndDisk.y(); + PersistentDiskConfiguration diskConfiguration = instanceAndDisk.z(); + Operation operation = compute.attachDisk(instance, deviceName, diskConfiguration); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Disk attached to instance " + instance); + } else { + System.out.println("Attempt to attach disk to instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Triple parse(String... args) throws Exception { + String message; + if (args.length == 4) { + String zone = args[0]; + String instance = args[1]; + String deviceName = args[2]; + String disk = args[3]; + return Triple.of(InstanceId.of(zone, instance), deviceName, + PersistentDiskConfiguration.of(DiskId.of(zone, disk))); + } else if (args.length > 4) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to detach a persistent disk from a Compute instance. + * + * @see + * Instances: detachDisk + */ + private static class DetachDiskAction extends ComputeAction> { + @Override + public void run(Compute compute, Tuple instanceAndDevice) + throws InterruptedException { + InstanceId instance = instanceAndDevice.x(); + String deviceName = instanceAndDevice.y(); + Operation operation = compute.detachDisk(instance, deviceName); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Disk detached from instance " + instance); + } else { + System.out.println("Attempt to detach disk from instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Tuple parse(String... args) throws Exception { + String message; + if (args.length == 3) { + String zone = args[0]; + String instance = args[1]; + String deviceName = args[2]; + return Tuple.of(InstanceId.of(zone, instance), deviceName); + } else if (args.length > 4) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to set the auto-delete property of a disk attached to a Compute + * instance. + * + * @see + * Instances: setDiskAutoDelete + */ + private static class SetDiskAutoDeleteAction + extends ComputeAction> { + @Override + public void run(Compute compute, Triple deviceAndAutoDelete) + throws InterruptedException { + InstanceId instance = deviceAndAutoDelete.x(); + String deviceName = deviceAndAutoDelete.y(); + Boolean autoDelete = deviceAndAutoDelete.z(); + Operation operation = compute.setDiskAutoDelete(instance, deviceName, autoDelete); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Auto-delete set for device " + deviceName + " of instance " + instance); + } else { + System.out.println("Attempt to set auto-delete for device " + deviceName + " of instance " + + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Triple parse(String... args) throws Exception { + String message; + if (args.length == 4) { + InstanceId instance = InstanceId.of(args[0], args[1]); + String deviceName = args[2]; + boolean autoDelete; + switch (args[3]) { + case "true": + autoDelete = true; + break; + case "false": + autoDelete = false; + break; + default: + throw new IllegalArgumentException( + "Couldn't parse autoDelete argument (must be either true or false)."); + } + return Triple.of(instance, deviceName, autoDelete); + } else if (args.length > 3) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " true|false"; + } + } + + /** + * This class demonstrates how to set the machine type for a Compute instance. + * + * @see + * Instances: setMachineType + */ + private static class SetMachineTypeAction + extends ComputeAction> { + @Override + public void run(Compute compute, Tuple instanceAndType) + throws InterruptedException { + InstanceId instance = instanceAndType.x(); + MachineTypeId machineType = instanceAndType.y(); + Operation operation = compute.setMachineType(instance, machineType); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Machine type set for instance " + instance); + } else { + System.out.println("Attempt to set machine type for instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Tuple parse(String... args) throws Exception { + String message; + if (args.length == 3) { + String zone = args[0]; + String instance = args[1]; + String machineType = args[2]; + return Tuple.of(InstanceId.of(zone, instance), MachineTypeId.of(zone, machineType)); + } else if (args.length > 3) { + message = "Too many arguments."; + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " "; + } + } + + /** + * This class demonstrates how to set the tags for a Compute instance. + * + * @see + * Instances: setTags + */ + private static class SetTagsAction extends ComputeAction>> { + @Override + public void run(Compute compute, Tuple> instanceAndTags) + throws InterruptedException { + InstanceId instanceId = instanceAndTags.x(); + List tags = instanceAndTags.y(); + Instance instance = compute.getInstance(instanceId); + if (instance == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + Operation operation = instance.setTags(tags); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Tags set for instance " + instanceId); + } else { + System.out.println("Attempt to set tags for instance " + instanceId + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Tuple> parse(String... args) throws Exception { + if (args.length >= 2) { + InstanceId instanceId = InstanceId.of(args[0], args[1]); + List tags = Lists.newArrayListWithCapacity(args.length - 2); + tags.addAll(Arrays.asList(args).subList(2, args.length)); + return Tuple.of(instanceId, tags); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " *"; + } + } + + /** + * This class demonstrates how to set the metadata for a Compute instance. + * + * @see + * Instances: setMetadata + */ + private static class SetMetadataAction extends ComputeAction>> { + @Override + public void run(Compute compute, Tuple> instanceAndMetadata) + throws InterruptedException { + InstanceId instanceId = instanceAndMetadata.x(); + Map metadata = instanceAndMetadata.y(); + Instance instance = compute.getInstance(instanceId); + if (instance == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + Operation operation = instance.setMetadata(metadata); + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Metadata set for instance " + instanceId); + } else { + System.out.println("Attempt to set metadata for instance " + instanceId + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Tuple> parse(String... args) throws Exception { + if (args.length >= 2) { + if ((args.length & 0x1) == 0x1) { + throw new IllegalArgumentException("Metadata must be a list of key-value pairs."); + } + InstanceId instanceId = InstanceId.of(args[0], args[1]); + Map metadata = Maps.newHashMapWithExpectedSize((args.length / 2) - 1); + for (int i = 2; i < args.length; i += 2) { + metadata.put(args[i], args[i + 1]); + } + return Tuple.of(instanceId, metadata); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + protected String params() { + return " ( )*"; + } + } + + /** + * This class demonstrates how to set the scheduling options for a Compute instance. + * + * @see + * Instances: setScheduling + */ + private static class SetSchedulingOptionsAction extends ComputeAction> { + @Override + public void run(Compute compute, Tuple instanceAndScheduling) + throws InterruptedException { + InstanceId instanceId = instanceAndScheduling.x(); + SchedulingOptions schedulingOptions = instanceAndScheduling.y(); + Operation operation = compute.setSchedulingOptions(instanceId, schedulingOptions); + if (operation == null) { + System.out.println("Instance " + instanceId + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Scheduling options set for instance " + instanceId); + } else { + System.out.println( + "Attempt to set scheduling options for instance " + instanceId + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + + @Override + Tuple parse(String... args) throws Exception { + String message; + if (args.length > 2) { + InstanceId instanceId = InstanceId.of(args[0], args[1]); + if (args.length == 3 && args[2].equals("preemptible")) { + return Tuple.of(instanceId, SchedulingOptions.preemptible()); + } else if (args.length == 5 && args[2].equals("standard")) { + boolean automaticRestart; + switch (args[3]) { + case "true": + automaticRestart = true; + break; + case "false": + automaticRestart = false; + break; + default: + throw new IllegalArgumentException( + "Couldn't parse automaticRestart argument (must be either true or false)."); + } + Maintenance maintenance = Maintenance.valueOf(args[4]); + return Tuple.of(instanceId, SchedulingOptions.standard(automaticRestart, maintenance)); + } else { + message = "Unexpected command line arguments."; + } + } else { + message = "Missing required arguments."; + } + throw new IllegalArgumentException(message); + } + + @Override + protected String params() { + return " preemptible|(standard true|false MIGRATE|TERMINATE)"; + } + } + + /** + * This class demonstrates how to reset a Compute instance. + * + * @see + * Instances: reset + */ + private static class ResetInstanceAction extends InstanceAction { + @Override + public void run(Compute compute, InstanceId instance) throws InterruptedException { + Operation operation = compute.reset(instance); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instance + " was reset"); + } else { + System.out.println("Attempt to reset instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to stop a Compute instance. + * + * @see + * Instances: stop + */ + private static class StopInstanceAction extends InstanceAction { + @Override + public void run(Compute compute, InstanceId instance) throws InterruptedException { + Operation operation = compute.stop(instance); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instance + " was stopped"); + } else { + System.out.println("Attempt to stop instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + /** + * This class demonstrates how to start a Compute instance. + * + * @see + * Instances: start + */ + private static class StartInstanceAction extends InstanceAction { + @Override + public void run(Compute compute, InstanceId instance) throws InterruptedException { + Operation operation = compute.start(instance); + if (operation == null) { + System.out.println("Instance " + instance + " does not exist"); + return; + } + while (!operation.isDone()) { + System.out.println( + "Waiting for operation " + operation.operationId().operation() + " to complete"); + Thread.sleep(1000L); + } + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instance + " was started"); + } else { + System.out.println("Attempt to start instance " + instance + " failed"); + System.out.println("Error: " + operation.errors()); + } + } + } + + static { + CREATE_ACTIONS.put("address", new CreateAddressAction()); + CREATE_ACTIONS.put("snapshot", new CreateSnapshotAction()); + CREATE_ACTIONS.put("image", new CreateImageAction()); + CREATE_ACTIONS.put("standard-disk", new CreateStandardDiskAction()); + CREATE_ACTIONS.put("snapshot-disk", new CreateSnapshotDiskAction()); + CREATE_ACTIONS.put("image-disk", new CreateImageDiskAction()); + CREATE_ACTIONS.put("standard-network", new CreateStandardNetworkAction()); + CREATE_ACTIONS.put("subnet-network", new CreateSubnetNetworkAction()); + CREATE_ACTIONS.put("subnetwork", new CreateSubnetworkAction()); + CREATE_ACTIONS.put("instance", new CreateInstanceAction()); + INFO_ACTIONS.put("diskType", new DiskTypeInfoAction()); + INFO_ACTIONS.put("machineType", new MachineTypeInfoAction()); + INFO_ACTIONS.put("region", new RegionInfoAction()); + INFO_ACTIONS.put("zone", new ZoneInfoAction()); + INFO_ACTIONS.put("global-operation", new GlobalOperationInfoAction()); + INFO_ACTIONS.put("zone-operation", new ZoneOperationInfoAction()); + INFO_ACTIONS.put("region-operation", new RegionOperationInfoAction()); + INFO_ACTIONS.put("license", new LicenseInfoAction()); + INFO_ACTIONS.put("address", new AddressInfoAction()); + INFO_ACTIONS.put("snapshot", new SnapshotInfoAction()); + INFO_ACTIONS.put("image", new ImageInfoAction()); + INFO_ACTIONS.put("disk", new DiskInfoAction()); + INFO_ACTIONS.put("network", new NetworkInfoAction()); + INFO_ACTIONS.put("subnetwork", new SubnetworkInfoAction()); + INFO_ACTIONS.put("instance", new InstanceInfoAction()); + LIST_ACTIONS.put("diskTypes", new ListDiskTypesAction()); + LIST_ACTIONS.put("machineTypes", new ListMachineTypesAction()); + LIST_ACTIONS.put("regions", new ListRegionsAction()); + LIST_ACTIONS.put("zones", new ListZonesAction()); + LIST_ACTIONS.put("global-operations", new ListGlobalOperationsAction()); + LIST_ACTIONS.put("zone-operations", new ListZoneOperationsAction()); + LIST_ACTIONS.put("region-operations", new ListRegionOperationsAction()); + LIST_ACTIONS.put("addresses", new ListAddressesAction()); + LIST_ACTIONS.put("snapshots", new ListSnapshotsAction()); + LIST_ACTIONS.put("images", new ListImagesAction()); + LIST_ACTIONS.put("disks", new ListDisksAction()); + LIST_ACTIONS.put("networks", new ListNetworksAction()); + LIST_ACTIONS.put("subnetworks", new ListSubnetworksAction()); + LIST_ACTIONS.put("instances", new ListInstancesAction()); + DELETE_ACTIONS.put("global-operation", new DeleteGlobalOperationAction()); + DELETE_ACTIONS.put("zone-operation", new DeleteZoneOperationAction()); + DELETE_ACTIONS.put("region-operation", new DeleteRegionOperationAction()); + DELETE_ACTIONS.put("address", new DeleteAddressAction()); + DELETE_ACTIONS.put("snapshot", new DeleteSnapshotAction()); + DELETE_ACTIONS.put("image", new DeleteImageAction()); + DELETE_ACTIONS.put("disk", new DeleteDiskAction()); + DELETE_ACTIONS.put("network", new DeleteNetworkAction()); + DELETE_ACTIONS.put("subnetwork", new DeleteSubnetworkAction()); + DELETE_ACTIONS.put("instance", new DeleteInstanceAction()); + ACTIONS.put("create", new ParentAction(CREATE_ACTIONS)); + ACTIONS.put("info", new ParentAction(INFO_ACTIONS)); + ACTIONS.put("list", new ParentAction(LIST_ACTIONS)); + ACTIONS.put("delete", new ParentAction(DELETE_ACTIONS)); + ACTIONS.put("get-serial-port", new GetSerialPortAction()); + ACTIONS.put("add-access-config", new AddAccessConfigAction()); + ACTIONS.put("delete-access-config", new DeleteAccessConfigAction()); + ACTIONS.put("attach-disk", new AttachDiskAction()); + ACTIONS.put("detach-disk", new DetachDiskAction()); + ACTIONS.put("set-disk-auto-delete", new SetDiskAutoDeleteAction()); + ACTIONS.put("set-machine-type", new SetMachineTypeAction()); + ACTIONS.put("set-tags", new SetTagsAction()); + ACTIONS.put("set-metadata", new SetMetadataAction()); + ACTIONS.put("set-scheduling-options", new SetSchedulingOptionsAction()); + ACTIONS.put("reset", new ResetInstanceAction()); + ACTIONS.put("stop", new StopInstanceAction()); + ACTIONS.put("start", new StartInstanceAction()); + } + + private static void printUsage() { + StringBuilder actionAndParams = new StringBuilder(); + for (Map.Entry entry : ACTIONS.entrySet()) { + actionAndParams.append("\n\t").append(entry.getKey()); + + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + actionAndParams.append(' ').append(param.replace("\n", "\n\t\t")); + } + } + System.out.printf("Usage: %s [] operation [entity] *%s%n", + ComputeExample.class.getSimpleName(), actionAndParams); + } + + @SuppressWarnings("unchecked") + public static void main(String... args) throws Exception { + if (args.length < 1) { + System.out.println("Missing required project id and action"); + printUsage(); + return; + } + ComputeOptions.Builder optionsBuilder = ComputeOptions.builder(); + ComputeAction action; + String actionName; + if (args.length >= 2 && !ACTIONS.containsKey(args[0])) { + actionName = args[1]; + optionsBuilder.projectId(args[0]); + action = ACTIONS.get(args[1]); + args = Arrays.copyOfRange(args, 2, args.length); + } else { + actionName = args[0]; + action = ACTIONS.get(args[0]); + args = Arrays.copyOfRange(args, 1, args.length); + } + if (action == null) { + System.out.println("Unrecognized action."); + printUsage(); + return; + } + Compute compute = optionsBuilder.build().service(); + Object request; + try { + request = action.parse(args); + } catch (IllegalArgumentException ex) { + System.out.println("Invalid input for action '" + actionName + "'. " + ex.getMessage()); + System.out.println("Expected: " + action.params()); + return; + } catch (Exception ex) { + System.out.println("Failed to parse request."); + ex.printStackTrace(); + return; + } + action.run(compute, request); + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateAddressDiskAndInstance.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateAddressDiskAndInstance.java new file mode 100644 index 000000000000..ea1857479fda --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateAddressDiskAndInstance.java @@ -0,0 +1,111 @@ +/* + * 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.examples.compute.snippets; + +import com.google.gcloud.compute.Address; +import com.google.gcloud.compute.AddressInfo; +import com.google.gcloud.compute.AttachedDisk; +import com.google.gcloud.compute.AttachedDisk.PersistentDiskConfiguration; +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.DiskId; +import com.google.gcloud.compute.DiskInfo; +import com.google.gcloud.compute.ImageDiskConfiguration; +import com.google.gcloud.compute.ImageId; +import com.google.gcloud.compute.InstanceId; +import com.google.gcloud.compute.InstanceInfo; +import com.google.gcloud.compute.MachineTypeId; +import com.google.gcloud.compute.NetworkId; +import com.google.gcloud.compute.NetworkInterface; +import com.google.gcloud.compute.NetworkInterface.AccessConfig; +import com.google.gcloud.compute.Operation; +import com.google.gcloud.compute.RegionAddressId; + +/** + * A snippet for Google Cloud Compute Engine showing how to create a disk and an address. The + * snippet also shows how to create a virtual machine instance using the created disk and address. + */ +public class CreateAddressDiskAndInstance { + + public static void main(String... args) throws InterruptedException { + // Create a service object + // Credentials are inferred from the environment. + Compute compute = ComputeOptions.defaultInstance().service(); + + // Create an external region address + RegionAddressId addressId = RegionAddressId.of("us-central1", "test-address"); + Operation operation = compute.create(AddressInfo.of(addressId)); + // Wait for operation to complete + while (!operation.isDone()) { + Thread.sleep(1000L); + } + // Check operation errors + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Address " + addressId + " was successfully created"); + } else { + // inspect operation.errors() + throw new RuntimeException("Address creation failed"); + } + + // Create a persistent disk + ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329"); + DiskId diskId = DiskId.of("us-central1-a", "test-disk"); + ImageDiskConfiguration diskConfiguration = ImageDiskConfiguration.of(imageId); + DiskInfo disk = DiskInfo.of(diskId, diskConfiguration); + operation = compute.create(disk); + // Wait for operation to complete + while (!operation.isDone()) { + Thread.sleep(1000L); + } + // Check operation errors + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Disk " + diskId + " was successfully created"); + } else { + // inspect operation.errors() + throw new RuntimeException("Disk creation failed"); + } + + // Create a virtual machine instance + Address externalIp = compute.getAddress(addressId); + InstanceId instanceId = InstanceId.of("us-central1-a", "test-instance"); + NetworkId networkId = NetworkId.of("default"); + PersistentDiskConfiguration attachConfiguration = + PersistentDiskConfiguration.builder(diskId).boot(true).build(); + AttachedDisk attachedDisk = AttachedDisk.of("dev0", attachConfiguration); + NetworkInterface networkInterface = NetworkInterface.builder(networkId) + .accessConfigurations(AccessConfig.of(externalIp.address())) + .build(); + MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1"); + InstanceInfo instance = + InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface); + operation = compute.create(instance); + // Wait for operation to complete + while (!operation.isDone()) { + Thread.sleep(1000L); + } + // Check operation errors + operation = operation.reload(); + if (operation.errors() == null) { + System.out.println("Instance " + instanceId + " was successfully created"); + } else { + // inspect operation.errors() + throw new RuntimeException("Instance creation failed"); + } + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateInstance.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateInstance.java new file mode 100644 index 000000000000..db72f25cc90e --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateInstance.java @@ -0,0 +1,54 @@ +/* + * 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.examples.compute.snippets; + +import com.google.gcloud.compute.AttachedDisk; +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.ImageId; +import com.google.gcloud.compute.Instance; +import com.google.gcloud.compute.InstanceId; +import com.google.gcloud.compute.InstanceInfo; +import com.google.gcloud.compute.MachineTypeId; +import com.google.gcloud.compute.NetworkId; +import com.google.gcloud.compute.NetworkInterface; +import com.google.gcloud.compute.Operation; + +/** + * A snippet for Google Cloud Compute Engine showing how to create a virtual machine instance. + */ +public class CreateInstance { + + public static void main(String... args) throws InterruptedException { + Compute compute = ComputeOptions.defaultInstance().service(); + ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329"); + NetworkId networkId = NetworkId.of("default"); + AttachedDisk attachedDisk = AttachedDisk.of(AttachedDisk.CreateDiskConfiguration.of(imageId)); + NetworkInterface networkInterface = NetworkInterface.of(networkId); + InstanceId instanceId = InstanceId.of("us-central1-a", "instance-name"); + MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1"); + Operation operation = + compute.create(InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface)); + while (!operation.isDone()) { + Thread.sleep(1000L); + } + if (operation.errors() == null) { + // use instance + Instance instance = compute.getInstance(instanceId); + } + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateSnapshot.java b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateSnapshot.java new file mode 100644 index 000000000000..a0684d63d9fb --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/gcloud/examples/compute/snippets/CreateSnapshot.java @@ -0,0 +1,48 @@ +/* + * 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.examples.compute.snippets; + +import com.google.gcloud.compute.Compute; +import com.google.gcloud.compute.ComputeOptions; +import com.google.gcloud.compute.Disk; +import com.google.gcloud.compute.DiskId; +import com.google.gcloud.compute.Operation; +import com.google.gcloud.compute.Snapshot; + +/** + * A snippet for Google Cloud Compute Engine showing how to create a snapshot of a disk if the disk + * exists. + */ +public class CreateSnapshot { + + public static void main(String... args) throws InterruptedException { + Compute compute = ComputeOptions.defaultInstance().service(); + DiskId diskId = DiskId.of("us-central1-a", "disk-name"); + Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields()); + if (disk != null) { + String snapshotName = "disk-name-snapshot"; + Operation operation = disk.createSnapshot(snapshotName); + while (!operation.isDone()) { + Thread.sleep(1000L); + } + if (operation.errors() == null) { + // use snapshot + Snapshot snapshot = compute.getSnapshot("disk-name-snapshot"); + } + } + } +}