organized google code into its own subdir

This commit is contained in:
adriancole 2013-04-28 21:54:40 -07:00
commit 98846381ba
155 changed files with 16605 additions and 0 deletions

View File

@ -0,0 +1,63 @@
jclouds Google Compute Engine Provider
======
Authenticating into the instances:
--------
User:
If no user is provided in GoogleComputeEngineTemplateOptions when launching an instance by default "jclouds" is used.
Credential:
GCE uses exclusively ssh keys to login into instances.
In order for an instance to be sshable a public key must be installed. Public keys are installed if they are present in the project or instance's metatada.
For an instance to be ssable one of the following must happen:
1 - the project's metadata has an adequately built "sshKeys" entry and a corresponding private key is provided in GoogleComputeEngineTemplateOptions when createNodesInGroup is called.
2 - an instance of GoogleComputeEngineTemplateOptions with an adequate public and private key is provided.
NOTE: if methods 2 is chosen the global project keys will not be installed in the instance.
Please refer to Google's documentation on how to form valid project wide ssh keys metadata entries.
FAQ:
--------
* Q. What is the identity for GCE?
A. the identity is the developer email which can be obtained from the admin GUI. Its usually something in the form: <my account id>@developer.gserviceaccount.com
* Q. What is the credential for GCE
A. the credential is a private key, in pem format. It can be extracted from the p12 keystore that is obtained when creating a "Service Account" (in the GUI: Google apis console > Api Access > Create another client ID > "Service Account"
* Q. How to convert a p12 keystore into a pem format jclouds Google Compute Engine can handle:
A.
1. Convert the p12 file into pem format (it will ask for the keystore password, which is usually "notasecret"):
openssl pkcs12 -in <my_keystore>.p12 -out <my_keystore>.pem -nodes
2. Extract only the pk and remove passphrase
openssl rsa -in <my_keystore>.pem -out <my_key>.pem
The last file (<my_key>.pem) should contain the pk that needs to be passed to `ContextBuilder.credential()` for the provider `google-compute-engine`.
Running the live tests:
--------
1. Place the following in your ~/.m2/settings.xml in a profile enabled when live:
```
<test.google-compute-engine.identity>YOUR_ACCOUNT_NUMBER@developer.gserviceaccount.com</test.google-compute-engine.identity>
<test.google-compute-engine.credential>-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQRRbRqVDtJLN1MO/xJoKqZuphDeBh5jIKueW3aNIiWs1XFcct+h
-- this text is literally from your <my_key>.pem
aH7xmpHSTbbXmQkuuv+z8EKijigprd/FoJpTX1f5/R+4wQ==
-----END RSA PRIVATE KEY-----</test.google-compute-engine.credential>
</properties>
```
2. mvn clean install -Plive

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to jclouds, Inc. (jclouds) under one or more
~ contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. jclouds licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>jclouds-labs-google</artifactId>
<version>1.7.0-SNAPSHOT</version>
</parent>
<!-- TODO: when out of labs, switch to org.jclouds.provider -->
<groupId>org.jclouds.labs</groupId>
<artifactId>google-compute-engine</artifactId>
<name>jclouds Google Compute Engine provider</name>
<description>jclouds components to access GoogleCompute</description>
<properties>
<test.google-compute-engine.identity>Email associated with the Google API client_id</test.google-compute-engine.identity>
<test.google-compute-engine.credential>Private key (PKCS12 file) associated with the Google API client_id</test.google-compute-engine.credential>
<test.google-compute-engine.api-version>v1beta13</test.google-compute-engine.api-version>
<test.google-compute-engine.build-version />
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${jclouds.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.labs</groupId>
<artifactId>oauth</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.jclouds.labs</groupId>
<artifactId>oauth</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${jclouds.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${jclouds.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${jclouds.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${jclouds.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${jclouds.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.google-compute-engine.identity>${test.google-compute-engine.identity}</test.google-compute-engine.identity>
<test.google-compute-engine.credential>${test.google-compute-engine.credential}</test.google-compute-engine.credential>
<test.google-compute-engine.api-version>${test.google-compute-engine.api-version}</test.google-compute-engine.api-version>
<test.google-compute-engine.build-version>${test.google-compute-engine.build-version}</test.google-compute-engine.build-version>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,139 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import java.io.Closeable;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.googlecomputeengine.features.DiskApi;
import org.jclouds.googlecomputeengine.features.FirewallApi;
import org.jclouds.googlecomputeengine.features.ImageApi;
import org.jclouds.googlecomputeengine.features.InstanceApi;
import org.jclouds.googlecomputeengine.features.KernelApi;
import org.jclouds.googlecomputeengine.features.MachineTypeApi;
import org.jclouds.googlecomputeengine.features.NetworkApi;
import org.jclouds.googlecomputeengine.features.OperationApi;
import org.jclouds.googlecomputeengine.features.ProjectApi;
import org.jclouds.googlecomputeengine.features.ZoneApi;
import org.jclouds.rest.annotations.Delegate;
import com.google.common.annotations.Beta;
/**
* Provides access to GoogleCompute.
* <p/>
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13">api doc</a>
*/
@Beta
public interface GoogleComputeEngineApi extends Closeable {
/**
* Provides access to Disk features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
DiskApi getDiskApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Firewall features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
FirewallApi getFirewallApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Image features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
ImageApi getImageApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Instance features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
InstanceApi getInstanceApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Kernel features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
KernelApi getKernelApiForProject(@PathParam("project") String projectName);
/**
* Provides access to MachineType features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
MachineTypeApi getMachineTypeApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Network features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
NetworkApi getNetworkApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Operation features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
OperationApi getOperationApiForProject(@PathParam("project") String projectName);
/**
* Provides access to Project features
*/
@Delegate
ProjectApi getProjectApi();
/**
* Provides access to Zone features
*
* @param projectName the name of the project
*/
@Delegate
@Path("/projects/{project}")
ZoneApi getZoneApiForProject(@PathParam("project") String projectName);
}

View File

@ -0,0 +1,109 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_PROVIDER_NAME;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.googlecomputeengine.compute.config.GoogleComputeEngineServiceContextModule;
import org.jclouds.googlecomputeengine.config.GoogleComputeEngineHttpApiModule;
import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
import org.jclouds.googlecomputeengine.config.OAuthModuleWithoutTypeAdapters;
import org.jclouds.oauth.v2.config.OAuthAuthenticationModule;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
*
* @author David Alves
*/
public class GoogleComputeEngineApiMetadata extends BaseHttpApiMetadata<GoogleComputeEngineApi> {
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public GoogleComputeEngineApiMetadata() {
this(new Builder());
}
protected GoogleComputeEngineApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseHttpApiMetadata.defaultProperties();
properties.put("oauth.endpoint", "https://accounts.google.com/o/oauth2/token");
properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
properties.put(PROPERTY_SESSION_INTERVAL, 3600);
properties.setProperty(TEMPLATE, "osFamily=GCEL,osVersionMatches=1[012].[01][04],locationId=us-central1-a," +
"loginUser=jclouds");
properties.put(OPERATION_COMPLETE_INTERVAL, 500);
properties.put(OPERATION_COMPLETE_TIMEOUT, 600000);
return properties;
}
public static class Builder extends BaseHttpApiMetadata.Builder<GoogleComputeEngineApi, Builder> {
protected Builder() {
id(GCE_PROVIDER_NAME)
.name("Google Compute Engine Api")
.identityName("Email associated with the Google API client_id")
.credentialName("Private key literal associated with the Google API client_id")
.documentation(URI.create("https://developers.google.com/compute/docs"))
.version("v1beta13")
.defaultEndpoint("https://www.googleapis.com/compute/v1beta13")
.defaultProperties(GoogleComputeEngineApiMetadata.defaultProperties())
.view(typeToken(ComputeServiceContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(GoogleComputeEngineHttpApiModule.class)
.add(GoogleComputeEngineParserModule.class)
.add(OAuthAuthenticationModule.class)
.add(OAuthModuleWithoutTypeAdapters.class)
.add(GoogleComputeEngineServiceContextModule.class)
.build());
}
@Override
public GoogleComputeEngineApiMetadata build() {
return new GoogleComputeEngineApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
}
}

View File

@ -0,0 +1,58 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import com.google.common.annotations.Beta;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
/**
* @author David Alves
*/
public interface GoogleComputeEngineConstants {
public static final String GCE_PROVIDER_NAME = "google-compute-engine";
/**
* The name of the project that keeps public resources.
*/
public static final String GOOGLE_PROJECT = "google";
public static final String COMPUTE_SCOPE = "https://www.googleapis.com/auth/compute";
public static final String COMPUTE_READONLY_SCOPE = "https://www.googleapis.com/auth/compute.readonly";
/**
* The total time, in msecs, to wait for an operation to complete.
*/
@Beta
public static final String OPERATION_COMPLETE_TIMEOUT = "jclouds.google-compute-engine.operation-complete-timeout";
/**
* The interval, in msecs, between calls to check whether an operation has completed.
*/
@Beta
public static final String OPERATION_COMPLETE_INTERVAL = "jclouds.google-compute-engine.operation-complete-interval";
public static final Location GOOGLE_PROVIDER_LOCATION = new LocationBuilder().scope(LocationScope.PROVIDER).id
(GCE_PROVIDER_NAME).description(GCE_PROVIDER_NAME).build();
}

View File

@ -0,0 +1,184 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListeningExecutorService;
import org.jclouds.Constants;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetImageStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.http.HttpResponse;
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
import static org.jclouds.util.Predicates2.retry;
/**
* @author David Alves
*/
public class GoogleComputeEngineService extends BaseComputeService {
private final Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups;
private final GroupNamingConvention.Factory namingConvention;
private final GoogleComputeEngineApi api;
private final Supplier<String> project;
private final Predicate<AtomicReference<Operation>> operationDonePredicate;
private final long operationCompleteCheckInterval;
private final long operationCompleteCheckTimeout;
@Inject
protected GoogleComputeEngineService(ComputeServiceContext context,
Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations,
ListNodesStrategy listNodesStrategy,
GetImageStrategy getImageStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider,
@Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>>
nodeRunning,
@Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>>
nodeTerminated,
@Named(TIMEOUT_NODE_SUSPENDED)
Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory,
PersistNodeCredentials persistNodeCredentials,
ComputeServiceConstants.Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension,
Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups,
GroupNamingConvention.Factory namingConvention,
GoogleComputeEngineApi api,
@UserProject Supplier<String> project,
Predicate<AtomicReference<Operation>> operationDonePredicate,
@Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
@Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
super(context, credentialStore, images, hardwareProfiles, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, userExecutor, imageExtension);
this.findOrphanedGroups = checkNotNull(findOrphanedGroups, "find orphaned groups function");
this.namingConvention = checkNotNull(namingConvention, "naming convention factory");
this.api = checkNotNull(api, "google compute api");
this.project = checkNotNull(project, "user project name");
this.operationDonePredicate = checkNotNull(operationDonePredicate, "operation completed predicate");
this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
"operation completed check interval");
this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
"operation completed check timeout");
}
@Override
protected synchronized void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) {
Set<String> orphanedGroups = findOrphanedGroups.apply(deadNodes);
for (String orphanedGroup : orphanedGroups) {
cleanUpNetworksAndFirewallsForGroup(orphanedGroup);
}
}
protected void cleanUpNetworksAndFirewallsForGroup(String groupName) {
String resourceName = namingConvention.create().sharedNameForGroup(groupName);
AtomicReference<Operation> operation = new AtomicReference<Operation>(api.getFirewallApiForProject(project.get())
.delete(resourceName));
retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
MILLISECONDS).apply(operation);
if (operation.get().getHttpError().isPresent()) {
HttpResponse response = operation.get().getHttpError().get();
logger.warn("delete orphaned firewall failed. Http Error Code: " + response.getStatusCode() +
" HttpError: " + response.getMessage());
}
operation = new AtomicReference<Operation>(api.getNetworkApiForProject(project.get()).delete(resourceName));
retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
MILLISECONDS).apply(operation);
if (operation.get().getHttpError().isPresent()) {
HttpResponse response = operation.get().getHttpError().get();
logger.warn("delete orphaned network failed. Http Error Code: " + response.getStatusCode() +
" HttpError: " + response.getMessage());
}
}
/**
* returns template options, except of type {@link org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions}.
*/
@Override
public GoogleComputeEngineTemplateOptions templateOptions() {
return GoogleComputeEngineTemplateOptions.class.cast(super.templateOptions());
}
}

View File

@ -0,0 +1,265 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.UncheckedTimeoutException;
import com.google.inject.Inject;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Zone;
import org.jclouds.http.HttpResponse;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import javax.inject.Named;
import java.net.URI;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.contains;
import static com.google.common.collect.Iterables.filter;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROJECT;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
import static org.jclouds.util.Predicates2.retry;
/**
* @author David Alves
*/
public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<Instance, MachineType, Image, Zone> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final GoogleComputeEngineApi api;
private final Supplier<String> userProject;
private final Function<TemplateOptions, ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions;
private final Predicate<AtomicReference<Operation>> retryOperationDonePredicate;
private final long operationCompleteCheckInterval;
private final long operationCompleteCheckTimeout;
@Inject
public GoogleComputeEngineServiceAdapter(GoogleComputeEngineApi api,
@UserProject Supplier<String> userProject,
Function<TemplateOptions,
ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions,
Predicate<AtomicReference<Operation>> operationDonePredicate,
@Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
@Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
this.api = checkNotNull(api, "google compute api");
this.userProject = checkNotNull(userProject, "user project name");
this.metatadaFromTemplateOptions = checkNotNull(metatadaFromTemplateOptions,
"metadata from template options function");
this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
"operation completed check interval");
this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
"operation completed check timeout");
this.retryOperationDonePredicate = retry(operationDonePredicate, operationCompleteCheckTimeout,
operationCompleteCheckInterval, TimeUnit.MILLISECONDS);
}
@Override
public NodeAndInitialCredentials<Instance> createNodeWithGroupEncodedIntoName(
final String group, final String name, Template template) {
checkNotNull(template, "template");
GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone();
checkState(options.getNetwork().isPresent(), "network was not present in template options");
Hardware hardware = checkNotNull(template.getHardware(), "hardware must be set");
URI machineType = checkNotNull(hardware.getUri(), "hardware uri must be set");
InstanceTemplate instanceTemplate = InstanceTemplate.builder()
.forMachineType(machineType);
if (options.isEnableNat()) {
instanceTemplate.addNetworkInterface(options.getNetwork().get(), Type.ONE_TO_ONE_NAT);
} else {
instanceTemplate.addNetworkInterface(options.getNetwork().get());
}
LoginCredentials credentials = getFromImageAndOverrideIfRequired(template.getImage(), options);
ImmutableMap.Builder<String, String> metadataBuilder = metatadaFromTemplateOptions.apply(options);
instanceTemplate.metadata(metadataBuilder.build());
instanceTemplate.tags(options.getTags());
instanceTemplate.serviceAccounts(options.getServiceAccounts());
instanceTemplate.image(checkNotNull(template.getImage().getUri(), "image URI is null"));
Operation operation = api.getInstanceApiForProject(userProject.get())
.createInZone(name, instanceTemplate, template.getLocation().getId());
if (options.shouldBlockUntilRunning()) {
waitOperationDone(operation);
}
// some times the newly created instances are not immediately returned
AtomicReference<Instance> instance = new AtomicReference<Instance>();
retry(new Predicate<AtomicReference<Instance>>() {
@Override
public boolean apply(AtomicReference<Instance> input) {
input.set(api.getInstanceApiForProject(userProject.get()).get(name));
return input.get() != null;
}
}, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance);
return new NodeAndInitialCredentials<Instance>(instance.get(), name, credentials);
}
@Override
public Iterable<MachineType> listHardwareProfiles() {
return api.getMachineTypeApiForProject(userProject.get()).list().concat();
}
@Override
public Iterable<Image> listImages() {
return ImmutableSet.<Image>builder()
.addAll(api.getImageApiForProject(userProject.get()).list().concat())
.addAll(api.getImageApiForProject(GOOGLE_PROJECT).list().concat())
.build();
}
@Override
public Image getImage(String id) {
return Objects.firstNonNull(api.getImageApiForProject(userProject.get()).get(id),
api.getImageApiForProject(GOOGLE_PROJECT).get(id));
}
@Override
public Iterable<Zone> listLocations() {
return api.getZoneApiForProject(userProject.get()).list().concat();
}
@Override
public Instance getNode(String name) {
return api.getInstanceApiForProject(userProject.get()).get(name);
}
@Override
public Iterable<Instance> listNodes() {
return api.getInstanceApiForProject(userProject.get()).list().concat();
}
@Override
public Iterable<Instance> listNodesByIds(final Iterable<String> ids) {
return filter(listNodes(), new Predicate<Instance>() {
@Override
public boolean apply(Instance instance) {
return contains(ids, instance.getName());
}
});
}
@Override
public void destroyNode(final String name) {
waitOperationDone(api.getInstanceApiForProject(userProject.get()).delete(name));
}
@Override
public void rebootNode(String name) {
throw new UnsupportedOperationException("reboot is not supported by GCE");
}
@Override
public void resumeNode(String name) {
throw new UnsupportedOperationException("resume is not supported by GCE");
}
@Override
public void suspendNode(String name) {
throw new UnsupportedOperationException("suspend is not supported by GCE");
}
private LoginCredentials getFromImageAndOverrideIfRequired(org.jclouds.compute.domain.Image image,
GoogleComputeEngineTemplateOptions options) {
LoginCredentials defaultCredentials = image.getDefaultCredentials();
String[] keys = defaultCredentials.getPrivateKey().split(":");
String publicKey = keys[0];
String privateKey = keys[1];
LoginCredentials.Builder credentialsBuilder = defaultCredentials.toBuilder();
credentialsBuilder.privateKey(privateKey);
// LoginCredentials from image stores the public key along with the private key in the privateKey field
// @see GoogleComputePopulateDefaultLoginCredentialsForImageStrategy
// so if options doesn't have a public key set we set it from the default
if (options.getPublicKey() == null) {
options.authorizePublicKey(publicKey);
}
if (options.hasLoginPrivateKeyOption()) {
credentialsBuilder.privateKey(options.getPrivateKey());
}
if (options.getLoginUser() != null) {
credentialsBuilder.identity(options.getLoginUser());
}
if (options.hasLoginPasswordOption()) {
credentialsBuilder.password(options.getLoginPassword());
}
if (options.shouldAuthenticateSudo() != null) {
credentialsBuilder.authenticateSudo(options.shouldAuthenticateSudo());
}
LoginCredentials credentials = credentialsBuilder.build();
options.overrideLoginCredentials(credentials);
return credentials;
}
private void waitOperationDone(Operation operation) {
AtomicReference<Operation> operationRef = new AtomicReference<Operation>(operation);
// wait for the operation to complete
if (!retryOperationDonePredicate.apply(operationRef)) {
throw new UncheckedTimeoutException("operation did not reach DONE state" + operationRef.get());
}
// check if the operation failed
if (operationRef.get().getHttpError().isPresent()) {
HttpResponse response = operationRef.get().getHttpError().get();
throw new IllegalStateException("operation failed. Http Error Code: " + response.getStatusCode() +
" HttpError: " + response.getMessage());
}
}
}

View File

@ -0,0 +1,194 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.config;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.domain.Location;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineService;
import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineServiceAdapter;
import org.jclouds.googlecomputeengine.compute.functions.BuildInstanceMetadata;
import org.jclouds.googlecomputeengine.compute.functions.GoogleComputeEngineImageToImage;
import org.jclouds.googlecomputeengine.compute.functions.InstanceToNodeMetadata;
import org.jclouds.googlecomputeengine.compute.functions.MachineTypeToHardware;
import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadNodes;
import org.jclouds.googlecomputeengine.compute.functions.ZoneToLocation;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
import org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.googlecomputeengine.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.googlecomputeengine.compute.strategy.UseNodeCredentialsButOverrideFromTemplate;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.domain.Zone;
import javax.inject.Singleton;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.uniqueIndex;
/**
* @author David Alves
*/
public class GoogleComputeEngineServiceContextModule
extends ComputeServiceAdapterContextModule<Instance, MachineType, Image, Zone> {
@Override
protected void configure() {
super.configure();
bind(ComputeService.class).to(GoogleComputeEngineService.class);
bind(new TypeLiteral<ComputeServiceAdapter<Instance, MachineType, Image, Zone>>() {})
.to(GoogleComputeEngineServiceAdapter.class);
bind(new TypeLiteral<Function<Instance, NodeMetadata>>() {})
.to(InstanceToNodeMetadata.class);
bind(new TypeLiteral<Function<MachineType, Hardware>>() {})
.to(MachineTypeToHardware.class);
bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {})
.to(GoogleComputeEngineImageToImage.class);
bind(new TypeLiteral<Function<Zone, Location>>() {})
.to(ZoneToLocation.class);
bind(new TypeLiteral<Function<TemplateOptions, ImmutableMap.Builder<String, String>>>() {})
.to(BuildInstanceMetadata.class);
bind(org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy.class)
.to(PopulateDefaultLoginCredentialsForImageStrategy.class);
bind(org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
CreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
bind(TemplateOptions.class).to(GoogleComputeEngineTemplateOptions.class);
bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Set<String>>>() {})
.to(OrphanedGroupsFromDeadNodes.class);
bind(new TypeLiteral<Predicate<String>>() {}).to(AllNodesInGroupTerminated.class);
bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class);
install(new LocationsFromComputeServiceAdapterModule<Instance, MachineType, Image, Zone>() {});
}
@Provides
@Singleton
@Memoized
public Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>> provideImagesMap(
final Supplier<Set<? extends org.jclouds.compute.domain.Image>> images) {
return new Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>>() {
@Override
public Map<URI, ? extends org.jclouds.compute.domain.Image> get() {
return uniqueIndex(images.get(), new Function<org.jclouds.compute.domain.Image, URI>() {
@Override
public URI apply(org.jclouds.compute.domain.Image input) {
return input.getUri();
}
});
}
};
}
@Provides
@Singleton
@Memoized
public Supplier<Map<URI, ? extends Hardware>> provideHardwaresMap(
final Supplier<Set<? extends Hardware>> hardwares) {
return new Supplier<Map<URI, ? extends Hardware>>() {
@Override
public Map<URI, ? extends Hardware> get() {
return uniqueIndex(hardwares.get(), new Function<Hardware, URI>() {
@Override
public URI apply(Hardware input) {
return input.getUri();
}
});
}
};
}
@Provides
@Singleton
@Memoized
public Supplier<Map<URI, ? extends Location>> provideLocations(
final GoogleComputeEngineApi api, final Function<Zone, Location> zoneToLocation,
final @UserProject Supplier<String> userProject) {
return new Supplier<Map<URI, ? extends Location>>() {
@Override
public Map<URI, ? extends Location> get() {
return uniqueIndex(transform(api.getZoneApiForProject(userProject.get()).list().concat(), zoneToLocation),
new Function<Location, URI>() {
@Override
public URI apply(Location input) {
return (URI) input.getMetadata().get("selfLink");
}
});
}
};
}
@Override
protected Optional<ImageExtension> provideImageExtension(Injector i) {
return Optional.absent();
}
@VisibleForTesting
public static final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus =
ImmutableMap.<Instance.Status, NodeMetadata.Status>builder()
.put(Instance.Status.PROVISIONING, NodeMetadata.Status.PENDING)
.put(Instance.Status.STAGING, NodeMetadata.Status.PENDING)
.put(Instance.Status.RUNNING, NodeMetadata.Status.RUNNING)
.put(Instance.Status.STOPPING, NodeMetadata.Status.PENDING)
.put(Instance.Status.STOPPED, NodeMetadata.Status.SUSPENDED)
.put(Instance.Status.TERMINATED, NodeMetadata.Status.TERMINATED).build();
@Singleton
@Provides
protected Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus() {
return toPortableNodeStatus;
}
}

View File

@ -0,0 +1,50 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import org.jclouds.compute.options.TemplateOptions;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
/**
* Prepares metadata from the provided TemplateOptions
*
* @author David Alves
*/
@Singleton
public class BuildInstanceMetadata implements Function<TemplateOptions, ImmutableMap.Builder<String, String>> {
@Override
public ImmutableMap.Builder apply(TemplateOptions input) {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
if (input.getPublicKey() != null) {
builder.put("sshKeys", format("%s:%s %s@localhost", checkNotNull(input.getLoginUser(),
"loginUser cannot be null"), input.getPublicKey(), input.getLoginUser()));
}
builder.putAll(input.getUserMetadata());
return builder;
}
}

View File

@ -0,0 +1,82 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.googlecomputeengine.domain.Image;
import java.util.List;
import static com.google.common.base.Joiner.on;
import static com.google.common.collect.Iterables.getLast;
import static com.google.common.collect.Iterables.limit;
import static com.google.common.collect.Iterables.skip;
import static org.jclouds.compute.domain.Image.Status;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
/**
* Transforms a google compute domain specific image to a generic Image object.
*
* @author David Alves
*/
public class GoogleComputeEngineImageToImage implements Function<Image, org.jclouds.compute.domain.Image> {
@Override
public org.jclouds.compute.domain.Image apply(Image image) {
ImageBuilder builder = new ImageBuilder()
.id(image.getName())
.name(image.getName())
.providerId(image.getId())
.description(image.getDescription().orNull())
.status(Status.AVAILABLE)
.location(GOOGLE_PROVIDER_LOCATION)
.uri(image.getSelfLink());
List<String> splits = Lists.newArrayList(image.getName().split("-"));
OperatingSystem.Builder osBuilder = defaultOperatingSystem(image);
if (splits == null || splits.size() == 0 || splits.size() < 3) {
return builder.operatingSystem(osBuilder.build()).build();
}
OsFamily family = OsFamily.fromValue(splits.get(0));
if (family != OsFamily.UNRECOGNIZED) {
osBuilder.family(family);
}
String version = on(".").join(limit(skip(splits, 1), splits.size() - 2));
osBuilder.version(version);
builder.version(getLast(splits));
return builder.operatingSystem(osBuilder.build()).build();
}
private OperatingSystem.Builder defaultOperatingSystem(Image image) {
return OperatingSystem.builder()
.family(OsFamily.LINUX)
.is64Bit(true)
.description(image.getName());
}
}

View File

