mirror of https://github.com/apache/jclouds.git
Merge pull request #1051 from dralves/gce-base
base pr for - jclouds provider for google compute engine
This commit is contained in:
commit
ff1fb6c1f6
|
@ -0,0 +1,16 @@
|
||||||
|
Status:
|
||||||
|
|
||||||
|
All the private apis are implemented and tested.
|
||||||
|
Snapshots are disabled because they are also disabled in GCE.
|
||||||
|
Just missing jcloud.compute glue code (coming soon!)
|
||||||
|
|
||||||
|
How to run the live tests:
|
||||||
|
|
||||||
|
Pre-requisites:
|
||||||
|
A Google Api account with Google Compute Engine enabled
|
||||||
|
The access pk (provided by google in PKCS12 format) in pem format.
|
||||||
|
|
||||||
|
running all tests:
|
||||||
|
|
||||||
|
mvn clean install -Plive -Dtest.google-compute.identity=<my account>@developer.gserviceaccount.com -Dtest.google-compute.credential=<path to pk.pem>
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?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</groupId>
|
||||||
|
<artifactId>jclouds-project</artifactId>
|
||||||
|
<version>1.6.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../project/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<groupId>org.jclouds.labs</groupId>
|
||||||
|
<artifactId>google-compute</artifactId>
|
||||||
|
<name>jclouds Google Compute Engine provider</name>
|
||||||
|
<description>jclouds components to access GoogleCompute</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jclouds.version>1.6.0-SNAPSHOT</jclouds.version>
|
||||||
|
<test.google-compute.identity>Email associated with the Google API client_id</test.google-compute.identity>
|
||||||
|
<test.google-compute.credential>Private key (PKCS12 file) associated with the Google API client_id</test.google-compute.credential>
|
||||||
|
<test.google-compute.api-version>v1beta13</test.google-compute.api-version>
|
||||||
|
<test.google-compute.build-version></test.google-compute.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-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>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.identity>${test.google-compute.identity}</test.google-compute.identity>
|
||||||
|
<test.google-compute.credential>${test.google-compute.credential}</test.google-compute.credential>
|
||||||
|
<test.google-compute.api-version>${test.google-compute.api-version}</test.google-compute.api-version>
|
||||||
|
<test.google-compute.build-version>${test.google-compute.build-version}</test.google-compute.build-version>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -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.googlecompute;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.googlecompute.features.OperationApi;
|
||||||
|
import org.jclouds.googlecompute.features.ProjectApi;
|
||||||
|
import org.jclouds.googlecompute.features.ZoneApi;
|
||||||
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to GoogleCompute.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see GoogleComputeAsyncApi
|
||||||
|
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13">api doc</a>
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
public interface GoogleComputeApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Project features
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
ProjectApi getProjectApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Operation features
|
||||||
|
*
|
||||||
|
* @param projectName the name of the project
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
@Path("/projects/{project}")
|
||||||
|
OperationApi getOperationApiForProject(@PathParam("project") String projectName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Zone features
|
||||||
|
*
|
||||||
|
* @param projectName the name of the project
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
@Path("/projects/{project}")
|
||||||
|
ZoneApi getZoneApiForProject(@PathParam("project") String projectName);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
* 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.googlecompute;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import org.jclouds.apis.ApiMetadata;
|
||||||
|
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
||||||
|
import org.jclouds.googlecompute.config.GoogleComputeRestClientModule;
|
||||||
|
import org.jclouds.googlecompute.config.OAuthModuleWithoutTypeAdapters;
|
||||||
|
import org.jclouds.oauth.v2.config.OAuthAuthenticationModule;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
|
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
|
||||||
|
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link ApiMetadata} for GoogleCompute v1beta13 API
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public class GoogleComputeApiMetadata extends BaseRestApiMetadata {
|
||||||
|
|
||||||
|
public static final TypeToken<RestContext<GoogleComputeApi, GoogleComputeAsyncApi>> CONTEXT_TOKEN = new
|
||||||
|
TypeToken<RestContext<GoogleComputeApi, GoogleComputeAsyncApi>>() {};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return new Builder().fromApiMetadata(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GoogleComputeApiMetadata() {
|
||||||
|
this(new Builder());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GoogleComputeApiMetadata(Builder builder) {
|
||||||
|
super(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Properties defaultProperties() {
|
||||||
|
Properties properties = BaseRestApiMetadata.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);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder extends BaseRestApiMetadata.Builder {
|
||||||
|
|
||||||
|
protected Builder() {
|
||||||
|
super(GoogleComputeApi.class, GoogleComputeAsyncApi.class);
|
||||||
|
id("google-compute")
|
||||||
|
.name("Google Compute Engine Api")
|
||||||
|
.identityName("Email associated with the Goole 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(GoogleComputeApiMetadata.defaultProperties())
|
||||||
|
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
|
||||||
|
.add(GoogleComputeRestClientModule.class)
|
||||||
|
.add(GoogleComputeParserModule.class)
|
||||||
|
.add(OAuthAuthenticationModule.class)
|
||||||
|
.add(OAuthModuleWithoutTypeAdapters.class).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GoogleComputeApiMetadata build() {
|
||||||
|
return new GoogleComputeApiMetadata(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder fromApiMetadata(ApiMetadata in) {
|
||||||
|
super.fromApiMetadata(in);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import org.jclouds.googlecompute.features.OperationAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.features.ProjectAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.features.ZoneAsyncApi;
|
||||||
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to GoogleCompute via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see GoogleComputeApi
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public interface GoogleComputeAsyncApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Project features
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
ProjectAsyncApi getProjectApi();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Operation features
|
||||||
|
*
|
||||||
|
* @param projectName the name of the project
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
@Path("/projects/{project}")
|
||||||
|
OperationAsyncApi getOperationApiForProject(@PathParam("project") String projectName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Zone features
|
||||||
|
*
|
||||||
|
* @param projectName the name of the project
|
||||||
|
*/
|
||||||
|
@Delegate
|
||||||
|
@Path("/projects/{project}")
|
||||||
|
ZoneAsyncApi getZoneApiForProject(@PathParam("project") String projectName);
|
||||||
|
}
|
|
@ -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.googlecompute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public interface GoogleComputeConstants {
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO storage scopes should be moved to the GCS api
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static final String STORAGE_WRITEONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.write_only";
|
||||||
|
|
||||||
|
public static final String STORAGE_READONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.read_only";
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.config;
|
||||||
|
|
||||||
|
import com.google.common.collect.ForwardingMap;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
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.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public class GoogleComputeParserModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public Map<Type, Object> provideCustomAdapterBindings() {
|
||||||
|
return ImmutableMap.<Type, Object>of(
|
||||||
|
Metadata.class, new MetadataTypeAdapter(),
|
||||||
|
Operation.class, new OperationTypeAdapter(),
|
||||||
|
Header.class, new HeaderTypeAdapter(),
|
||||||
|
ClaimSet.class, new ClaimSetTypeAdapter(),
|
||||||
|
Project.class, new ProjectTypeAdapter()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
* 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.googlecompute.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.features.OperationApi;
|
||||||
|
import org.jclouds.googlecompute.features.OperationAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.features.ProjectApi;
|
||||||
|
import org.jclouds.googlecompute.features.ProjectAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.features.ZoneApi;
|
||||||
|
import org.jclouds.googlecompute.features.ZoneAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.handlers.GoogleComputeErrorHandler;
|
||||||
|
import org.jclouds.googlecompute.predicates.OperationDonePredicate;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
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.rest.ConfiguresRestClient;
|
||||||
|
import org.jclouds.rest.annotations.Identity;
|
||||||
|
import org.jclouds.rest.config.RestClientModule;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the GoogleCompute connection.
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
@ConfiguresRestClient
|
||||||
|
public class GoogleComputeRestClientModule extends RestClientModule<GoogleComputeApi, GoogleComputeAsyncApi> {
|
||||||
|
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>>builder()
|
||||||
|
.put(OperationApi.class, OperationAsyncApi.class)
|
||||||
|
.put(ProjectApi.class, ProjectAsyncApi.class)
|
||||||
|
.put(ZoneApi.class, ZoneAsyncApi.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public GoogleComputeRestClientModule() {
|
||||||
|
super(DELEGATE_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(GoogleComputeErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoogleComputeErrorHandler.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleComputeErrorHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@UserProject
|
||||||
|
public String provideProject(@Identity String identity) {
|
||||||
|
checkState(identity.indexOf("@") != 1, "identity should be in project_id@developer.gserviceaccount.com format");
|
||||||
|
return Iterables.get(Splitter.on("@").split(identity), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.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 {
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.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.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.googlecompute.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;
|
||||||
|
|
||||||
|
protected ListPage(Kind kind, String id, URI selfLink, String nextPageToken, Iterable<T> items) {
|
||||||
|
this.kind = checkNotNull(kind, "kind of %id", id);
|
||||||
|
this.id = checkNotNull(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 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,513 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.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 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, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp),
|
||||||
|
checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
|
||||||
|
this.targetLink = checkNotNull(targetLink, "targetLink of %s", name);
|
||||||
|
this.targetId = checkNotNull(targetId, "targetId of %s", name);
|
||||||
|
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 ?
|
||||||
|
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 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)
|
||||||
|
.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()).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.googlecompute.domain.Operation.Error#getCode()
|
||||||
|
*/
|
||||||
|
public Builder code(String code) {
|
||||||
|
this.code = code;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.domain.Operation.Error#getLocation()
|
||||||
|
*/
|
||||||
|
public Builder location(String location) {
|
||||||
|
this.location = location;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.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.Optional.fromNullable;
|
||||||
|
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, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), checkNotNull(selfLink,
|
||||||
|
"selfLink of %s", name), checkNotNull(name, "name"), fromNullable(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.googlecompute.domain.Project.Quota#getMetric()
|
||||||
|
*/
|
||||||
|
public Builder metric(String metric) {
|
||||||
|
this.metric = checkNotNull(metric, "metric");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.domain.Project.Quota#getUsage()
|
||||||
|
*/
|
||||||
|
public Builder usage(Double usage) {
|
||||||
|
this.usage = usage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.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, Optional<Date> creationTimestamp, URI selfLink, String name,
|
||||||
|
Optional<String> description) {
|
||||||
|
this.kind = checkNotNull(kind, "kind");
|
||||||
|
this.id = id;
|
||||||
|
this.creationTimestamp = creationTimestamp;
|
||||||
|
this.selfLink = selfLink;
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
this.description = 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, id, 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.id, that.id)
|
||||||
|
&& 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, fromNullable(creationTimestamp), selfLink, name,
|
||||||
|
fromNullable(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.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, checkNotNull(id, "id of %name", name), fromNullable(creationTimestamp),
|
||||||
|
checkNotNull(selfLink, "selfLink of %name", name), checkNotNull(name, "name"), fromNullable(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.googlecompute.domain.Zone.MaintenanceWindow#getName()
|
||||||
|
*/
|
||||||
|
public Builder name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.domain.Zone.MaintenanceWindow#getDescription()
|
||||||
|
*/
|
||||||
|
public Builder description(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.domain.Zone.MaintenanceWindow#getBeginTime()
|
||||||
|
*/
|
||||||
|
public Builder beginTime(Date beginTime) {
|
||||||
|
this.beginTime = beginTime;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jclouds.googlecompute.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.options.ListOptions;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Operations via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/operations"/>
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public Operation get(String operationName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the specified operation resource.
|
||||||
|
*
|
||||||
|
* @param operationName name of the operation resource to delete.
|
||||||
|
*/
|
||||||
|
public void delete(String operationName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
public ListPage<Operation> listFirstPage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
public ListPage<Operation> listAtMarker(@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.googlecompute.domain.ListPage
|
||||||
|
*/
|
||||||
|
public ListPage<Operation> listAtMarker(@Nullable String marker, ListOptions listOptions);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#list(org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
public 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.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
public PagedIterable<Operation> list(ListOptions listOptions);
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.functions.internal.ParseOperations;
|
||||||
|
import org.jclouds.googlecompute.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;
|
||||||
|
|
||||||
|
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 static org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
|
||||||
|
import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
|
||||||
|
import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Operations via their REST API.
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see OperationApi
|
||||||
|
*/
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(OAuthAuthenticator.class)
|
||||||
|
public interface OperationAsyncApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#get(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations/{operation}")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Operation> get(@PathParam("operation") String operationName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#delete(String)
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("/operations/{operation}")
|
||||||
|
@OAuthScopes(COMPUTE_SCOPE)
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Void> delete(@PathParam("operation") String operationName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#listFirstPage()
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ResponseParser(ParseOperations.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Operation>> listFirstPage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#listAtMarker(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ResponseParser(ParseOperations.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Operation>> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ResponseParser(ParseOperations.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Operation>> listAtMarker(@QueryParam("pageToken") @Nullable String marker,
|
||||||
|
ListOptions listOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#list()
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ResponseParser(ParseOperations.class)
|
||||||
|
@Transform(ParseOperations.ToPagedIterable.class)
|
||||||
|
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<? extends PagedIterable<Operation>> list();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see OperationApi#list(org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/operations")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ResponseParser(ParseOperations.class)
|
||||||
|
@Transform(ParseOperations.ToPagedIterable.class)
|
||||||
|
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<? extends PagedIterable<Operation>> list(ListOptions listOptions);
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Projects via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see ProjectAsyncApi
|
||||||
|
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/projects"/>
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
Project get(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.
|
||||||
|
*/
|
||||||
|
Operation setCommonInstanceMetadata(String projectName, Map<String, String> commonInstanceMetadata);
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.features;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
import org.jclouds.googlecompute.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;
|
||||||
|
|
||||||
|
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 java.util.Map;
|
||||||
|
|
||||||
|
import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Projects via their REST API.
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see ProjectApi
|
||||||
|
*/
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(OAuthAuthenticator.class)
|
||||||
|
public interface ProjectAsyncApi {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ProjectApi#get(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
@Path("/projects/{project}")
|
||||||
|
ListenableFuture<Project> get(@PathParam("project") String projectName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ProjectApi#setCommonInstanceMetadata(String, java.util.Map)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("/projects/{project}/setCommonInstanceMetadata")
|
||||||
|
@OAuthScopes(COMPUTE_SCOPE)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
ListenableFuture<Operation> setCommonInstanceMetadata(@PathParam("project") String projectName,
|
||||||
|
@BinderParam(MetadataBinder.class)
|
||||||
|
Map<String, String> commonInstanceMetadata);
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.concurrent.Timeout;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.options.ListOptions;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides synchronous access to Zones via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see <a href="https://developers.google.com/compute/docs/reference/v1beta13/zones"/>
|
||||||
|
*/
|
||||||
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
Zone get(String zoneName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
ListPage<Zone> listFirstPage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
ListPage<Zone> listAtMarker(@Nullable 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
|
||||||
|
*/
|
||||||
|
ListPage<Zone> listAtMarker(@Nullable String marker, ListOptions listOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#list(org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
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.googlecompute.options.ListOptions)
|
||||||
|
* @see PagedIterable
|
||||||
|
*/
|
||||||
|
PagedIterable<Zone> list(ListOptions listOptions);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.functions.internal.ParseZones;
|
||||||
|
import org.jclouds.googlecompute.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;
|
||||||
|
|
||||||
|
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 static org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
|
||||||
|
import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
|
||||||
|
import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Zones via their REST API.
|
||||||
|
*
|
||||||
|
* @author David Alves
|
||||||
|
* @see ZoneApi
|
||||||
|
*/
|
||||||
|
@SkipEncoding({'/', '='})
|
||||||
|
@RequestFilters(OAuthAuthenticator.class)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public interface ZoneAsyncApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#get(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones/{zone}")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Zone> get(@PathParam("zone") String zoneName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#listFirstPage()
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@ResponseParser(ParseZones.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Zone>> listFirstPage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#listAtMarker(String)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@ResponseParser(ParseZones.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Zone>> listAtMarker(String marker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@ResponseParser(ParseZones.class)
|
||||||
|
@Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<ListPage<Zone>> listAtMarker(String marker, ListOptions listOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#list()
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@ResponseParser(ParseZones.class)
|
||||||
|
@Transform(ParseZones.ToPagedIterable.class)
|
||||||
|
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<? extends PagedIterable<Zone>> list();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ZoneApi#list(org.jclouds.googlecompute.options.ListOptions)
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("/zones")
|
||||||
|
@OAuthScopes(COMPUTE_READONLY_SCOPE)
|
||||||
|
@ResponseParser(ParseZones.class)
|
||||||
|
@Transform(ParseZones.ToPagedIterable.class)
|
||||||
|
@Fallback(EmptyPagedIterableOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<? extends PagedIterable<Zone>> list(ListOptions listOptions);
|
||||||
|
}
|
|
@ -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.googlecompute.functions.internal;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import org.jclouds.collect.IterableWithMarker;
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.collect.PagedIterables;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.options.ListOptions;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.rest.InvocationContext;
|
||||||
|
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 = Iterables.tryFind(Arrays.asList(request.getCaller().get().getArgs()),
|
||||||
|
Predicates.instanceOf(String.class));
|
||||||
|
|
||||||
|
Optional<Object> listOptions = Iterables.tryFind(request.getArgs(),
|
||||||
|
Predicates.instanceOf(ListOptions.class));
|
||||||
|
|
||||||
|
assert project.isPresent() : String.format("programming error, method %s should have a string param for the " +
|
||||||
|
"project", request.getCaller().get().getMethod());
|
||||||
|
|
||||||
|
return PagedIterables.advance(input, fetchNextPage(project.get().toString(), (String) input.nextMarker().orNull(),
|
||||||
|
(ListOptions) listOptions.orNull()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract Function<Object, IterableWithMarker<T>> fetchNextPage(String projectName, String marker,
|
||||||
|
ListOptions listOptions);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public I setContext(HttpRequest request) {
|
||||||
|
this.request = GeneratedHttpRequest.class.cast(request);
|
||||||
|
return (I) this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.functions.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import org.jclouds.collect.IterableWithMarker;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.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 GoogleComputeApi api;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected ToPagedIterable(GoogleComputeApi api) {
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<Object, IterableWithMarker<Operation>> fetchNextPage(final String projectName,
|
||||||
|
final String marker,
|
||||||
|
final ListOptions options) {
|
||||||
|
return new Function<Object, IterableWithMarker<Operation>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IterableWithMarker<Operation> apply(Object input) {
|
||||||
|
return api.getOperationApiForProject(projectName).listAtMarker(marker, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.functions.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import org.jclouds.collect.IterableWithMarker;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.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 GoogleComputeApi api;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected ToPagedIterable(GoogleComputeApi api) {
|
||||||
|
this.api = checkNotNull(api, "api");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Function<Object, IterableWithMarker<Zone>> fetchNextPage(final String projectName, final String marker,
|
||||||
|
final ListOptions options) {
|
||||||
|
return new Function<Object, IterableWithMarker<Zone>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IterableWithMarker<Zone> apply(Object input) {
|
||||||
|
return api.getZoneApiForProject(projectName).listAtMarker(marker, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.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 GoogleComputeErrorHandler 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.handlers;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
||||||
|
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 GoogleComputeParserModule.Metadata(metadataEntries));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.predicates;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.config.UserProject;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.features.OperationApi;
|
||||||
|
|
||||||
|
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 OperationApi api;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
OperationDonePredicate(GoogleComputeApi api, @UserProject String project) {
|
||||||
|
this.api = api.getOperationApiForProject(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(AtomicReference<Operation> input) {
|
||||||
|
checkNotNull(input, "input");
|
||||||
|
Operation current = api.get(input.get().getName());
|
||||||
|
switch (current.getStatus()) {
|
||||||
|
case DONE:
|
||||||
|
input.set(current);
|
||||||
|
return true;
|
||||||
|
case PENDING:
|
||||||
|
case RUNNING:
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
org.jclouds.googlecompute.GoogleComputeApiMetadata
|
|
@ -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.googlecompute;
|
||||||
|
|
||||||
|
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 GoogleComputeApiMetadataTest extends BaseApiMetadataTest {
|
||||||
|
public GoogleComputeApiMetadataTest() {
|
||||||
|
super(new GoogleComputeApiMetadata(), ImmutableSet.<TypeToken<? extends View>>of());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute;
|
||||||
|
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import org.jclouds.oauth.v2.BaseOauthAuthenticatedRestContextLiveTest;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
@Test(groups = "live")
|
||||||
|
public class GoogleComputeAuthenticatedRestContextLiveTest extends BaseOauthAuthenticatedRestContextLiveTest {
|
||||||
|
|
||||||
|
|
||||||
|
public GoogleComputeAuthenticatedRestContextLiveTest() {
|
||||||
|
provider = "google-compute";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getScopes() {
|
||||||
|
return GoogleComputeConstants.COMPUTE_SCOPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeToken<RestContext<GoogleComputeApi, GoogleComputeAsyncApi>> contextType() {
|
||||||
|
return GoogleComputeApiMetadata.CONTEXT_TOKEN;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeExpectTest;
|
||||||
|
import org.jclouds.googlecompute.options.ListOptions;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseOperationListTest;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseOperationTest;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.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 BaseGoogleComputeExpectTest<GoogleComputeApi> {
|
||||||
|
|
||||||
|
private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
|
||||||
|
".com/compute/v1beta13/projects/myproject/operations";
|
||||||
|
|
||||||
|
public void testGetOperationResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Authorization", "Bearer " + TOKEN).build();
|
||||||
|
|
||||||
|
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource("/operation.json")).build();
|
||||||
|
|
||||||
|
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
|
||||||
|
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
|
||||||
|
|
||||||
|
assertEquals(operationApi.get("operation-1352178598164-4cdcc9d031510-4aa46279"),
|
||||||
|
new ParseOperationTest().expected());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetOperationResponseIs4xx() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
|
||||||
|
.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");
|
||||||
|
|
||||||
|
assertNull(operationApi.get("operation-1352178598164-4cdcc9d031510-4aa46279"));
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.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.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeApiLiveTest;
|
||||||
|
import org.jclouds.googlecompute.options.ListOptions;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static org.jclouds.googlecompute.features.ProjectApiLiveTest.addItemToMetadata;
|
||||||
|
import static org.jclouds.googlecompute.features.ProjectApiLiveTest.deleteItemFromMetadata;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public class OperationApiLiveTest extends BaseGoogleComputeApiLiveTest {
|
||||||
|
|
||||||
|
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 context.getApi().getOperationApiForProject(getUserProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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(context.getApi().getProjectApi(),
|
||||||
|
getUserProject(), METADATA_ITEM_KEY, METADATA_ITEM_VALUE), 20);
|
||||||
|
deleteOperation = assertOperationDoneSucessfully(deleteItemFromMetadata(context.getApi()
|
||||||
|
.getProjectApi(), getUserProject(), 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeConstants;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeExpectTest;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseMetadataTest;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseOperationTest;
|
||||||
|
import org.jclouds.googlecompute.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 BaseGoogleComputeExpectTest<GoogleComputeApi> {
|
||||||
|
|
||||||
|
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(GoogleComputeConstants.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(GoogleComputeConstants.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(GoogleComputeConstants.COMPUTE_SCOPE),
|
||||||
|
TOKEN_RESPONSE, setMetadata,
|
||||||
|
setMetadataResponse).getProjectApi();
|
||||||
|
|
||||||
|
assertEquals(api.setCommonInstanceMetadata("myproject", new ParseMetadataTest().expected()),
|
||||||
|
new ParseOperationTest().expected());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.features;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeApiLiveTest;
|
||||||
|
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 BaseGoogleComputeApiLiveTest {
|
||||||
|
|
||||||
|
private static final String METADATA_ITEM_KEY = "projectLiveTestTestProp";
|
||||||
|
private static final String METADATA_ITEM_VALUE = "projectLiveTestTestValue";
|
||||||
|
|
||||||
|
private ProjectApi projectApi() {
|
||||||
|
return context.getApi().getProjectApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Project project;
|
||||||
|
private int initialMetadataSize;
|
||||||
|
|
||||||
|
@Test(groups = "live")
|
||||||
|
public void testGetProjectWhenExists() {
|
||||||
|
this.project = projectApi().get(getUserProject());
|
||||||
|
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(), getUserProject(), METADATA_ITEM_KEY,
|
||||||
|
METADATA_ITEM_VALUE), 20);
|
||||||
|
this.project = projectApi().get(getUserProject());
|
||||||
|
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(), getUserProject(), METADATA_ITEM_KEY), 20);
|
||||||
|
this.project = projectApi().get(getUserProject());
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.features;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeExpectTest;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseZoneListTest;
|
||||||
|
import org.jclouds.googlecompute.parse.ParseZoneTest;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.jclouds.googlecompute.GoogleComputeConstants.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 BaseGoogleComputeExpectTest<GoogleComputeApi> {
|
||||||
|
|
||||||
|
public static final String ZONES_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/google/zones";
|
||||||
|
|
||||||
|
public void testGetZoneResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(ZONES_URL_PREFIX + "/us-central2-a")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Authorization", "Bearer " + TOKEN).build();
|
||||||
|
|
||||||
|
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource("/zone_get.json")).build();
|
||||||
|
|
||||||
|
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
|
||||||
|
TOKEN_RESPONSE, get, operationResponse).getZoneApiForProject("google");
|
||||||
|
|
||||||
|
assertEquals(api.get("us-central2-a"),
|
||||||
|
new ParseZoneTest().expected());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGetZoneResponseIs4xx() throws Exception {
|
||||||
|
HttpRequest get = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(ZONES_URL_PREFIX + "/us-central2-a")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Authorization", "Bearer " + TOKEN).build();
|
||||||
|
|
||||||
|
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
|
||||||
|
TOKEN_RESPONSE, get, operationResponse).getZoneApiForProject("google");
|
||||||
|
|
||||||
|
assertNull(api.get("us-central2-a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListZoneNoOptionsResponseIs2xx() throws Exception {
|
||||||
|
HttpRequest list = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(ZONES_URL_PREFIX)
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Authorization", "Bearer " + TOKEN).build();
|
||||||
|
|
||||||
|
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource("/zone_list.json")).build();
|
||||||
|
|
||||||
|
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
|
||||||
|
TOKEN_RESPONSE, list, operationResponse).getZoneApiForProject("google");
|
||||||
|
|
||||||
|
assertEquals(api.listFirstPage().toString(),
|
||||||
|
new ParseZoneListTest().expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListZoneWithPaginationOptionsResponseIs4xx() {
|
||||||
|
HttpRequest list = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method("GET")
|
||||||
|
.endpoint(ZONES_URL_PREFIX)
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Authorization", "Bearer " + TOKEN).build();
|
||||||
|
|
||||||
|
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
|
||||||
|
|
||||||
|
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
|
||||||
|
TOKEN_RESPONSE, list, operationResponse).getZoneApiForProject("google");
|
||||||
|
|
||||||
|
assertTrue(api.list().concat().isEmpty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.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.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeApiLiveTest;
|
||||||
|
import org.jclouds.googlecompute.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 BaseGoogleComputeApiLiveTest {
|
||||||
|
|
||||||
|
private Zone zone;
|
||||||
|
|
||||||
|
private ZoneApi api() {
|
||||||
|
return context.getApi().getZoneApiForProject(getUserProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.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 GoogleComputeErrorHandlerTest {
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
|
||||||
|
GoogleComputeErrorHandler function = new GoogleComputeErrorHandler();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 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.googlecompute.internal;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class BaseGoogleComputeApiExpectTest extends BaseGoogleComputeExpectTest<GoogleComputeApi> {
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.inject.Key;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import org.jclouds.apis.BaseContextLiveTest;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApi;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeApiMetadata;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeAsyncApi;
|
||||||
|
import org.jclouds.googlecompute.config.UserProject;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.oauth.v2.OAuthTestUtils;
|
||||||
|
import org.jclouds.predicates.Retryables;
|
||||||
|
import org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.AssertJUnit.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public class BaseGoogleComputeApiLiveTest extends BaseContextLiveTest<RestContext<GoogleComputeApi,
|
||||||
|
GoogleComputeAsyncApi>> {
|
||||||
|
|
||||||
|
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-east1-a";
|
||||||
|
|
||||||
|
protected static final String NETWORK_API_URL_SUFFIX = "/networks/";
|
||||||
|
protected static final String DEFAULT_NETWORK_NAME = "default";
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
|
||||||
|
public BaseGoogleComputeApiLiveTest() {
|
||||||
|
provider = "google-compute";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Properties setupProperties() {
|
||||||
|
Properties properties = super.setupProperties();
|
||||||
|
OAuthTestUtils.setCredentialFromPemFile(properties, "google-compute.credential");
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TypeToken<RestContext<GoogleComputeApi, GoogleComputeAsyncApi>> contextType() {
|
||||||
|
return GoogleComputeApiMetadata.CONTEXT_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getUserProject() {
|
||||||
|
return context.utils().injector().getInstance(Key.get(String.class, UserProject.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Predicate<AtomicReference<Operation>> getOperationDonePredicate() {
|
||||||
|
return context.utils().getInjector().getInstance(Key.get(new TypeLiteral<Predicate<AtomicReference<Operation>>>
|
||||||
|
() {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
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(getOperationDonePredicate(), 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 static Operation waitOperationDone(Predicate<AtomicReference<Operation>> operationDonePredicate,
|
||||||
|
Operation operation, long maxWaitSeconds) {
|
||||||
|
AtomicReference<Operation> operationReference = new AtomicReference<Operation>(operation);
|
||||||
|
Retryables.retry(operationDonePredicate, operationReference, maxWaitSeconds, 1, TimeUnit.SECONDS);
|
||||||
|
return operationReference.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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.googlecompute.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import org.jclouds.googlecompute.GoogleComputeAsyncApi;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class BaseGoogleComputeAsyncApiExpectTest extends BaseGoogleComputeExpectTest<GoogleComputeAsyncApi> {
|
||||||
|
public GoogleComputeAsyncApi createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
|
||||||
|
return createInjector(fn, module, props).getInstance(GoogleComputeAsyncApi.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/**
|
||||||
|
* 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.googlecompute.internal;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Ticker;
|
||||||
|
import com.google.inject.Binder;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import org.jclouds.collect.PagedIterable;
|
||||||
|
import org.jclouds.collect.PagedIterables;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.oauth.v2.OAuthConstants;
|
||||||
|
import org.jclouds.rest.internal.BaseRestApiExpectTest;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.jclouds.crypto.CryptoStreams.base64Url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class BaseGoogleComputeExpectTest<T> extends BaseRestApiExpectTest<T> {
|
||||||
|
|
||||||
|
private static final String header = "{\"alg\":\"none\",\"typ\":\"JWT\"}";
|
||||||
|
|
||||||
|
private static final String CLAIMS_TEMPLATE = "{" +
|
||||||
|
"\"iss\":\"identity\"," +
|
||||||
|
"\"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();
|
||||||
|
|
||||||
|
|
||||||
|
public BaseGoogleComputeExpectTest() {
|
||||||
|
provider = "google-compute";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Module createModule() {
|
||||||
|
return new Module() {
|
||||||
|
@Override
|
||||||
|
public void configure(Binder binder) {
|
||||||
|
binder.bind(Ticker.class).toInstance(new Ticker() {
|
||||||
|
@Override
|
||||||
|
public long read() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(header.getBytes(Charset.forName("UTF-8"))) + "." +
|
||||||
|
// Base64 Encoded Claims
|
||||||
|
base64Url(claims.getBytes(Charset.forName("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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.internal;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
||||||
|
import org.jclouds.json.BaseItemParserTest;
|
||||||
|
import org.jclouds.json.config.GsonModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public abstract class BaseGoogleComputeParseTest<T> extends BaseItemParserTest<T> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Injector injector() {
|
||||||
|
return Guice.createInjector(new GsonModule(), new GoogleComputeParserModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.googlecompute.parse;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.jclouds.googlecompute.config.GoogleComputeParserModule;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ParseMetadataTest extends BaseGoogleComputeParseTest<GoogleComputeParserModule.Metadata> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/metadata.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public GoogleComputeParserModule.Metadata expected() {
|
||||||
|
return new GoogleComputeParserModule.Metadata(
|
||||||
|
ImmutableMap.<String, String>builder()
|
||||||
|
.put("propA", "valueA")
|
||||||
|
.put("propB", "valueB")
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.parse;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.domain.Resource;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
public class ParseOperationListTest extends BaseGoogleComputeParseTest<ListPage<Operation>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/operation_list.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public ListPage<Operation> expected() {
|
||||||
|
return ListPage.<Operation>builder()
|
||||||
|
.kind(Resource.Kind.OPERATION_LIST)
|
||||||
|
.id("projects/myproject/operations")
|
||||||
|
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/operations"))
|
||||||
|
.addItem(new ParseOperationTest().expected())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.parse;
|
||||||
|
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.googlecompute.domain.Operation;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
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 ParseOperationTest extends BaseGoogleComputeParseTest<Operation> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/operation.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Operation expected() {
|
||||||
|
SimpleDateFormatDateService dateService = new SimpleDateFormatDateService();
|
||||||
|
return Operation.builder().id("13053095055850848306")
|
||||||
|
.selfLink(URI.create("https://www.googleapis" +
|
||||||
|
".com/compute/v1beta13/projects/myproject/operations/operation" +
|
||||||
|
"-1354084865060-4cf88735faeb8-bbbb12cb"))
|
||||||
|
.name("operation-1354084865060-4cf88735faeb8-bbbb12cb")
|
||||||
|
.targetLink(URI.create("https://www.googleapis" +
|
||||||
|
".com/compute/v1beta13/projects/myproject/instances/instance-api-live" +
|
||||||
|
"-test-instance"))
|
||||||
|
.targetId("13053094017547040099")
|
||||||
|
.status(Operation.Status.DONE)
|
||||||
|
.user("user@developer.gserviceaccount.com")
|
||||||
|
.progress(100)
|
||||||
|
.insertTime(dateService.iso8601DateParse("2012-11-28T06:41:05.060"))
|
||||||
|
.startTime(dateService.iso8601DateParse("2012-11-28T06:41:05.142"))
|
||||||
|
.operationType("insert")
|
||||||
|
.httpErrorStatusCode(400)
|
||||||
|
.httpErrorMessage("BAD REQUEST")
|
||||||
|
.addError(Operation.Error.builder()
|
||||||
|
.code("RESOURCE_ALREADY_EXISTS")
|
||||||
|
.message("The resource " +
|
||||||
|
"'projects/myproject/instances/instance-api-live-test-instance' already" +
|
||||||
|
" exists")
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.parse;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ParseProjectTest extends BaseGoogleComputeParseTest<Project> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/project.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Project expected() {
|
||||||
|
return Project.builder()
|
||||||
|
.id("13024414184846275913")
|
||||||
|
.creationTimestamp(new Date(Long.parseLong("1351109596252")))
|
||||||
|
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject"))
|
||||||
|
.name("myproject")
|
||||||
|
.description("")
|
||||||
|
.commonInstanceMetadata(
|
||||||
|
ImmutableMap.<String, String>builder()
|
||||||
|
.put("propA", "valueA")
|
||||||
|
.put("propB", "valueB")
|
||||||
|
.build())
|
||||||
|
.addQuota("INSTANCES", 0, 8)
|
||||||
|
.addQuota("CPUS", 0, 8)
|
||||||
|
.addQuota("EPHEMERAL_ADDRESSES", 0, 8)
|
||||||
|
.addQuota("DISKS", 0, 8)
|
||||||
|
.addQuota("DISKS_TOTAL_GB", 0, 100)
|
||||||
|
.addQuota("SNAPSHOTS", 0, 1000)
|
||||||
|
.addQuota("NETWORKS", 1, 5)
|
||||||
|
.addQuota("FIREWALLS", 2, 100)
|
||||||
|
.addQuota("IMAGES", 0, 100)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.parse;
|
||||||
|
|
||||||
|
import org.jclouds.googlecompute.domain.Project;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Alves
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ParseQuotaTest extends BaseGoogleComputeParseTest<Project.Quota> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/quota.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Project.Quota expected() {
|
||||||
|
return Project.Quota.builder().metric("INSTANCES").usage(0.0).limit(8.0).build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.googlecompute.parse;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.googlecompute.domain.ListPage;
|
||||||
|
import org.jclouds.googlecompute.domain.Resource;
|
||||||
|
import org.jclouds.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
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 ParseZoneListTest extends BaseGoogleComputeParseTest<ListPage<Zone>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/zone_list.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public ListPage<Zone> expected() {
|
||||||
|
return ListPage.<Zone>builder()
|
||||||
|
.kind(Resource.Kind.ZONE_LIST)
|
||||||
|
.id("projects/google/zones")
|
||||||
|
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/zones"))
|
||||||
|
.items(ImmutableSet.of(
|
||||||
|
new ParseZoneTest().expected()
|
||||||
|
, Zone.builder()
|
||||||
|
.id("13024414164050619686")
|
||||||
|
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse
|
||||||
|
("2012-10-24T20:13:19.271"))
|
||||||
|
.selfLink(URI.create("https://www.googleapis" +
|
||||||
|
".com/compute/v1beta13/projects/google/zones/us-east1-a"))
|
||||||
|
.name("us-east1-a")
|
||||||
|
.description("us-east1-a")
|
||||||
|
.status(Zone.Status.UP)
|
||||||
|
.addMaintenanceWindow(Zone.MaintenanceWindow.builder()
|
||||||
|
.name("2013-02-17-planned-outage")
|
||||||
|
.description("maintenance zone")
|
||||||
|
.beginTime(new SimpleDateFormatDateService().iso8601DateParse
|
||||||
|
("2013-02-17T08:00:00.000"))
|
||||||
|
.endTime(new SimpleDateFormatDateService().iso8601DateParse
|
||||||
|
("2013-03-03T08:00:00.000"))
|
||||||
|
.build())
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.googlecompute.parse;
|
||||||
|
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.googlecompute.domain.Zone;
|
||||||
|
import org.jclouds.googlecompute.internal.BaseGoogleComputeParseTest;
|
||||||
|
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 ParseZoneTest extends BaseGoogleComputeParseTest<Zone> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/zone_get.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Zone expected() {
|
||||||
|
return Zone.builder()
|
||||||
|
.id("13020128040171887099")
|
||||||
|
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-10-19T16:42:54.131"))
|
||||||
|
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/zones/us-central2-a"))
|
||||||
|
.name("us-central2-a")
|
||||||
|
.description("us-central2-a")
|
||||||
|
.status(Zone.Status.DOWN)
|
||||||
|
.addMaintenanceWindow(Zone.MaintenanceWindow.builder()
|
||||||
|
.name("2012-11-10-planned-outage")
|
||||||
|
.description("maintenance zone")
|
||||||
|
.beginTime(new SimpleDateFormatDateService().iso8601DateParse("2012-11-10T20:00:00.000"))
|
||||||
|
.endTime(new SimpleDateFormatDateService().iso8601DateParse("2012-12-02T20:00:00.000"))
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<configuration scan="false">
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds.log</file>
|
||||||
|
|
||||||
|
<encoder>
|
||||||
|
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<file>target/test-data/jclouds-wire.log</file>
|
||||||
|
|
||||||
|
<encoder>
|
||||||
|
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root>
|
||||||
|
<level value="warn"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.jclouds">
|
||||||
|
<level value="DEBUG"/>
|
||||||
|
<appender-ref ref="FILE"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.wire">
|
||||||
|
<level value="DEBUG"/>
|
||||||
|
<appender-ref ref="WIREFILE"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
<logger name="jclouds.headers">
|
||||||
|
<level value="DEBUG"/>
|
||||||
|
<appender-ref ref="WIREFILE"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
</configuration>
|
|
@ -0,0 +1 @@
|
||||||
|
{"kind":"compute#metadata","items":[{"key":"propA","value":"valueA"},{"key":"propB","value":"valueB"}]}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"kind": "compute#operation",
|
||||||
|
"id": "13053095055850848306",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
|
||||||
|
"name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
|
||||||
|
"targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
|
||||||
|
"targetId": "13053094017547040099",
|
||||||
|
"status": "DONE",
|
||||||
|
"user": "user@developer.gserviceaccount.com",
|
||||||
|
"progress": 100,
|
||||||
|
"insertTime": "2012-11-28T06:41:05.060",
|
||||||
|
"startTime": "2012-11-28T06:41:05.142",
|
||||||
|
"httpErrorStatusCode": 400,
|
||||||
|
"httpErrorMessage": "BAD REQUEST",
|
||||||
|
"error": {
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "RESOURCE_ALREADY_EXISTS",
|
||||||
|
"message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operationType": "insert"
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"kind": "compute#operationList",
|
||||||
|
"id": "projects/myproject/operations",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"kind": "compute#operation",
|
||||||
|
"id": "13053095055850848306",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
|
||||||
|
"name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
|
||||||
|
"targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
|
||||||
|
"targetId": "13053094017547040099",
|
||||||
|
"status": "DONE",
|
||||||
|
"user": "user@developer.gserviceaccount.com",
|
||||||
|
"progress": 100,
|
||||||
|
"insertTime": "2012-11-28T06:41:05.060",
|
||||||
|
"startTime": "2012-11-28T06:41:05.142",
|
||||||
|
"httpErrorStatusCode": 400,
|
||||||
|
"httpErrorMessage": "BAD REQUEST",
|
||||||
|
"error": {
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": "RESOURCE_ALREADY_EXISTS",
|
||||||
|
"message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operationType": "insert"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"kind": "compute#project",
|
||||||
|
"id": "13024414184846275913",
|
||||||
|
"creationTimestamp": "2012-10-24T20:13:16.252",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject",
|
||||||
|
"name": "myproject",
|
||||||
|
"description": "",
|
||||||
|
"commonInstanceMetadata": {
|
||||||
|
"kind": "compute#metadata",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"key": "propA",
|
||||||
|
"value": "valueA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "propB",
|
||||||
|
"value": "valueB"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"quotas": [
|
||||||
|
{
|
||||||
|
"metric": "INSTANCES",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "CPUS",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "EPHEMERAL_ADDRESSES",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "DISKS",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "DISKS_TOTAL_GB",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "SNAPSHOTS",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "NETWORKS",
|
||||||
|
"usage": 1,
|
||||||
|
"limit": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "FIREWALLS",
|
||||||
|
"usage": 2,
|
||||||
|
"limit": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metric": "IMAGES",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"metric": "INSTANCES",
|
||||||
|
"usage": 0,
|
||||||
|
"limit": 8
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"kind": "compute#zone",
|
||||||
|
"id": "13020128040171887099",
|
||||||
|
"creationTimestamp": "2012-10-19T16:42:54.131",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/zones/us-central2-a",
|
||||||
|
"name": "us-central2-a",
|
||||||
|
"description": "us-central2-a",
|
||||||
|
"status": "DOWN",
|
||||||
|
"maintenanceWindows": [
|
||||||
|
{
|
||||||
|
"name": "2012-11-10-planned-outage",
|
||||||
|
"description": "maintenance zone",
|
||||||
|
"beginTime": "2012-11-10T20:00:00.000",
|
||||||
|
"endTime": "2012-12-02T20:00:00.000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"kind": "compute#zoneList",
|
||||||
|
"id": "projects/google/zones",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/zones",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"kind": "compute#zone",
|
||||||
|
"id": "13020128040171887099",
|
||||||
|
"creationTimestamp": "2012-10-19T16:42:54.131",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/zones/us-central2-a",
|
||||||
|
"name": "us-central2-a",
|
||||||
|
"description": "us-central2-a",
|
||||||
|
"status": "DOWN",
|
||||||
|
"maintenanceWindows": [
|
||||||
|
{
|
||||||
|
"name": "2012-11-10-planned-outage",
|
||||||
|
"description": "maintenance zone",
|
||||||
|
"beginTime": "2012-11-10T20:00:00.000",
|
||||||
|
"endTime": "2012-12-02T20:00:00.000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "compute#zone",
|
||||||
|
"id": "13024414164050619686",
|
||||||
|
"creationTimestamp": "2012-10-24T20:13:19.271",
|
||||||
|
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/zones/us-east1-a",
|
||||||
|
"name": "us-east1-a",
|
||||||
|
"description": "us-east1-a",
|
||||||
|
"status": "UP",
|
||||||
|
"maintenanceWindows": [
|
||||||
|
{
|
||||||
|
"name": "2013-02-17-planned-outage",
|
||||||
|
"description": "maintenance zone",
|
||||||
|
"beginTime": "2013-02-17T08:00:00.000",
|
||||||
|
"endTime": "2013-03-03T08:00:00.000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -45,6 +45,7 @@
|
||||||
<module>cdmi</module>
|
<module>cdmi</module>
|
||||||
<module>joyent-cloudapi</module>
|
<module>joyent-cloudapi</module>
|
||||||
<module>joyentcloud</module>
|
<module>joyentcloud</module>
|
||||||
|
<module>google-compute</module>
|
||||||
<module>greenqloud-compute</module>
|
<module>greenqloud-compute</module>
|
||||||
<module>greenqloud-storage</module>
|
<module>greenqloud-storage</module>
|
||||||
<module>iam</module>
|
<module>iam</module>
|
||||||
|
|
Loading…
Reference in New Issue