You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ra...@apache.org on 2014/11/30 11:43:00 UTC
[15/18] stratos git commit: Jclouds gce apis (gce + oauth) 1.8.1
clone with custom changes
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
new file mode 100644
index 0000000..14af9cd
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableSet.of;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.domain.Network;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange;
+import org.jclouds.googlecomputeengine.features.FirewallApi;
+import org.jclouds.googlecomputeengine.options.FirewallOptions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends
+ org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet {
+
+ public static final String EXTERIOR_RANGE = "0.0.0.0/0";
+ public static final String DEFAULT_INTERNAL_NETWORK_RANGE = "10.0.0.0/8";
+
+ private final GoogleComputeEngineApi api;
+ private final Supplier<String> userProject;
+ private final LoadingCache<NetworkAndAddressRange, Network> networkMap;
+ private final Predicate<AtomicReference<Operation>> operationDonePredicate;
+ private final long operationCompleteCheckInterval;
+ private final long operationCompleteCheckTimeout;
+ private final FirewallTagNamingConvention.Factory firewallTagNamingConvention;
+
+ @Inject
+ protected CreateNodesWithGroupEncodedIntoNameThenAddToSet(
+ CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
+ ListNodesStrategy listNodesStrategy,
+ GroupNamingConvention.Factory namingConvention,
+ @Named(Constants.PROPERTY_USER_THREADS)
+ ListeningExecutorService userExecutor,
+ CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+ GoogleComputeEngineApi api,
+ @UserProject Supplier<String> userProject,
+ @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate,
+ @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
+ @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout,
+ LoadingCache<NetworkAndAddressRange, Network> networkMap,
+ FirewallTagNamingConvention.Factory firewallTagNamingConvention) {
+ super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
+
+ this.api = checkNotNull(api, "google compute api");
+ this.userProject = checkNotNull(userProject, "user project name");
+ this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
+ "operation completed check interval");
+ this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
+ "operation completed check timeout");
+ this.operationDonePredicate = checkNotNull(operationDonePredicate, "operationDonePredicate");
+ this.networkMap = checkNotNull(networkMap, "networkMap");
+ this.firewallTagNamingConvention = checkNotNull(firewallTagNamingConvention, "firewallTagNamingConvention");
+ }
+
+ @Override
+ public synchronized Map<?, ListenableFuture<Void>> execute(String group, int count,
+ Template template,
+ Set<NodeMetadata> goodNodes,
+ Map<NodeMetadata, Exception> badNodes,
+ Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
+
+ String sharedResourceName = namingConvention.create().sharedNameForGroup(group);
+ Template mutableTemplate = template.clone();
+ GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class.cast(mutableTemplate
+ .getOptions());
+ assert template.getOptions().equals(templateOptions) : "options didn't clone properly";
+
+ // get or create the network and create a firewall with the users configuration
+ Network network = getOrCreateNetwork(templateOptions, sharedResourceName);
+ getOrCreateFirewalls(templateOptions, network, firewallTagNamingConvention.get(group));
+ templateOptions.network(network.getSelfLink());
+ templateOptions.userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group);
+
+ return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses);
+ }
+
+ /**
+ * Try and find a network either previously created by jclouds or user defined.
+ */
+ private Network getOrCreateNetwork(GoogleComputeEngineTemplateOptions templateOptions, String sharedResourceName) {
+
+ String networkName = templateOptions.getNetworkName().or(sharedResourceName);
+
+ return networkMap.apply(new NetworkAndAddressRange(networkName, DEFAULT_INTERNAL_NETWORK_RANGE, null));
+ }
+
+ /**
+ * Ensures that a firewall exists for every inbound port that the instance requests.
+ * <p>
+ * For each port, there must be a firewall with a name following the {@link FirewallTagNamingConvention},
+ * with a target tag also following the {@link FirewallTagNamingConvention}, which opens the requested port
+ * for all sources on both TCP and UDP protocols.
+ * @see org.jclouds.googlecomputeengine.features.FirewallApi#patch(String, org.jclouds.googlecomputeengine.options.FirewallOptions)
+ */
+ private void getOrCreateFirewalls(GoogleComputeEngineTemplateOptions templateOptions, Network network,
+ FirewallTagNamingConvention naming) {
+
+ String projectName = userProject.get();
+ FirewallApi firewallApi = api.getFirewallApiForProject(projectName);
+ Set<AtomicReference<Operation>> operations = Sets.newHashSet();
+
+ for (Integer port : templateOptions.getInboundPorts()) {
+ String name = naming.name(port);
+ Firewall firewall = firewallApi.get(name);
+ if (firewall == null) {
+ ImmutableSet<Firewall.Rule> rules = ImmutableSet.of(Firewall.Rule.permitTcpRule(port), Firewall.Rule.permitUdpRule(port));
+ FirewallOptions firewallOptions = new FirewallOptions()
+ .name(name)
+ .network(network.getSelfLink())
+ .allowedRules(rules)
+ .sourceTags(templateOptions.getTags())
+ .sourceRanges(of(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE))
+ .targetTags(ImmutableSet.of(name));
+ AtomicReference<Operation> operation = Atomics.newReference(firewallApi.createInNetwork(
+ firewallOptions.getName(),
+ network.getSelfLink(),
+ firewallOptions));
+ operations.add(operation);
+ }
+ }
+
+ for (AtomicReference<Operation> operation : operations) {
+ retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
+ MILLISECONDS).apply(operation);
+ checkState(!operation.get().getHttpError().isPresent(),
+ "Could not create firewall, operation failed" + operation);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
new file mode 100644
index 0000000..082d9ed
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ssh.internal.RsaSshKeyPairGenerator;
+
+import com.google.inject.Inject;
+
+@Singleton
+public class PopulateDefaultLoginCredentialsForImageStrategy implements
+ org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy {
+
+ private final TemplateBuilderSpec templateBuilder;
+ private final RsaSshKeyPairGenerator keyPairGenerator;
+ private String compoundKey;
+
+ @Inject
+ PopulateDefaultLoginCredentialsForImageStrategy(@Named(TEMPLATE) String templateSpec,
+ RsaSshKeyPairGenerator keyPairGenerator)
+ throws NoSuchAlgorithmException {
+ this.templateBuilder = TemplateBuilderSpec.parse(checkNotNull(templateSpec, "template builder spec"));
+ checkNotNull(templateBuilder.getLoginUser(), "template builder spec must provide a loginUser");
+ this.keyPairGenerator = checkNotNull(keyPairGenerator, "keypair generator");
+ }
+
+ @PostConstruct
+ private void generateKeys() {
+ Map<String, String> keys = keyPairGenerator.get();
+ // as we need to store both the pubk and the pk, store them separated by : (base64 does not contain that char)
+ compoundKey = String.format("%s:%s", checkNotNull(keys.get("public"), "public key cannot be null"),
+ checkNotNull(keys.get("private"), "private key cannot be null"));
+ }
+
+ @Override
+ public LoginCredentials apply(Object image) {
+ return LoginCredentials.builder()
+ .authenticateSudo(templateBuilder.getAuthenticateSudo() != null ?
+ templateBuilder.getAuthenticateSudo() : false)
+ .privateKey(compoundKey)
+ .user(templateBuilder.getLoginUser()).build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
new file mode 100644
index 0000000..ff75a03
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/UseNodeCredentialsButOverrideFromTemplate.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.RunScriptOptions;
+import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
+import org.jclouds.domain.LoginCredentials;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * GCE needs the credentials to create the node so the node credentials already take the Image credentials into account,
+ * as such only overriding the TemplateOptions credentials is required.
+ */
+@Singleton
+public class UseNodeCredentialsButOverrideFromTemplate extends PrioritizeCredentialsFromTemplate {
+
+
+ @Inject
+ public UseNodeCredentialsButOverrideFromTemplate(
+ Function<Template, LoginCredentials> credentialsFromImageOrTemplateOptions) {
+ super(credentialsFromImageOrTemplateOptions);
+ }
+
+ public LoginCredentials apply(Template template, LoginCredentials fromNode) {
+ RunScriptOptions options = checkNotNull(template.getOptions(), "template options are required");
+ LoginCredentials.Builder builder = LoginCredentials.builder(fromNode);
+ if (options.getLoginUser() != null)
+ builder.user(template.getOptions().getLoginUser());
+ if (options.getLoginPassword() != null)
+ builder.password(options.getLoginPassword());
+ if (options.getLoginPrivateKey() != null)
+ builder.privateKey(options.getLoginPrivateKey());
+ if (options.shouldAuthenticateSudo() != null && options.shouldAuthenticateSudo())
+ builder.authenticateSudo(true);
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
new file mode 100644
index 0000000..2a1b3f2
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineHttpApiModule.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.config;
+
+import static com.google.common.base.Suppliers.compose;
+import static com.google.inject.name.Names.named;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.domain.Credentials;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Project;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
+import org.jclouds.googlecomputeengine.handlers.GoogleComputeEngineErrorHandler;
+import org.jclouds.googlecomputeengine.predicates.GlobalOperationDonePredicate;
+import org.jclouds.googlecomputeengine.predicates.RegionOperationDonePredicate;
+import org.jclouds.googlecomputeengine.predicates.ZoneOperationDonePredicate;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.Uris;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.location.Provider;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.implicit.FirstZone;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures the GoogleCompute connection.
+ */
+@ConfiguresHttpApi
+public class GoogleComputeEngineHttpApiModule extends HttpApiModule<GoogleComputeEngineApi> {
+ public GoogleComputeEngineHttpApiModule() {
+ }
+
+ @Override
+ protected void configure() {
+ bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+ bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+ }).annotatedWith(named("global")).to(GlobalOperationDonePredicate.class);
+ bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+ }).annotatedWith(named("region")).to(RegionOperationDonePredicate.class);
+ bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() {
+ }).annotatedWith(named("zone")).to(ZoneOperationDonePredicate.class);
+ bind(ImplicitLocationSupplier.class).to(FirstZone.class).in(Scopes.SINGLETON);
+ super.configure();
+ }
+
+ @Override
+ protected void bindErrorHandlers() {
+ bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoogleComputeEngineErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoogleComputeEngineErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleComputeEngineErrorHandler.class);
+ }
+
+ @Provides
+ @Singleton
+ @UserProject
+ public Supplier<String> supplyProject(@Provider final Supplier<Credentials> creds,
+ final GoogleComputeEngineApi api,
+ AtomicReference<AuthorizationException> authException,
+ @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+ return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+ compose(new Function<Credentials, String>() {
+ public String apply(Credentials in) {
+ // ID should be of the form project_id@developer.gserviceaccount.com
+ // OR (increasingly often) project_id-extended_uid@developer.gserviceaccount.com
+ // where project_id is the NUMBER;
+ // HERE we also accept simply "project" as the identity, if no "@" is present;
+ // this is used in tests, but not sure if it is valid in the wild.
+ String projectName = in.identity;
+ if (projectName.indexOf("@") != -1) {
+ projectName = Iterables.get(Splitter.on("@").split(projectName), 0);
+ if (projectName.indexOf("-") != -1) {
+ // if ID is of the form project_id-extended_uid@developer.gserviceaccount.com
+ projectName = Iterables.get(Splitter.on("-").split(projectName), 0);
+ }
+ }
+ Project project = api.getProjectApi().get(projectName);
+ return project.getName();
+ }
+ }, creds), seconds, TimeUnit.SECONDS);
+ }
+
+ @Provides
+ @Singleton
+ @Named("machineTypeToURI")
+ public Function<String, URI> provideMachineTypeNameToURIFunction(@Provider final Supplier<URI> endpoint,
+ @UserProject final Supplier<String> userProject) {
+ return new Function<String, URI>() {
+ @Override
+ public URI apply(String input) {
+ SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(input);
+ return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+ .appendPath("/zones/").appendPath(slashEncodedIds.getFirstId())
+ .appendPath("/machineTypes/").appendPath(slashEncodedIds.getSecondId()).build();
+ }
+ };
+ }
+
+ @Provides
+ @Singleton
+ @Named("networkToURI")
+ public Function<String, URI> provideNetworkNameToURIFunction(@Provider final Supplier<URI> endpoint,
+ @UserProject final Supplier<String> userProject) {
+ return new Function<String, URI>() {
+ @Override
+ public URI apply(String input) {
+ return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+ .appendPath("/global/networks/").appendPath(input).build();
+ }
+ };
+ }
+
+ @Provides
+ @Singleton
+ @Named("zoneToURI")
+ public Function<String, URI> provideZoneNameToURIFunction(@Provider final Supplier<URI> endpoint,
+ @UserProject final Supplier<String> userProject) {
+ return new Function<String, URI>() {
+ @Override
+ public URI apply(String input) {
+ return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+ .appendPath("/zones/").appendPath(input).build();
+ }
+ };
+ }
+
+ @Provides
+ @Singleton
+ @Named("regionToURI")
+ public Function<String, URI> provideRegionNameToURIFunction(@Provider final Supplier<URI> endpoint,
+ @UserProject final Supplier<String> userProject) {
+ return new Function<String, URI>() {
+ @Override
+ public URI apply(String input) {
+ return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get())
+ .appendPath("/regions/").appendPath(input).build();
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
new file mode 100644
index 0000000..cd7e8d1
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineParserModule.java
@@ -0,0 +1,413 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.config;
+
+import static org.jclouds.googlecomputeengine.domain.Firewall.Rule;
+
+import java.beans.ConstructorProperties;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
+import org.jclouds.googlecomputeengine.domain.Metadata;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.Project;
+import org.jclouds.googlecomputeengine.domain.Quota;
+import org.jclouds.googlecomputeengine.options.FirewallOptions;
+import org.jclouds.googlecomputeengine.options.RouteOptions;
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.net.domain.IpProtocol;
+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 com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Range;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+public class GoogleComputeEngineParserModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(GsonModule.DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
+ }
+
+ @Provides
+ @Singleton
+ public Map<Type, Object> provideCustomAdapterBindings() {
+ return new ImmutableMap.Builder<Type, Object>()
+ .put(Metadata.class, new MetadataTypeAdapter())
+ .put(Operation.class, new OperationTypeAdapter())
+ .put(Header.class, new HeaderTypeAdapter())
+ .put(ClaimSet.class, new ClaimSetTypeAdapter())
+ .put(Project.class, new ProjectTypeAdapter())
+ .put(Instance.class, new InstanceTypeAdapter())
+ .put(InstanceTemplate.class, new InstanceTemplateTypeAdapter())
+ .put(FirewallOptions.class, new FirewallOptionsTypeAdapter())
+ .put(RouteOptions.class, new RouteOptionsTypeAdapter())
+ .put(Rule.class, new RuleTypeAdapter())
+ .build();
+ }
+
+ /**
+ * Parser for operations that unwraps errors avoiding an extra intermediate object.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/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", "region", "zone"
+ })
+ 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, URI region, URI zone) {
+ super(id, creationTimestamp, selfLink, name, description, targetLink, targetId, clientOperationId,
+ status, statusMessage, user, progress, insertTime, startTime, endTime, httpErrorStatusCode,
+ httpErrorMessage, operationType, null, region, zone);
+ }
+ }
+ }
+
+ @Singleton
+ private static class InstanceTemplateTypeAdapter implements JsonSerializer<InstanceTemplate> {
+
+ @Override
+ public JsonElement serialize(InstanceTemplate src, Type typeOfSrc, JsonSerializationContext context) {
+ InstanceTemplateInternal template = new InstanceTemplateInternal(src);
+ JsonObject instance = (JsonObject) context.serialize(template, InstanceTemplateInternal.class);
+
+ // deal with network
+ JsonArray networkInterfaces = new JsonArray();
+ for (InstanceTemplate.NetworkInterface networkInterface : template.getNetworkInterfaces()){
+ networkInterfaces.add(context.serialize(networkInterface, InstanceTemplate.NetworkInterface.class));
+ }
+ instance.add("networkInterfaces", networkInterfaces);
+
+ // deal with persistent disks
+ if (src.getDisks() != null && !src.getDisks().isEmpty()) {
+ JsonArray disks = new JsonArray();
+ for (InstanceTemplate.PersistentDisk persistentDisk : src.getDisks()) {
+ JsonObject disk = (JsonObject) context.serialize(persistentDisk, InstanceTemplate.PersistentDisk.class);
+ disk.addProperty("type", "PERSISTENT");
+ disks.add(disk);
+ }
+ instance.add("disks", disks);
+ }
+
+ // deal with metadata
+ if (src.getMetadata() != null && !src.getMetadata().isEmpty()) {
+ Metadata metadata = Metadata.builder()
+ .items(src.getMetadata())
+ .build();
+ JsonObject metadataJson = (JsonObject) context.serialize(metadata);
+ instance.add("metadata", metadataJson);
+ return instance;
+ }
+
+ return instance;
+ }
+
+ private static class InstanceTemplateInternal extends InstanceTemplate {
+ private InstanceTemplateInternal(InstanceTemplate template) {
+ super(template.getMachineType());
+ name(template.getName());
+ description(template.getDescription());
+ image(template.getImage());
+ serviceAccounts(template.getServiceAccounts());
+ networkInterfaces(template.getNetworkInterfaces());
+ }
+ }
+ }
+
+ @Singleton
+ private static class InstanceTypeAdapter implements JsonDeserializer<Instance> {
+
+ @Override
+ public Instance deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
+ JsonParseException {
+ Instance.Builder instanceBuilder = ((Instance) context.deserialize(json,
+ InstanceInternal.class)).toBuilder();
+ JsonObject object = (JsonObject) json;
+ if (object.get("disks") != null) {
+ JsonArray disks = (JsonArray) object.get("disks");
+ for (JsonElement element : disks) {
+ JsonObject disk = (JsonObject) element;
+ if (disk.get("type").getAsString().equals("PERSISTENT")) {
+ instanceBuilder.addDisk((Instance.PersistentAttachedDisk) context.deserialize(disk,
+ Instance.PersistentAttachedDisk.class));
+ } else {
+ instanceBuilder.addDisk((Instance.AttachedDisk) context.deserialize(disk,
+ Instance.AttachedDisk.class));
+ }
+ }
+
+ }
+
+ return Instance.builder().fromInstance(instanceBuilder.build()).build();
+ }
+
+
+ private static class InstanceInternal extends Instance {
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "tags", "machineType",
+ "status", "statusMessage", "zone", "networkInterfaces", "metadata", "serviceAccounts"
+ })
+ private InstanceInternal(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ Tags tags, URI machineType, Status status, String statusMessage,
+ URI zone, Set<NetworkInterface> networkInterfaces, Metadata metadata,
+ Set<ServiceAccount> serviceAccounts) {
+ super(id, creationTimestamp, selfLink, name, description, tags, machineType,
+ status, statusMessage, zone, networkInterfaces, null, metadata, serviceAccounts);
+ }
+ }
+ }
+
+ /**
+ * Parser for Metadata.
+ */
+ @Singleton
+ private static class MetadataTypeAdapter implements JsonDeserializer<Metadata>, JsonSerializer<Metadata> {
+
+
+ @Override
+ public Metadata deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
+ JsonParseException {
+ ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+ JsonObject metadata = json.getAsJsonObject();
+ JsonArray items = metadata.getAsJsonArray("items");
+ if (items != null) {
+ for (JsonElement element : items) {
+ JsonObject object = element.getAsJsonObject();
+ builder.put(object.get("key").getAsString(), object.get("value").getAsString());
+ }
+ }
+ String fingerprint = null;
+ if (metadata.getAsJsonPrimitive("fingerprint") != null) {
+ fingerprint = metadata.getAsJsonPrimitive("fingerprint").getAsString();
+ } else {
+ fingerprint = "";
+ }
+ return new Metadata(fingerprint, 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.getItems().entrySet()) {
+ JsonObject object = new JsonObject();
+ object.addProperty("key", entry.getKey());
+ object.addProperty("value", entry.getValue());
+ items.add(object);
+ }
+ metadataObject.add("items", items);
+ if (src.getFingerprint() != null) {
+ metadataObject.addProperty("fingerprint", src.getFingerprint());
+ }
+ return metadataObject;
+ }
+ }
+
+
+
+ @Singleton
+ private static class ProjectTypeAdapter implements JsonDeserializer<Project> {
+
+ @Override
+ public Project deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
+ JsonParseException {
+ return Project.builder().fromProject((Project) context.deserialize(json, ProjectInternal.class)).build();
+ }
+
+ private static class ProjectInternal extends Project {
+
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "commonInstanceMetadata", "quotas",
+ "externalIpAddresses"
+ })
+ private ProjectInternal(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ Metadata commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
+ super(id, creationTimestamp, selfLink, name, description, commonInstanceMetadata, quotas,
+ externalIpAddresses);
+ }
+
+ }
+ }
+
+ @Singleton
+ private static class FirewallOptionsTypeAdapter implements JsonSerializer<FirewallOptions> {
+
+ @Override
+ public JsonElement serialize(FirewallOptions src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject firewall = new JsonObject();
+ if (src.getName() != null) {
+ firewall.addProperty("name", src.getName());
+ }
+ if (src.getNetwork() != null) {
+ firewall.addProperty("network", src.getNetwork().toString());
+ }
+ if (!src.getSourceRanges().isEmpty()) {
+ firewall.add("sourceRanges", buildArrayOfStrings(src.getSourceRanges()));
+ }
+ if (!src.getSourceTags().isEmpty()) {
+ firewall.add("sourceTags", buildArrayOfStrings(src.getSourceTags()));
+ }
+ if (!src.getTargetTags().isEmpty()) {
+ firewall.add("targetTags", buildArrayOfStrings(src.getTargetTags()));
+ }
+ if (!src.getAllowed().isEmpty()) {
+ JsonArray rules = new JsonArray();
+ for (Rule rule : src.getAllowed()) {
+ rules.add(context.serialize(rule, Firewall.Rule.class));
+ }
+ firewall.add("allowed", rules);
+ }
+ return firewall;
+ }
+ }
+
+ @Singleton
+ private static class RouteOptionsTypeAdapter implements JsonSerializer<RouteOptions> {
+
+ @Override
+ public JsonElement serialize(RouteOptions src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject route = new JsonObject();
+ if (src.getName() != null) {
+ route.addProperty("name", src.getName());
+ }
+ if (src.getNetwork() != null) {
+ route.addProperty("network", src.getNetwork().toString());
+ }
+ if (src.getNextHopGateway() != null) {
+ route.addProperty("nextHopGateway", src.getNextHopGateway().toString());
+ }
+ if (src.getNextHopInstance() != null) {
+ route.addProperty("nextHopInstance", src.getNextHopInstance().toString());
+ }
+ if (src.getNextHopNetwork() != null) {
+ route.addProperty("nextHopNetwork", src.getNextHopNetwork().toString());
+ }
+ if (src.getDestRange() != null) {
+ route.addProperty("destRange", src.getDestRange());
+ }
+ if (src.getDescription() != null) {
+ route.addProperty("description", src.getDescription());
+ }
+ if (src.getPriority() != null) {
+ route.addProperty("priority", src.getPriority());
+ }
+ if (src.getNextHopIp() != null) {
+ route.addProperty("nextHopIp", src.getNextHopIp());
+ }
+ if (!src.getTags().isEmpty()) {
+ route.add("tags", buildArrayOfStrings(src.getTags()));
+ }
+ return route;
+ }
+ }
+
+ private static JsonArray buildArrayOfStrings(Set<String> strings) {
+ JsonArray array = new JsonArray();
+ for (String string : strings) {
+ array.add(new JsonPrimitive(string));
+ }
+ return array;
+ }
+
+
+ private static class RuleTypeAdapter implements JsonDeserializer<Firewall.Rule>, JsonSerializer<Firewall.Rule> {
+
+ @Override
+ public Firewall.Rule deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws
+ JsonParseException {
+ JsonObject rule = json.getAsJsonObject();
+ Rule.Builder builder = Rule.builder();
+ builder.IpProtocol(IpProtocol.fromValue(rule.get("IPProtocol").getAsString()));
+ if (rule.get("ports") != null) {
+ JsonArray ports = (JsonArray) rule.get("ports");
+ for (JsonElement port : ports) {
+ String portAsString = port.getAsString();
+ if (portAsString.contains("-")) {
+ String[] split = portAsString.split("-");
+ builder.addPortRange(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
+ } else {
+ builder.addPort(Integer.parseInt(portAsString));
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ @Override
+ public JsonElement serialize(Firewall.Rule src, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject ruleObject = new JsonObject();
+ ruleObject.addProperty("IPProtocol", src.getIpProtocol().value());
+ if (src.getPorts() != null && !src.getPorts().isEmpty()) {
+ JsonArray ports = new JsonArray();
+ for (Range<Integer> range : src.getPorts().asRanges()) {
+ ports.add(new JsonPrimitive(range.lowerEndpoint() == range.upperEndpoint() ? range.lowerEndpoint() + "" :
+ range.lowerEndpoint() + "-" + range.upperEndpoint()));
+ }
+ ruleObject.add("ports", ports);
+ }
+ return ruleObject;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
new file mode 100644
index 0000000..03f2f46
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/OAuthModuleWithoutTypeAdapters.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.config;
+
+import org.jclouds.oauth.v2.config.CredentialType;
+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;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Overrides OAuthModule leaving TypeAdapters bindings out.
+ * <p/>
+ * TODO overcome this by using multibindings on GSonModule?
+ */
+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);
+ bind(CredentialType.class).toProvider(OAuthModule.CredentialTypeFromPropertyOrDefault.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
new file mode 100644
index 0000000..e932d1c
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/config/UserProject.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Qualifies a property as the user's project id.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
+@Qualifier
+public @interface UserProject {
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
new file mode 100644
index 0000000..2cc8d8e
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/AbstractDisk.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+/**
+ * A persistent disk resource
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/disks"/>
+ */
+@Beta
+public abstract class AbstractDisk extends Resource {
+
+ protected final Integer sizeGb;
+ protected final String status;
+
+ protected AbstractDisk(Kind kind, String id, Date creationTimestamp, URI selfLink, String name, String description,
+ Integer sizeGb, String status) {
+ super(kind, id, creationTimestamp, selfLink, name, description);
+ this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
+ this.status = checkNotNull(status, "status of %s", name);
+ }
+
+ /**
+ * @return size of the persistent disk, specified in GB.
+ */
+ public int getSizeGb() {
+ return sizeGb;
+ }
+
+ /**
+ * @return the status of disk creation.
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return super.string()
+ .omitNullValues()
+ .add("sizeGb", sizeGb)
+ .add("status", status);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder<?> builder() {
+ return new ConcreteBuilder();
+ }
+
+ public Builder<?> toBuilder() {
+ return new ConcreteBuilder().fromAbstractDisk(this);
+ }
+
+ public abstract static class Builder<T extends Builder<T>> extends Resource.Builder<T> {
+
+ protected Integer sizeGb;
+ protected String status;
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.AbstractDisk#getSizeGb()
+ */
+ public T sizeGb(Integer sizeGb) {
+ this.sizeGb = sizeGb;
+ return self();
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.AbstractDisk#getStatus()
+ */
+ public T status(String status) {
+ this.status = status;
+ return self();
+ }
+
+ public T fromAbstractDisk(AbstractDisk in) {
+ return super.fromResource(in)
+ .sizeGb(in.getSizeGb())
+ .status(in.getStatus());
+ }
+
+ }
+
+ private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+ @Override
+ protected ConcreteBuilder self() {
+ return this;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
new file mode 100644
index 0000000..207cf75
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Address.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Represents an Address resource.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/addresses"/>
+ */
+@Beta
+public final class Address extends Resource {
+
+ private final String status;
+ private final Optional<URI> user;
+ private final URI region;
+ private final String address;
+
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "status", "user",
+ "region", "address"
+ })
+ private Address(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ String status, URI user, URI region, String address) {
+ super(Kind.ADDRESS, id, creationTimestamp, selfLink, name, description);
+ this.status = checkNotNull(status, "status of %s", name);
+ this.user = fromNullable(user);
+ this.region = checkNotNull(region, "region of %s", name);
+ this.address = checkNotNull(address, "address of %s", name);
+ }
+
+ /**
+ * @return The status of the address. Valid items are RESERVED and IN USE.
+ * A reserved address is currently available to the project and can be
+ * used by a resource. An in-use address is currently being used by a resource.
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * @return URL of the resource currently using this address.
+ */
+ public Optional<URI> getUser() {
+ return user;
+ }
+
+ /**
+ * @return URL of the region where the address resides.
+ */
+ public URI getRegion() {
+ return region;
+ }
+
+ /**
+ * @return The IP address represented by this resource.
+ */
+ public String getAddress() {
+ return address;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Address that = Address.class.cast(obj);
+ return equal(this.kind, that.kind)
+ && equal(this.name, that.name)
+ && equal(this.region, that.region);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return super.string()
+ .omitNullValues()
+ .add("status", status)
+ .add("user", user.orNull())
+ .add("region", region)
+ .add("address", address);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromAddress(this);
+ }
+
+ public static final class Builder extends Resource.Builder<Builder> {
+ private String status;
+ private URI user;
+ private URI region;
+ private String address;
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Address#getStatus()
+ */
+ public Builder status(String status) {
+ this.status = status;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Address#getUser()
+ */
+ public Builder user(URI user) {
+ this.user = user;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Address#getRegion()
+ */
+ public Builder region(URI region) {
+ this.region = region;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Address#getAddress()
+ */
+ public Builder address(String address) {
+ this.address = address;
+ return this;
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ public Address build() {
+ return new Address(super.id, super.creationTimestamp, super.selfLink, super.name,
+ super.description, status, user, region, address);
+ }
+
+ public Builder fromAddress(Address in) {
+ return super.fromResource(in)
+ .status(in.getStatus())
+ .user(in.getUser().orNull())
+ .region(in.getRegion())
+ .address(in.getAddress());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
new file mode 100644
index 0000000..5a48acf
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Deprecated.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Optional.fromNullable;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Deprecation information for an image or kernel
+ */
+public class Deprecated {
+ private final Optional<String> state;
+ private final Optional<URI> replacement;
+ private final Optional<String> deprecated;
+ private final Optional<String> obsolete;
+ private final Optional<String> deleted;
+
+ @ConstructorProperties({"state", "replacement", "deprecated", "obsolete", "deleted"})
+ public Deprecated(String state, URI replacement, String deprecated, String obsolete,
+ String deleted) {
+ this.state = fromNullable(state);
+ this.replacement = fromNullable(replacement);
+ this.deprecated = fromNullable(deprecated);
+ this.obsolete = fromNullable(obsolete);
+ this.deleted = fromNullable(deleted);
+ }
+
+ /**
+ * @return The deprecation state of this image.
+ */
+ public Optional<String> getState() {
+ return state;
+ }
+
+ /**
+ * @return A fully-qualified URL of the suggested replacement for the deprecated image.
+ */
+ public Optional<URI> getReplacement() {
+ return replacement;
+ }
+
+ /**
+ * @return An optional RFC3339 timestamp for when the deprecation state of this resource will be changed to DEPRECATED.
+ */
+ public Optional<String> getDeprecated() {
+ return deprecated;
+ }
+
+ /**
+ * @return An optional RFC3339 timestamp on or after which the deprecation state of this resource will be changed toOBSOLETE.
+ */
+ public Optional<String> getObsolete() {
+ return obsolete;
+ }
+
+ /**
+ * @return An optional RFC3339 timestamp on or after which the deprecation state of this resource will be changed to DELETED.
+ */
+ public Optional<String> getDeleted() {
+ return deleted;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(state, replacement, deprecated, obsolete, deleted);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Deprecated that = Deprecated.class.cast(obj);
+ return equal(this.state, that.state)
+ && equal(this.replacement, that.replacement)
+ && equal(this.deprecated, that.deprecated)
+ && equal(this.obsolete, that.obsolete)
+ && equal(this.deleted, that.deleted);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return toStringHelper(this)
+ .omitNullValues()
+ .add("state", state.orNull())
+ .add("replacement", replacement.orNull())
+ .add("deprecated", deprecated.orNull())
+ .add("obsolete", obsolete.orNull())
+ .add("deleted", deleted.orNull());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromDeprecated(this);
+ }
+
+ public static class Builder {
+ private String state;
+ private URI replacement;
+ private String deprecated;
+ private String obsolete;
+ private String deleted;
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Deprecated#getState()
+ */
+ public Builder state(String state) {
+ this.state = state;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Deprecated#getReplacement()
+ */
+ public Builder replacement(URI replacement) {
+ this.replacement = replacement;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Deprecated#getDeprecated()
+ */
+ public Builder deprecated(String deprecated) {
+ this.deprecated = deprecated;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Deprecated#getObsolete()
+ */
+ public Builder obsolete(String obsolete) {
+ this.obsolete = obsolete;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Deprecated#getDeprecated()
+ */
+ public Builder deleted(String deleted) {
+ this.deleted = deleted;
+ return this;
+ }
+
+ public Deprecated build() {
+ return new Deprecated(state, replacement, deprecated, obsolete, deleted);
+ }
+
+ public Builder fromDeprecated(Deprecated in) {
+ return new Builder().state(in.getState().orNull())
+ .replacement(in.getReplacement().orNull())
+ .deprecated(in.getDeprecated().orNull())
+ .obsolete(in.getObsolete().orNull())
+ .deleted(in.getDeleted().orNull());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
new file mode 100644
index 0000000..91d1502
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Disk.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+/**
+ * A persistent disk resource
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/disks"/>
+ */
+@Beta
+public final class Disk extends AbstractDisk {
+
+ private final URI zone;
+
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "sizeGb", "zone",
+ "status"
+ })
+ private Disk(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ Integer sizeGb, URI zone, String status) {
+ super(Kind.DISK, id, creationTimestamp, selfLink, name, description, sizeGb, status);
+ this.zone = checkNotNull(zone, "zone of %s", name);
+ }
+
+ /**
+ * @return URL for the zone where the persistent disk resides.
+ */
+ public URI getZone() {
+ return zone;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Disk that = Disk.class.cast(obj);
+ return equal(this.kind, that.kind)
+ && equal(this.name, that.name)
+ && equal(this.zone, that.zone);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return super.string()
+ .omitNullValues()
+ .add("zone", zone);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromDisk(this);
+ }
+
+ public static final class Builder extends AbstractDisk.Builder<Builder> {
+
+ private URI zone;
+
+ /**
+ * @see Disk#getZone()
+ */
+ public Builder zone(URI zone) {
+ this.zone = zone;
+ return this;
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ public Disk build() {
+ return new Disk(super.id, super.creationTimestamp, super.selfLink, super.name,
+ super.description, super.sizeGb, zone, super.status);
+ }
+
+ public Builder fromDisk(Disk in) {
+ return super.fromAbstractDisk(in)
+ .zone(in.getZone());
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3ddce9df/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
new file mode 100644
index 0000000..aee2cd4
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/domain/Firewall.java
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.googlecomputeengine.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Range.closed;
+import static com.google.common.collect.Range.singleton;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+import java.util.Set;
+
+import org.jclouds.net.domain.IpProtocol;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.RangeSet;
+import com.google.common.collect.TreeRangeSet;
+
+/**
+ * Represents a network firewall
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/firewalls"/>
+ * @see <a href="https://developers.google.com/compute/docs/networking#firewalls"/>
+ */
+@Beta
+public final class Firewall extends Resource {
+
+ private final URI network;
+ private final Set<String> sourceRanges;
+ private final Set<String> sourceTags;
+ private final Set<String> targetTags;
+ private final Set<Rule> allowed;
+
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "network", "sourceRanges",
+ "sourceTags", "targetTags", "allowed"
+ })
+ protected Firewall(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ URI network, Set<String> sourceRanges, Set<String> sourceTags, Set<String> targetTags,
+ Set<Rule> allowed) {
+ super(Kind.FIREWALL, id, creationTimestamp, selfLink, name, description);
+ this.network = checkNotNull(network, "network of %s", name);
+ this.sourceRanges = sourceRanges == null ? ImmutableSet.<String>of() : sourceRanges;
+ this.sourceTags = sourceTags == null ? ImmutableSet.<String>of() : sourceTags;
+ this.targetTags = targetTags == null ? ImmutableSet.<String>of() : targetTags;
+ this.allowed = allowed == null ? ImmutableSet.<Rule>of() : allowed;
+ }
+
+ /**
+ * @return URI of the network to which this firewall is applied; provided by the client when the firewall is created.
+ */
+ public URI getNetwork() {
+ return network;
+ }
+
+ /**
+ * One or both of sourceRanges and sourceTags may be set; an inbound connection is allowed if either the range or
+ * the tag of the source matches.
+ *
+ * @return a list of IP address blocks expressed in CIDR format which this rule applies to.
+ */
+ public Set<String> getSourceRanges() {
+ return sourceRanges;
+ }
+
+ /**
+ * @return a list of instance items which this rule applies to. One or both of sourceRanges and sourceTags may be
+ * set; an inbound connection is allowed if either the range or the tag of the source matches.
+ */
+ public Set<String> getSourceTags() {
+ return sourceTags;
+ }
+
+ /**
+ * If no targetTags are specified, the firewall rule applies to all instances on the specified network.
+ *
+ * @return a list of instance items indicating sets of instances located on network which may make network
+ * connections as specified in allowed.
+ */
+ public Set<String> getTargetTags() {
+ return targetTags;
+ }
+
+ /**
+ * Each rule specifies a protocol and port-range tuple that describes a permitted connection.
+ *
+ * @return the list of rules specified by this firewall.
+ */
+ public Set<Rule> getAllowed() {
+ return allowed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return super.string()
+ .add("network", network)
+ .add("sourceRanges", sourceRanges)
+ .add("sourceTags", sourceTags)
+ .add("targetTags", targetTags)
+ .add("allowed", allowed);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromFirewall(this);
+ }
+
+ public static final class Builder extends Resource.Builder<Builder> {
+
+ private URI network;
+ private ImmutableSet.Builder<String> sourceRanges = ImmutableSet.builder();
+ private ImmutableSet.Builder<String> sourceTags = ImmutableSet.builder();
+ private ImmutableSet.Builder<String> targetTags = ImmutableSet.builder();
+ private ImmutableSet.Builder<Rule> allowed = ImmutableSet.builder();
+
+ /**
+ * @see Firewall#getNetwork()
+ */
+ public Builder network(URI network) {
+ this.network = network;
+ return this;
+ }
+
+ /**
+ * @see Firewall#getSourceRanges()
+ */
+ public Builder addSourceRange(String sourceRange) {
+ this.sourceRanges.add(checkNotNull(sourceRange));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getSourceRanges()
+ */
+ public Builder sourceRanges(Set<String> sourceRanges) {
+ this.sourceRanges.addAll(checkNotNull(sourceRanges));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getSourceTags()
+ */
+ public Builder addSourceTag(String sourceTag) {
+ this.sourceTags.add(checkNotNull(sourceTag));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getSourceTags()
+ */
+ public Builder sourceTags(Set<String> sourceTags) {
+ this.sourceTags.addAll(checkNotNull(sourceTags));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getTargetTags()
+ */
+ public Builder addTargetTag(String targetTag) {
+ this.targetTags.add(checkNotNull(targetTag));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getTargetTags()
+ */
+ public Builder targetTags(Set<String> targetTags) {
+ this.targetTags.addAll(checkNotNull(targetTags));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getAllowed()
+ */
+ public Builder addAllowed(Rule firewallRule) {
+ this.allowed.add(checkNotNull(firewallRule));
+ return this;
+ }
+
+ /**
+ * @see Firewall#getAllowed()
+ */
+ public Builder allowed(Set<Rule> firewallRules) {
+ this.allowed = ImmutableSet.builder();
+ this.allowed.addAll(firewallRules);
+ return this;
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ public Firewall build() {
+ return new Firewall(super.id, super.creationTimestamp, super.selfLink, super.name,
+ super.description, network, sourceRanges.build(), sourceTags.build(), targetTags.build(),
+ allowed.build());
+ }
+
+ public Builder fromFirewall(Firewall in) {
+ return super.fromResource(in).network(in.getNetwork()).sourceRanges(in.getSourceRanges()).sourceTags(in
+ .getSourceTags()).targetTags(in.getTargetTags()).allowed(in.getAllowed());
+ }
+
+ }
+
+ /**
+ * A Firewall rule. Rule specifies a protocol and port-range tuple that describes a
+ * permitted connection.
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1/firewalls"/>
+ */
+ public static final class Rule {
+
+ private final IpProtocol ipProtocol;
+ private final RangeSet<Integer> ports;
+
+ /* Some handy shortcuts */
+ public static Rule permitTcpRule(Integer start, Integer end) { return Rule.builder().IpProtocol(IpProtocol.TCP).addPortRange(start, end).build(); }
+ public static Rule permitTcpRule(Integer port) { return Rule.builder().IpProtocol(IpProtocol.TCP).addPort(port).build(); }
+ public static Rule permitUdpRule(Integer start, Integer end) { return Rule.builder().IpProtocol(IpProtocol.UDP).addPortRange(start, end).build(); }
+ public static Rule permitUdpRule(Integer port) { return Rule.builder().IpProtocol(IpProtocol.UDP).addPort(port).build(); }
+ @ConstructorProperties({
+ "IpProtocol", "ports"
+ })
+ private Rule(IpProtocol IpProtocol, RangeSet<Integer> ports) {
+ this.ipProtocol = checkNotNull(IpProtocol);
+ this.ports = ports == null ? TreeRangeSet.<Integer>create() : ports;
+ }
+
+ /**
+ * This can either be a well known protocol string (tcp, udp or icmp) or the IP protocol number.
+ *
+ * @return this is the IP protocol that is allowed for this rule.
+ */
+ public IpProtocol getIpProtocol() {
+ return ipProtocol;
+ }
+
+ /**
+ * Each entry must be either an integer or a range. If not specified, connections through any port are allowed.
+ * Example inputs include: ["22"], ["80,"443"], and ["12345-12349"].
+ * <p/>
+ * It is an error to specify this for any protocol that isn't UDP or TCP.
+ *
+ * @return An optional list of ports which are allowed.
+ */
+ public RangeSet<Integer> getPorts() {
+ return ports;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ipProtocol, ports);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Rule that = Rule.class.cast(obj);
+ return equal(this.ipProtocol, that.ipProtocol)
+ && equal(this.ports, that.ports);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Objects.ToStringHelper string() {
+ return toStringHelper(this)
+ .add("IpProtocol", ipProtocol).add("ports", ports);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromFirewallRule(this);
+ }
+
+ public static final class Builder {
+
+ private IpProtocol ipProtocol;
+ private RangeSet<Integer> ports = TreeRangeSet.create();
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getIpProtocol()
+ */
+ public Builder IpProtocol(IpProtocol IpProtocol) {
+ this.ipProtocol = IpProtocol;
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
+ */
+ public Builder addPort(Integer port) {
+ this.ports.add(singleton(checkNotNull(port, "port")));
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
+ */
+ public Builder addPortRange(Integer start, Integer end) {
+ checkState(checkNotNull(start, "start") < checkNotNull(end, "end"),
+ "start of range must be lower than end of range");
+ this.ports.add(closed(start, end));
+ return this;
+ }
+
+ /**
+ * @see org.jclouds.googlecomputeengine.domain.Firewall.Rule#getPorts()
+ */
+ public Builder ports(RangeSet<Integer> ports) {
+ this.ports = TreeRangeSet.create();
+ this.ports.addAll(ports);
+ return this;
+ }
+
+ public Rule build() {
+ return new Rule(ipProtocol, ports);
+ }
+
+ public Builder fromFirewallRule(Rule firewallRule) {
+ return new Builder().IpProtocol(firewallRule.getIpProtocol()).ports(firewallRule.getPorts());
+ }
+ }
+
+ }
+}