@ -0,0 +1,114 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.domain.Location;
import org.jclouds.googlecomputeengine.domain.Instance;
import javax.inject.Inject;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Transforms a google compute domain Instance into a generic NodeMetatada object.
*
* @author David Alves
*/
public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> {
private final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus;
private final GroupNamingConvention nodeNamingConvention;
private final Supplier<Map<URI, ? extends Image>> images;
private final Supplier<Map<URI, ? extends Hardware>> hardwares;
private final Supplier<Map<URI, ? extends Location>> locations;
@Inject
public InstanceToNodeMetadata(Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus,
GroupNamingConvention.Factory namingConvention,
@Memoized Supplier<Map<URI, ? extends Image>> images,
@Memoized Supplier<Map<URI, ? extends Hardware>> hardwares,
@Memoized Supplier<Map<URI, ? extends Location>> locations) {
this.toPortableNodeStatus = toPortableNodeStatus;
this.nodeNamingConvention = namingConvention.createWithoutPrefix();
this.images = images;
this.hardwares = hardwares;
this.locations = locations;
}
@Override
public NodeMetadata apply(Instance input) {
Map<URI, ? extends Image> imagesMap = images.get();
Image image = checkNotNull(imagesMap.get(checkNotNull(input.getImage(), "image")),
"no image for %s. images: %s", input.getImage(), imagesMap.values());
return new NodeMetadataBuilder()
.id(input.getName())
.name(input.getName())
.providerId(input.getId())
.hostname(input.getName())
.imageId(image.getId())
.location(checkNotNull(locations.get().get(input.getZone()), "location for %s", input.getZone()))
.hardware(checkNotNull(hardwares.get().get(input.getMachineType()), "hardware type for %s",
input.getMachineType().toString()))
.operatingSystem(image.getOperatingSystem())
.status(toPortableNodeStatus.get(input.getStatus()))
.tags(input.getTags())
.uri(input.getSelfLink())
.userMetadata(input.getMetadata())
.group(nodeNamingConvention.groupInUniqueNameOrNull(input.getName()))
.privateAddresses(collectPrivateAddresses(input))
.publicAddresses(collectPublicAddresses(input))
.build();
}
private Set<String> collectPrivateAddresses(Instance input) {
ImmutableSet.Builder<String> privateAddressesBuilder = ImmutableSet.builder();
for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
if (networkInterface.getNetworkIP().isPresent()) {
privateAddressesBuilder.add(networkInterface.getNetworkIP().get());
}
}
return privateAddressesBuilder.build();
}
private Set<String> collectPublicAddresses(Instance input) {
ImmutableSet.Builder<String> publicAddressesBuilder = ImmutableSet.builder();
for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) {
for (Instance.NetworkInterface.AccessConfig accessConfig : networkInterface.getAccessConfigs()) {
if (accessConfig.getNatIP().isPresent()) {
publicAddressesBuilder.add(accessConfig.getNatIP().get());
}
}
}
return publicAddressesBuilder.build();
}
}

View File

