| /* |
| * 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.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. |
| * |
| * @author David Alves |
| */ |
| @ConfiguresHttpApi |
| public class GoogleComputeEngineHttpApiModule extends HttpApiModule<GoogleComputeEngineApi> { |
| public GoogleComputeEngineHttpApiModule() { |
| } |
| |
| @Override |
| protected void configure() { |
| bind(DateAdapter.class).to(Iso8601DateAdapter.class); |
| bind(new TypeLiteral<Predicate<AtomicReference<Operation>>>() { |
| }).annotatedWith(named("global")).to(GlobalOperationDonePredicate.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(final @Provider Supplier<URI> endpoint, |
| final @UserProject 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(final @Provider Supplier<URI> endpoint, |
| final @UserProject Supplier<String> userProject) { |
| return new Function<String, URI>() { |
| @Override |
| public URI apply(String input) { |
| return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()) |
| .appendPath("/global/networks/").appendPath(input).build(); |
| } |
| }; |
| } |
| |
| @Provides |
| @Singleton |
| @Named("zoneToURI") |
| public Function<String, URI> provideZoneNameToURIFunction(final @Provider Supplier<URI> endpoint, |
| final @UserProject Supplier<String> userProject) { |
| return new Function<String, URI>() { |
| @Override |
| public URI apply(String input) { |
| return Uris.uriBuilder(endpoint.get()).appendPath("/projects/").appendPath(userProject.get()) |
| .appendPath("/zones/").appendPath(input).build(); |
| } |
| }; |
| } |
| } |