@ -0,0 +1,60 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.googlecomputeengine.domain.MachineType;
/**
* Transforms a google compute domain specific machine type to a generic Hardware object.
*
* @author David Alves
*/
public class MachineTypeToHardware implements Function<MachineType, Hardware> {
@Override
public Hardware apply(MachineType input) {
return new HardwareBuilder()
.id(input.getName())
.name(input.getName())
.hypervisor("kvm")
.processor(new Processor(input.getGuestCpus(), 1.0))
.providerId(input.getId())
.ram(input.getMemoryMb())
.uri(input.getSelfLink())
.volumes(collectVolumes(input))
.build();
}
private Iterable<Volume> collectVolumes(MachineType input) {
ImmutableSet.Builder<Volume> volumes = ImmutableSet.builder();
for (MachineType.EphemeralDisk disk : input.getEphemeralDisks()) {
volumes.add(new VolumeImpl(null, Volume.Type.LOCAL, new Integer(disk.getDiskGb()).floatValue(), null, true,
false));
}
return volumes.build();
}
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import org.jclouds.compute.domain.NodeMetadata;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Set;
/**
* @author David Alves
*/
@Singleton
public class OrphanedGroupsFromDeadNodes implements Function<Set<? extends NodeMetadata>, Set<String>> {
private final Predicate<String> isOrphanedGroupPredicate;
@Inject
public OrphanedGroupsFromDeadNodes(Predicate<String> isOrphanedGroupPredicate) {
this.isOrphanedGroupPredicate = isOrphanedGroupPredicate;
}
@Override
public Set<String> apply(Set<? extends NodeMetadata> deadNodes) {
Set<String> groups = Sets.newLinkedHashSet();
for (NodeMetadata deadNode : deadNodes) {
groups.add(deadNode.getGroup());
}
Set<String> orphanedGroups = Sets.newLinkedHashSet();
for (String group : groups) {
if (isOrphanedGroupPredicate.apply(group)) {
orphanedGroups.add(group);
}
}
return orphanedGroups;
}
}

View File

@ -0,0 +1,49 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.googlecomputeengine.domain.Zone;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION;
/**
* Transforms a google compute domain specific zone to a generic Zone object.
*
* @author David Alves
*/
public class ZoneToLocation implements Function<Zone, Location> {
@Override
public Location apply(Zone input) {
return new LocationBuilder()
.description(input.getDescription().orNull())
.metadata(ImmutableMap.of("selfLink", (Object) checkNotNull(input.getSelfLink(), "zone URI")))
.id(input.getName())
.scope(LocationScope.ZONE)
.parent(GOOGLE_PROVIDER_LOCATION)
.build();
}
}

View File

@ -0,0 +1,280 @@
package org.jclouds.googlecomputeengine.compute.options;
import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.scriptbuilder.domain.Statement;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Optional.fromNullable;
import static org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
/**
* Instance options specific to Google Compute Engine.
*
* @author David Alves
*/
public class GoogleComputeEngineTemplateOptions extends TemplateOptions {
private Optional<URI> network = Optional.absent();
private Optional<String> networkName = Optional.absent();
private Set<Instance.ServiceAccount> serviceAccounts = Sets.newLinkedHashSet();
private boolean enableNat = true;
@Override
public GoogleComputeEngineTemplateOptions clone() {
GoogleComputeEngineTemplateOptions options = new GoogleComputeEngineTemplateOptions();
copyTo(options);
return options;
}
@Override
public void copyTo(TemplateOptions to) {
super.copyTo(to);
if (to instanceof GoogleComputeEngineTemplateOptions) {
GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to);
eTo.network(getNetwork().orNull());
eTo.network(getNetworkName().orNull());
eTo.serviceAccounts(getServiceAccounts());
eTo.enableNat(isEnableNat());
}
}
/**
* @see #getNetworkName()
*/
public GoogleComputeEngineTemplateOptions network(String networkName) {
this.networkName = fromNullable(networkName);
return this;
}
/**
* @see #getNetwork()
*/
public GoogleComputeEngineTemplateOptions network(URI network) {
this.network = fromNullable(network);
return this;
}
/**
* @see #getServiceAccounts()
* @see ServiceAccount
*/
public GoogleComputeEngineTemplateOptions addServiceAccount(ServiceAccount serviceAccout) {
this.serviceAccounts.add(serviceAccout);
return this;
}
/**
* @see #getServiceAccounts()
* @see ServiceAccount
*/
public GoogleComputeEngineTemplateOptions serviceAccounts(Set<ServiceAccount> serviceAccounts) {
this.serviceAccounts = Sets.newLinkedHashSet(serviceAccounts);
return this;
}
/**
* @see #isEnableNat()
*/
public GoogleComputeEngineTemplateOptions enableNat(boolean enableNat) {
this.enableNat = enableNat;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions blockOnPort(int port, int seconds) {
return GoogleComputeEngineTemplateOptions.class.cast(super.blockOnPort(port, seconds));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions inboundPorts(int... ports) {
return GoogleComputeEngineTemplateOptions.class.cast(super.inboundPorts(ports));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions authorizePublicKey(String publicKey) {
return GoogleComputeEngineTemplateOptions.class.cast(super.authorizePublicKey(publicKey));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions installPrivateKey(String privateKey) {
return GoogleComputeEngineTemplateOptions.class.cast(super.installPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions blockUntilRunning(boolean blockUntilRunning) {
return GoogleComputeEngineTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions dontAuthorizePublicKey() {
return GoogleComputeEngineTemplateOptions.class.cast(super.dontAuthorizePublicKey());
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions nameTask(String name) {
return GoogleComputeEngineTemplateOptions.class.cast(super.nameTask(name));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions runAsRoot(boolean runAsRoot) {
return GoogleComputeEngineTemplateOptions.class.cast(super.runAsRoot(runAsRoot));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions runScript(Statement script) {
return GoogleComputeEngineTemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) {
return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions overrideLoginPassword(String password) {
return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginPassword(password));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions overrideLoginPrivateKey(String privateKey) {
return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions overrideLoginUser(String loginUser) {
return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginUser(loginUser));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) {
return GoogleComputeEngineTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions userMetadata(Map<String, String> userMetadata) {
return GoogleComputeEngineTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions userMetadata(String key, String value) {
return GoogleComputeEngineTemplateOptions.class.cast(super.userMetadata(key, value));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions tags(Iterable<String> tags) {
return GoogleComputeEngineTemplateOptions.class.cast(super.tags(tags));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions wrapInInitScript(boolean wrapInInitScript) {
return GoogleComputeEngineTemplateOptions.class.cast(super.wrapInInitScript(wrapInInitScript));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions runScript(String script) {
return GoogleComputeEngineTemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public GoogleComputeEngineTemplateOptions blockOnComplete(boolean blockOnComplete) {
return GoogleComputeEngineTemplateOptions.class.cast(super.blockOnComplete(blockOnComplete));
}
/**
* @return the ServiceAccounts to enable in the instances.
*/
public Set<Instance.ServiceAccount> getServiceAccounts() {
return serviceAccounts;
}
/**
* @return the URI of an existing network the instances will be attached to. If no network URI or network name are
* provided a new network will be created for the project.
*/
public Optional<URI> getNetwork() {
return network;
}
/**
* @return the name of an existing network the instances will be attached to, the network is assumed to belong to
* user's project. If no network URI network name are provided a new network will be created for the project.
*/
public Optional<String> getNetworkName() {
return networkName;
}
/**
* @return whether an AccessConfig with Type ONE_TO_ONE_NAT should be enabled in the instances. When true
* instances will have a NAT address that will be publicly accessible.
*/
public boolean isEnableNat() {
return enableNat;
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.predicates;
import com.google.common.base.Predicate;
import org.jclouds.compute.ComputeService;
import javax.inject.Inject;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.all;
import static com.google.common.collect.Sets.filter;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
import static org.jclouds.compute.predicates.NodePredicates.all;
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
/**
* @author David Alves
*/
@Singleton
public class AllNodesInGroupTerminated implements Predicate<String> {
private final ComputeService computeService;
@Inject
public AllNodesInGroupTerminated(ComputeService computeService) {
this.computeService = checkNotNull(computeService, "compute service");
}
@Override
public boolean apply(String groupName) {
return all(filter(computeService.listNodesDetailsMatching(all()), inGroup(groupName)), TERMINATED);
}
}

View File

@ -0,0 +1,196 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.strategy;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import org.jclouds.Constants;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.of;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
import static org.jclouds.util.Predicates2.retry;
/**
* @author David Alves
*/
public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet {
public static final String EXTERIOR_RANGE = "0.0.0.0/0";
public static final String DEFAULT_INTERNAL_NETWORK_RANGE = "10.0.0.0/8";
private final GoogleComputeEngineApi api;
private final Supplier<String> userProject;
private final Predicate<AtomicReference<Operation>> operationDonePredicate;
private final long operationCompleteCheckInterval;
private final long operationCompleteCheckTimeout;
@Inject
protected CreateNodesWithGroupEncodedIntoNameThenAddToSet(
CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
@Named(Constants.PROPERTY_USER_THREADS)
ListeningExecutorService userExecutor,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
GoogleComputeEngineApi api,
@UserProject Supplier<String> userProject,
Predicate<AtomicReference<Operation>> operationDonePredicate,
@Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
@Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.api = checkNotNull(api, "google compute api");
this.userProject = checkNotNull(userProject, "user project name");
this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
"operation completed check interval");
this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
"operation completed check timeout");
this.operationDonePredicate = operationDonePredicate;
}
@Override
public synchronized Map<?, ListenableFuture<Void>> execute(String group, int count,
Template template,
Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes,
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
String sharedResourceName = namingConvention.create().sharedNameForGroup(group);
Template mutableTemplate = template.clone();
GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class.cast(mutableTemplate
.getOptions());
assert template.getOptions().equals(templateOptions) : "options didn't clone properly";
// get or create the network and create a firewall with the users configuration
Network network = getOrCreateNetwork(templateOptions, sharedResourceName);
getOrCreateFirewall(templateOptions, network, sharedResourceName);
templateOptions.network(network.getSelfLink());
return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
}
/**
* Try and find a network either previously created by jclouds or user defined.
*/
private Network getOrCreateNetwork(GoogleComputeEngineTemplateOptions templateOptions, String sharedResourceName) {
String networkName = templateOptions.getNetworkName().or(sharedResourceName);
// check if the network was previously created (cache???)
Network network = api.getNetworkApiForProject(userProject.get()).get(networkName);
if (network != null) {
return network;
} else if (templateOptions.getNetwork().isPresent()) {
throw new IllegalArgumentException("requested network " + networkName + " does not exist");
}
AtomicReference<Operation> operation = new AtomicReference<Operation>(api.getNetworkApiForProject(userProject
.get()).createInIPv4Range(sharedResourceName, DEFAULT_INTERNAL_NETWORK_RANGE));
retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
MILLISECONDS).apply(operation);
checkState(!operation.get().getHttpError().isPresent(),"Could not create network, operation failed" + operation);
return checkNotNull(api.getNetworkApiForProject(userProject.get()).get(sharedResourceName),
"no network with name %s was found", sharedResourceName);
}
/**
* Tries to find if a firewall already exists for this group, if not it creates one.
*
* @see org.jclouds.googlecomputeengine.features.FirewallAsyncApi#patch(String, org.jclouds.googlecomputeengine.options.FirewallOptions)
*/
private void getOrCreateFirewall(GoogleComputeEngineTemplateOptions templateOptions, Network network,
String sharedResourceName) {
Firewall firewall = api.getFirewallApiForProject(userProject.get()).get(sharedResourceName);
if (firewall != null) {
return;
}
ImmutableSet.Builder<Firewall.Rule> rules = ImmutableSet.builder();
Firewall.Rule.Builder tcpRule = Firewall.Rule.builder();
tcpRule.IPProtocol(Firewall.Rule.IPProtocol.TCP);
Firewall.Rule.Builder udpRule = Firewall.Rule.builder();
udpRule.IPProtocol(Firewall.Rule.IPProtocol.UDP);
for (Integer port : templateOptions.getInboundPorts()) {
tcpRule.addPort(port);
udpRule.addPort(port);
}
rules.add(tcpRule.build());
rules.add(udpRule.build());
FirewallOptions options = new FirewallOptions()
.name(sharedResourceName)
.network(network.getSelfLink())
.sourceTags(templateOptions.getTags())
.allowedRules(rules.build())
.sourceRanges(of(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE));
AtomicReference<Operation> operation = new AtomicReference<Operation>(api.getFirewallApiForProject(userProject
.get()).createInNetwork(
sharedResourceName,
network.getSelfLink(),
options));
retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
MILLISECONDS).apply(operation);
checkState(!operation.get().getHttpError().isPresent(),"Could not create firewall, operation failed" + operation);
}
}

View File

@ -0,0 +1,73 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.strategy;
import com.google.inject.Inject;
import org.jclouds.compute.domain.TemplateBuilderSpec;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.inject.Singleton;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
/**
* @author David Alves
*/
@Singleton
public class PopulateDefaultLoginCredentialsForImageStrategy implements
org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy {
private final TemplateBuilderSpec templateBuilder;
private final RsaSshKeyPairGenerator keyPairGenerator;
private String compoundKey;
@Inject
PopulateDefaultLoginCredentialsForImageStrategy(@Named(TEMPLATE) String templateSpec,
RsaSshKeyPairGenerator keyPairGenerator)
throws NoSuchAlgorithmException {
this.templateBuilder = TemplateBuilderSpec.parse(checkNotNull(templateSpec, "template builder spec"));
checkNotNull(templateBuilder.getLoginUser(), "template builder spec must provide a loginUser");
this.keyPairGenerator = checkNotNull(keyPairGenerator, "keypair generator");
}
@PostConstruct
private void generateKeys() {
Map<String, String> keys = keyPairGenerator.get();
// as we need to store both the pubk and the pk, store them separated by : (base64 does not contain that char)
compoundKey = String.format("%s:%s", checkNotNull(keys.get("public"), "public key cannot be null"),
checkNotNull(keys.get("private"), "private key cannot be null"));
}
@Override
public LoginCredentials apply(Object image) {
return LoginCredentials.builder()
.authenticateSudo(templateBuilder.getAuthenticateSudo() != null ?
templateBuilder.getAuthenticateSudo() : false)
.privateKey(compoundKey)
.user(templateBuilder.getLoginUser()).build();
}
}

View File

@ -0,0 +1,42 @@
package org.jclouds.googlecomputeengine.compute.strategy;
import com.google.common.base.Function;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.domain.LoginCredentials;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* GCE needs the credentials to create the node so the node credentials already take the Image credentials into account,
* as such only overriding the TemplateOptions credentials is required.
*
* @author David Alves
*/
@Singleton
public class UseNodeCredentialsButOverrideFromTemplate extends PrioritizeCredentialsFromTemplate {
@Inject
public UseNodeCredentialsButOverrideFromTemplate(
Function<Template, LoginCredentials> credentialsFromImageOrTemplateOptions) {
super(credentialsFromImageOrTemplateOptions);
}
public LoginCredentials apply(Template template, LoginCredentials fromNode) {
RunScriptOptions options = checkNotNull(template.getOptions(), "template options are required");
LoginCredentials.Builder builder = LoginCredentials.builder(fromNode);
if (options.getLoginUser() != null)
builder.user(template.getOptions().getLoginUser());
if (options.getLoginPassword() != null)
builder.password(options.getLoginPassword());
if (options.getLoginPrivateKey() != null)
builder.privateKey(options.getLoginPrivateKey());
if (options.shouldAuthenticateSudo() != null && options.shouldAuthenticateSudo())
builder.authenticateSudo(true);
return builder.build();
}
}

View File

@ -0,0 +1,132 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.config;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Suppliers.compose;
import java.net.URI;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.handlers.GoogleComputeEngineErrorHandler;
import org.jclouds.googlecomputeengine.predicates.OperationDonePredicate;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.Uris;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.location.Provider;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
* Configures the GoogleCompute connection.
*
* @author David Alves
*/
@ConfiguresHttpApi
public class GoogleComputeEngineHttpApiModule extends HttpApiModule<GoogleComputeEngineApi> {
public GoogleComputeEngineHttpApiModule() {
}
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {}).to(OperationDonePredicate.class);
super.configure();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoogleComputeEngineErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoogleComputeEngineErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleComputeEngineErrorHandler.class);
}
@Provides
@Singleton
@UserProject
public Supplier<String> supplyProject(@org.jclouds.location.Provider final Supplier<Credentials> creds) {
return compose(new Function<Credentials, String>() {
public String apply(Credentials in) {
checkState(in.identity.indexOf("@") != 1, "identity should be in project_id@developer.gserviceaccount.com" +
" format");
return Iterables.get(Splitter.on("@").split(in.identity), 0);
}
}, creds);
}
@Provides
@Singleton
@Named("machineTypes")
public Function<String, URI> provideMachineTypeNameToURIFunction(final @Provider Supplier<URI> endpoint,
final @UserProject Supplier<String> userProject) {
return new Function<String, URI>() {
@Override
public URI apply(String input) {
return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
("/machineTypes/").appendPath(input).build();
}
};
}
@Provides
@Singleton
@Named("networks")
public Function<String, URI> provideNetworkNameToURIFunction(final @Provider Supplier<URI> endpoint,
final @UserProject Supplier<String> userProject) {
return new Function<String, URI>() {
@Override
public URI apply(String input) {
return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
("/networks/").appendPath(input).build();
}
};
}
@Provides
@Singleton
@Named("zones")
public Function<String, URI> provideZoneNameToURIFunction(final @Provider Supplier<URI> endpoint,
final @UserProject Supplier<String> userProject) {
return new Function<String, URI>() {
@Override
public URI apply(String input) {
return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()).appendPath
("/zones/").appendPath(input).build();
}
};
}
}

View File

@ -0,0 +1,375 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.config;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Range;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.json.config.GsonModule;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import org.jclouds.oauth.v2.json.ClaimSetTypeAdapter;
import org.jclouds.oauth.v2.json.HeaderTypeAdapter;
import javax.inject.Singleton;
import java.beans.ConstructorProperties;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import static org.jclouds.googlecomputeengine.domain.Firewall.Rule;
/**
* @author David Alves
*/
public class GoogleComputeEngineParserModule extends AbstractModule {
@Override
protected void configure() {
bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
}
@Provides
@Singleton
public Map<Type, Object> provideCustomAdapterBindings() {
return new ImmutableMap.Builder<Type, Object>()
.put(Metadata.class, new MetadataTypeAdapter())
.put(Operation.class, new OperationTypeAdapter())
.put(Header.class, new HeaderTypeAdapter())
.put(ClaimSet.class, new ClaimSetTypeAdapter())
.put(Project.class, new ProjectTypeAdapter())
.put(Instance.class, new InstanceTypeAdapter())
.put(InstanceTemplate.class, new InstanceTemplateTypeAdapter())
.put(FirewallOptions.class, new FirewallOptionsTypeAdapter())
.put(Rule.class, new RuleTypeAdapter())
.build();
}
/**
* Parser for operations that unwraps errors avoiding an extra intermediate object.
*
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
*/
@Singleton
private static class OperationTypeAdapter implements JsonDeserializer<Operation> {
@Override
public Operation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
Operation.Builder operationBuilder = ((Operation) context.deserialize(json,
OperationInternal.class)).toBuilder();
JsonObject error = json.getAsJsonObject().getAsJsonObject("error");
if (error != null) {
JsonArray array = error.getAsJsonArray("errors");
if (array != null) {
for (JsonElement element : array) {
operationBuilder.addError((Operation.Error) context.deserialize(element, Operation.Error.class));
}
}
}
return operationBuilder.build();
}
private static class OperationInternal extends Operation {
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "targetLink", "targetId",
"clientOperationId", "status", "statusMessage", "user", "progress", "insertTime", "startTime",
"endTime", "httpErrorStatusCode", "httpErrorMessage", "operationType"
})
private OperationInternal(String id, Date creationTimestamp, URI selfLink, String name,
String description, URI targetLink, String targetId, String clientOperationId,
Status status, String statusMessage, String user, int progress, Date insertTime,
Date startTime, Date endTime, int httpErrorStatusCode, String httpErrorMessage,
String operationType) {
super(id, creationTimestamp, selfLink, name, description, targetLink, targetId, clientOperationId,
status, statusMessage, user, progress, insertTime, startTime, endTime, httpErrorStatusCode,
httpErrorMessage, operationType, null);
}
}
}
@Singleton
private static class InstanceTemplateTypeAdapter implements JsonSerializer<InstanceTemplate> {
@Override
public JsonElement serialize(InstanceTemplate src, Type typeOfSrc, JsonSerializationContext context) {
InstanceTemplateInternal template = new InstanceTemplateInternal(src);
JsonObject instance = (JsonObject) context.serialize(template, InstanceTemplateInternal.class);
// deal with network
JsonArray networkInterfaces = new JsonArray();
for (InstanceTemplate.NetworkInterface networkInterface : template.getNetworkInterfaces()){
networkInterfaces.add(context.serialize(networkInterface, InstanceTemplate.NetworkInterface.class));
}
instance.add("networkInterfaces", networkInterfaces);
// deal with persistent disks
if (src.getDisks() != null && !src.getDisks().isEmpty()) {
JsonArray disks = new JsonArray();
for (InstanceTemplate.PersistentDisk persistentDisk : src.getDisks()) {
JsonObject disk = (JsonObject) context.serialize(persistentDisk, InstanceTemplate.PersistentDisk.class);
disk.addProperty("type", "PERSISTENT");
disks.add(disk);
}
instance.add("disks", disks);
}
// deal with metadata
if (src.getMetadata() != null && !src.getMetadata().isEmpty()) {
JsonObject metadata = (JsonObject) context.serialize(new Metadata(src.getMetadata()));
instance.add("metadata", metadata);
return instance;
}
return instance;
}
private static class InstanceTemplateInternal extends InstanceTemplate {
private InstanceTemplateInternal(InstanceTemplate template) {
super(template.getMachineType());
name(template.getName());
description(template.getDescription());
zone(template.getZone());
image(template.getImage());
tags(template.getTags());
serviceAccounts(template.getServiceAccounts());
networkInterfaces(template.getNetworkInterfaces());
}
}
}
@Singleton
private static class InstanceTypeAdapter implements JsonDeserializer<Instance> {
@Override
public Instance deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
Instance.Builder instanceBuilder = ((Instance) context.deserialize(json,
InstanceInternal.class)).toBuilder();
JsonObject object = (JsonObject) json;
if (object.get("disks") != null) {
JsonArray disks = (JsonArray) object.get("disks");
for (JsonElement element : disks) {
JsonObject disk = (JsonObject) element;
if (disk.get("type").getAsString().equals("PERSISTENT")) {
instanceBuilder.addDisk((Instance.PersistentAttachedDisk) context.deserialize(disk,
Instance.PersistentAttachedDisk.class));
} else {
instanceBuilder.addDisk((Instance.AttachedDisk) context.deserialize(disk,
Instance.AttachedDisk.class));
}
}
}
return Instance.builder().fromInstance(instanceBuilder.build()).build();
}
private static class InstanceInternal extends Instance {
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "tags", "image", "machineType",
"status", "statusMessage", "zone", "networkInterfaces", "metadata", "serviceAccounts"
})
private InstanceInternal(String id, Date creationTimestamp, URI selfLink, String name, String description,
Set<String> tags, URI image, URI machineType, Status status, String statusMessage,
URI zone, Set<NetworkInterface> networkInterfaces, Metadata metadata,
Set<ServiceAccount> serviceAccounts) {
super(id, creationTimestamp, selfLink, name, description, tags, image, machineType,
status, statusMessage, zone, networkInterfaces, null, metadata, serviceAccounts);
}
}
}
/**
* Parser for Metadata.
*/
@Singleton
private static class MetadataTypeAdapter implements JsonDeserializer<Metadata>, JsonSerializer<Metadata> {
@Override
public Metadata deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
JsonObject metadata = json.getAsJsonObject();
JsonArray items = metadata.getAsJsonArray("items");
if (items != null) {
for (JsonElement element : items) {
JsonObject object = element.getAsJsonObject();
builder.put(object.get("key").getAsString(), object.get("value").getAsString());
}
}
return new Metadata(builder.build());
}
@Override
public JsonElement serialize(Metadata src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject metadataObject = new JsonObject();
metadataObject.add("kind", new JsonPrimitive("compute#metadata"));
JsonArray items = new JsonArray();
for (Map.Entry<String, String> entry : src.entrySet()) {
JsonObject object = new JsonObject();
object.addProperty("key", entry.getKey());
object.addProperty("value", entry.getValue());
items.add(object);
}
metadataObject.add("items", items);
return metadataObject;
}
}
public static class Metadata extends ForwardingMap<String, String> {
private final Map<String, String> delegate;
public Metadata(Map<String, String> delegate) {
this.delegate = delegate;
}
@Override
protected Map<String, String> delegate() {
return delegate;
}
}
@Singleton
private static class ProjectTypeAdapter implements JsonDeserializer<Project> {
@Override
public Project deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
return Project.builder().fromProject((Project) context.deserialize(json, ProjectInternal.class)).build();
}
private static class ProjectInternal extends Project {
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "commonInstanceMetadata", "quotas",
"externalIpAddresses"
})
private ProjectInternal(String id, Date creationTimestamp, URI selfLink, String name, String description,
Metadata commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
super(id, creationTimestamp, selfLink, name, description, commonInstanceMetadata, quotas,
externalIpAddresses);
}
}
}
@Singleton
private static class FirewallOptionsTypeAdapter implements JsonSerializer<FirewallOptions> {
@Override
public JsonElement serialize(FirewallOptions src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject firewall = new JsonObject();
if (src.getName() != null) {
firewall.addProperty("name", src.getName());
}
if (src.getNetwork() != null) {
firewall.addProperty("network", src.getNetwork().toString());
}
if (!src.getSourceRanges().isEmpty()) {
firewall.add("sourceRanges", buildArrayOfStrings(src.getSourceRanges()));
}
if (!src.getSourceTags().isEmpty()) {
firewall.add("sourceTags", buildArrayOfStrings(src.getSourceTags()));
}
if (!src.getTargetTags().isEmpty()) {
firewall.add("targetTags", buildArrayOfStrings(src.getTargetTags()));
}
if (!src.getAllowed().isEmpty()) {
JsonArray rules = new JsonArray();
for (Rule rule : src.getAllowed()) {
rules.add(context.serialize(rule, Firewall.Rule.class));
}
firewall.add("allowed", rules);
}
return firewall;
}
}
private static JsonArray buildArrayOfStrings(Set<String> strings) {
JsonArray array = new JsonArray();
for (String string : strings) {
array.add(new JsonPrimitive(string));
}
return array;
}
private static class RuleTypeAdapter implements JsonDeserializer<Firewall.Rule>, JsonSerializer<Firewall.Rule> {
@Override
public Firewall.Rule deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
JsonParseException {
JsonObject rule = json.getAsJsonObject();
Rule.Builder builder = Rule.builder();
builder.IPProtocol(Rule.IPProtocol.fromValue(rule.get("IPProtocol").getAsString()));
if (rule.get("ports") != null) {
JsonArray ports = (JsonArray) rule.get("ports");
for (JsonElement port : ports) {
String portAsString = port.getAsString();
if (portAsString.contains("-")) {
String[] split = portAsString.split("-");
builder.addPortRange(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
} else {
builder.addPort(Integer.parseInt(portAsString));
}
}
}
return builder.build();
}
@Override
public JsonElement serialize(Firewall.Rule src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject ruleObject = new JsonObject();
ruleObject.addProperty("IPProtocol", src.getIPProtocol().value());
if (src.getPorts() != null && !src.getPorts().isEmpty()) {
JsonArray ports = new JsonArray();
for (Range<Integer> range : src.getPorts().asRanges()) {
ports.add(new JsonPrimitive(range.lowerEndpoint() == range.upperEndpoint() ? range.lowerEndpoint() + "" :
range.lowerEndpoint() + "-" + range.upperEndpoint()));
}
ruleObject.add("ports", ports);
}
return ruleObject;
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.config;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.TypeLiteral;
import org.jclouds.oauth.v2.config.OAuthModule;
import org.jclouds.oauth.v2.domain.OAuthCredentials;
import org.jclouds.oauth.v2.domain.Token;
import org.jclouds.oauth.v2.domain.TokenRequest;
import org.jclouds.oauth.v2.functions.BuildTokenRequest;
import org.jclouds.oauth.v2.functions.FetchToken;
import org.jclouds.oauth.v2.functions.OAuthCredentialsSupplier;
import org.jclouds.oauth.v2.functions.SignOrProduceMacForToken;
import org.jclouds.rest.internal.GeneratedHttpRequest;
/**
* Overrides OAuthModule leaving TypeAdapters bindings out.
* <p/>
* TODO overcome this by using multibindings on GSonModule?
*
* @author David Alves
*/
public class OAuthModuleWithoutTypeAdapters extends OAuthModule {
@Override
protected void configure() {
bind(new TypeLiteral<Function<byte[], byte[]>>() {}).to(SignOrProduceMacForToken.class);
bind(new TypeLiteral<Supplier<OAuthCredentials>>() {}).to(OAuthCredentialsSupplier.class);
bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() {}).to(BuildTokenRequest.class);
bind(new TypeLiteral<Function<TokenRequest, Token>>() {}).to(FetchToken.class);
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.config;
import javax.inject.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Qualifies a property as the user's project id.
*
* @author David Alves
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Qualifier
public @interface UserProject {
}

View File

@ -0,0 +1,154 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A persistent disk resource
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/disks"/>
*/
@Beta
public final class Disk extends Resource {
private final Integer sizeGb;
private final URI zone;
private final String status;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "sizeGb", "zone",
"status"
})
private Disk(String id, Date creationTimestamp, URI selfLink, String name, String description,
Integer sizeGb, URI zone, String status) {
super(Kind.DISK, id, creationTimestamp, selfLink, name, description);
this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
this.zone = checkNotNull(zone, "zone of %s", name);
this.status = checkNotNull(status, "status of %s", name);
}
/**
* @return size of the persistent disk, specified in GB.
*/
public int getSizeGb() {
return sizeGb;
}
/**
* @return URL for the zone where the persistent disk resides.
*/
public URI getZone() {
return zone;
}
/**
* @return the status of disk creation.
*/
public String getStatus() {
return status;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.omitNullValues()
.add("sizeGb", sizeGb)
.add("zone", zone)
.add("status", status);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromDisk(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private Integer sizeGb;
private URI zone;;
private String status;
/**
* @see Disk#getSizeGb()
*/
public Builder sizeGb(Integer sizeGb) {
this.sizeGb = sizeGb;
return this;
}
/**
* @see Disk#getZone()
*/
public Builder zone(URI zone) {
this.zone = zone;
return this;
}
/**
* @see Disk#getStatus()
*/
public Builder status(String status) {
this.status = status;
return this;
}
@Override
protected Builder self() {
return this;
}
public Disk build() {
return new Disk(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, sizeGb, zone, status);
}
public Builder fromDisk(Disk in) {
return super.fromResource(in)
.sizeGb(in.getSizeGb())
.zone(in.getZone())
.status(in.getStatus());
}
}
}

View File

@ -0,0 +1,395 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Range.closed;
import static com.google.common.collect.Range.singleton;
/**
* Represents a network firewall
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
* @see <a href="https://developers.google.com/compute/docs/networking#firewalls"/>
*/
@Beta
public final class Firewall extends Resource {
private final URI network;
private final Set<String> sourceRanges;
private final Set<String> sourceTags;
private final Set<String> targetTags;
private final Set<Rule> allowed;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "network", "sourceRanges",
"sourceTags", "targetTags", "allowed"
})
protected Firewall(String id, Date creationTimestamp, URI selfLink, String name, String description,
URI network, Set<String> sourceRanges, Set<String> sourceTags, Set<String> targetTags,
Set<Rule> allowed) {
super(Kind.FIREWALL, id, creationTimestamp, selfLink, name, description);
this.network = checkNotNull(network, "network of %s", name);
this.sourceRanges = sourceRanges == null ? ImmutableSet.<String>of() : sourceRanges;
this.sourceTags = sourceTags == null ? ImmutableSet.<String>of() : sourceTags;
this.targetTags = targetTags == null ? ImmutableSet.<String>of() : targetTags;
this.allowed = allowed == null ? ImmutableSet.<Rule>of() : allowed;
}
/**
* @return URI of the network to which this firewall is applied; provided by the client when the firewall is created.
*/
public URI getNetwork() {
return network;
}
/**
* One or both of sourceRanges and sourceTags may be set; an inbound connection is allowed if either the range or
* the tag of the source matches.
*
* @return a list of IP address blocks expressed in CIDR format which this rule applies to.
*/
public Set<String> getSourceRanges() {
return sourceRanges;
}
/**
* @return a list of instance tags which this rule applies to. One or both of sourceRanges and sourceTags may be
* set; an inbound connection is allowed if either the range or the tag of the source matches.
*/
public Set<String> getSourceTags() {
return sourceTags;
}
/**
* If no targetTags are specified, the firewall rule applies to all instances on the specified network.
*
* @return a list of instance tags indicating sets of instances located on network which may make network
* connections as specified in allowed.
*/
public Set<String> getTargetTags() {
return targetTags;
}
/**
* Each rule specifies a protocol and port-range tuple that describes a permitted connection.
*
* @return the list of rules specified by this firewall.
*/
public Set<Rule> getAllowed() {
return allowed;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.add("network", network)
.add("sourceRanges", sourceRanges)
.add("sourceTags", sourceTags)
.add("targetTags", targetTags)
.add("allowed", allowed);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromFirewall(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private URI network;
private ImmutableSet.Builder<String> sourceRanges = ImmutableSet.builder();
private ImmutableSet.Builder<String> sourceTags = ImmutableSet.builder();
private ImmutableSet.Builder<String> targetTags = ImmutableSet.builder();
private ImmutableSet.Builder<Rule> allowed = ImmutableSet.builder();
/**
* @see Firewall#getNetwork()
*/
public Builder network(URI network) {
this.network = network;
return this;
}
/**
* @see Firewall#getSourceRanges()
*/
public Builder addSourceRange(String sourceRange) {
this.sourceRanges.add(checkNotNull(sourceRange));
return this;
}
/**
* @see Firewall#getSourceRanges()
*/
public Builder sourceRanges(Set<String> sourceRanges) {
this.sourceRanges.addAll(checkNotNull(sourceRanges));
return this;
}
/**
* @see Firewall#getSourceTags()
*/
public Builder addSourceTag(String sourceTag) {
this.sourceTags.add(checkNotNull(sourceTag));
return this;
}
/**
* @see Firewall#getSourceTags()
*/
public Builder sourceTags(Set<String> sourceTags) {
this.sourceTags.addAll(checkNotNull(sourceTags));
return this;
}
/**
* @see Firewall#getTargetTags()
*/
public Builder addTargetTag(String targetTag) {
this.targetTags.add(checkNotNull(targetTag));
return this;
}
/**
* @see Firewall#getTargetTags()
*/
public Builder targetTags(Set<String> targetTags) {
this.targetTags.addAll(checkNotNull(targetTags));
return this;
}
/**
* @see Firewall#getAllowed()
*/
public Builder addAllowed(Rule firewallRule) {
this.allowed.add(checkNotNull(firewallRule));
return this;
}
/**
* @see Firewall#getAllowed()
*/
public Builder allowed(Set<Rule> firewallRules) {
this.allowed = ImmutableSet.builder();
this.allowed.addAll(firewallRules);
return this;
}
@Override
protected Builder self() {
return this;
}
public Firewall build() {
return new Firewall(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, network, sourceRanges.build(), sourceTags.build(), targetTags.build(),
allowed.build());
}
public Builder fromFirewall(Firewall in) {
return super.fromResource(in).network(in.getNetwork()).sourceRanges(in.getSourceRanges()).sourceTags(in
.getSourceTags()).targetTags(in.getTargetTags()).allowed(in.getAllowed());
}
}
/**
* A Firewall rule. Rule specifies a protocol and port-range tuple that describes a
* permitted connection.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
*/
public static final class Rule {
public enum IPProtocol {
TCP, UDP, ICMP, UNKNOWN;
public String value() {
return name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static IPProtocol fromValue(String protocol) {
return valueOf(protocol.toUpperCase());
}
}
private final IPProtocol ipProtocol;
private final RangeSet<Integer> ports;
@ConstructorProperties({
"IPProtocol", "ports"
})
private Rule(IPProtocol IPProtocol, RangeSet<Integer> ports) {
this.ipProtocol = checkNotNull(IPProtocol);
this.ports = ports == null ? TreeRangeSet.<Integer>create() : ports;
}
/**
* This can either be a well known protocol string (tcp, udp or icmp) or the IP protocol number.
*
* @return this is the IP protocol that is allowed for this rule.
*/
public IPProtocol getIPProtocol() {
return ipProtocol;
}
/**
* Each entry must be either an integer or a range. If not specified, connections through any port are allowed.
* Example inputs include: ["22"], ["80,"443"], and ["12345-12349"].
* <p/>
* It is an error to specify this for any protocol that isn't UDP or TCP.
*
* @return An optional list of ports which are allowed.
*/
public RangeSet<Integer> getPorts() {
return ports;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(ipProtocol, ports);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Rule that = Rule.class.cast(obj);
return equal(this.ipProtocol, that.ipProtocol)
&& equal(this.ports, that.ports);
}
/**
* {@inheritDoc}
*/
public Objects.ToStringHelper string() {
return toStringHelper(this)
.add("IPProtocol", ipProtocol).add("ports", ports);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromFirewallRule(this);
}
public static final class Builder {
private IPProtocol ipProtocol;
private RangeSet<Integer> ports = TreeRangeSet.create();
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getIPProtocol()
*/
public Builder IPProtocol(IPProtocol IPProtocol) {
this.ipProtocol = IPProtocol;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
*/
public Builder addPort(Integer port) {
this.ports.add(singleton(checkNotNull(port, "port")));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
*/
public Builder addPortRange(Integer start, Integer end) {
checkState(checkNotNull(start, "start") < checkNotNull(end, "end"),
"start of range must be lower than end of range");
this.ports.add(closed(start, end));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
*/
public Builder ports(RangeSet<Integer> ports) {
this.ports = TreeRangeSet.create();
this.ports.addAll(ports);
return this;
}
public Rule build() {
return new Rule(ipProtocol, ports);
}
public Builder fromFirewallRule(Rule firewallRule) {
return new Builder().IPProtocol(firewallRule.getIPProtocol()).ports(firewallRule.getPorts());
}
}
}
}

View File

@ -0,0 +1,290 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a disk image to use on an instance.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
*/
@Beta
public final class Image extends Resource {
private final String sourceType;
private final Optional<URI> preferredKernel;
private final RawDisk rawDisk;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "sourceType", "preferredKernel",
"rawDisk"
})
protected Image(String id, Date creationTimestamp, URI selfLink, String name, String description,
String sourceType, URI preferredKernel, RawDisk rawDisk) {
super(Kind.IMAGE, id, creationTimestamp, selfLink, name, description);
this.sourceType = checkNotNull(sourceType, "sourceType of %s", name);
this.preferredKernel = fromNullable(preferredKernel);
this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name); ;
}
/**
* @return must be RAW; provided by the client when the disk image is created.
*/
public String getSourceType() {
return sourceType;
}
/**
* @return An optional URL of the preferred kernel for use with this disk image.
*/
public Optional<URI> getPreferredKernel() {
return preferredKernel;
}
/**
* @return the raw disk image parameters.
*/
public RawDisk getRawDisk() {
return rawDisk;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.omitNullValues()
.add("sourceType", sourceType)
.add("preferredKernel", preferredKernel.orNull())
.add("rawDisk", rawDisk);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromImage(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private String sourceType;
private URI preferredKernel;
private RawDisk rawDisk;
/**
* @see Image#getSourceType()
*/
public Builder sourceType(String sourceType) {
this.sourceType = checkNotNull(sourceType, "sourceType");
return this;
}
/**
* @see Image#getPreferredKernel()
*/
public Builder preferredKernel(URI preferredKernel) {
this.preferredKernel = preferredKernel;
return this;
}
/**
* @see Image#getRawDisk()
*/
public Builder rawDisk(RawDisk rawDisk) {
this.rawDisk = checkNotNull(rawDisk);
return this;
}
@Override
protected Builder self() {
return this;
}
public Image build() {
return new Image(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, sourceType, preferredKernel, rawDisk);
}
public Builder fromImage(Image in) {
return super.fromResource(in)
.sourceType(in.getSourceType())
.preferredKernel(in.getPreferredKernel().orNull())
.rawDisk(in.getRawDisk());
}
}
/**
* A raw disk image, usually the base for an image.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
*/
public static class RawDisk {
private final String source;
private final String containerType;
private final Optional<String> sha1Checksum;
@ConstructorProperties({
"source", "containerType", "sha1Checksum"
})
private RawDisk(String source, String containerType, String sha1Checksum) {
this.source = checkNotNull(source, "source");
this.containerType = checkNotNull(containerType, "containerType");
this.sha1Checksum = fromNullable(sha1Checksum);
}
/**
* @return the full Google Cloud Storage URL where the disk image is stored; provided by the client when the disk
* image is created.
*/
public String getSource() {
return source;
}
/**
* @return the format used to encode and transmit the block device.
*/
public String getContainerType() {
return containerType;
}
/**
* @return an optional SHA1 checksum of the disk image before unpackaging; provided by the client when the disk
* image is created.
*/
public Optional<String> getSha1Checksum() {
return sha1Checksum;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(source, containerType, sha1Checksum);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
RawDisk that = RawDisk.class.cast(obj);
return equal(this.source, that.source)
&& equal(this.containerType, that.containerType)
&& equal(this.sha1Checksum, that.sha1Checksum);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("source", source)
.add("containerType", containerType)
.add("sha1Checksum", sha1Checksum.orNull());
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromImageRawDisk(this);
}
public static class Builder {
private String source;
private String containerType;
private String sha1Checksum;
/**
* @see org.jclouds.googlecomputeengine.domain.Image.RawDisk#getSource()
*/
public Builder source(String source) {
this.source = checkNotNull(source);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Image.RawDisk#getContainerType()
*/
public Builder containerType(String containerType) {
this.containerType = checkNotNull(containerType);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Image.RawDisk#getSha1Checksum()
*/
public Builder sha1Checksum(String sha1Checksum) {
this.sha1Checksum = sha1Checksum;
return this;
}
public RawDisk build() {
return new RawDisk(source, containerType, sha1Checksum);
}
public Builder fromImageRawDisk(RawDisk rawDisk) {
return new Builder().source(rawDisk.getSource())
.containerType(rawDisk.getContainerType())
.sha1Checksum(rawDisk.getSha1Checksum().orNull());
}
}
}
}

View File

@ -0,0 +1,483 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
/**
* Optional information for creating an instance.
*
* @author David Alves
*/
public class InstanceTemplate {
protected String name;
protected String description;
protected URI machineType;
protected URI zone;
protected URI image;
protected Set<String> tags = Sets.newLinkedHashSet();
protected Set<Instance.ServiceAccount> serviceAccounts = Sets.newLinkedHashSet();
protected transient Set<PersistentDisk> disks = Sets.newLinkedHashSet();
protected transient Set<NetworkInterface> networkInterfaces = Sets.newLinkedHashSet();
protected transient Map<String, String> metadata = Maps.newLinkedHashMap();
protected transient String machineTypeName;
protected transient String zoneName;
protected InstanceTemplate(URI machineType) {
this.machineType = checkNotNull(machineType, "machineType");
}
protected InstanceTemplate(String machineTypeName) {
this.machineTypeName = checkNotNull(machineTypeName, "machineTypeName");
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getName()
*/
public InstanceTemplate name(String name) {
this.name = name;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDescription()
*/
public InstanceTemplate description(String description) {
this.description = description;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getImage()
*/
public InstanceTemplate image(URI image) {
this.image = image;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMachineType()
*/
public InstanceTemplate machineType(URI machineType) {
this.machineType = machineType;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMachineType()
*/
public InstanceTemplate machineType(String machineTypeName) {
this.machineTypeName = machineTypeName;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
*/
public InstanceTemplate zone(String zoneName) {
this.zoneName = zoneName;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
*/
public InstanceTemplate zone(URI zone) {
this.zone = zone;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
*/
public InstanceTemplate addTag(String tag) {
this.tags.add(checkNotNull(tag, "tag"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
*/
public InstanceTemplate tags(Set<String> tags) {
this.tags = Sets.newLinkedHashSet();
this.tags.addAll(checkNotNull(tags, "tags"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDisks()
*/
public InstanceTemplate addDisk(PersistentDisk.Mode mode, URI source) {
this.disks.add(new PersistentDisk(mode, source, null, null));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDisks()
*/
public InstanceTemplate addDisk(PersistentDisk.Mode mode, URI source, String deviceName, Boolean deleteOnTerminate) {
this.disks.add(new PersistentDisk(mode, source, deviceName, deleteOnTerminate));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDisks()
*/
public InstanceTemplate disks(Set<PersistentDisk> disks) {
this.disks = Sets.newLinkedHashSet();
this.disks.addAll(checkNotNull(disks, "disks"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate addNetworkInterface(URI network) {
this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null,null));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate addNetworkInterface(URI network, Type type) {
this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null,
ImmutableSet.of(Instance.NetworkInterface.AccessConfig.builder()
.type(type)
.build())));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate addNetworkInterface(NetworkInterface networkInterface) {
this.networkInterfaces.add(networkInterface);
return this;
}
public InstanceTemplate networkInterfaces(Set<NetworkInterface> networkInterfaces) {
this.networkInterfaces = Sets.newLinkedHashSet(networkInterfaces);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMetadata()
*/
public InstanceTemplate addMetadata(String key, String value) {
this.metadata.put(checkNotNull(key, "key"), checkNotNull(value, "value of %", key));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMetadata()
*/
public InstanceTemplate metadata(Map<String, String> metadata) {
this.metadata = Maps.newLinkedHashMap();
this.metadata.putAll(checkNotNull(metadata, "metadata"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getServiceAccounts()
*/
public InstanceTemplate addServiceAccount(Instance.ServiceAccount serviceAccount) {
this.serviceAccounts.add(checkNotNull(serviceAccount, "serviceAccount"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getServiceAccounts()
*/
public InstanceTemplate serviceAccounts(Set<Instance.ServiceAccount> serviceAccounts) {
this.serviceAccounts = Sets.newLinkedHashSet();
this.serviceAccounts.addAll(checkNotNull(serviceAccounts, "serviceAccounts"));
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDescription()
*/
public String getDescription() {
return description;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getDisks()
*/
public Set<PersistentDisk> getDisks() {
return disks;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getImage()
*/
public URI getImage() {
return image;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMachineType()
*/
public URI getMachineType() {
return machineType;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMachineType()
*/
public String getMachineTypeName() {
return machineTypeName;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getMetadata()
*/
public Map<String, String> getMetadata() {
return metadata;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getNetworkInterfaces()
*/
public Set<NetworkInterface> getNetworkInterfaces() {
return networkInterfaces;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getServiceAccounts()
*/
public Set<Instance.ServiceAccount> getServiceAccounts() {
return serviceAccounts;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getTags()
*/
public Set<String> getTags() {
return tags;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getName()
*/
public String getName() {
return name;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
*/
public URI getZone() {
return zone;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Instance#getZone()
*/
public String getZoneName() {
return zoneName;
}
public static Builder builder() {
return new Builder();
}
public static InstanceTemplate fromInstanceTemplate(InstanceTemplate instanceTemplate) {
return Builder.fromInstanceTemplate(instanceTemplate);
}
public static class Builder {
public InstanceTemplate forMachineType(URI machineType) {
return new InstanceTemplate(machineType);
}
public InstanceTemplate forMachineType(String machineTypeName) {
return new InstanceTemplate(machineTypeName);
}
public static InstanceTemplate fromInstanceTemplate(InstanceTemplate instanceTemplate) {
return InstanceTemplate.builder()
.forMachineType(instanceTemplate.getMachineType())
.networkInterfaces(instanceTemplate.getNetworkInterfaces())
.name(instanceTemplate.getName())
.description(instanceTemplate.getDescription())
.zone(instanceTemplate.getZone())
.image(instanceTemplate.getImage())
.tags(instanceTemplate.getTags())
.disks(instanceTemplate.getDisks())
.metadata(instanceTemplate.getMetadata())
.serviceAccounts(instanceTemplate.getServiceAccounts());
}
}
public static class PersistentDisk {
public enum Mode {
READ_WRITE,
READ_ONLY
}
public PersistentDisk(Mode mode, URI source, String deviceName, Boolean deleteOnTerminate) {
this.mode = checkNotNull(mode, "mode");
this.source = checkNotNull(source, "source");
this.deviceName = deviceName;
this.deleteOnTerminate = deleteOnTerminate;
}
private final Mode mode;
private final URI source;
private final Boolean deleteOnTerminate;
private final String deviceName;
/**
* @return the mode in which to attach this disk, either READ_WRITE or READ_ONLY.
*/
public Mode getMode() {
return mode;
}
/**
* @return the URL of the persistent disk resource.
*/
public URI getSource() {
return source;
}
/**
* @return Must be unique within the instance when specified. This represents a unique
* device name that is reflected into the /dev/ tree of a Linux operating system running within the
* instance. If not specified, a default will be chosen by the system.
*/
public String getDeviceName() {
return deviceName;
}
/**
* @return If true, delete the disk and all its data when the associated instance is deleted.
*/
public boolean isDeleteOnTerminate() {
return deleteOnTerminate;
}
}
public static class NetworkInterface {
private final URI network;
private final String networkIP;
private final Set<Instance.NetworkInterface.AccessConfig> accessConfigs;
public NetworkInterface(URI network, String networkIP, Set<Instance.NetworkInterface.AccessConfig>
accessConfigs) {
this.networkIP = networkIP;
this.network = network;
this.accessConfigs = accessConfigs != null ? accessConfigs : ImmutableSet.<Instance.NetworkInterface.AccessConfig>of();
}
public Set<Instance.NetworkInterface.AccessConfig> getAccessConfigs() {
return accessConfigs;
}
public URI getNetwork() {
return network;
}
public String getNetworkIP() {
return networkIP;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof InstanceTemplate) {
final InstanceTemplate other = InstanceTemplate.class.cast(object);
return equal(description, other.description)
&& equal(tags, other.tags)
&& equal(image, other.image)
&& equal(disks, other.disks)
&& equal(networkInterfaces, other.networkInterfaces)
&& equal(metadata, other.metadata)
&& equal(serviceAccounts, other.serviceAccounts);
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(description, tags, image, disks, networkInterfaces, metadata, serviceAccounts);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
Objects.ToStringHelper toString = Objects.toStringHelper("")
.omitNullValues();
toString.add("description", description);
if (tags.size() > 0)
toString.add("tags", tags);
if (disks.size() > 0)
toString.add("disks", disks);
if (metadata.size() > 0)
toString.add("metadata", metadata);
if (serviceAccounts.size() > 0)
toString.add("serviceAccounts", serviceAccounts);
toString.add("image", image);
toString.add("networkInterfaces", networkInterfaces);
return toString;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
/**
* Represents a kernel.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/kernels"/>
*/
@Beta
public final class Kernel extends Resource {
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description"
})
private Kernel(String id, Date creationTimestamp, URI selfLink, String name, String description) {
super(Kind.KERNEL, id, creationTimestamp, selfLink, name, description);
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromKernel(this);
}
public static final class Builder extends Resource.Builder<Builder> {
@Override
protected Builder self() {
return this;
}
public Kernel build() {
return new Kernel(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description);
}
public Builder fromKernel(Kernel in) {
return super.fromResource(in);
}
}
}

View File

@ -0,0 +1,183 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import org.jclouds.collect.IterableWithMarker;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Iterator;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.googlecomputeengine.domain.Resource.Kind;
/**
* The collection returned from any <code>listFirstPage()</code> method.
*
* @author David Alves
*/
public class ListPage<T> extends IterableWithMarker<T> {
private final Kind kind;
private final String id;
private final URI selfLink;
private final String nextPageToken;
private final Iterable<T> items;
@ConstructorProperties({
"kind", "id", "selfLink", "nextPageToken", "items"
})
protected ListPage(Kind kind, String id, URI selfLink, String nextPageToken, Iterable<T> items) {
this.id = checkNotNull(id, "id");
this.kind = checkNotNull(kind, "kind of %id", id);
this.selfLink = checkNotNull(selfLink, "selfLink of %id", id);
this.nextPageToken = nextPageToken;
this.items = items != null ? ImmutableSet.copyOf(items) : ImmutableSet.<T>of();
}
public Kind getKind() {
return kind;
}
public String getId() {
return id;
}
public URI getSelfLink() {
return selfLink;
}
@Override
public Optional<Object> nextMarker() {
return Optional.<Object>fromNullable(nextPageToken);
}
@Override
public Iterator<T> iterator() {
return checkNotNull(items, "items").iterator();
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(kind, id);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
ListPage<?> that = ListPage.class.cast(obj);
return equal(this.kind, that.kind)
&& equal(this.id, that.id);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("kind", kind)
.add("id", id)
.add("selfLink", selfLink)
.add("nextPageToken", nextPageToken)
.add("items", items);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static <T> Builder<T> builder() {
return new Builder<T>();
}
public Builder<T> toBuilder() {
return new Builder<T>().fromPagedList(this);
}
public static final class Builder<T> {
private Kind kind;
private String id;
private URI selfLink;
private String nextPageToken;
private ImmutableSet.Builder<T> items = ImmutableSet.builder();
public Builder<T> kind(Kind kind) {
this.kind = kind;
return this;
}
public Builder<T> id(String id) {
this.id = id;
return this;
}
public Builder<T> selfLink(URI selfLink) {
this.selfLink = selfLink;
return this;
}
public Builder<T> addItem(T item) {
this.items.add(item);
return this;
}
public Builder<T> items(Iterable<T> items) {
this.items.addAll(items);
return this;
}
public Builder<T> nextPageToken(String nextPageToken) {
this.nextPageToken = nextPageToken;
return this;
}
public ListPage<T> build() {
return new ListPage<T>(kind, id, selfLink, nextPageToken, items.build());
}
public Builder<T> fromPagedList(ListPage<T> in) {
return this
.kind(in.getKind())
.id(in.getId())
.selfLink(in.getSelfLink())
.nextPageToken((String) in.nextMarker().orNull())
.items(in);
}
}
}

View File

@ -0,0 +1,337 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a machine type used to host an instance.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/machineTypes"/>
*/
@Beta
public final class MachineType extends Resource {
private final Integer guestCpus;
private final Integer memoryMb;
private final Integer imageSpaceGb;
private final List<EphemeralDisk> ephemeralDisks;
private final Integer maximumPersistentDisks;
private final Long maximumPersistentDisksSizeGb;
private final Set<String> availableZone;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "guestCpus", "memoryMb",
"imageSpaceGb", "ephemeralDisks", "maximumPersistentDisks", "maximumPersistentDisksSizeGb", "availableZone"
})
private MachineType(String id, Date creationTimestamp, URI selfLink, String name, String description,
int guestCpus, int memoryMb, int imageSpaceGb, List<EphemeralDisk> ephemeralDisks,
int maximumPersistentDisks, long maximumPersistentDisksSizeGb, Set<String> availableZone) {
super(Kind.MACHINE_TYPE, id, creationTimestamp, selfLink, name, description);
this.guestCpus = checkNotNull(guestCpus, "guestCpus of %s", name);
this.memoryMb = checkNotNull(memoryMb, "memoryMb of %s", name);
this.imageSpaceGb = checkNotNull(imageSpaceGb, "imageSpaceGb of %s", name);
this.ephemeralDisks = ephemeralDisks == null ? ImmutableList.<EphemeralDisk>of() : ephemeralDisks;
this.maximumPersistentDisks = checkNotNull(maximumPersistentDisks, "maximumPersistentDisks of %s", name);
this.maximumPersistentDisksSizeGb = maximumPersistentDisksSizeGb;
this.availableZone = availableZone == null ? ImmutableSet.<String>of() : availableZone;
}
/**
* @return count of CPUs exposed to the instance.
*/
public int getGuestCpus() {
return guestCpus;
}
/**
* @return physical memory assigned to the instance, defined in MB.
*/
public int getMemoryMb() {
return memoryMb;
}
/**
* @return space allotted for the image, defined in GB.
*/
public int getImageSpaceGb() {
return imageSpaceGb;
}
/**
* @return extended ephemeral disks assigned to the instance.
*/
public List<EphemeralDisk> getEphemeralDisks() {
return ephemeralDisks;
}
/**
* @return maximum persistent disks allowed.
*/
public int getMaximumPersistentDisks() {
return maximumPersistentDisks;
}
/**
* @return maximum total persistent disks size (GB) allowed.
*/
public long getMaximumPersistentDisksSizeGb() {
return maximumPersistentDisksSizeGb;
}
/**
* @return the zones that this machine type can run in.
*/
public Set<String> getAvailableZone() {
return availableZone;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.add("guestCpus", guestCpus)
.add("memoryMb", memoryMb)
.add("imageSpaceGb", imageSpaceGb)
.add("ephemeralDisks", ephemeralDisks)
.add("maximumPersistentDisks", maximumPersistentDisks)
.add("maximumPersistentDisksSizeGb", maximumPersistentDisksSizeGb)
.add("availableZone", availableZone);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromMachineType(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private Integer guestCpus;
private Integer memoryMb;
private Integer imageSpaceGb;
private ImmutableList.Builder<EphemeralDisk> ephemeralDisks = ImmutableList.builder();
private Integer maximumPersistentDisks;
private Long maximumPersistentDisksSizeGb;
private ImmutableSet.Builder<String> availableZone = ImmutableSet.builder();
/**
* @see MachineType#getGuestCpus()
*/
public Builder guestCpus(int guesCpus) {
this.guestCpus = guesCpus;
return this;
}
/**
* @see MachineType#getMemoryMb()
*/
public Builder memoryMb(int memoryMb) {
this.memoryMb = memoryMb;
return this;
}
/**
* @see MachineType#getImageSpaceGb()
*/
public Builder imageSpaceGb(int imageSpaceGb) {
this.imageSpaceGb = imageSpaceGb;
return this;
}
/**
* @see MachineType#getEphemeralDisks()
*/
public Builder addEphemeralDisk(int diskGb) {
this.ephemeralDisks.add(EphemeralDisk.builder().diskGb(diskGb).build());
return this;
}
/**
* @see MachineType#getEphemeralDisks()
*/
public Builder ephemeralDisks(List<EphemeralDisk> ephemeralDisks) {
this.ephemeralDisks.addAll(ephemeralDisks);
return this;
}
/**
* @see MachineType#getMaximumPersistentDisks()
*/
public Builder maximumPersistentDisks(int maximumPersistentDisks) {
this.maximumPersistentDisks = maximumPersistentDisks;
return this;
}
/**
* @see MachineType#getMaximumPersistentDisksSizeGb()
*/
public Builder maximumPersistentDisksSizeGb(long maximumPersistentDisksSizeGb) {
this.maximumPersistentDisksSizeGb = maximumPersistentDisksSizeGb;
return this;
}
/**
* @see MachineType#getAvailableZone()
*/
public Builder addAvailableZone(String availableZone) {
this.availableZone.add(availableZone);
return this;
}
/**
* @see MachineType#getAvailableZone()
*/
public Builder availableZones(Set<String> availableZone) {
this.availableZone.addAll(availableZone);
return this;
}
@Override
protected Builder self() {
return this;
}
public MachineType build() {
return new MachineType(id, creationTimestamp, selfLink, name, description, guestCpus, memoryMb,
imageSpaceGb, ephemeralDisks.build(), maximumPersistentDisks, maximumPersistentDisksSizeGb,
availableZone.build());
}
public Builder fromMachineType(MachineType in) {
return super.fromResource(in).memoryMb(in.getMemoryMb()).imageSpaceGb(in.getImageSpaceGb()).ephemeralDisks(in
.getEphemeralDisks()).maximumPersistentDisks(in.getMaximumPersistentDisks())
.maximumPersistentDisksSizeGb(in.getMaximumPersistentDisksSizeGb()).availableZones(in
.getAvailableZone());
}
}
/**
* An ephemeral disk of a MachineType
*/
public static final class EphemeralDisk {
private final int diskGb;
@ConstructorProperties({
"diskGb"
})
private EphemeralDisk(int diskGb) {
this.diskGb = diskGb;
}
/**
* @return size of the ephemeral disk, defined in GB.
*/
public int getDiskGb() {
return diskGb;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(diskGb);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
EphemeralDisk that = EphemeralDisk.class.cast(obj);
return equal(this.diskGb, that.diskGb);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.add("diskGb", diskGb);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromEphemeralDisk(this);
}
public static class Builder {
private int diskGb;
/**
* @see org.jclouds.googlecomputeengine.domain.MachineType.EphemeralDisk#getDiskGb()
*/
public Builder diskGb(int diskGb) {
this.diskGb = diskGb;
return this;
}
public EphemeralDisk build() {
return new EphemeralDisk(diskGb);
}
public Builder fromEphemeralDisk(EphemeralDisk in) {
return new Builder().diskGb(in.getDiskGb());
}
}
}
}

View File

@ -0,0 +1,137 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a network used to enable instance communication.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/networks"/>
*/
@Beta
public final class Network extends Resource {
private final String IPv4Range;
private final Optional<String> gatewayIPv4;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "IPv4Range",
"gatewayIPv4"
})
protected Network(String id, Date creationTimestamp, URI selfLink, String name, String description,
String IPv4Range, String gatewayIPv4) {
super(Kind.NETWORK, id, creationTimestamp, selfLink, name, description);
this.IPv4Range = checkNotNull(IPv4Range);
this.gatewayIPv4 = fromNullable(gatewayIPv4);
}
/**
* @return Required; The range of internal addresses that are legal on this network. This range is a CIDR
* specification, for example: 192.168.0.0/16.
*/
public String getIPv4Range() {
return IPv4Range;
}
/**
* This must be within the range specified by IPv4Range, and is typically the first usable address in that range.
* If not specified, the default value is the first usable address in IPv4Range.
*
* @return an optional address that is used for default routing to other networks.
*/
public Optional<String> getGatewayIPv4() {
return gatewayIPv4;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.omitNullValues()
.add("IPv4Range", IPv4Range)
.add("gatewayIPv4", gatewayIPv4.orNull());
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromNetwork(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private String IPv4Range;
private String gatewayIPv4;
/**
* @see Network#getIPv4Range()
*/
public Builder IPv4Range(String IPv4Range) {
this.IPv4Range = IPv4Range;
return this;
}
/**
* @see Network#getGatewayIPv4()
*/
public Builder gatewayIPv4(String gatewayIPv4) {
this.gatewayIPv4 = gatewayIPv4;
return this;
}
@Override
protected Builder self() {
return this;
}
public Network build() {
return new Network(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, IPv4Range, gatewayIPv4);
}
public Builder fromNetwork(Network in) {
return super.fromResource(in);
}
}
}

View File

@ -0,0 +1,519 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import org.jclouds.http.HttpResponse;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import java.util.List;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Describes an operation being executed on some Resource
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
*/
@Beta
public class Operation extends Resource {
public static enum Status {
PENDING,
RUNNING,
DONE
}
private final URI targetLink;
private final Optional<String> targetId;
private final Optional<String> clientOperationId;
private final Status status;
private final Optional<String> statusMessage;
private final String user;
private final Optional<Integer> progress;
private final Date insertTime;
private final Optional<Date> startTime;
private final Optional<Date> endTime;
private final Optional<HttpResponse> httpError;
private final String operationType;
private final List<Error> errors;
protected Operation(String id, Date creationTimestamp, URI selfLink, String name, String description,
URI targetLink, String targetId, String clientOperationId, Status status,
String statusMessage, String user, Integer progress, Date insertTime, Date startTime,
Date endTime, Integer httpErrorStatusCode, String httpErrorMessage, String operationType,
List<Error> errors) {
super(Kind.OPERATION, id, creationTimestamp, selfLink, name, description);
this.targetLink = checkNotNull(targetLink, "targetLink of %s", name);
this.targetId = fromNullable(targetId);
this.clientOperationId = fromNullable(clientOperationId);
this.status = checkNotNull(status, "status of %s", name);
this.statusMessage = fromNullable(statusMessage);
this.user = checkNotNull(user, "user of %s", name);
this.progress = fromNullable(progress);
this.insertTime = checkNotNull(insertTime, "insertTime of %s", name);
this.startTime = fromNullable(startTime);
this.endTime = fromNullable(endTime);
this.httpError = httpErrorStatusCode != null && httpErrorStatusCode != 0 ?
Optional.of(HttpResponse.builder()
.statusCode(httpErrorStatusCode)
.message(httpErrorMessage)
.build())
: Optional.<HttpResponse>absent();
this.operationType = checkNotNull(operationType, "insertTime of %s", name);
this.errors = errors == null ? ImmutableList.<Error>of() : ImmutableList.copyOf(errors);
}
/**
* @return URL of the resource the operation is mutating.
*/
public URI getTargetLink() {
return targetLink;
}
/**
* @return unique target id which identifies a particular incarnation of the target.
*/
public Optional<String> getTargetId() {
return targetId;
}
/**
* @return An optional identifier specified by the client when the mutation was initiated. Must be unique for all
* operation resources in the project.
*/
public Optional<String> getClientOperationId() {
return clientOperationId;
}
/**
* @return Status of the operation. Can be one of the following: PENDING, RUNNING, or DONE.
*/
public Status getStatus() {
return status;
}
/**
* @return An optional textual description of the current status of the operation.
*/
public Optional<String> getStatusMessage() {
return statusMessage;
}
/**
* @return User who requested the operation, for example "user@example.com".
*/
public String getUser() {
return user;
}
/**
* @return an optional progress indicator that ranges from 0 to 100. This should not be used to guess at when the
* operation will be complete. This number should be monotonically increasing as the operation progresses
* (output only).
*/
public Optional<Integer> getProgress() {
return progress;
}
/**
* @return the time that this operation was requested.
*/
public Date getInsertTime() {
return insertTime;
}
/**
* @return the time that this operation was started by the server.
*/
public Optional<Date> getStartTime() {
return startTime;
}
/**
* @return the time that this operation was completed.
*/
public Optional<Date> getEndTime() {
return endTime;
}
/**
* @return if operation fails, the HttpResponse with error status code returned and the message, e.g. NOT_FOUND.
*/
public Optional<HttpResponse> getHttpError() {
return httpError;
}
/**
* @return type of the operation. Examples include insert, update, and delete.
*/
public String getOperationType() {
return operationType;
}
/**
* @return if error occurred during processing of this operation, this field will be populated.
*/
public List<Error> getErrors() {
return errors;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.omitNullValues()
.add("targetLink", targetLink)
.add("targetId", targetId.orNull())
.add("clientOperationId", clientOperationId.orNull())
.add("status", status)
.add("statusMessage", statusMessage.orNull())
.add("user", user)
.add("progress", progress.orNull())
.add("insertTime", insertTime)
.add("startTime", startTime.orNull())
.add("endTime", endTime.orNull())
.add("httpError", httpError.orNull())
.add("operationType", operationType)
.add("errors", errors);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromOperation(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private URI targetLink;
private String targetId;
private String clientOperationId;
private Status status;
private String statusMessage;
private String user;
private Integer progress;
private Date insertTime;
private Date startTime;
private Date endTime;
private Integer httpErrorStatusCode;
private String httpErrorMessage;
private String operationType;
private ImmutableList.Builder<Error> errors = ImmutableList.builder();
/**
* @see Operation#getTargetLink()
*/
public Builder targetLink(URI targetLink) {
this.targetLink = targetLink;
return self();
}
/**
* @see Operation#getTargetId()
*/
public Builder targetId(String targetId) {
this.targetId = targetId;
return self();
}
/**
* @see Operation#getClientOperationId()
*/
public Builder clientOperationId(String clientOperationId) {
this.clientOperationId = clientOperationId;
return self();
}
/**
* @see Operation#getStatus()
*/
public Builder status(Status status) {
this.status = status;
return self();
}
/**
* @see Operation#getStatusMessage()
*/
public Builder statusMessage(String statusMessage) {
this.statusMessage = statusMessage;
return self();
}
/**
* @see Operation#getUser()
*/
public Builder user(String user) {
this.user = user;
return self();
}
/**
* @see Operation#getProgress()
*/
public Builder progress(Integer progress) {
this.progress = progress;
return self();
}
/**
* @see Operation#getInsertTime()
*/
public Builder insertTime(Date insertTime) {
this.insertTime = insertTime;
return self();
}
/**
* @see Operation#getStartTime()
*/
public Builder startTime(Date startTime) {
this.startTime = startTime;
return self();
}
/**
* @see Operation#getEndTime()
*/
public Builder endTime(Date endTime) {
this.endTime = endTime;
return self();
}
/**
* @see Operation#getHttpError()
*/
public Builder httpErrorStatusCode(Integer httpErrorStatusCode) {
this.httpErrorStatusCode = httpErrorStatusCode;
return self();
}
/**
* @see Operation#getHttpError()
*/
public Builder httpErrorMessage(String httpErrorMessage) {
this.httpErrorMessage = httpErrorMessage;
return self();
}
/**
* @see Operation#getOperationType()
*/
public Builder operationType(String operationType) {
this.operationType = operationType;
return self();
}
/**
* @see Operation#getErrors()
*/
public Builder errors(Iterable<Error> errors) {
if (errors != null)
this.errors.addAll(errors);
return self();
}
/**
* @see Operation#getErrors()
*/
public Builder addError(Error error) {
this.errors.add(error);
return self();
}
@Override
protected Builder self() {
return this;
}
public Operation build() {
return new Operation(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, targetLink, targetId, clientOperationId, status, statusMessage, user, progress,
insertTime, startTime, endTime, httpErrorStatusCode, httpErrorMessage, operationType,
errors.build());
}
public Builder fromOperation(Operation in) {
return super.fromResource(in)
.targetLink(in.getTargetLink())
.targetId(in.getTargetId().orNull())
.clientOperationId(in.getClientOperationId().orNull())
.status(in.getStatus())
.statusMessage(in.getStatusMessage().orNull())
.user(in.getUser())
.progress(in.getProgress().get())
.insertTime(in.getInsertTime())
.startTime(in.getStartTime().orNull())
.endTime(in.getEndTime().orNull())
.httpErrorStatusCode(in.getHttpError().isPresent() ? in.getHttpError().get().getStatusCode() : null)
.httpErrorMessage(in.getHttpError().isPresent() ? in.getHttpError().get().getMessage() : null)
.operationType(in.getOperationType()).errors(in.getErrors());
}
}
/**
* A particular error for an operation including the details.
*/
public static final class Error {
private final String code;
private final Optional<String> location;
private final Optional<String> message;
@ConstructorProperties({
"code", "location", "message"
})
private Error(String code, String location, String message) {
this.code = checkNotNull(code, "code");
this.location = fromNullable(location);
this.message = fromNullable(message);
}
/**
* @return the error type identifier for this error.
*/
public String getCode() {
return code;
}
/**
* @return indicates the field in the request which caused the error..
*/
public Optional<String> getLocation() {
return location;
}
/**
* @return an optional, human-readable error message.
*/
public Optional<String> getMessage() {
return message;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(code, location, message);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Error that = Error.class.cast(obj);
return equal(this.code, that.code)
&& equal(this.location, that.location)
&& equal(this.message, that.message);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("code", code)
.add("location", location.orNull())
.add("message", message.orNull());
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromOperationErrorDetail(this);
}
public static final class Builder {
private String code;
private String location;
private String message;
/**
* @see org.jclouds.googlecomputeengine.domain.Operation.Error#getCode()
*/
public Builder code(String code) {
this.code = code;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Operation.Error#getLocation()
*/
public Builder location(String location) {
this.location = location;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Operation.Error#getMessage()
*/
public Builder message(String message) {
this.message = message;
return this;
}
public Error build() {
return new Error(code, location, message);
}
public Builder fromOperationErrorDetail(Error in) {
return new Builder().code(in.getCode()).location(in.getLocation().orNull()).message
(in.getMessage().orNull());
}
}
}
}

View File

@ -0,0 +1,305 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A Project resource is the root collection and settings resource for all Google Compute Engine resources.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/projects"/>
*/
@Beta
public class Project extends Resource {
private final Map<String, String> commonInstanceMetadata;
private final Set<Quota> quotas;
private final Set<String> externalIpAddresses;
protected Project(String id, Date creationTimestamp, URI selfLink, String name, String description,
Map<String, String> commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
super(Kind.PROJECT, id, creationTimestamp, selfLink, name, description);
this.commonInstanceMetadata = commonInstanceMetadata == null ? ImmutableMap.<String,
String>of() : ImmutableMap.copyOf(commonInstanceMetadata);
this.quotas = quotas == null ? ImmutableSet.<Quota>of() : ImmutableSet.copyOf(quotas);
this.externalIpAddresses = externalIpAddresses == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf
(externalIpAddresses);
}
/**
* @return metadata key/value pairs available to all instances contained in this project.
*/
public Map<String, String> getCommonInstanceMetadata() {
return commonInstanceMetadata;
}
/**
* @return quotas assigned to this project.
*/
public Set<Quota> getQuotas() {
return quotas;
}
/**
* @return internet available IP addresses available for use in this project.
*/
@Nullable
public Set<String> getExternalIpAddresses() {
return externalIpAddresses;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.add("commonInstanceMetadata", commonInstanceMetadata)
.add("quotas", quotas)
.add("externalIpAddresses", externalIpAddresses);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromProject(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private ImmutableMap.Builder<String, String> commonInstanceMetadata = ImmutableMap.builder();
private ImmutableSet.Builder<Quota> quotas = ImmutableSet.builder();
private ImmutableSet.Builder<String> externalIpAddresses = ImmutableSet.builder();
/**
* @see Project#getCommonInstanceMetadata()
*/
public Builder addCommonInstanceMetadata(String key, String value) {
this.commonInstanceMetadata.put(key, value);
return this;
}
/**
* @see Project#getCommonInstanceMetadata()
*/
public Builder commonInstanceMetadata(Map<String, String> commonInstanceMetadata) {
this.commonInstanceMetadata.putAll(checkNotNull(commonInstanceMetadata, "commonInstanceMetadata"));
return this;
}
/**
* @see Project#getQuotas()
*/
public Builder addQuota(String metric, double usage, double limit) {
this.quotas.add(Quota.builder().metric(metric).usage(usage).limit(limit).build());
return this;
}
/**
* @see Project#getQuotas()
*/
public Builder quotas(Set<Quota> quotas) {
this.quotas.addAll(checkNotNull(quotas));
return this;
}
/**
* @see Project#getExternalIpAddresses()
*/
public Builder addExternalIpAddress(String externalIpAddress) {
this.externalIpAddresses.add(checkNotNull(externalIpAddress, "externalIpAddress"));
return this;
}
/**
* @see Project#getExternalIpAddresses()
*/
public Builder externalIpAddresses(Set<String> externalIpAddresses) {
this.externalIpAddresses.addAll(checkNotNull(externalIpAddresses, "externalIpAddresses"));
return this;
}
@Override
protected Builder self() {
return this;
}
public Project build() {
return new Project(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, commonInstanceMetadata.build(), quotas.build(), externalIpAddresses.build());
}
public Builder fromProject(Project in) {
return super.fromResource(in).commonInstanceMetadata(in.getCommonInstanceMetadata()).quotas(in.getQuotas())
.externalIpAddresses(in.getExternalIpAddresses());
}
}
/**
* Quotas assigned to a given project
*
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/projects#resource"/>
*/
public static final class Quota {
private String metric;
private double usage;
private double limit;
@ConstructorProperties({
"metric", "usage", "limit"
})
protected Quota(String metric, Double usage, Double limit) {
this.metric = checkNotNull(metric, "metric");
this.usage = checkNotNull(usage, "usage");
this.limit = checkNotNull(limit, "limit");
}
/**
* @return name of the quota metric.
*/
public String getMetric() {
return metric;
}
/**
* @return current usage of this metric.
*/
public Double getUsage() {
return usage;
}
/**
* @return quota limit for this metric.
*/
public Double getLimit() {
return limit;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(metric);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Quota that = Quota.class.cast(obj);
return equal(this.metric, that.metric);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("metric", metric)
.add("usage", usage)
.add("limit", limit);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromQuota(this);
}
public static class Builder {
private String metric;
private Double usage;
private Double limit;
/**
* @see org.jclouds.googlecomputeengine.domain.Project.Quota#getMetric()
*/
public Builder metric(String metric) {
this.metric = checkNotNull(metric, "metric");
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Project.Quota#getUsage()
*/
public Builder usage(Double usage) {
this.usage = usage;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Project.Quota#getLimit()
*/
public Builder limit(Double limit) {
this.limit = limit;
return this;
}
public Quota build() {
return new Quota(metric, usage, limit);
}
public Builder fromQuota(Quota quota) {
return new Builder().metric(quota.getMetric()).usage(quota.getUsage()).limit(quota.getLimit());
}
}
}
}

View File

@ -0,0 +1,281 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.CaseFormat;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Objects.ToStringHelper;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Base class for Google Compute Engine resources.
*
* @author David Alves
*/
@Beta
public class Resource {
public enum Kind {
DISK,
DISK_LIST,
FIREWALL,
FIREWALL_LIST,
IMAGE,
IMAGE_LIST,
OPERATION,
OPERATION_LIST,
INSTANCE,
INSTANCE_LIST,
KERNEL,
KERNEL_LIST,
MACHINE_TYPE,
MACHINE_TYPE_LIST,
PROJECT,
NETWORK,
NETWORK_LIST,
ZONE,
ZONE_LIST;
public String value() {
return Joiner.on("#").join("compute", CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()));
}
@Override
public String toString() {
return value();
}
public static Kind fromValue(String kind) {
return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat
.UPPER_UNDERSCORE,
Iterables.getLast(Splitter.on("#").split(checkNotNull(kind,
"kind")))));
}
}
protected final Kind kind;
protected final String id;
protected final Optional<Date> creationTimestamp;
protected final URI selfLink;
protected final String name;
protected final Optional<String> description;
@ConstructorProperties({
"kind", "id", "creationTimestamp", "selfLink", "name", "description"
})
protected Resource(Kind kind, String id, Date creationTimestamp, URI selfLink, String name,
String description) {
this.kind = checkNotNull(kind, "kind");
this.id = checkNotNull(id, "id");
this.creationTimestamp = fromNullable(creationTimestamp);
this.selfLink = checkNotNull(selfLink, "selfLink");
this.name = checkNotNull(name, "name");
this.description = fromNullable(description);
}
/**
* @return the Type of the resource
*/
public Kind getKind() {
return kind;
}
/**
* @return unique identifier for the resource; defined by the server.
*/
public String getId() {
return id;
}
/**
* @return creation timestamp in RFC3339 text format.
*/
public Optional<Date> getCreationTimestamp() {
return creationTimestamp;
}
/**
* @return server defined URL for the resource.
*/
public URI getSelfLink() {
return selfLink;
}
/**
* @return name of the resource.
*/
public String getName() {
return name;
}
/**
* @return an optional textual description of the resource.
*/
@Nullable
public Optional<String> getDescription() {
return description;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(kind, name);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Resource that = Resource.class.cast(obj);
return equal(this.kind, that.kind)
&& equal(this.name, that.name);
}
/**
* {@inheritDoc}
*/
protected ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("kind", kind)
.add("id", id)
.add("name", name)
.add("creationTimestamp", creationTimestamp.orNull())
.add("selfLink", selfLink)
.add("name", name)
.add("description", description.orNull());
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromResource(this);
}
public abstract static class Builder<T extends Builder<T>> {
protected abstract T self();
protected Kind kind;
protected String id;
protected Date creationTimestamp;
protected URI selfLink;
protected String name;
protected String description;
/**
* @see Resource#getKind()
*/
protected T kind(Kind kind) {
this.kind = kind;
return self();
}
/**
* @see Resource#getId()
*/
public T id(String id) {
this.id = id;
return self();
}
/**
* @see Resource#getCreationTimestamp()
*/
public T creationTimestamp(Date creationTimestamp) {
this.creationTimestamp = creationTimestamp;
return self();
}
/**
* @see Resource#getSelfLink()
*/
public T selfLink(URI selfLink) {
this.selfLink = selfLink;
return self();
}
/**
* @see Resource#getName()
*/
public T name(String name) {
this.name = name;
return self();
}
/**
* @see Resource#getDescription()
*/
public T description(String description) {
this.description = description;
return self();
}
public Resource build() {
return new Resource(kind, id, creationTimestamp, selfLink, name, description);
}
public T fromResource(Resource in) {
return this
.kind(in.getKind())
.id(in.getId())
.creationTimestamp(in.getCreationTimestamp().orNull())
.selfLink(in.getSelfLink())
.name(in.getName())
.description(in.getDescription().orNull());
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
}

View File

@ -0,0 +1,337 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import org.jclouds.javax.annotation.Nullable;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a zone resource.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
*/
@Beta
public final class Zone extends Resource {
public enum Status {
UP,
DOWN
}
private final Status status;
private final Set<MaintenanceWindow> maintenanceWindows;
private final Set<String> availableMachineTypes;
@ConstructorProperties({
"id", "creationTimestamp", "selfLink", "name", "description", "status", "maintenanceWindows",
"availableMachineTypes"
})
private Zone(String id, Date creationTimestamp, URI selfLink, String name, String description,
Status status, Set<MaintenanceWindow> maintenanceWindows, Set<String> availableMachineTypes) {
super(Kind.ZONE, id, creationTimestamp, selfLink, name, description);
this.status = checkNotNull(status, "status of %name", name);
this.maintenanceWindows = maintenanceWindows == null ? ImmutableSet.<MaintenanceWindow>of() : ImmutableSet
.copyOf(maintenanceWindows);
this.availableMachineTypes = availableMachineTypes == null ? ImmutableSet.<String>of() : ImmutableSet
.copyOf(availableMachineTypes);
}
/**
* @return Status of the zone. "UP" or "DOWN".
*/
public Status getStatus() {
return status;
}
/**
* @return scheduled maintenance windows for the zone. When the zone is in a maintenance window,
* all resources which reside in the zone will be unavailable.
*/
public Set<MaintenanceWindow> getMaintenanceWindows() {
return maintenanceWindows;
}
/**
* @return the machine types that can be used in this zone.
*/
@Nullable
public Set<String> getAvailableMachineTypes() {
return availableMachineTypes;
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return super.string()
.add("status", status)
.add("maintenanceWindows", maintenanceWindows)
.add("availableMachineTypes", availableMachineTypes);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return new Builder().fromZone(this);
}
public static final class Builder extends Resource.Builder<Builder> {
private Status status;
private ImmutableSet.Builder<MaintenanceWindow> maintenanceWindows = ImmutableSet.builder();
private ImmutableSet.Builder<String> availableMachineTypes = ImmutableSet.builder();
/**
* @see Zone#getStatus()
*/
public Builder status(Status status) {
this.status = status;
return this;
}
/**
* @see Zone#getMaintenanceWindows()
*/
public Builder addMaintenanceWindow(MaintenanceWindow maintenanceWindow) {
this.maintenanceWindows.add(checkNotNull(maintenanceWindow, "maintenanceWindow"));
return this;
}
/**
* @see Zone#getMaintenanceWindows()
*/
public Builder maintenanceWindows(Set<MaintenanceWindow> maintenanceWindows) {
this.maintenanceWindows.addAll(checkNotNull(maintenanceWindows, "maintenanceWindows"));
return this;
}
/**
* @see Zone#getAvailableMachineTypes()
*/
public Builder addAvailableMachineType(String availableMachineType) {
this.availableMachineTypes.add(checkNotNull(availableMachineType, "availableMachineType"));
return this;
}
/**
* @see Zone#getAvailableMachineTypes()
*/
public Builder availableMachineTypes(Set<String> availableMachineTypes) {
this.availableMachineTypes.addAll(checkNotNull(availableMachineTypes, "availableMachineTypes"));
return this;
}
@Override
protected Builder self() {
return this;
}
public Zone build() {
return new Zone(super.id, super.creationTimestamp, super.selfLink, super.name,
super.description, status, maintenanceWindows.build(), availableMachineTypes.build());
}
public Builder fromZone(Zone in) {
return super.fromResource(in)
.status(in.getStatus())
.maintenanceWindows(in.getMaintenanceWindows())
.availableMachineTypes(in.getAvailableMachineTypes());
}
}
/**
* Scheduled maintenance windows for the zone. When the zone is in a maintenance window,
* all resources which reside in the zone will be unavailable.
*
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
*/
public static final class MaintenanceWindow {
private final String name;
private final Optional<String> description;
private final Date beginTime;
private final Date endTime;
@ConstructorProperties({
"name", "description", "beginTime", "endTime"
})
private MaintenanceWindow(String name, String description, Date beginTime, Date endTime) {
this.name = checkNotNull(name, "name");
this.description = fromNullable(description);
this.beginTime = checkNotNull(beginTime, "beginTime of %name", name);
this.endTime = checkNotNull(endTime, "endTime of %name", name);
}
/**
* @return name of the maintenance window.
*/
public String getName() {
return name;
}
/**
* @return textual description of the maintenance window.
*/
public Optional<String> getDescription() {
return description;
}
/**
* @return begin time of the maintenance window.
*/
public Date getBeginTime() {
return beginTime;
}
/**
* @return end time of the maintenance window.
*/
public Date getEndTime() {
return endTime;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hashCode(name, description, beginTime, endTime);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
MaintenanceWindow that = MaintenanceWindow.class.cast(obj);
return equal(this.name, that.name)
&& equal(this.beginTime, that.beginTime)
&& equal(this.endTime, that.endTime);
}
/**
* {@inheritDoc}
*/
protected Objects.ToStringHelper string() {
return toStringHelper(this)
.omitNullValues()
.add("name", name)
.add("description", description.orNull())
.add("beginTime", beginTime)
.add("endTime", endTime);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromZoneMaintenanceWindow(this);
}
public static final class Builder {
private String name;
private String description;
private Date beginTime;
private Date endTime;
/**
* @see org.jclouds.googlecomputeengine.domain.Zone.MaintenanceWindow#getName()
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Zone.MaintenanceWindow#getDescription()
*/
public Builder description(String description) {
this.description = description;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Zone.MaintenanceWindow#getBeginTime()
*/
public Builder beginTime(Date beginTime) {
this.beginTime = beginTime;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Zone.MaintenanceWindow#getEndTime()
*/
public Builder endTime(Date endTime) {
this.endTime = endTime;
return this;
}
public MaintenanceWindow build() {
return new MaintenanceWindow(name, description, beginTime, endTime);
}
public Builder fromZoneMaintenanceWindow(MaintenanceWindow in) {
return new Builder()
.name(in.getName())
.description(in.getDescription().orNull())
.beginTime(in.getBeginTime())
.endTime(in.getEndTime());
}
}
}
}

View File

@ -0,0 +1,191 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import java.net.URI;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.ParseDisks;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Disks via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/disks"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface DiskApi {
/**
* Returns the specified persistent disk resource.
*
* @param diskName name of the persistent disk resource to return.
* @return a Disk resource.
*/
@Named("Disks:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks/{disk}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Disk get(@PathParam("disk") String diskName);
/**
* Creates a persistent disk resource in the specified project specifying the size of the disk.
*
*
* @param diskName the name of disk.
* @param sizeGb the size of the disk
* @param zone the URi of the zone where the disk is to be created.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Disks:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes({COMPUTE_SCOPE})
@MapBinder(BindToJsonPayload.class)
Operation createInZone(@PayloadParam("name") String diskName,
@PayloadParam("sizeGb") int sizeGb,
@PayloadParam("zone") URI zone);
/**
* Deletes the specified persistent disk resource.
*
* @param diskName name of the persistent disk resource to delete.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Disks:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks/{disk}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Operation delete(@PathParam("disk") String diskName);
/**
* @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Disks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseDisks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Disk> listFirstPage();
/**
* @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Disks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseDisks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Disk> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the listPage of persistent disk resources contained within the specified project.
* By default the listPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has
* not been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the listPage
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Disks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseDisks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Disk> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
/**
* A paged version of DiskApi#listPage()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see DiskApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Disks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseDisks.class)
@Transform(ParseDisks.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Disk> list();
@Named("Disks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/disks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseDisks.class)
@Transform(ParseDisks.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Disk> list(ListOptions options);
}

View File

@ -0,0 +1,231 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import java.net.URI;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.PATCH;
import org.jclouds.googlecomputeengine.functions.internal.ParseFirewalls;
import org.jclouds.googlecomputeengine.handlers.FirewallBinder;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Firewalls via their REST API.
* <p/>
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/firewalls"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface FirewallApi {
/**
* Returns the specified image resource.
*
* @param firewallName name of the firewall resource to return.
* @return an Firewall resource
*/
@Named("Firewalls:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls/{firewall}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Firewall get(@PathParam("firewall") String firewallName);
/**
* Creates a firewall resource in the specified project using the data included in the request.
*
* @param name the name of the firewall to be inserted.
* @param network the network to which to add the firewall
* @param firewallOptions the options of the firewall to add
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Firewalls:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes({COMPUTE_SCOPE})
@MapBinder(FirewallBinder.class)
Operation createInNetwork(@PayloadParam("name") String name,
@PayloadParam("network") URI network,
@PayloadParam("options") FirewallOptions firewallOptions);
/**
* Updates the specified firewall resource with the data included in the request.
*
* @param firewallName the name firewall to be updated.
* @param firewallOptions the new firewall.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Firewalls:update")
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/firewalls/{firewall}")
@OAuthScopes({COMPUTE_SCOPE})
Operation update(@PathParam("firewall") String firewallName,
@BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
/**
* Updates the specified firewall resource, with patch semantics, with the data included in the request.
*
* @param firewallName the name firewall to be updated.
* @param firewallOptions the new firewall.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Firewalls:patch")
@PATCH
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/firewalls/{firewall}")
@OAuthScopes({COMPUTE_SCOPE})
Operation patch(@PathParam("firewall") String firewallName,
@BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
/**
* Deletes the specified image resource.
*
* @param imageName name of the firewall resource to delete.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field. If the image did not exist the result is null.
*/
@Named("Firewalls:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls/{firewall}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Operation delete(@PathParam("firewall") String firewallName);
/**
* @see FirewallApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Firewalls:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseFirewalls.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Firewall> listFirstPage();
/**
* @see FirewallApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Firewalls:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseFirewalls.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Firewall> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the list of firewall resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Firewalls:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseFirewalls.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Firewall> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
/**
* @see FirewallApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Firewalls:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseFirewalls.class)
@Transform(ParseFirewalls.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Firewall> list();
/**
* A paged version of FirewallApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see FirewallApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Firewalls:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseFirewalls.class)
@Transform(ParseFirewalls.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Firewall> list(ListOptions options);
}

View File

@ -0,0 +1,171 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.ParseImages;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
/**
* Provides access to Images via their REST API.
* <p/>
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/images"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface ImageApi {
/**
* Returns the specified image resource.
*
* @param imageName name of the image resource to return.
* @return an Image resource
*/
@Named("Images:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{image}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Image get(@PathParam("image") String imageName);
/**
* Deletes the specified image resource.
*
* @param imageName name of the image resource to delete.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field. If the image did not exist the result is null.
*/
@Named("Images:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{image}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Operation delete(@PathParam("image") String imageName);
/**
* @see ImageApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Images:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseImages.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Image> listFirstPage();
/**
* @see ImageApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Images:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseImages.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Image> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the list of image resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Images:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseImages.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Image> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
/**
* A paged version of ImageApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see ImageApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Images:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseImages.class)
@Transform(ParseImages.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Image> list();
/**
* A paged version of ImageApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see ImageApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Images:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseImages.class)
@Transform(ParseImages.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Image> list(ListOptions options);
}

View File

@ -0,0 +1,246 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.ParseInstances;
import org.jclouds.googlecomputeengine.handlers.InstanceBinder;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Instances via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/instances"/>
* @see InstanceApi
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface InstanceApi {
/**
* Returns the specified instance resource.
*
* @param instanceName name of the instance resource to return.
* @return an Instance resource
*/
@Named("Instances:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances/{instance}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Instance get(@PathParam("instance") String instanceName);
/**
* Creates a instance resource in the specified project using the data included in the request.
*
* @param instanceName this name of the instance to be created
* @param template the instance template
* @param zone the name of the zone where the instance will be created
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Instances:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes({COMPUTE_SCOPE})
@MapBinder(InstanceBinder.class)
Operation createInZone(@PayloadParam("name") String instanceName,
@PayloadParam("template") InstanceTemplate template,
@PayloadParam("zone") String zone);
/**
* Deletes the specified instance resource.
*
* @param instanceName name of the instance resource to delete.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field. If the instance did not exist the result is null.
*/
@Named("Instances:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances/{instance}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Operation delete(@PathParam("instance") String instanceName);
/**
* A paged version of InstanceApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see InstanceApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Instances:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseInstances.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Instance> listFirstPage();
/**
* Retrieves the list of instance resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Instances:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseInstances.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Instance> listAtMarker(@Nullable String marker);
/**
* @see InstanceApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Instances:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseInstances.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Instance> listAtMarker(@Nullable String marker, ListOptions options);
/**
* @see InstanceApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Instances:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseInstances.class)
@Transform(ParseInstances.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Instance> list();
/**
* @see InstanceApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Instances:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseInstances.class)
@Transform(ParseInstances.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Instance> list(ListOptions options);
/**
* Adds an access config to an instance's network interface.
*
* @param instanceName the instance name.
* @param accessConfig the AccessConfig to add.
* @param networkInterfaceName network interface name.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Instances:addAccessConfig")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/instances/{instance}/addAccessConfig")
@OAuthScopes({COMPUTE_SCOPE})
Operation addAccessConfigToNic(@PathParam("instance") String instanceName,
@BinderParam(BindToJsonPayload.class)
Instance.NetworkInterface.AccessConfig accessConfig,
@QueryParam("network_interface") String networkInterfaceName);
/**
* Deletes an access config from an instance's network interface.
*
* @param instanceName the instance name.
* @param accessConfigName the name of the access config to delete
* @param networkInterfaceName network interface name.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Instances:deleteAccessConfig")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances/{instance}/deleteAccessConfig")
@OAuthScopes(COMPUTE_SCOPE)
Operation deleteAccessConfigFromNic(@PathParam("instance") String instanceName,
@QueryParam("access_config") String accessConfigName,
@QueryParam("network_interface") String networkInterfaceName);
/**
* Returns the specified instance's serial port output.
*
* @param instanceName the instance name.
* @return if successful, this method returns a SerialPortOutput containing the instance's serial output.
*/
@Named("Instances:serialPort")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/instances/{instance}/serialPort")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
Instance.SerialPortOutput getSerialPortOutput(@PathParam("instance") String instanceName);
}

View File

@ -0,0 +1,143 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Kernel;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.functions.internal.ParseKernels;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
/**
* Provides access to Kernels via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/kernels"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface KernelApi {
/**
* Returns the specified kernel resource
*
* @param kernelName name of the kernel resource to return.
* @return If successful, this method returns a Kernel resource
*/
@Named("Kernels:get")
@GET
@Path("/kernels/{kernel}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Kernel get(@PathParam("kernel") String kernelName);
/**
* @see KernelApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Kernels:list")
@GET
@Path("/kernels")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseKernels.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Kernel> listFirstPage();
/**
* @see KernelApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Kernels:list")
@GET
@Path("/kernels")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseKernels.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Kernel> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the list of kernel resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Kernels:list")
@GET
@Path("/kernels")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseKernels.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Kernel> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
ListOptions listOptions);
/**
* @see KernelApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Kernels:list")
@GET
@Path("/kernels")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseKernels.class)
@Transform(ParseKernels.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Kernel> list();
/**
* A paged version of KernelApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see KernelApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Kernels:list")
@GET
@Path("/kernels")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseKernels.class)
@Transform(ParseKernels.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Kernel> list(ListOptions listOptions);
}

View File

@ -0,0 +1,144 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.functions.internal.ParseMachineTypes;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
/**
* Provides access to MachineTypes via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/machineTypes"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface MachineTypeApi {
/**
* Returns the specified machine type resource
*
* @param machineTypeName name of the machine type resource to return.
* @return If successful, this method returns a MachineType resource
*/
@Named("MachineTypes:get")
@GET
@Path("/machineTypes/{machineType}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
MachineType get(@PathParam("machineType") String machineTypeName);
/**
* @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("MachineTypes:list")
@GET
@Path("/machineTypes")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseMachineTypes.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<MachineType> listFirstPage();
/**
* @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("MachineTypes:list")
@GET
@Path("/machineTypes")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseMachineTypes.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<MachineType> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the list of machine type resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("MachineTypes:list")
@GET
@Path("/machineTypes")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseMachineTypes.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<MachineType> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
ListOptions listOptions);
/**
* @see MachineTypeApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("MachineTypes:list")
@GET
@Path("/machineTypes")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseMachineTypes.class)
@Transform(ParseMachineTypes.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<MachineType> list();
/**
* A paged version of MachineTypeApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see MachineTypeApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("MachineTypes:list")
@GET
@Path("/machineTypes")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseMachineTypes.class)
@Transform(ParseMachineTypes.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<MachineType> list(ListOptions listOptions);
}

View File

@ -0,0 +1,209 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.ParseNetworks;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Networks via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/networks"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface NetworkApi {
/**
* Returns the specified persistent network resource.
*
* @param networkName name of the persistent network resource to return.
* @return a Network resource.
*/
@Named("Networks:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks/{network}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Network get(@PathParam("network") String networkName);
/**
* Creates a persistent network resource in the specified project with the specified range.
*
* @param networkName the network name
* @param IPv4Range the range of the network to be inserted.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Networks:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes({COMPUTE_SCOPE})
@MapBinder(BindToJsonPayload.class)
Operation createInIPv4Range(@PayloadParam("name") String networkName,
@PayloadParam("IPv4Range") String IPv4Range);
/**
* Creates a persistent network resource in the specified project with the specified range and specified gateway.
*
* @param networkName the network name
* @param IPv4Range the range of the network to be inserted.
* @param gatewayIPv4 the range of the network to be inserted.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Networks:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes({COMPUTE_SCOPE})
@MapBinder(BindToJsonPayload.class)
Operation createInIPv4RangeWithGateway(@PayloadParam("name") String networkName,
@PayloadParam("IPv4Range") String IPv4Range,
@PayloadParam("gatewayIPv4") String gatewayIPv4);
/**
* Deletes the specified persistent network resource.
*
* @param networkName name of the persistent network resource to delete.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
@Named("Networks:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks/{network}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Operation delete(@PathParam("network") String networkName);
/**
* @see NetworkApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Networks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseNetworks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Network> listFirstPage();
/**
* @see NetworkApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Networks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseNetworks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Network> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the list of persistent network resources contained within the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Networks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseNetworks.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Network> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
ListOptions options);
/**
* @see NetworkApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Networks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseNetworks.class)
@Transform(ParseNetworks.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Network> list();
/**
* A paged version of NetworkApi#list()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see NetworkApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Networks:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Path("/networks")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseNetworks.class)
@Transform(ParseNetworks.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Network> list(ListOptions options);
}

View File

@ -0,0 +1,162 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.functions.internal.ParseOperations;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
/**
* Provides access to Operations via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface OperationApi {
/**
* Retrieves the specified operation resource.
*
* @param operationName name of the operation resource to return.
* @return If successful, this method returns an Operation resource
*/
@Named("Operations:get")
@GET
@Path("/operations/{operation}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
Operation get(@PathParam("operation") String operationName);
/**
* Deletes the specified operation resource.
*
* @param operationName name of the operation resource to delete.
*/
@Named("Operations:delete")
@DELETE
@Path("/operations/{operation}")
@OAuthScopes(COMPUTE_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
void delete(@PathParam("operation") String operationName);
/**
* @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Operations:list")
@GET
@Path("/operations")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(ParseOperations.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Operation> listFirstPage();
/**
* @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Operations:list")
@GET
@Path("/operations")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(ParseOperations.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Operation> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
/**
* Retrieves the listFirstPage of operation resources contained within the specified project.
* By default the listFirstPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults()
* has not been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list, starting at marker
* @see ListOptions
* @see org.jclouds.googlecomputeengine.domain.ListPage
*/
@Named("Operations:list")
@GET
@Path("/operations")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(ParseOperations.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Operation> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
ListOptions listOptions);
/**
* @see OperationApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Operations:list")
@GET
@Path("/operations")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(ParseOperations.class)
@Transform(ParseOperations.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Operation> list();
/**
* A paged version of OperationApi#listFirstPage()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see PagedIterable
* @see OperationApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Operations:list")
@GET
@Path("/operations")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@ResponseParser(ParseOperations.class)
@Transform(ParseOperations.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Operation> list(ListOptions listOptions);
}

View File

@ -0,0 +1,97 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.googlecomputeengine.handlers.MetadataBinder;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
/**
* Provides access to Projects via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/projects"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
public interface ProjectApi {
/**
* Returns the specified project resource.
*
* @param projectName name of the project to return
* @return if successful, this method returns a Project resource
*/
@Named("Projects:get")
@GET
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@Fallback(NullOnNotFoundOr404.class)
@Path("/projects/{project}")
Project get(@PathParam("project") String projectName);
/**
* Sets metadata common to all instances within the specified project using the data included in the request.
* <p/>
* NOTE: This *sets* metadata items on the project (vs *adding* items to metadata),
* if there are pre-existing metadata items that must be kept these must be fetched first and then re-set on the
* new Metadata, e.g.
* <pre><tt>
* Metadata.Builder current = projectApi.get("myProject").getCommonInstanceMetadata().toBuilder();
* current.addItem("newItem","newItemValue");
* projectApi.setCommonInstanceMetadata(current.build());
* </tt></pre>
*
* @param projectName name of the project to return
* @param commonInstanceMetadata the metadata to set
* @return an Operations resource. To check on the status of an operation, poll the Operations resource returned
* to you, and look for the status field.
*/
@Named("Projects:setCommonInstanceMetadata")
@POST
@Path("/projects/{project}/setCommonInstanceMetadata")
@OAuthScopes(COMPUTE_SCOPE)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Operation setCommonInstanceMetadata(@PathParam("project") String projectName,
@BinderParam(MetadataBinder.class)
Map<String, String> commonInstanceMetadata);
}

View File

@ -0,0 +1,139 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Zone;
import org.jclouds.googlecomputeengine.functions.internal.ParseZones;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
/**
* Provides access to Zones via their REST API.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
*/
@SkipEncoding({'/', '='})
@RequestFilters(OAuthAuthenticator.class)
@Consumes(MediaType.APPLICATION_JSON)
public interface ZoneApi {
/**
* Returns the specified zone resource
*
* @param zoneName name of the zone resource to return.
* @return If successful, this method returns a Zone resource
*/
@Named("Zones:get")
@GET
@Path("/zones/{zone}")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Zone get(@PathParam("zone") String zoneName);
/**
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Zones:list")
@GET
@Path("/zones")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseZones.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Zone> listFirstPage();
/**
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Zones:list")
@GET
@Path("/zones")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseZones.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Zone> listAtMarker(String marker);
/**
* Retrieves the listFirstPage of zone resources available to the specified project.
* By default the listFirstPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults()
* has not been set.
*
* @param marker marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the listFirstPage
* @see ListOptions
* @see ListPage
*/
@Named("Zones:list")
@GET
@Path("/zones")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseZones.class)
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
ListPage<Zone> listAtMarker(String marker, ListOptions listOptions);
/**
* @see ZoneApi#list(org.jclouds.googlecomputeengine.options.ListOptions)
*/
@Named("Zones:list")
@GET
@Path("/zones")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseZones.class)
@Transform(ParseZones.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Zone> list();
/**
* A paged version of ZoneApi#listFirstPage()
*
* @return a Paged, Fluent Iterable that is able to fetch additional pages when required
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecomputeengine.options.ListOptions)
* @see PagedIterable
*/
@Named("Zones:list")
@GET
@Path("/zones")
@OAuthScopes(COMPUTE_READONLY_SCOPE)
@ResponseParser(ParseZones.class)
@Transform(ParseZones.ToPagedIterable.class)
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
PagedIterable<Zone> list(ListOptions listOptions);
}

View File

@ -0,0 +1,71 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.collect.PagedIterables;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.tryFind;
/**
* @author Adrian Cole
*/
@Beta
public abstract class BaseToPagedIterable<T, I extends BaseToPagedIterable<T, I>> implements
Function<ListPage<T>, PagedIterable<T>>, InvocationContext<I> {
private GeneratedHttpRequest request;
@Override
public PagedIterable<T> apply(ListPage<T> input) {
if (input.nextMarker() == null)
return PagedIterables.of(input);
Optional<Object> project = tryFind(request.getCaller().get().getArgs(), instanceOf(String.class));
Optional<Object> listOptions = tryFind(request.getInvocation().getArgs(), instanceOf(ListOptions.class));
assert project.isPresent() : String.format("programming error, method %s should have a string param for the "
+ "project", request.getCaller().get().getInvokable());
return PagedIterables.advance(
input, fetchNextPage(project.get().toString(), (ListOptions) listOptions.orNull()));
}
protected abstract Function<Object, IterableWithMarker<T>> fetchNextPage(String projectName,
ListOptions listOptions);
@SuppressWarnings("unchecked")
@Override
public I setContext(HttpRequest request) {
this.request = GeneratedHttpRequest.class.cast(request);
return (I) this;
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import javax.ws.rs.HttpMethod;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that the annotated method responds to HTTP PATCH requests
*
* @author David Alves
* @see javax.ws.rs.HttpMethod
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@HttpMethod("PATCH")
public @interface PATCH {
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
@Singleton
public class ParseDisks extends ParseJson<ListPage<Disk>> {
@Inject
public ParseDisks(Json json) {
super(json, new TypeLiteral<ListPage<Disk>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Disk, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Disk>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Disk>>() {
@Override
public IterableWithMarker<Disk> apply(Object input) {
return api.getDiskApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseFirewalls extends ParseJson<ListPage<Firewall>> {
@Inject
public ParseFirewalls(Json json) {
super(json, new TypeLiteral<ListPage<Firewall>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Firewall, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Firewall>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Firewall>>() {
@Override
public IterableWithMarker<Firewall> apply(Object input) {
return api.getFirewallApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseImages extends ParseJson<ListPage<Image>> {
@Inject
public ParseImages(Json json) {
super(json, new TypeLiteral<ListPage<Image>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Image, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Image>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Image>>() {
@Override
public IterableWithMarker<Image> apply(Object input) {
return api.getImageApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseInstances extends ParseJson<ListPage<Instance>> {
@Inject
public ParseInstances(Json json) {
super(json, new TypeLiteral<ListPage<Instance>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Instance, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Instance>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Instance>>() {
@Override
public IterableWithMarker<Instance> apply(Object input) {
return api.getInstanceApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Kernel;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseKernels extends ParseJson<ListPage<Kernel>> {
@Inject
public ParseKernels(Json json) {
super(json, new TypeLiteral<ListPage<Kernel>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Kernel, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Kernel>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Kernel>>() {
@Override
public IterableWithMarker<Kernel> apply(Object input) {
return api.getKernelApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseMachineTypes extends ParseJson<ListPage<MachineType>> {
@Inject
public ParseMachineTypes(Json json) {
super(json, new TypeLiteral<ListPage<MachineType>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<MachineType, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<MachineType>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<MachineType>>() {
@Override
public IterableWithMarker<MachineType> apply(Object input) {
return api.getMachineTypeApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseNetworks extends ParseJson<ListPage<Network>> {
@Inject
public ParseNetworks(Json json) {
super(json, new TypeLiteral<ListPage<Network>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Network, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Network>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Network>>() {
@Override
public IterableWithMarker<Network> apply(Object input) {
return api.getNetworkApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseOperations extends ParseJson<ListPage<Operation>> {
@Inject
public ParseOperations(Json json) {
super(json, new TypeLiteral<ListPage<Operation>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Operation, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Operation>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Operation>>() {
@Override
public IterableWithMarker<Operation> apply(Object input) {
return api.getOperationApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.functions.internal;
import com.google.common.base.Function;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Zone;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import javax.inject.Inject;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class ParseZones extends ParseJson<ListPage<Zone>> {
@Inject
public ParseZones(Json json) {
super(json, new TypeLiteral<ListPage<Zone>>() {});
}
public static class ToPagedIterable extends BaseToPagedIterable<Zone, ToPagedIterable> {
private final GoogleComputeEngineApi api;
@Inject
protected ToPagedIterable(GoogleComputeEngineApi api) {
this.api = checkNotNull(api, "api");
}
@Override
protected Function<Object, IterableWithMarker<Zone>> fetchNextPage(final String projectName,
final ListOptions options) {
return new Function<Object, IterableWithMarker<Zone>>() {
@Override
public IterableWithMarker<Zone> apply(Object input) {
return api.getZoneApiForProject(projectName).listAtMarker(input.toString(), options);
}
};
}
}
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.handlers;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Inject;
import java.net.URI;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class FirewallBinder implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
FirewallOptions options = (FirewallOptions) checkNotNull(postParams.get("options"), "firewallOptions");
String name = (String) checkNotNull(postParams.get("name"), "name");
URI network = (URI) checkNotNull(postParams.get("network"), "network");
options.name(name);
options.network(network);
return bindToRequest(request, options);
}
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return jsonBinder.bindToRequest(request, input);
}
}

View File

@ -0,0 +1,66 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.handlers;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import javax.inject.Singleton;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
/**
* This will parse and set an appropriate exception on the command object.
*
* @author Adrian Cole
*/
@Singleton
public class GoogleComputeEngineErrorHandler implements HttpErrorHandler {
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
byte[] data = closeClientButKeepContentStream(response);
String message = data != null ? new String(data) : null;
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 400:
break;
case 401:
case 403:
exception = new AuthorizationException(message, exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
case 409:
exception = new IllegalStateException(message, exception);
break;
}
command.setException(exception);
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.handlers;
import com.google.common.base.Function;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Inject;
import javax.inject.Named;
import java.net.URI;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class InstanceBinder implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
@Inject
@Named("machineTypes")
Function<String, URI> machineTypesToURI;
@Inject
@Named("zones")
Function<String, URI> zonesToURI;
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
InstanceTemplate template = (InstanceTemplate) checkNotNull(postParams.get("template"), "template");
template.name(checkNotNull(postParams.get("name"), "name").toString());
template.zone(zonesToURI.apply((String) checkNotNull(postParams.get("zone"), "zone")));
if (template.getMachineTypeName() != null) {
template.machineType(machineTypesToURI.apply(template.getMachineTypeName()));
}
template.zone((String) null);
template.machineType((String) null);
return bindToRequest(request, template);
}
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return jsonBinder.bindToRequest(request, input);
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.handlers;
import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Inject;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class MetadataBinder implements Binder {
@Inject
private BindToJsonPayload jsonBinder;
@Override
@SuppressWarnings("unchecked")
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
Map<String, String> metadataEntries = (Map<String, String>) checkNotNull(input, "input metadata");
return jsonBinder.bindToRequest(request, new GoogleComputeEngineParserModule.Metadata(metadataEntries));
}
}

View File

@ -0,0 +1,168 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.googlecomputeengine.domain.Firewall;
import java.net.URI;
import java.util.Set;
/**
* Options to create a firewall.
*
* @see Firewall
* @author David Alves
*/
public class FirewallOptions {
private String name;
private URI network;
private ImmutableSet.Builder<String> sourceRanges = ImmutableSet.builder();
private ImmutableSet.Builder<String> sourceTags = ImmutableSet.builder();
private ImmutableSet.Builder<String> targetTags = ImmutableSet.builder();
private ImmutableSet.Builder<Firewall.Rule> allowed = ImmutableSet.builder();
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getAllowed()
*/
public Set<Firewall.Rule> getAllowed() {
return allowed.build();
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getAllowed()
*/
public FirewallOptions addAllowedRule(Firewall.Rule allowedRule) {
this.allowed.add(allowedRule);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getAllowed()
*/
public FirewallOptions allowedRules(Set<Firewall.Rule> allowedRules) {
this.allowed = ImmutableSet.builder();
this.allowed.addAll(allowedRules);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getName()
*/
public FirewallOptions name(String name) {
this.name = name;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getName()
*/
public String getName() {
return name;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getNetwork()
*/
public FirewallOptions network(URI network) {
this.network = network;
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getNetwork()
*/
public URI getNetwork() {
return network;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceRanges()
*/
public Set<String> getSourceRanges() {
return sourceRanges.build();
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceRanges()
*/
public FirewallOptions addSourceRange(String sourceRange) {
this.sourceRanges.add(sourceRange);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceRanges()
*/
public FirewallOptions sourceRanges(Set<String> sourceRanges) {
this.sourceRanges = ImmutableSet.builder();
this.sourceRanges.addAll(sourceRanges);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceTags()
*/
public Set<String> getSourceTags() {
return sourceTags.build();
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceTags()
*/
public FirewallOptions addSourceTag(String sourceTag) {
this.sourceTags.add(sourceTag);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getSourceTags()
*/
public FirewallOptions sourceTags(Set<String> sourceTags) {
this.sourceTags = ImmutableSet.builder();
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getTargetTags()
*/
public Set<String> getTargetTags() {
return targetTags.build();
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getTargetTags()
*/
public FirewallOptions addTargetTag(String targetTag) {
this.targetTags.add(targetTag);
return this;
}
/**
* @see org.jclouds.googlecomputeengine.domain.Firewall#getTargetTags()
*/
public FirewallOptions targetTags(Set<String> targetTags) {
this.targetTags = ImmutableSet.builder();
this.targetTags.addAll(targetTags);
return this;
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Allows to optionally specify a filter, max results and a page token for <code>listFirstPage()</code> REST methods.
*
* @author David Alves
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations/listFirstPage"/>
*/
public class ListOptions extends BaseHttpRequestOptions {
/**
* Optional. Filter expression for filtering listed resources, in the form filter={expression}. Your {expression}
* must contain the following:
* <p/>
* {@code <field_name> <comparison_string> <literal_string>}
* <ul>
* <li>{@code <field_name>}: The name of the field you want to compare. The field name must be valid for the
* type of resource being filtered. Only atomic field types are supported (string, number,
* boolean). Array and object fields are not currently supported.</li>
* <li>{@code <comparison_string>}: The comparison string, either eq (equals) or ne (not equals).</li>
* <li>{@code <literal_string>}: The literal string value to filter to. The literal value must be valid
* for the type of field (string, number, boolean). For string fields, the literal value is interpreted as a
* regular expression using RE2 syntax. The literal value must match the entire field. For example,
* when filtering instances, name eq my_instance won't work, but name eq .*my_instance will work.</li>
* </ul>
* <p/>
* For example:
* <p/>
* {@code filter=status ne RUNNING}
* <p/>
* The above filter returns only results whose status field does not equal RUNNING. You can also enclose your
* literal string in single, double, or no quotes. For example, all three of the following would be valid
* expressions:
* <p/>
* {@code filter=status ne "RUNNING"}<br/>
* {@code filter=status ne 'RUNNING'}<br/>
* {@code filter=status ne RUNNING}<br/>
* <p/>
* Complex regular expressions can also be used, like the following:
* {@code name eq '."my_instance_[0-9]+'}
*/
public ListOptions filter(String filter) {
this.queryParameters.put("filter", checkNotNull(filter, "filter"));
return this;
}
/**
* Sets Maximum count of results to be returned. Maximum and default value is 100. Acceptable values are 0 to
* 100, inclusive. (Default: 100)
*/
public ListOptions maxResults(Integer maxResults) {
this.queryParameters.put("maxResults", checkNotNull(maxResults, "maxResults") + "");
return this;
}
public static class Builder {
/**
* @see ListOptions#filter(String)
*/
public ListOptions filter(String filter) {
return new ListOptions().filter(filter);
}
/**
* @see ListOptions#maxResults(Integer)
*/
public ListOptions maxResults(Integer maxResults) {
return new ListOptions().maxResults(maxResults);
}
}
}

View File

@ -0,0 +1,63 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.predicates;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Operation;
import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Tests that an Operation is done, returning the completed Operation when it is.
*
* @author David Alves
*/
public class OperationDonePredicate implements Predicate<AtomicReference<Operation>> {
private final GoogleComputeEngineApi api;
private final Supplier<String> project;
@Inject
OperationDonePredicate(GoogleComputeEngineApi api, @UserProject Supplier<String> project) {
this.api = api;
this.project = project;
}
@Override
public boolean apply(AtomicReference<Operation> input) {
checkNotNull(input, "input");
Operation current = api.getOperationApiForProject(project.get()).get(input.get().getName());
switch (current.getStatus()) {
case DONE:
input.set(current);
return true;
case PENDING:
case RUNNING:
default:
return false;
}
}
}

View File

@ -0,0 +1 @@
org.jclouds.googlecomputeengine.GoogleComputeEngineApiMetadata

View File

@ -0,0 +1,41 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import org.jclouds.View;
import org.jclouds.apis.internal.BaseApiMetadataTest;
import org.testng.annotations.Test;
/**
* Tests that GoogleComputeApiMetadata is properly registered in ServiceLoader
* <p/>
* <pre>
* META-INF/services/org.jclouds.apis.ApiMetadata
* </pre>
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "GoogleComputeApiMetadataTest")
public class GoogleComputeEngineApiMetadataTest extends BaseApiMetadataTest {
public GoogleComputeEngineApiMetadataTest() {
super(new GoogleComputeEngineApiMetadata(), ImmutableSet.<TypeToken<? extends View>>of());
}
}

View File

@ -0,0 +1,39 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import org.jclouds.oauth.v2.internal.BaseOAuthAuthenticatedApiLiveTest;
import org.testng.annotations.Test;
/**
* @author David Alves
*/
@Test(groups = "live")
public class GoogleComputeEngineAuthenticatedRestContextLiveTest extends BaseOAuthAuthenticatedApiLiveTest<GoogleComputeEngineApi> {
public GoogleComputeEngineAuthenticatedRestContextLiveTest() {
provider = "google-compute-engine";
}
@Override
public String getScopes() {
return GoogleComputeEngineConstants.COMPUTE_SCOPE;
}
}

View File

@ -0,0 +1,119 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.features.ImageApi;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.testng.Assert.assertSame;
/**
* A test specifically for the paging system. The code used is common to all list() methods so we're using Images
* but it could be anything else.
*
* @author David Alves
*/
@Test(groups = "unit")
public class PageSystemExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public void testGetSinglePage() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list_single_page.json")).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject");
PagedIterable<Image> images = imageApi.list();
// expect one page
assertSame(images.size(), 1);
// with three images
assertSame(images.concat().size(), 3);
}
public void testGetMultiplePages() {
HttpRequest list1 = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images?maxResults=3")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpRequest list2 = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images?pageToken" +
"=CgVJTUFHRRIbZ29vZ2xlLmNlbnRvcy02LTItdjIwMTIwNjIx&maxResults=3")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpRequest list3 = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images?pageToken" +
"=CgVJTUFHRRIbZ29vZ2xlLmdjZWwtMTAtMDQtdjIwMTIxMTA2&maxResults=3")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse list1response = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list_multiple_page_1.json")).build();
HttpResponse list2Response = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list_multiple_page_2.json")).build();
HttpResponse list3Response = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list_single_page.json")).build();
ImageApi imageApi = orderedRequestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list1, list1response, list2, list2Response, list3, list3Response)
.getImageApiForProject("myproject");
PagedIterable<Image> images = imageApi.list(new ListOptions.Builder().maxResults(3));
int imageCounter = 0;
for (IterableWithMarker<Image> page : images) {
for (Image image : page) {
imageCounter++;
}
}
assertSame(imageCounter, 9);
}
}

View File

@ -0,0 +1,415 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location;
import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.features.InstanceApiExpectTest;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineServiceExpectTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.jclouds.googlecomputeengine.features.FirewallApiExpectTest.GET_FIREWALL_REQUEST;
import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_PROJECT_IMAGES_REQUEST;
import static org.jclouds.googlecomputeengine.features.ImageApiExpectTest.LIST_PROJECT_IMAGES_RESPONSE;
import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_INSTANCES_REQUEST;
import static org.jclouds.googlecomputeengine.features.InstanceApiExpectTest.LIST_INSTANCES_RESPONSE;
import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_MACHINE_TYPES_REQUEST;
import static org.jclouds.googlecomputeengine.features.MachineTypeApiExpectTest.LIST_MACHINE_TYPES_RESPONSE;
import static org.jclouds.googlecomputeengine.features.NetworkApiExpectTest.GET_NETWORK_REQUEST;
import static org.jclouds.googlecomputeengine.features.OperationApiExpectTest.GET_OPERATION_REQUEST;
import static org.jclouds.googlecomputeengine.features.OperationApiExpectTest.GET_OPERATION_RESPONSE;
import static org.jclouds.googlecomputeengine.features.ZoneApiExpectTest.LIST_ZONES_REQ;
import static org.jclouds.googlecomputeengine.features.ZoneApiExpectTest.LIST_ZONES_RESPONSE;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class GoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngineServiceExpectTest {
public static final HttpRequest LIST_GOOGLE_IMAGES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/google/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_GOOGLE_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/image_list_single_page.json")).build();
private HttpRequest INSERT_NETWORK_REQUEST = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromStringWithContentType("{\"name\":\"jclouds-test\",\"IPv4Range\":\"10.0.0.0/8\"}",
MediaType.APPLICATION_JSON))
.build();
private HttpRequest INSERT_FIREWALL_REQUEST = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromStringWithContentType("{\"name\":\"jclouds-test\",\"network\":\"https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/jclouds-test\"," +
"\"sourceRanges\":[\"10.0.0.0/8\",\"0.0.0.0/0\"],\"allowed\":[{\"IPProtocol\":\"tcp\"," +
"\"ports\":[\"22\"]}," +
"{\"IPProtocol\":\"udp\",\"ports\":[\"22\"]}]}",
MediaType.APPLICATION_JSON))
.build();
private HttpResponse GET_NETWORK_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType("{\n" +
" \"kind\": \"compute#network\",\n" +
" \"id\": \"13024414170909937976\",\n" +
" \"creationTimestamp\": \"2012-10-24T20:13:19.967\",\n" +
" \"selfLink\": \"https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/jclouds-test\",\n" +
" \"name\": \"jclouds-test\",\n" +
" \"description\": \"test network\",\n" +
" \"IPv4Range\": \"10.0.0.0/8\",\n" +
" \"gatewayIPv4\": \"10.0.0.1\"\n" +
"}", MediaType.APPLICATION_JSON)).build();
private HttpResponse SUCESSFULL_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
private HttpResponse getInstanceResponseForInstanceAndNetworkAndStatus(String instanceName, String networkName,
String status) throws
IOException {
return HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType(
replaceInstanceNameNetworkAndStatusOnResource("/instance_get.json",
instanceName, networkName, status),
"application/json")).build();
}
private HttpResponse getListInstancesResponseForSingleInstanceAndNetworkAndStatus(String instanceName,
String networkName,
String status) {
return HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType(
replaceInstanceNameNetworkAndStatusOnResource("/instance_list.json",
instanceName, networkName, status),
"application/json")).build();
}
private String replaceInstanceNameNetworkAndStatusOnResource(String resourceName, String instanceName,
String networkName, String status) {
try {
return Strings2.toStringAndClose(this.getClass().getResourceAsStream(resourceName)).replace("test-0",
instanceName).replace("default", networkName).replace("RUNNING", status);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
private HttpRequest createInstanceRequestForInstance(String instanceName, String networkName, String publicKey) {
return HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromStringWithContentType("{\"name\":\"" + instanceName + "\"," +
"\"machineType\":\"https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1\"," +
"\"zone\":\"https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/zones/us-central1-a\"," +
"\"image\":\"https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106\"," +
"\"tags\":[],\"serviceAccounts\":[]," +
"\"networkInterfaces\":[{\"network\":\"https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/" + networkName + "\"," +
"\"accessConfigs\":[{\"type\":\"ONE_TO_ONE_NAT\"}]}]," +
"\"metadata\":{\"kind\":\"compute#metadata\",\"items\":[{\"key\":\"sshKeys\"," +
"\"value\":\"jclouds:" +
publicKey + " jclouds@localhost\"}]}}",
MediaType.APPLICATION_JSON)).build();
}
private HttpRequest getInstanceRequestForInstance(String instanceName) {
return HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/" + instanceName)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
}
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
overrides.put("google-compute-engine.identity", "myproject");
try {
overrides.put("google-compute-engine.credential", toStringAndClose(getClass().getResourceAsStream("/testpk.pem")));
} catch (IOException e) {
Throwables.propagate(e);
}
return overrides;
}
@Test(enabled = false)
public void testThrowsAuthorizationException() throws Exception {
Properties properties = new Properties();
properties.setProperty("oauth.identity", "MOMMA");
properties.setProperty("oauth.credential", "MiA");
ComputeService client = requestsSendResponses(ImmutableMap.<HttpRequest, HttpResponse>of(), createModule(),
properties);
Template template = client.templateBuilder().build();
Template toMatch = client.templateBuilder().imageId(template.getImage().getId()).build();
assertEquals(toMatch.getImage(), template.getImage());
}
@Test
public void testTemplateMatch() throws Exception {
ImmutableMap<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.
<HttpRequest, HttpResponse>builder()
.put(requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE)
.put(LIST_ZONES_REQ, LIST_ZONES_RESPONSE)
.put(LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE)
.put(LIST_GOOGLE_IMAGES_REQUEST, LIST_GOOGLE_IMAGES_RESPONSE)
.put(LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE)
.build();
ComputeService client = requestsSendResponses(requestResponseMap);
Template template = client.templateBuilder().build();
Template toMatch = client.templateBuilder().imageId(template.getImage().getId()).build();
assertEquals(toMatch.getImage(), template.getImage());
}
@Test
public void testNetworksAndFirewallDeletedWhenAllGroupNodesAreTerminated() throws IOException {
HttpRequest deleteNodeRequest = HttpRequest.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-delete-networks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpRequest deleteFirewallRequest = HttpRequest.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test-delete")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpRequest deleteNetworkReqquest = HttpRequest.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/jclouds-test-delete")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
List<HttpRequest> orderedRequests = ImmutableList.<HttpRequest>builder()
.add(requestForScopes(COMPUTE_READONLY_SCOPE))
.add(getInstanceRequestForInstance("test-delete-networks"))
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_ZONES_REQ)
.add(LIST_MACHINE_TYPES_REQUEST)
.add(requestForScopes(COMPUTE_SCOPE))
.add(deleteNodeRequest)
.add(GET_OPERATION_REQUEST)
.add(getInstanceRequestForInstance("test-delete-networks"))
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_ZONES_REQ)
.add(LIST_MACHINE_TYPES_REQUEST)
.add(LIST_INSTANCES_REQUEST)
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_ZONES_REQ)
.add(LIST_MACHINE_TYPES_REQUEST)
.add(deleteFirewallRequest)
.add(GET_OPERATION_REQUEST)
.add(deleteNetworkReqquest)
.add(GET_OPERATION_REQUEST)
.build();
List<HttpResponse> orderedResponses = ImmutableList.<HttpResponse>builder()
.add(TOKEN_RESPONSE)
.add(getInstanceResponseForInstanceAndNetworkAndStatus("test-delete-networks", "test-network", Instance
.Status.RUNNING.name()))
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.add(TOKEN_RESPONSE)
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.add(getInstanceResponseForInstanceAndNetworkAndStatus("test-delete-networks", "test-network", Instance
.Status.TERMINATED.name()))
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.add(getListInstancesResponseForSingleInstanceAndNetworkAndStatus("test-delete-networks",
"test-network", Instance
.Status.TERMINATED.name()))
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.build();
ComputeService client = orderedRequestsSendResponses(orderedRequests, orderedResponses);
client.destroyNode("test-delete-networks");
}
public void testListLocationsWhenResponseIs2xx() throws Exception {
ImmutableMap<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.
<HttpRequest, HttpResponse>builder()
.put(requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE)
.put(LIST_ZONES_REQ, LIST_ZONES_RESPONSE)
.put(LIST_INSTANCES_REQUEST, LIST_INSTANCES_RESPONSE)
.put(LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE)
.put(LIST_GOOGLE_IMAGES_REQUEST, LIST_GOOGLE_IMAGES_RESPONSE)
.put(LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE)
.build();
ComputeService apiWhenServersExist = requestsSendResponses(requestResponseMap);
Set<? extends Location> locations = apiWhenServersExist.listAssignableLocations();
assertNotNull(locations);
assertEquals(locations.size(), 2);
assertEquals(locations.iterator().next().getId(), "us-central1-a");
assertNotNull(apiWhenServersExist.listNodes());
assertEquals(apiWhenServersExist.listNodes().size(), 1);
assertEquals(apiWhenServersExist.listNodes().iterator().next().getId(), "test-0");
assertEquals(apiWhenServersExist.listNodes().iterator().next().getName(), "test-0");
}
@Test(dependsOnMethods = "testListLocationsWhenResponseIs2xx")
public void testCreateNodeWhenNetworkNorFirewallExistDoesNotExist() throws RunNodesException, IOException {
String payload = Strings2.toStringAndClose(InstanceApiExpectTest.class.getResourceAsStream("/instance_get.json"));
payload = payload.replace("test-0", "test-1");
HttpResponse getInstanceResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromStringWithContentType(payload, "application/json")).build();
List<HttpRequest> orderedRequests = ImmutableList.<HttpRequest>builder()
.add(requestForScopes(COMPUTE_READONLY_SCOPE))
.add(LIST_ZONES_REQ)
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_MACHINE_TYPES_REQUEST)
.add(GET_NETWORK_REQUEST)
.add(requestForScopes(COMPUTE_SCOPE))
.add(INSERT_NETWORK_REQUEST)
.add(GET_OPERATION_REQUEST)
.add(GET_NETWORK_REQUEST)
.add(GET_FIREWALL_REQUEST)
.add(INSERT_FIREWALL_REQUEST)
.add(GET_OPERATION_REQUEST)
.add(LIST_INSTANCES_REQUEST)
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_ZONES_REQ)
.add(LIST_MACHINE_TYPES_REQUEST)
.add(createInstanceRequestForInstance("test-1", "jclouds-test", openSshKey))
.add(GET_OPERATION_REQUEST)
.add(getInstanceRequestForInstance("test-1"))
.add(LIST_PROJECT_IMAGES_REQUEST)
.add(LIST_GOOGLE_IMAGES_REQUEST)
.add(LIST_ZONES_REQ)
.add(LIST_MACHINE_TYPES_REQUEST)
.build();
List<HttpResponse> orderedResponses = ImmutableList.<HttpResponse>builder()
.add(TOKEN_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.add(HttpResponse.builder().statusCode(404).build())
.add(TOKEN_RESPONSE)
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.add(GET_NETWORK_RESPONSE)
.add(HttpResponse.builder().statusCode(404).build())
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.add(LIST_INSTANCES_RESPONSE)
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.add(SUCESSFULL_OPERATION_RESPONSE)
.add(GET_OPERATION_RESPONSE)
.add(getInstanceResponse)
.add(LIST_PROJECT_IMAGES_RESPONSE)
.add(LIST_GOOGLE_IMAGES_RESPONSE)
.add(LIST_ZONES_RESPONSE)
.add(LIST_MACHINE_TYPES_RESPONSE)
.build();
ComputeService computeService = orderedRequestsSendResponses(orderedRequests, orderedResponses);
GoogleComputeEngineTemplateOptions options = computeService.templateOptions().as(GoogleComputeEngineTemplateOptions.class);
getOnlyElement(computeService.createNodesInGroup("test", 1, options));
}
}

View File

@ -0,0 +1,92 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute;
import static org.testng.Assert.assertTrue;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
/**
* @author David Alves
*/
@Test(groups = "live", singleThreaded = true)
public class GoogleComputeEngineServiceLiveTest extends BaseComputeServiceLiveTest {
public GoogleComputeEngineServiceLiveTest() {
provider = "google-compute-engine";
}
/**
* Nodes may have additional metadata entries (particularly they may have an "sshKeys" entry)
*/
protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
assertTrue(node.getUserMetadata().keySet().containsAll(userMetadata.keySet()));
}
// do not run until the auth exception problem is figured out.
@Test(enabled = false)
@Override
public void testCorrectAuthException() throws Exception {
}
// reboot is not supported by GCE
@Test(enabled = true, dependsOnMethods = "testGet")
public void testReboot() throws Exception {
}
// suspend/Resume is not supported by GCE
@Test(enabled = true, dependsOnMethods = "testReboot")
public void testSuspendResume() throws Exception {
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodesByIds() throws Exception {
super.testGetNodesWithDetails();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testGetNodesWithDetails() throws Exception {
super.testGetNodesWithDetails();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
@Override
public void testListNodes() throws Exception {
super.testListNodes();
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails", "testListNodesByIds" })
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
@Override
protected Module getSshModule() {
return new SshjSshClientModule();
}
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.googlecomputeengine.domain.Image;
import org.testng.annotations.Test;
import java.net.URI;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class GoogleComputeEngineImageToImageTest {
Image.Builder imageBuilder = Image.builder()
.id("1234")
.selfLink(URI.create("http://test.com"))
.sourceType("RAW")
.description("")
.rawDisk(Image.RawDisk.builder().source("").containerType("TAR").build());
public void testArbitratyImageName() {
GoogleComputeEngineImageToImage imageToImage = new GoogleComputeEngineImageToImage();
Image image = imageBuilder.name("arbitratyname").build();
org.jclouds.compute.domain.Image transformed = imageToImage.apply(image);
assertEquals(transformed.getName(), image.getName());
assertEquals(transformed.getId(), image.getName());
assertEquals(transformed.getProviderId(), image.getId());
assertSame(transformed.getOperatingSystem().getFamily(), OsFamily.LINUX);
}
public void testWellFormedImageName() {
GoogleComputeEngineImageToImage imageToImage = new GoogleComputeEngineImageToImage();
Image image = imageBuilder.name("ubuntu-12-04-v123123").build();
org.jclouds.compute.domain.Image transformed = imageToImage.apply(image);
assertEquals(transformed.getName(), image.getName());
assertEquals(transformed.getId(), image.getName());
assertEquals(transformed.getProviderId(), image.getId());
assertSame(transformed.getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assertEquals(transformed.getOperatingSystem().getVersion(), "12.04");
}
}

View File

@ -0,0 +1,141 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.compute.functions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.easymock.EasyMock;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
import org.testng.annotations.Test;
import java.util.Set;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
public class OrphanedGroupsFromDeadNodesTest {
private static class IdAndGroupOnlyNodeMetadata extends NodeMetadataImpl {
public IdAndGroupOnlyNodeMetadata(String id, String group, Status status) {
super(null, null, id, null, null, ImmutableMap.<String, String>of(), ImmutableSet.<String>of(), group, null,
null, null, status, null, 0, ImmutableSet.<String>of(), ImmutableSet.<String>of(), null, null);
}
}
@Test
public void testDetectsAllOrphanedGroupsWhenAllNodesTerminated() {
Set<? extends NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
Set<? extends NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
Set<? extends NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
ComputeService mock = createMock(ComputeService.class);
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) deadNodesGroup1).once();
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) deadNodesGroup2).once();
replay(mock);
OrphanedGroupsFromDeadNodes orphanedGroupsFromDeadNodes = new OrphanedGroupsFromDeadNodes(new
AllNodesInGroupTerminated(mock));
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
assertSame(orphanedGroups.size(), 2);
assertTrue(orphanedGroups.contains("1"));
assertTrue(orphanedGroups.contains("2"));
}
@Test
public void testDetectsAllOrphanedGroupsWhenSomeNodesTerminatedAndOtherMissing() {
Set<? extends NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
Set<? extends NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.TERMINATED)).build();
Set<? extends NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
ComputeService mock = createMock(ComputeService.class);
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) deadNodesGroup1).once();
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) ImmutableSet.of()).once();
replay(mock);
OrphanedGroupsFromDeadNodes orphanedGroupsFromDeadNodes = new OrphanedGroupsFromDeadNodes(new
AllNodesInGroupTerminated(mock));
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
assertSame(orphanedGroups.size(), 2);
assertTrue(orphanedGroups.contains("1"));
assertTrue(orphanedGroups.contains("2"));
}
@Test
public void testDetectsAllOrphanedGroupsWhenSomeNodesAreAlive() {
Set<? extends NodeMetadata> deadNodesGroup1 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("a", "1", NodeMetadata.Status.TERMINATED)).build();
Set<? extends NodeMetadata> deadNodesGroup2 = (Set) ImmutableSet.builder()
.add(new IdAndGroupOnlyNodeMetadata("b", "2", NodeMetadata.Status.RUNNING)).build();
Set<? extends NodeMetadata> allDeadNodes = Sets.union(deadNodesGroup1, deadNodesGroup2);
ComputeService mock = createMock(ComputeService.class);
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) deadNodesGroup1).once();
expect(mock.listNodesDetailsMatching(EasyMock.<Predicate<ComputeMetadata>>anyObject()))
.andReturn((Set) deadNodesGroup2).once();
replay(mock);
OrphanedGroupsFromDeadNodes orphanedGroupsFromDeadNodes = new OrphanedGroupsFromDeadNodes(new
AllNodesInGroupTerminated(mock));
Set<String> orphanedGroups = orphanedGroupsFromDeadNodes.apply(allDeadNodes);
assertSame(orphanedGroups.size(), 1);
assertTrue(orphanedGroups.contains("1"));
}
}

View File

@ -0,0 +1,172 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseDiskListTest;
import org.jclouds.googlecomputeengine.parse.ParseDiskTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class DiskApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public void testGetDiskResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/disk_get.json")).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getDiskApiForProject("myproject");
assertEquals(api.get("testimage1"),
new ParseDiskTest().expected());
}
public void testGetDiskResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/testimage1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getDiskApiForProject("myproject");
assertNull(api.get("testimage1"));
}
public void testInsertDiskResponseIs2xx() {
HttpRequest insert = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/disk_insert.json", MediaType.APPLICATION_JSON))
.build();
HttpResponse insertDiskResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert,
insertDiskResponse).getDiskApiForProject("myproject");
assertEquals(api.createInZone("testimage1", 1, URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
, new ParseOperationTest().expected());
}
public void testDeleteDiskResponseIs2xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/disks/testimage1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getDiskApiForProject("myproject");
assertEquals(api.delete("testimage1"),
new ParseOperationTest().expected());
}
public void testDeleteDiskResponseIs4xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/disks/testimage1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getDiskApiForProject("myproject");
assertNull(api.delete("testimage1"));
}
public void testListDisksResponseIs2xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/disks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/disk_list.json")).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getDiskApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseDiskListTest().expected().toString());
}
public void testListDisksResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/disks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
DiskApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getDiskApiForProject("myproject");
assertTrue(api.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.net.URI;
import java.util.List;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* @author David Alves
*/
public class DiskApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String DISK_NAME = "disk-api-live-test-disk";
private static final int TIME_WAIT = 10;
private URI zoneUrl;
private int sizeGb = 1;
private DiskApi api() {
return api.getDiskApiForProject(userProject.get());
}
@Test(groups = "live")
public void testInsertDisk() {
Project project = api.getProjectApi().get(userProject.get());
zoneUrl = getDefaultZoneUrl(project.getName());
assertOperationDoneSucessfully(api().createInZone(DISK_NAME, sizeGb, zoneUrl), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertDisk")
public void testGetDisk() {
Disk disk = api().get(DISK_NAME);
assertNotNull(disk);
assertDiskEquals(disk);
}
@Test(groups = "live", dependsOnMethods = "testGetDisk")
public void testListDisk() {
PagedIterable<Disk> disks = api().list(new ListOptions.Builder()
.filter("name eq " + DISK_NAME));
List<Disk> disksAsList = Lists.newArrayList(disks.concat());
assertEquals(disksAsList.size(), 1);
assertDiskEquals(Iterables.getOnlyElement(disksAsList));
}
@Test(groups = "live", dependsOnMethods = "testListDisk")
public void testDeleteDisk() {
assertOperationDoneSucessfully(api().delete(DISK_NAME), TIME_WAIT);
}
private void assertDiskEquals(Disk result) {
assertEquals(result.getName(), DISK_NAME);
assertEquals(result.getSizeGb(), sizeGb);
assertEquals(result.getZone(), zoneUrl);
}
}

View File

@ -0,0 +1,305 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.googlecomputeengine.parse.ParseFirewallListTest;
import org.jclouds.googlecomputeengine.parse.ParseFirewallTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payload;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.util.Set;
import static com.google.common.base.Joiner.on;
import static com.google.common.collect.Iterables.transform;
import static java.lang.String.format;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
import static org.jclouds.io.Payloads.newStringPayload;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class FirewallApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final HttpRequest GET_FIREWALL_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static HttpResponse GET_FIREWALL_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/firewall_get.json")).build();
public void testGetFirewallResponseIs2xx() throws Exception {
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_FIREWALL_REQUEST, GET_FIREWALL_RESPONSE).getFirewallApiForProject("myproject");
assertEquals(api.get("jclouds-test"), new ParseFirewallTest().expected());
}
public static Payload firewallPayloadFirewallOfName(String firewallName,
String networkName,
Set<String> sourceRanges,
Set<String> sourceTags,
Set<String> targetTags,
Set<String> portRanges) throws IOException {
Function<String, String> addQuotes = new Function<String, String>() {
@Override
public String apply(String input) {
return "\"" + input + "\"";
}
};
String ports = on(",").skipNulls().join(transform(portRanges, addQuotes));
Payload payload = newStringPayload(
format(toStringAndClose(FirewallApiExpectTest.class.getResourceAsStream("/firewall_insert.json")),
firewallName,
networkName,
on(",").skipNulls().join(transform(sourceRanges, addQuotes)),
on(",").skipNulls().join(transform(sourceTags, addQuotes)),
on(",").skipNulls().join(transform(targetTags, addQuotes)),
ports,
ports));
payload.getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
return payload;
}
public void testGetFirewallResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getFirewallApiForProject("myproject");
assertNull(api.get("jclouds-test"));
}
public void testInsertFirewallResponseIs2xx() throws IOException {
HttpRequest request = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse insertFirewallResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, request, insertFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.createInNetwork("myfw", URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"),
new FirewallOptions()
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testUpdateFirewallResponseIs2xx() throws IOException {
HttpRequest update = HttpRequest
.builder()
.method("PUT")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse updateFirewallResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, update,
updateFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.update("myfw",
new FirewallOptions()
.name("myfw")
.network(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testPatchFirewallResponseIs2xx() throws IOException {
HttpRequest update = HttpRequest
.builder()
.method("PATCH")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse updateFirewallResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, update,
updateFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.patch("myfw",
new FirewallOptions()
.name("myfw")
.network(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testDeleteFirewallResponseIs2xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls/default-allow-internal")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getFirewallApiForProject("myproject");
assertEquals(api.delete("default-allow-internal"),
new ParseOperationTest().expected());
}
public void testDeleteFirewallResponseIs4xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls/default-allow-internal")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getFirewallApiForProject("myproject");
assertNull(api.delete("default-allow-internal"));
}
public void testListFirewallsResponseIs2xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/firewall_list.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getFirewallApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseFirewallListTest().expected().toString());
}
public void testListFirewallsResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/firewalls")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getFirewallApiForProject("myproject");
assertTrue(api.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,168 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.List;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.googlecomputeengine.domain.Firewall.Rule.IPProtocol;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* @author David Alves
*/
public class FirewallApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String FIREWALL_NAME = "firewall-api-live-test-firewall";
private static final String FIREWALL_NETWORK_NAME = "firewall-api-live-test-network";
private static final String IPV4_RANGE = "10.0.0.0/8";
private static final int TIME_WAIT = 30;
private FirewallApi api() {
return api.getFirewallApiForProject(userProject.get());
}
@Test(groups = "live")
public void testInsertFirewall() {
// need to create the network first
assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
(FIREWALL_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
FirewallOptions firewall = new FirewallOptions()
.addAllowedRule(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22).build())
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
assertOperationDoneSucessfully(api().createInNetwork(FIREWALL_NAME, getNetworkUrl(userProject.get(),
FIREWALL_NETWORK_NAME), firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertFirewall")
public void testUpdateFirewall() {
FirewallOptions firewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(userProject.get(),FIREWALL_NETWORK_NAME))
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2")
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()));
assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testUpdateFirewall")
public void testPatchFirewall() {
FirewallOptions firewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(userProject.get(),FIREWALL_NETWORK_NAME))
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.build(),
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()))
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testPatchFirewall")
public void testGetFirewall() {
FirewallOptions patchedFirewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(userProject.get(), FIREWALL_NETWORK_NAME))
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.build(),
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()))
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
Firewall firewall = api().get(FIREWALL_NAME);
assertNotNull(firewall);
assertFirewallEquals(firewall, patchedFirewall);
}
@Test(groups = "live", dependsOnMethods = "testGetFirewall")
public void testListFirewall() {
PagedIterable<Firewall> firewalls = api().list(new ListOptions.Builder()
.filter("name eq " + FIREWALL_NAME));
List<Firewall> firewallsAsList = Lists.newArrayList(firewalls.concat());
assertEquals(firewallsAsList.size(), 1);
}
@Test(groups = "live", dependsOnMethods = "testListFirewall")
public void testDeleteFirewall() {
assertOperationDoneSucessfully(api().delete(FIREWALL_NAME), TIME_WAIT);
assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
(FIREWALL_NETWORK_NAME), TIME_WAIT);
}
private void assertFirewallEquals(Firewall result, FirewallOptions expected) {
assertEquals(result.getName(), expected.getName());
assertEquals(getOnlyElement(result.getSourceRanges()), getOnlyElement(expected.getSourceRanges()));
assertEquals(getOnlyElement(result.getSourceTags()), getOnlyElement(expected.getSourceTags()));
assertEquals(getOnlyElement(result.getTargetTags()), getOnlyElement(expected.getTargetTags()));
assertEquals(result.getAllowed(), expected.getAllowed());
}
}

View File

@ -0,0 +1,144 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseImageListTest;
import org.jclouds.googlecomputeengine.parse.ParseImageTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class ImageApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final HttpRequest LIST_PROJECT_IMAGES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_PROJECT_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/image_list.json")).build();
public void testGetImageResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_get.json")).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getImageApiForProject("google");
assertEquals(imageApi.get("centos-6-2-v20120326"),
new ParseImageTest().expected());
}
public void testGetImageResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/centos-6-2-v20120326")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getImageApiForProject("google");
assertNull(imageApi.get("centos-6-2-v20120326"));
}
public void testDeleteImageResponseIs2xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getImageApiForProject("myproject");
assertEquals(imageApi.delete("centos-6-2-v20120326"),
new ParseOperationTest().expected());
}
public void testDeleteImageResponseIs4xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images/centos-6-2-v20120326")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getImageApiForProject("myproject");
assertNull(imageApi.delete("centos-6-2-v20120326"));
}
public void testListImagesResponseIs2xx() {
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE).getImageApiForProject
("myproject");
assertEquals(imageApi.listFirstPage().toString(),
new ParseImageListTest().expected().toString());
}
public void testListImagesResponseIs4xx() {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_PROJECT_IMAGES_REQUEST, operationResponse).getImageApiForProject("myproject");
assertTrue(imageApi.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,81 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.Iterator;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* TODO figure out how to test insert and delete as this requires an image .tar.gz to be present in GCS
*
* @author David Alves
*/
public class ImageApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private Image image;
private ImageApi api() {
return api.getImageApiForProject("google");
}
@Test(groups = "live")
public void testListImage() {
PagedIterable<Image> images = api().list(new ListOptions.Builder().maxResults(1));
Iterator<IterableWithMarker<Image>> pageIterator = images.iterator();
assertTrue(pageIterator.hasNext());
IterableWithMarker<Image> singlePageIterator = pageIterator.next();
List<Image> imageAsList = Lists.newArrayList(singlePageIterator);
assertSame(imageAsList.size(), 1);
this.image = Iterables.getOnlyElement(imageAsList);
}
@Test(groups = "live", dependsOnMethods = "testListImage")
public void testGetImage() {
Image image = api().get(this.image.getName());
assertNotNull(image);
assertImageEquals(image, this.image);
}
private void assertImageEquals(Image result, Image expected) {
assertEquals(result.getName(), expected.getName());
}
}

View File

@ -0,0 +1,230 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseInstanceListTest;
import org.jclouds.googlecomputeengine.parse.ParseInstanceSerialOutputTest;
import org.jclouds.googlecomputeengine.parse.ParseInstanceTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import static java.net.URI.create;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class InstanceApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final HttpRequest GET_INSTANCE_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse GET_INSTANCE_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/instance_get.json")).build();
public static final HttpRequest LIST_INSTANCES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_INSTANCES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/instance_list.json")).build();
public static final HttpResponse CREATE_INSTANCE_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/operation.json")).build();
public void testGetInstanceResponseIs2xx() throws Exception {
InstanceApi api = requestsSendResponses(
requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
GET_INSTANCE_REQUEST, GET_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
assertEquals(api.get("test-1"), new ParseInstanceTest().expected());
}
public void testGetInstanceResponseIs4xx() throws Exception {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_INSTANCE_REQUEST, operationResponse).getInstanceApiForProject("myproject");
assertNull(api.get("test-1"));
}
public void testGetInstanceSerialPortOutput() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-1/serialPort")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/instance_serial_port.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getInstanceApiForProject("myproject");
assertEquals(api.getSerialPortOutput("test-1"), new ParseInstanceSerialOutputTest().expected());
}
public void testInsertInstanceResponseIs2xxNoOptions() {
HttpRequest insert = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/instance_insert_simple.json", MediaType.APPLICATION_JSON))
.build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert,
CREATE_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
.addNetworkInterface(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"));
assertEquals(api.createInZone("test-1", options, "us-central1-a"), new ParseOperationTest().expected());
}
public void testInsertInstanceResponseIs2xxAllOptions() {
HttpRequest insert = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/instance_insert.json", MediaType.APPLICATION_JSON))
.build();
HttpResponse insertInstanceResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert, insertInstanceResponse).getInstanceApiForProject("myproject");
InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
.addNetworkInterface(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"), Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
.description("desc")
.image(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106"))
.addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE,
create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test"))
.addTag("aTag")
.addServiceAccount(Instance.ServiceAccount.builder().email("default").addScopes("myscope").build())
.addMetadata("aKey", "aValue");
assertEquals(api.createInZone("test-0", options, "us-central1-a"),
new ParseOperationTest().expected());
}
public void testDeleteInstanceResponseIs2xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
assertEquals(api.delete("test-1"),
new ParseOperationTest().expected());
}
public void testDeleteInstanceResponseIs4xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
assertNull(api.delete("test-1"));
}
public void testListInstancesResponseIs2xx() {
InstanceApi api = requestsSendResponses(
requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
LIST_INSTANCES_REQUEST, LIST_INSTANCES_RESPONSE).getInstanceApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseInstanceListTest().expected().toString());
}
public void testListInstancesResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getInstanceApiForProject("myproject");
assertTrue(api.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,123 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.List;
import java.util.Properties;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Module;
/**
* @author David Alves
*/
public class InstanceApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String INSTANCE_NETWORK_NAME = "instance-api-live-test-network";
private static final String INSTANCE_NAME = "instance-api-live-test-instance";
private static final String DISK_NAME = "instance-live-test-disk";
private static final String IPV4_RANGE = "10.0.0.0/8";
private static final int TIME_WAIT = 600;
private InstanceTemplate instance;
@Override
protected GoogleComputeEngineApi create(Properties props, Iterable<Module> modules) {
GoogleComputeEngineApi api = super.create(props, modules);
instance = InstanceTemplate.builder()
.forMachineType(getDefaultMachineTypekUrl(userProject.get()))
.addNetworkInterface(getNetworkUrl(userProject.get(), INSTANCE_NETWORK_NAME),
Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
.addMetadata("mykey", "myvalue")
.addTag("atag")
.description("a description")
.addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE, getDiskUrl(userProject.get(), DISK_NAME))
.zone(getDefaultZoneUrl(userProject.get()));
return api;
}
private InstanceApi api() {
return api.getInstanceApiForProject(userProject.get());
}
@Test(groups = "live")
public void testInsertInstance() {
// need to create the network first
assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).createInIPv4Range
(INSTANCE_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
assertOperationDoneSucessfully(api.getDiskApiForProject(userProject.get()).createInZone
("instance-live-test-disk", 1, getDefaultZoneUrl(userProject.get())), TIME_WAIT);
assertOperationDoneSucessfully(api().createInZone(INSTANCE_NAME, instance, DEFAULT_ZONE_NAME), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
public void testGetInstance() {
Instance instance = api().get(INSTANCE_NAME);
assertNotNull(instance);
assertInstanceEquals(instance, this.instance);
}
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
public void testListInstance() {
PagedIterable<Instance> instances = api().list(new ListOptions.Builder()
.filter("name eq " + INSTANCE_NAME));
List<Instance> instancesAsList = Lists.newArrayList(instances.concat());
assertEquals(instancesAsList.size(), 1);
assertInstanceEquals(Iterables.getOnlyElement(instancesAsList), instance);
}
@Test(groups = "live", dependsOnMethods = "testListInstance")
public void testDeleteInstance() {
assertOperationDoneSucessfully(api().delete(INSTANCE_NAME), TIME_WAIT);
assertOperationDoneSucessfully(api.getDiskApiForProject(userProject.get()).delete(DISK_NAME),
TIME_WAIT);
assertOperationDoneSucessfully(api.getNetworkApiForProject(userProject.get()).delete
(INSTANCE_NETWORK_NAME), TIME_WAIT);
}
private void assertInstanceEquals(Instance result, InstanceTemplate expected) {
assertEquals(result.getName(), expected.getName());
assertEquals(result.getTags(), expected.getTags());
assertEquals(result.getMetadata(), expected.getMetadata());
}
}

View File

@ -0,0 +1,112 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseKernelListTest;
import org.jclouds.googlecomputeengine.parse.ParseKernelTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class KernelApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public void testGetKernelResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/kernels/12941177846308850718")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/kernel.json")).build();
KernelApi kernelApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getKernelApiForProject("myproject");
assertEquals(kernelApi.get("12941177846308850718"),
new ParseKernelTest().expected());
}
public void testGetKernelResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/kernels/12941177846308850718")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
KernelApi kernelApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getKernelApiForProject("myproject");
assertNull(kernelApi.get("12941177846308850718"));
}
public void testListKernelNoOptionsResponseIs2xx() throws Exception {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/kernels")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/kernel_list.json")).build();
KernelApi kernelApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getKernelApiForProject("myproject");
assertEquals(kernelApi.listFirstPage().toString(),
new ParseKernelListTest().expected().toString());
}
public void testListKernelsResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/kernels")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
KernelApi kernelApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getKernelApiForProject("myproject");
assertTrue(kernelApi.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,79 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Kernel;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.Iterator;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
public class KernelApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private Kernel kernel;
private KernelApi api() {
return api.getKernelApiForProject("google");
}
@Test(groups = "live")
public void testListKernel() {
PagedIterable<Kernel> kernels = api().list(new ListOptions.Builder()
.maxResults(1));
Iterator<IterableWithMarker<Kernel>> pageIterator = kernels.iterator();
assertTrue(pageIterator.hasNext());
IterableWithMarker<Kernel> singlePageIterator = pageIterator.next();
List<Kernel> kernelAsList = Lists.newArrayList(singlePageIterator);
assertSame(kernelAsList.size(), 1);
this.kernel = Iterables.getOnlyElement(kernelAsList);
}
@Test(groups = "live", dependsOnMethods = "testListKernel")
public void testGetKernel() {
Kernel kernel = api().get(this.kernel.getName());
assertNotNull(kernel);
assertKernelEquals(kernel, this.kernel);
}
private void assertKernelEquals(Kernel result, Kernel expected) {
assertEquals(result.getName(), expected.getName());
}
}

View File

@ -0,0 +1,107 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseMachineTypeListTest;
import org.jclouds.googlecomputeengine.parse.ParseMachineTypeTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class MachineTypeApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final HttpRequest LIST_MACHINE_TYPES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_MACHINE_TYPES_RESPONSE = HttpResponse.builder()
.statusCode(200)
.payload(staticPayloadFromResource("/machinetype_list.json"))
.build();
public void testGetMachineTypeResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/machinetype.json")).build();
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getMachineTypeApiForProject("myproject");
assertEquals(machineTypeApi.get("n1-standard-1"),
new ParseMachineTypeTest().expected());
}
public void testGetMachineTypeResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getMachineTypeApiForProject("myproject");
assertNull(machineTypeApi.get("n1-standard-1"));
}
public void testListMachineTypeNoOptionsResponseIs2xx() throws Exception {
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE).getMachineTypeApiForProject
("myproject");
assertEquals(machineTypeApi.listFirstPage().toString(),
new ParseMachineTypeListTest().expected().toString());
}
public void testLisOperationWithPaginationOptionsResponseIs4xx() {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, operationResponse).getMachineTypeApiForProject("myproject");
assertTrue(machineTypeApi.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,78 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.Iterator;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
public class MachineTypeApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private MachineType machineType;
private MachineTypeApi api() {
return api.getMachineTypeApiForProject(userProject.get());
}
@Test(groups = "live")
public void testListMachineType() {
PagedIterable<MachineType> machineTypes = api().list(new ListOptions.Builder()
.maxResults(1));
Iterator<IterableWithMarker<MachineType>> pageIterator = machineTypes.iterator();
assertTrue(pageIterator.hasNext());
IterableWithMarker<MachineType> singlePageIterator = pageIterator.next();
List<MachineType> machineTypeAsList = Lists.newArrayList(singlePageIterator);
assertSame(machineTypeAsList.size(), 1);
this.machineType = Iterables.getOnlyElement(machineTypeAsList);
}
@Test(groups = "live", dependsOnMethods = "testListMachineType")
public void testGetMachineType() {
MachineType machineType = api().get(this.machineType.getName());
assertNotNull(machineType);
assertMachineTypeEquals(machineType, this.machineType);
}
private void assertMachineTypeEquals(MachineType result, MachineType expected) {
assertEquals(result.getName(), expected.getName());
}
}

View File

@ -0,0 +1,170 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseNetworkListTest;
import org.jclouds.googlecomputeengine.parse.ParseNetworkTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class NetworkApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final HttpRequest GET_NETWORK_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse GET_NETWORK_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/network_get.json")).build();
public void testGetNetworkResponseIs2xx() throws Exception {
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_NETWORK_REQUEST, GET_NETWORK_RESPONSE).getNetworkApiForProject("myproject");
assertEquals(api.get("jclouds-test"),
new ParseNetworkTest().expected());
}
public void testGetNetworkResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getNetworkApiForProject("myproject");
assertNull(api.get("jclouds-test"));
}
public void testInsertNetworkResponseIs2xx() {
HttpRequest insert = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/network_insert.json", MediaType.APPLICATION_JSON))
.build();
HttpResponse insertNetworkResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert,
insertNetworkResponse).getNetworkApiForProject("myproject");
assertEquals(api.createInIPv4Range("test-network", "10.0.0.0/8"), new ParseOperationTest().expected());
}
public void testDeleteNetworkResponseIs2xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getNetworkApiForProject("myproject");
assertEquals(api.delete("jclouds-test"),
new ParseOperationTest().expected());
}
public void testDeleteNetworkResponseIs4xx() {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getNetworkApiForProject("myproject");
assertNull(api.delete("jclouds-test"));
}
public void testListNetworksResponseIs2xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/network_list.json")).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getNetworkApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseNetworkListTest().expected().toString());
}
public void testListNetworksResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getNetworkApiForProject("myproject");
assertTrue(api.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,89 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.List;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* @author David Alves
*/
public class NetworkApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String NETWORK_NAME = "network-api-live-test-network";
private static final String IPV4_RANGE = "10.0.0.0/8";
private static final int TIME_WAIT = 10;
private NetworkApi api() {
return api.getNetworkApiForProject(userProject.get());
}
@Test(groups = "live")
public void testInsertNetwork() {
assertOperationDoneSucessfully(api().createInIPv4Range(NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertNetwork")
public void testGetNetwork() {
Network network = api().get(NETWORK_NAME);
assertNotNull(network);
assertNetworkEquals(network);
}
@Test(groups = "live", dependsOnMethods = "testGetNetwork")
public void testListNetwork() {
PagedIterable<Network> networks = api().list(new ListOptions.Builder()
.filter("name eq " + NETWORK_NAME));
List<Network> networksAsList = Lists.newArrayList(networks.concat());
assertEquals(networksAsList.size(), 1);
assertNetworkEquals(Iterables.getOnlyElement(networksAsList));
}
@Test(groups = "live", dependsOnMethods = "testListNetwork")
public void testDeleteNetwork() {
assertOperationDoneSucessfully(api().delete(NETWORK_NAME), TIME_WAIT);
}
private void assertNetworkEquals(Network result) {
assertEquals(result.getName(), NETWORK_NAME);
assertEquals(result.getIPv4Range(), IPV4_RANGE);
}
}

View File

@ -0,0 +1,164 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.googlecomputeengine.parse.ParseOperationListTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class OperationApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/operations";
public static final HttpRequest GET_OPERATION_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse GET_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/operation.json")).build();
public void testGetOperationResponseIs2xx() throws Exception {
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_OPERATION_REQUEST, GET_OPERATION_RESPONSE).getOperationApiForProject("myproject");
assertEquals(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"),
new ParseOperationTest().expected());
}
public void testGetOperationResponseIs4xx() throws Exception {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_OPERATION_REQUEST, operationResponse).getOperationApiForProject("myproject");
assertNull(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"));
}
public void testDeleteOperationResponseIs2xx() throws Exception {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(204).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, operationResponse).getOperationApiForProject("myproject");
operationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
}
public void testDeleteOperationResponseIs4xx() throws Exception {
HttpRequest delete = HttpRequest
.builder()
.method("DELETE")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, operationResponse).getOperationApiForProject("myproject");
operationApi.delete("operation-1352178598164-4cdcc9d031510-4aa46279");
}
public void testLisOperationWithNoOptionsResponseIs2xx() {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation_list.json")).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
assertEquals(operationApi.listFirstPage().toString(),
new ParseOperationListTest().expected().toString());
}
public void testListOperationWithPaginationOptionsResponseIs2xx() {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX +
"?pageToken=CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcG" +
"VyYXRpb24tMTM1MjI0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz&" +
"filter=" +
"status%20eq%20done&" +
"maxResults=3")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation_list.json")).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
assertEquals(operationApi.listAtMarker("CglPUEVSQVRJT04SOzU5MDQyMTQ4Nzg1Mi5vcGVyYXRpb24tMTM1Mj" +
"I0NDI1ODAzMC00Y2RkYmU2YTJkNmIwLWVkMzIyMzQz",
new ListOptions.Builder().filter("status eq done").maxResults(3)).toString(),
new ParseOperationListTest().expected().toString());
}
public void testListOperationWithPaginationOptionsResponseIs4xx() {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
assertTrue(operationApi.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,96 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.concurrent.atomic.AtomicInteger;
import static org.jclouds.googlecomputeengine.features.ProjectApiLiveTest.addItemToMetadata;
import static org.jclouds.googlecomputeengine.features.ProjectApiLiveTest.deleteItemFromMetadata;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
/**
* @author David Alves
*/
public class OperationApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String METADATA_ITEM_KEY = "operationLiveTestTestProp";
private static final String METADATA_ITEM_VALUE = "operationLiveTestTestValue";
private Operation addOperation;
private Operation deleteOperation;
private OperationApi api() {
return api.getOperationApiForProject(userProject.get());
}
@Test(groups = "live")
public void testCreateOperations() {
//create some operations by adding and deleting metadata items
// this will make sure there is stuff to listFirstPage
addOperation = assertOperationDoneSucessfully(addItemToMetadata(api.getProjectApi(),
userProject.get(), METADATA_ITEM_KEY, METADATA_ITEM_VALUE), 20);
deleteOperation = assertOperationDoneSucessfully(deleteItemFromMetadata(api
.getProjectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
assertNotNull(addOperation);
assertNotNull(deleteOperation);
}
@Test(groups = "live", dependsOnMethods = "testCreateOperations")
public void testGetOperation() {
Operation operation = api().get(addOperation.getName());
assertNotNull(operation);
assertOperationEquals(operation, this.addOperation);
}
@Test(groups = "live", dependsOnMethods = "testCreateOperations")
public void testListOperationsWithFiltersAndPagination() {
PagedIterable<Operation> operations = api().list(new ListOptions.Builder()
.filter("operationType eq setMetadata")
.maxResults(1));
// make sure that in spite of having only one result per page we get at least two results
final AtomicInteger counter = new AtomicInteger();
operations.firstMatch(new Predicate<IterableWithMarker<Operation>>() {
@Override
public boolean apply(IterableWithMarker<Operation> input) {
counter.addAndGet(Iterables.size(input));
return counter.get() == 2;
}
});
}
private void assertOperationEquals(Operation result, Operation expected) {
assertEquals(result.getName(), expected.getName());
}
}

View File

@ -0,0 +1,101 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.GoogleComputeEngineConstants;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseMetadataTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.jclouds.googlecomputeengine.parse.ParseProjectTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class ProjectApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final String PROJECTS_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects";
public void testGetProjectResponseIs2xx() throws Exception {
HttpRequest getProjectRequest = HttpRequest
.builder()
.method("GET")
.endpoint(PROJECTS_URL_PREFIX + "/myproject")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse getProjectResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/project.json")).build();
ProjectApi api = requestsSendResponses(requestForScopes(GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, getProjectRequest,
getProjectResponse).getProjectApi();
assertEquals(api.get("myproject"), new ParseProjectTest().expected());
}
public void testGetProjectResponseIs4xx() throws Exception {
HttpRequest getProjectRequest = HttpRequest
.builder()
.method("GET")
.endpoint(PROJECTS_URL_PREFIX + "/myproject")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse getProjectResponse = HttpResponse.builder().statusCode(404).build();
ProjectApi api = requestsSendResponses(requestForScopes(GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, getProjectRequest,
getProjectResponse).getProjectApi();
assertNull(api.get("myproject"));
}
public void testSetCommonInstanceMetadata() {
HttpRequest setMetadata = HttpRequest
.builder()
.method("POST")
.endpoint(PROJECTS_URL_PREFIX + "/myproject/setCommonInstanceMetadata")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/metadata.json", MediaType.APPLICATION_JSON))
.build();
HttpResponse setMetadataResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
ProjectApi api = requestsSendResponses(requestForScopes(GoogleComputeEngineConstants.COMPUTE_SCOPE),
TOKEN_RESPONSE, setMetadata,
setMetadataResponse).getProjectApi();
assertEquals(api.setCommonInstanceMetadata("myproject", new ParseMetadataTest().expected()),
new ParseOperationTest().expected());
}
}

View File

@ -0,0 +1,123 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
/**
* @author David Alves
*/
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Project;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.testng.annotations.Test;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.not;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
public class ProjectApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private static final String METADATA_ITEM_KEY = "projectLiveTestTestProp";
private static final String METADATA_ITEM_VALUE = "projectLiveTestTestValue";
private ProjectApi projectApi() {
return api.getProjectApi();
}
private Project project;
private int initialMetadataSize;
@Test(groups = "live")
public void testGetProjectWhenExists() {
this.project = projectApi().get(userProject.get());
assertNotNull(project);
assertNotNull(project.getId());
assertNotNull(project.getName());
}
@Test(groups = "live")
public void testGetProjectWhenNotExists() {
Project project = projectApi().get("momma");
assertNull(project);
}
@Test(groups = "live", dependsOnMethods = "testGetProjectWhenExists")
public void addItemToMetadata() {
this.initialMetadataSize = project.getCommonInstanceMetadata().size();
assertOperationDoneSucessfully(addItemToMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY,
METADATA_ITEM_VALUE), 20);
this.project = projectApi().get(userProject.get());
assertNotNull(project);
assertTrue(this.project.getCommonInstanceMetadata().containsKey(METADATA_ITEM_KEY),
this.project.toString());
assertEquals(this.project.getCommonInstanceMetadata().get(METADATA_ITEM_KEY),
METADATA_ITEM_VALUE);
}
@Test(groups = "live", dependsOnMethods = "addItemToMetadata")
public void testDeleteItemFromMetadata() {
assertOperationDoneSucessfully(deleteItemFromMetadata(projectApi(), userProject.get(), METADATA_ITEM_KEY), 20);
this.project = projectApi().get(userProject.get());
assertNotNull(project);
assertFalse(project.getCommonInstanceMetadata().containsKey(METADATA_ITEM_KEY));
assertSame(this.project.getCommonInstanceMetadata().size(), initialMetadataSize);
}
/**
* Adds an item to the Project's metadata
* <p/>
* Beyond it's use here it is also used as a cheap way of generating Operations to both test the OperationApi and
* the pagination system.
*/
public static Operation addItemToMetadata(ProjectApi projectApi, String projectName, String key, String value) {
Project project = projectApi.get(projectName);
assertNotNull(project);
ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
metadataBuilder.putAll(project.getCommonInstanceMetadata());
metadataBuilder.put(key, value);
return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build());
}
/**
* Deletes an item from the Project's metadata
* <p/>
* Beyond it's use here it is also used as a cheap way of generating Operation's to both test the OperationApi and
* the pagination system.
*/
public static Operation deleteItemFromMetadata(ProjectApi projectApi, String projectName, String key) {
Project project = projectApi.get(projectName);
assertNotNull(project);
ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
metadataBuilder.putAll(Maps.filterKeys(project.getCommonInstanceMetadata(), not(equalTo(key))));
return projectApi.setCommonInstanceMetadata(projectName, metadataBuilder.build());
}
}

View File

@ -0,0 +1,101 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiExpectTest;
import org.jclouds.googlecomputeengine.parse.ParseZoneListTest;
import org.jclouds.googlecomputeengine.parse.ParseZoneTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.COMPUTE_READONLY_SCOPE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class ZoneApiExpectTest extends BaseGoogleComputeEngineApiExpectTest {
public static final String ZONES_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones";
public static final HttpRequest GET_ZONE_REQ = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX + "/us-central1-a")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpRequest LIST_ZONES_REQ = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_ZONES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/zone_list.json")).build();
public void testGetZoneResponseIs2xx() throws Exception {
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/zone_get.json")).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_ZONE_REQ, operationResponse).getZoneApiForProject("myproject");
assertEquals(api.get("us-central1-a"),
new ParseZoneTest().expected());
}
public void testGetZoneResponseIs4xx() throws Exception {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, GET_ZONE_REQ, operationResponse).getZoneApiForProject("myproject");
assertNull(api.get("us-central1-a"));
}
public void testListZoneNoOptionsResponseIs2xx() throws Exception {
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_ZONES_REQ, LIST_ZONES_RESPONSE).getZoneApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseZoneListTest().expected().toString());
}
public void testListZoneWithPaginationOptionsResponseIs4xx() {
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, LIST_ZONES_REQ, operationResponse).getZoneApiForProject("myproject");
assertTrue(api.list().concat().isEmpty());
}
}

View File

@ -0,0 +1,79 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.features;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecomputeengine.domain.Zone;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiLiveTest;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.testng.annotations.Test;
import java.util.Iterator;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
/**
* @author David Alves
*/
public class ZoneApiLiveTest extends BaseGoogleComputeEngineApiLiveTest {
private Zone zone;
private ZoneApi api() {
return api.getZoneApiForProject(userProject.get());
}
@Test(groups = "live")
public void testListZone() {
PagedIterable<Zone> zones = api().list(new ListOptions.Builder()
.maxResults(1));
Iterator<IterableWithMarker<Zone>> pageIterator = zones.iterator();
assertTrue(pageIterator.hasNext());
IterableWithMarker<Zone> singlePageIterator = pageIterator.next();
List<Zone> zoneAsList = Lists.newArrayList(singlePageIterator);
assertSame(zoneAsList.size(), 1);
this.zone = Iterables.getOnlyElement(zoneAsList);
}
@Test(groups = "live", dependsOnMethods = "testListZone")
public void testGetZone() {
Zone zone = api().get(this.zone.getName());
assertNotNull(zone);
assertZoneEquals(zone, this.zone);
}
private void assertZoneEquals(Zone result, Zone expected) {
assertEquals(result.getName(), expected.getName());
}
}

View File

@ -0,0 +1,97 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.handlers;
import org.easymock.IArgumentMatcher;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
import java.net.URI;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.EasyMock.verify;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "GoogleComputeErrorHandlerTest")
public class GoogleComputeEngineErrorHandlerTest {
@Test
public void test409MakesIllegalStateException() {
assertCodeMakes(
"POST",
URI.create("https://www.googleapis.com/compute/v1beta13"),
409,
"HTTP/1.1 409 Conflict",
"\"{\"code\":\"InvalidState\",\"message\":\"An incompatible transition has already been queued for this" +
" resource\"}\"",
IllegalStateException.class);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "application/json", content, expected);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {
GoogleComputeEngineErrorHandler function = new GoogleComputeEngineErrorHandler();
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected));
replay(command);
function.handleError(command, response);
verify(command);
}
public static Exception classEq(final Class<? extends Exception> in) {
reportMatcher(new IArgumentMatcher() {
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("classEq(");
buffer.append(in);
buffer.append(")");
}
@Override
public boolean matches(Object arg) {
return arg.getClass() == in;
}
});
return null;
}
}

View File

@ -0,0 +1,36 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import java.util.Properties;
/**
* @author Adrian Cole
*/
public class BaseGoogleComputeEngineApiExpectTest extends BaseGoogleComputeEngineExpectTest<GoogleComputeEngineApi> {
@Override
protected Properties setupProperties() {
Properties properties = super.setupProperties();
properties.put("google-compute-engine.identity", "myproject");
return properties;
}
}

View File

@ -0,0 +1,123 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.net.URI;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.config.UserProject;
import org.jclouds.googlecomputeengine.domain.Operation;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* @author David Alves
*/
public class BaseGoogleComputeEngineApiLiveTest extends BaseApiLiveTest<GoogleComputeEngineApi> {
protected static final String API_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/";
protected static final String ZONE_API_URL_SUFFIX = "/zones/";
protected static final String DEFAULT_ZONE_NAME = "us-central1-a";
protected static final String NETWORK_API_URL_SUFFIX = "/networks/";
protected static final String DEFAULT_NETWORK_NAME = "live-test-network";
protected static final String MACHINE_TYPE_API_URL_SUFFIX = "/machineTypes/";
protected static final String DEFAULT_MACHINE_TYPE_NAME = "n1-standard-1";
protected static final String GOOGLE_PROJECT = "google";
protected Supplier<String> userProject;
protected Predicate<AtomicReference<Operation>> operationDonePredicate;
public BaseGoogleComputeEngineApiLiveTest() {
provider = "google-compute-engine";
}
protected GoogleComputeEngineApi create(Properties props, Iterable<Module> modules) {
Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
userProject = injector.getInstance(Key.get(new TypeLiteral<Supplier<String>>() {
}, UserProject.class));
operationDonePredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
}));
return injector.getInstance(GoogleComputeEngineApi.class);
}
protected Operation assertOperationDoneSucessfully(Operation operation, long maxWaitSeconds) {
operation = waitOperationDone(operation, maxWaitSeconds);
assertEquals(operation.getStatus(), Operation.Status.DONE);
assertTrue(operation.getErrors().isEmpty());
return operation;
}
protected Operation waitOperationDone(Operation operation, long maxWaitSeconds) {
return waitOperationDone(operationDonePredicate, operation, maxWaitSeconds);
}
protected URI getDefaultZoneUrl(String project) {
return getZoneUrl(project, DEFAULT_ZONE_NAME);
}
protected URI getZoneUrl(String project, String zone) {
return URI.create(API_URL_PREFIX + project + ZONE_API_URL_SUFFIX + zone);
}
protected URI getDefaultNetworkUrl(String project) {
return getNetworkUrl(project, DEFAULT_NETWORK_NAME);
}
protected URI getNetworkUrl(String project, String network) {
return URI.create(API_URL_PREFIX + project + NETWORK_API_URL_SUFFIX + network);
}
protected URI getDefaultMachineTypekUrl(String project) {
return gettMachineTypeUrl(project, DEFAULT_MACHINE_TYPE_NAME);
}
protected URI gettMachineTypeUrl(String project, String machineType) {
return URI.create(API_URL_PREFIX + project + MACHINE_TYPE_API_URL_SUFFIX + machineType);
}
protected URI getDiskUrl(String project, String diskName) {
return URI.create(API_URL_PREFIX + project + "/disks/" + diskName);
}
protected static Operation waitOperationDone(Predicate<AtomicReference<Operation>> operationDonePredicate,
Operation operation, long maxWaitSeconds) {
AtomicReference<Operation> operationReference = new AtomicReference<Operation>(operation);
retry(operationDonePredicate, maxWaitSeconds, 1, SECONDS).apply(operationReference);
return operationReference.get();
}
}

View File

@ -0,0 +1,191 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.base.Ticker;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.PagedIterable;
import org.jclouds.collect.PagedIterables;
import org.jclouds.crypto.Crypto;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payload;
import org.jclouds.oauth.v2.OAuthConstants;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
import org.jclouds.ssh.SshKeys;
import org.jclouds.util.Strings2;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.io.BaseEncoding.base64Url;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.jclouds.crypto.Pems.privateKeySpec;
import static org.jclouds.crypto.Pems.publicKeySpec;
import static org.jclouds.crypto.PemsTest.PRIVATE_KEY;
import static org.jclouds.crypto.PemsTest.PUBLIC_KEY;
import static org.jclouds.io.Payloads.newStringPayload;
/**
* @author Adrian Cole
*/
public class BaseGoogleComputeEngineExpectTest<T> extends BaseRestApiExpectTest<T> {
private static final String header = "{\"alg\":\"none\",\"typ\":\"JWT\"}";
private static final String CLAIMS_TEMPLATE = "{" +
"\"iss\":\"myproject\"," +
"\"scope\":\"%s\"," +
"\"aud\":\"https://accounts.google.com/o/oauth2/token\"," +
"\"exp\":3600," +
"\"iat\":0}";
protected static final String TOKEN = "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M";
protected static final HttpResponse TOKEN_RESPONSE = HttpResponse.builder().statusCode(200).payload(
payloadFromString("{\n" +
" \"access_token\" : \"" + TOKEN + "\",\n" +
" \"token_type\" : \"Bearer\",\n" +
" \"expires_in\" : 3600\n" +
"}")).build();
protected String openSshKey;
public BaseGoogleComputeEngineExpectTest() {
provider = "google-compute-engine";
}
@Override
protected Module createModule() {
return new Module() {
@Override
public void configure(Binder binder) {
// predictable time
binder.bind(Ticker.class).toInstance(new Ticker() {
@Override
public long read() {
return 0;
}
});
try {
KeyFactory keyfactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyfactory.generatePrivate(privateKeySpec(newStringPayload
(PRIVATE_KEY)));
PublicKey publicKey = keyfactory.generatePublic(publicKeySpec(newStringPayload(PUBLIC_KEY)));
KeyPair keyPair = new KeyPair(publicKey, privateKey);
openSshKey = SshKeys.encodeAsOpenSSH(RSAPublicKey.class.cast(publicKey));
final Crypto crypto = createMock(Crypto.class);
KeyPairGenerator rsaKeyPairGenerator = createMock(KeyPairGenerator.class);
final SecureRandom secureRandom = createMock(SecureRandom.class);
expect(crypto.rsaKeyPairGenerator()).andReturn(rsaKeyPairGenerator).anyTimes();
rsaKeyPairGenerator.initialize(2048, secureRandom);
expectLastCall().anyTimes();
expect(rsaKeyPairGenerator.genKeyPair()).andReturn(keyPair).anyTimes();
replay(crypto, rsaKeyPairGenerator, secureRandom);
binder.bind(Crypto.class).toInstance(crypto);
binder.bind(SecureRandom.class).toInstance(secureRandom);
} catch (NoSuchAlgorithmException e) {
propagate(e);
} catch (InvalidKeySpecException e) {
propagate(e);
} catch (IOException e) {
propagate(e);
}
// predictable node names
final AtomicInteger suffix = new AtomicInteger();
binder.bind(new TypeLiteral<Supplier<String>>() {
}).toInstance(new Supplier<String>() {
@Override
public String get() {
return suffix.getAndIncrement() + "";
}
});
}
};
}
@Override
protected Properties setupProperties() {
Properties props = super.setupProperties();
// use no sig algorithm for expect tests (means no credential is required either)
props.put("jclouds.oauth.signature-or-mac-algorithm", OAuthConstants.NO_ALGORITHM);
return props;
}
protected HttpRequest requestForScopes(String... scopes) {
String claims = String.format(CLAIMS_TEMPLATE, Joiner.on(",").join(scopes));
String payload = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" +
// Base64 Encoded Header
"assertion=" + base64Url().omitPadding().encode(header.getBytes(UTF_8)) + "." +
// Base64 Encoded Claims
base64Url().omitPadding().encode(claims.getBytes(UTF_8)) + ".";
return HttpRequest.builder()
.method("POST")
.endpoint(URI.create("https://accounts.google.com/o/oauth2/token"))
.addHeader("Accept", MediaType.APPLICATION_JSON)
.payload(payloadFromStringWithContentType(payload, "application/x-www-form-urlencoded"))
.build();
}
/**
* Parse tests don't apply @Transform so we need to apply the transformation to PagedIterable on the result of
* expected()
*/
protected <T> PagedIterable<T> toPagedIterable(ListPage<T> list) {
return PagedIterables.of(list);
}
protected static Payload staticPayloadFromResource(String resource) {
try {
return payloadFromString(Strings2.toStringAndClose(BaseGoogleComputeEngineExpectTest.class.getResourceAsStream
(resource)));
} catch (IOException e) {
throw propagate(e);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
/**
* @author David Alves
*/
public abstract class BaseGoogleComputeEngineParseTest<T> extends BaseItemParserTest<T> {
@Override
protected Injector injector() {
return Guice.createInjector(new GsonModule(), new GoogleComputeEngineParserModule());
}
}

View File

@ -0,0 +1,54 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import com.google.common.base.Function;
import com.google.inject.Module;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApiMetadata;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import java.util.Properties;
/**
* @author David Alves
*/
public abstract class BaseGoogleComputeEngineServiceContextExpectTest<T> extends BaseGoogleComputeEngineExpectTest<T> implements
Function<ComputeServiceContext, T> {
@Override
public T createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return apply(createComputeServiceContext(fn, module, props));
}
private ComputeServiceContext createComputeServiceContext(Function<HttpRequest, HttpResponse> fn, Module module,
Properties props) {
return createInjector(fn, module, props).getInstance(ComputeServiceContext.class);
}
@Override
protected ApiMetadata createApiMetadata() {
return new GoogleComputeEngineApiMetadata();
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.internal;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
/**
* @author David Alves
*/
public class BaseGoogleComputeEngineServiceExpectTest extends BaseGoogleComputeEngineServiceContextExpectTest<ComputeService> {
@Override
public ComputeService apply(ComputeServiceContext input) {
return input.getComputeService();
}
}

View File

@ -0,0 +1,65 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecomputeengine.parse;
import com.google.common.collect.ImmutableSet;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.googlecomputeengine.domain.Disk;
import org.jclouds.googlecomputeengine.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Resource;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
import org.testng.annotations.Test;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import java.net.URI;
/**
* @author David Alves
*/
@Test(groups = "unit")
public class ParseDiskListTest extends BaseGoogleComputeEngineParseTest<ListPage<Disk>> {
@Override
public String resource() {
return "/disk_list.json";
}
@Override
@Consumes(MediaType.APPLICATION_JSON)
public ListPage<Disk> expected() {
return ListPage.<Disk>builder()
.kind(Resource.Kind.DISK_LIST)
.id("projects/myproject/disks")
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks"))
.items(ImmutableSet.of(Disk.builder()
.id("13050421646334304115")
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-11-25T01:38:48.306"))
.selfLink(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/disks/testimage1"))
.name("testimage1")
.sizeGb(1)
.zone(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/zones/us-central1-a"))
.status("READY")
.build())
).build();
}
}

Some files were not shown because too many files have changed in this diff Show More