support changing credentials at runtime

This commit is contained in:
Adrian Cole 2013-01-15 21:25:51 -08:00
parent a9d335c6cc
commit a7e4564c8e
13 changed files with 172 additions and 181 deletions

View File

@ -29,13 +29,15 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.internal.VolumeImpl; import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;
import org.jclouds.predicates.SocketOpen; import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -68,9 +70,9 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected ConcurrentMap<String, NodeMetadata> provideNodesForIdentity(@Identity String identity) protected ConcurrentMap<String, NodeMetadata> provideNodesForIdentity(@Provider Supplier<Credentials> creds)
throws ExecutionException { throws ExecutionException {
return backing.get(identity); return backing.get(creds.get().identity);
} }
protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build( protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build(
@ -85,8 +87,8 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Named("NODE_ID") @Named("NODE_ID")
protected Integer provideNodeIdForIdentity(@Identity String identity) throws ExecutionException { protected Integer provideNodeIdForIdentity(@Provider Supplier<Credentials> creds) throws ExecutionException {
return nodeIds.get(identity).incrementAndGet(); return nodeIds.get(creds.get().identity).incrementAndGet();
} }
@Singleton @Singleton

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds; package org.jclouds;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.containsPattern; import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.instanceOf;
@ -30,6 +31,8 @@ import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.filterKeys;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_API; import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_API_VERSION;
@ -84,12 +87,12 @@ import com.google.common.base.Objects;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ExecutionList; import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -189,18 +192,18 @@ public class ContextBuilder {
protected final String providerId; protected final String providerId;
protected Optional<String> endpoint = Optional.absent(); protected Optional<String> endpoint = Optional.absent();
protected Optional<String> identity = Optional.absent(); protected Optional<String> identity = Optional.absent();
protected Optional<Supplier<Credentials>> credentialsSupplierOption = Optional.absent();
@Nullable @Nullable
protected String credential; protected String credential;
protected ApiMetadata apiMetadata; protected ApiMetadata apiMetadata;
protected String apiVersion; protected String apiVersion;
protected String buildVersion; protected String buildVersion;
protected Optional<Properties> overrides = Optional.absent(); protected Optional<Properties> overrides = Optional.absent();
protected List<Module> modules = Lists.newArrayListWithCapacity(3); protected List<Module> modules = newArrayListWithCapacity(3);
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata) return toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata).toString();
.toString();
} }
protected ContextBuilder(ProviderMetadata providerMetadata) { protected ContextBuilder(ProviderMetadata providerMetadata) {
@ -232,6 +235,20 @@ public class ContextBuilder {
return this; return this;
} }
/**
* returns the current login credentials. jclouds will not cache this value. Use this when you need to change
* credentials at runtime.
*/
public ContextBuilder credentialsSupplier(Supplier<Credentials> credentialsSupplier) {
this.credentialsSupplierOption = Optional.of(checkNotNull(credentialsSupplier, "credentialsSupplier"));
return this;
}
/**
* constant value of the cloud identity and credential.
*
* @param credential (optional depending on {@link ApiMetadata#getCredentialName()}
*/
public ContextBuilder credentials(String identity, @Nullable String credential) { public ContextBuilder credentials(String identity, @Nullable String credential) {
this.identity = Optional.of(checkNotNull(identity, "identity")); this.identity = Optional.of(checkNotNull(identity, "identity"));
this.credential = credential; this.credential = credential;
@ -289,14 +306,29 @@ public class ContextBuilder {
Properties expanded = expandProperties(resolved); Properties expanded = expandProperties(resolved);
Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded, Supplier<Credentials> credentialsSupplier = buildCredentialsSupplier(expanded);
PROPERTY_CREDENTIAL));
ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata).apply(expanded); ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata)
.apply(expanded);
//We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash is used to be something readable. // We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash
// is used to be something readable.
return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(), return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(),
providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), creds.identity))), providerMetadata, creds, modules); providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), credentialsSupplier))),
providerMetadata, credentialsSupplier, modules);
}
protected Supplier<Credentials> buildCredentialsSupplier(Properties expanded) {
Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded,
PROPERTY_CREDENTIAL));
Supplier<Credentials> credentialsSupplier;
if (credentialsSupplierOption.isPresent()) {
credentialsSupplier = credentialsSupplierOption.get();
} else {
credentialsSupplier = Suppliers.ofInstance(creds);
}
return credentialsSupplier;
} }
private static String getAndRemove(Properties expanded, String key) { private static String getAndRemove(Properties expanded, String key) {
@ -340,7 +372,7 @@ public class ContextBuilder {
return Guice.createInjector(new BindPropertiesToExpandedValues(resolved)).getInstance(Properties.class); return Guice.createInjector(new BindPropertiesToExpandedValues(resolved)).getInstance(Properties.class);
} }
public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Credentials creds, List<Module> inputModules) { public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Supplier<Credentials> creds, List<Module> inputModules) {
List<Module> modules = newArrayList(); List<Module> modules = newArrayList();
modules.addAll(inputModules); modules.addAll(inputModules);
boolean restModuleSpecifiedByUser = restClientModulePresent(inputModules); boolean restModuleSpecifiedByUser = restClientModulePresent(inputModules);
@ -411,8 +443,7 @@ public class ContextBuilder {
@SuppressWarnings( { "unchecked" }) @SuppressWarnings( { "unchecked" })
static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId, static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId,
String providerId) { String providerId) {
return Maps.filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId return filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId + ").*"));
+ ").*"));
} }
@VisibleForTesting @VisibleForTesting

View File

@ -26,12 +26,13 @@ import static java.lang.String.format;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.crypto.Crypto; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.annotations.Credential; import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
/** /**
* Uses Basic Authentication to sign the request. * Uses Basic Authentication to sign the request.
@ -43,22 +44,24 @@ import org.jclouds.rest.annotations.Identity;
@Singleton @Singleton
public class BasicAuthentication implements HttpRequestFilter { public class BasicAuthentication implements HttpRequestFilter {
private final String header; private final Supplier<Credentials> creds;
@Inject @Inject
public BasicAuthentication(@Identity String user, @Credential String password, Crypto crypto) { public BasicAuthentication(@Provider Supplier<Credentials> creds) {
checkNotNull(user, "user"); this.creds = checkNotNull(creds, "creds");
checkNotNull(password, "password");
this.header = basic(user, password);
} }
public static String basic(String user, String password) { public static String basic(String user, String password) {
return new StringBuilder("Basic ").append(base64().encode(format("%s:%s", user, password).getBytes(UTF_8))) return new StringBuilder("Basic ").append(
base64().encode(
format("%s:%s", checkNotNull(user, "user"), checkNotNull(password, "password")).getBytes(UTF_8)))
.toString(); .toString();
} }
@Override @Override
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
return request.toBuilder().replaceHeader(AUTHORIZATION, header).build(); Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
return request.toBuilder().replaceHeader(AUTHORIZATION, basic(currentCreds.identity, currentCreds.credential))
.build();
} }
} }

View File

@ -18,26 +18,31 @@
*/ */
package org.jclouds.internal; package org.jclouds.internal;
import com.google.common.base.Objects; import static com.google.common.base.Objects.equal;
import com.google.common.collect.ImmutableMap; import static com.google.common.base.Objects.toStringHelper;
import com.google.common.io.Closeables; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Singleton; import static com.google.common.io.Closeables.closeQuietly;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.Context; import org.jclouds.Context;
import org.jclouds.annotations.Name; import org.jclouds.annotations.Name;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.location.Provider;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.Identity;
import javax.inject.Inject; import com.google.common.base.Objects;
import java.net.URI; import com.google.common.base.Supplier;
import java.util.Map; import com.google.common.collect.ImmutableMap;
import java.util.Set; import com.google.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -46,15 +51,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class ContextImpl implements Context { public class ContextImpl implements Context {
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final String identity; private final Supplier<Credentials> creds;
private final Utils utils; private final Utils utils;
private final Closer closer; private final Closer closer;
private final String name; private final String name;
@Inject @Inject
protected ContextImpl(@Name String name, ProviderMetadata providerMetadata, @Identity String identity, Utils utils, Closer closer) { protected ContextImpl(@Name String name, ProviderMetadata providerMetadata, @Provider Supplier<Credentials> creds,
Utils utils, Closer closer) {
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata"); this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
this.identity = checkNotNull(identity, "identity"); this.creds = checkNotNull(creds, "creds");
this.utils = checkNotNull(utils, "utils"); this.utils = checkNotNull(utils, "utils");
this.closer = checkNotNull(closer, "closer"); this.closer = checkNotNull(closer, "closer");
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
@ -65,7 +71,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public void close() { public void close() {
Closeables.closeQuietly(closer); closeQuietly(closer);
} }
/** /**
@ -89,7 +95,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public String getIdentity() { public String getIdentity() {
return identity; return creds.get().identity;
} }
/** /**
@ -134,7 +140,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(providerMetadata, identity); return Objects.hashCode(providerMetadata, creds);
} }
/** /**
@ -149,7 +155,7 @@ public class ContextImpl implements Context {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
ContextImpl that = ContextImpl.class.cast(obj); ContextImpl that = ContextImpl.class.cast(obj);
return Objects.equal(this.providerMetadata, that.providerMetadata) && Objects.equal(this.identity, that.identity); return equal(this.providerMetadata, that.providerMetadata) && equal(this.creds, that.creds);
} }
/** /**
@ -157,7 +163,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper("").add("providerMetadata", providerMetadata).add("identity", identity).toString(); return toStringHelper("").add("providerMetadata", providerMetadata).add("identity", getIdentity()).toString();
} }
/** /**
@ -191,7 +197,7 @@ public class ContextImpl implements Context {
public Map<String, Object> getMetadata() { public Map<String, Object> getMetadata() {
return ImmutableMap.<String, Object> of("endpoint", URI.create(providerMetadata.getEndpoint()), "apiVersion", return ImmutableMap.<String, Object> of("endpoint", URI.create(providerMetadata.getEndpoint()), "apiVersion",
providerMetadata.getApiMetadata().getVersion(), "buildVersion", providerMetadata.getApiMetadata() providerMetadata.getApiMetadata().getVersion(), "buildVersion", providerMetadata.getApiMetadata()
.getBuildVersion().or(""), "identity", identity); .getBuildVersion().or(""), "identity", getIdentity());
} }
/** /**

View File

@ -33,9 +33,8 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.annotations.Api; import org.jclouds.rest.annotations.Api;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -56,9 +55,9 @@ import com.google.inject.name.Names;
public class BindProviderMetadataContextAndCredentials extends AbstractModule { public class BindProviderMetadataContextAndCredentials extends AbstractModule {
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final Credentials creds; private final Supplier<Credentials> creds;
public BindProviderMetadataContextAndCredentials(ProviderMetadata providerMetadata, Credentials creds) { public BindProviderMetadataContextAndCredentials(ProviderMetadata providerMetadata, Supplier<Credentials> creds) {
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata"); this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
this.creds = checkNotNull(creds, "creds"); this.creds = checkNotNull(creds, "creds");
} }
@ -70,11 +69,7 @@ public class BindProviderMetadataContextAndCredentials extends AbstractModule {
toBind.putAll(providerMetadata.getApiMetadata().getDefaultProperties()); toBind.putAll(providerMetadata.getApiMetadata().getDefaultProperties());
toBind.putAll(providerMetadata.getDefaultProperties()); toBind.putAll(providerMetadata.getDefaultProperties());
Names.bindProperties(binder(), toBind); Names.bindProperties(binder(), toBind);
bind(Credentials.class).annotatedWith(Provider.class).toInstance(creds); bind(new TypeLiteral<Supplier<Credentials>>(){}).annotatedWith(Provider.class).toInstance(creds);
bindConstant().annotatedWith(Identity.class).to(creds.identity);
// nullable
bind(String.class).annotatedWith(Credential.class).toProvider(
com.google.inject.util.Providers.of(creds.credential));
bindConstant().annotatedWith(Provider.class).to(providerMetadata.getId()); bindConstant().annotatedWith(Provider.class).to(providerMetadata.getId());
bind(new TypeLiteral<Set<String>>() { bind(new TypeLiteral<Set<String>>() {
}).annotatedWith(Iso3166.class).toInstance(providerMetadata.getIso3166Codes()); }).annotatedWith(Iso3166.class).toInstance(providerMetadata.getIso3166Codes());

View File

@ -1,42 +0,0 @@
/**
* 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.rest.annotations;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Designates that this Resource qualifies an object to a key on a provider.
*
* @author Adrian Cole
*/
@Target( { ANNOTATION_TYPE, FIELD, METHOD, PARAMETER })
@Retention(RUNTIME)
@Qualifier
public @interface Credential {
}

View File

@ -1,42 +0,0 @@
/**
* 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.rest.annotations;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Designates that this Resource qualifies an object to an identity on a provider.
*
* @author Adrian Cole
*/
@Target( { ANNOTATION_TYPE, FIELD, METHOD, PARAMETER })
@Retention(RUNTIME)
@Qualifier
public @interface Identity {
}

View File

@ -23,13 +23,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.annotations.Name; import org.jclouds.annotations.Name;
import org.jclouds.domain.Credentials;
import org.jclouds.internal.ContextImpl; import org.jclouds.internal.ContextImpl;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.location.Provider;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@ -45,9 +47,10 @@ public class RestContextImpl<S, A> extends ContextImpl implements RestContext<S,
private final S syncApi; private final S syncApi;
@Inject @Inject
protected RestContextImpl(@Name String name, ProviderMetadata providerMetadata, @Identity String identity, Utils utils, Closer closer, protected RestContextImpl(@Name String name, ProviderMetadata providerMetadata,
Injector injector, TypeLiteral<S> syncApi, TypeLiteral<A> asyncApi) { @Provider Supplier<Credentials> creds, Utils utils, Closer closer, Injector injector, TypeLiteral<S> syncApi,
super(name, providerMetadata, identity, utils, closer); TypeLiteral<A> asyncApi) {
super(name, providerMetadata, creds, utils, closer);
checkNotNull(injector, "injector"); checkNotNull(injector, "injector");
this.asyncApi = injector.getInstance(Key.get(checkNotNull(asyncApi, "asyncApi"))); this.asyncApi = injector.getInstance(Key.get(checkNotNull(asyncApi, "asyncApi")));
this.syncApi = injector.getInstance(Key.get(checkNotNull(syncApi, "syncApi"))); this.syncApi = injector.getInstance(Key.get(checkNotNull(syncApi, "syncApi")));

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds; package org.jclouds;
import static com.google.common.base.Suppliers.ofInstance;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
@ -27,6 +28,7 @@ import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.domain.Credentials;
import org.jclouds.events.config.EventBusModule; import org.jclouds.events.config.EventBusModule;
import org.jclouds.http.IntegrationTestAsyncClient; import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.http.IntegrationTestClient; import org.jclouds.http.IntegrationTestClient;
@ -40,7 +42,6 @@ import org.jclouds.providers.AnonymousProviderMetadata;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.CredentialStoreModule; import org.jclouds.rest.config.CredentialStoreModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -115,8 +116,23 @@ public class ContextBuilderTest {
overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo"); overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo");
overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR"); overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR");
ContextBuilder withCredsInProps = testContextBuilder().overrides(overrides); ContextBuilder withCredsInProps = testContextBuilder().overrides(overrides);
String identity = withCredsInProps.buildInjector().getInstance(Key.get(String.class, Identity.class)); Credentials creds = withCredsInProps.buildInjector()
assertEquals(identity, "foo"); .getInstance(Key.get(new TypeLiteral<Supplier<Credentials>>() {
}, Provider.class)).get();
assertEquals(creds, new Credentials("foo", "BAR"));
}
@Test
public void testProviderMetadataWithCredentialsSetSupplier() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo");
overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR");
ContextBuilder withCredsSupplier = testContextBuilder().credentialsSupplier(
ofInstance(new Credentials("foo", "BAR")));
Credentials creds = withCredsSupplier.buildInjector()
.getInstance(Key.get(new TypeLiteral<Supplier<Credentials>>() {
}, Provider.class)).get();
assertEquals(creds, new Credentials("foo", "BAR"));
} }
@Test @Test

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.config; package org.jclouds.config;
import static com.google.common.base.Suppliers.ofInstance;
import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createMock;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -74,7 +75,7 @@ public class BindRestContextWithWildcardExtendsExplicitAndRawTypeTest {
private Injector injectorFor(ProviderMetadata md) { private Injector injectorFor(ProviderMetadata md) {
return Guice.createInjector( return Guice.createInjector(
new BindNameToContext("test"), new BindNameToContext("test"),
new BindProviderMetadataContextAndCredentials(md, new Credentials("user", "pass")), new BindProviderMetadataContextAndCredentials(md, ofInstance(new Credentials("user", "pass"))),
new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class.cast(md new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class.cast(md
.getApiMetadata())), .getApiMetadata())),

View File

@ -18,31 +18,50 @@
*/ */
package org.jclouds.http.filters; package org.jclouds.http.filters;
import static com.google.common.base.Suppliers.ofInstance;
import static com.google.common.collect.Queues.newArrayDeque;
import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static java.util.Arrays.asList;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.security.NoSuchAlgorithmException; import java.util.Deque;
import java.security.cert.CertificateException;
import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit") @Test(groups = "unit")
public class BasicAuthenticationTest { public class BasicAuthenticationTest {
private static final Credentials credential1 = new Credentials("Aladdin", "open sesame");
private static final Credentials credential2 = new Credentials("Little", "Mermaid");
private static final String USER = "Aladdin"; public void testAuth() {
private static final String PASSWORD = "open sesame"; HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build();
request = new BasicAuthentication(ofInstance(credential1)).filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
request = new BasicAuthentication(ofInstance(credential2)).filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic TGl0dGxlOk1lcm1haWQ=");
}
public void testAuth() throws NoSuchAlgorithmException, CertificateException { public void testAuthWithRuntimePasswordChange() {
BasicAuthentication filter = new BasicAuthentication(USER, PASSWORD, new JCECrypto(null)); Supplier<Credentials> credentialRotation = new Supplier<Credentials>() {
Deque<Credentials> rotation = newArrayDeque(asList(credential1, credential2));
public Credentials get() {
return rotation.poll();
}
};
BasicAuthentication filter = new BasicAuthentication(credentialRotation);
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build();
request = filter.filter(request); request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic TGl0dGxlOk1lcm1haWQ=");
} }
} }

View File

@ -23,11 +23,14 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.fail; import static org.testng.Assert.fail;
import org.jclouds.domain.Credentials;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
/** /**
@ -36,10 +39,12 @@ import com.google.common.reflect.TypeToken;
@Test(groups = "unit", testName = "BaseViewTest") @Test(groups = "unit", testName = "BaseViewTest")
public class BaseViewTest { public class BaseViewTest {
static Supplier<Credentials> creds = Suppliers.ofInstance(new Credentials("identity", null));
private static class Water extends ContextImpl { private static class Water extends ContextImpl {
protected Water() { protected Water() {
super("water", createMock(ProviderMetadata.class), "identity", createMock(Utils.class), createMock(Closer.class)); super("water", createMock(ProviderMetadata.class), creds, createMock(Utils.class), createMock(Closer.class));
} }
public void close() { public void close() {
@ -49,7 +54,7 @@ public class BaseViewTest {
private static class PeanutButter extends ContextImpl { private static class PeanutButter extends ContextImpl {
protected PeanutButter() { protected PeanutButter() {
super("peanutbutter", createMock(ProviderMetadata.class), "identity", createMock(Utils.class), createMock(Closer.class)); super("peanutbutter", createMock(ProviderMetadata.class), creds, createMock(Utils.class), createMock(Closer.class));
} }
public void close() { public void close() {

View File

@ -41,11 +41,11 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.annotations.Api; import org.jclouds.rest.annotations.Api;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Key; import com.google.inject.Key;
@ -63,8 +63,6 @@ public class BindProviderMetadataContextAndCredentialsTest {
private final javax.inject.Provider<Context> backend; private final javax.inject.Provider<Context> backend;
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final Credentials creds; private final Credentials creds;
private final String identity;
private final String credential;
private final String providerId; private final String providerId;
private final Set<String> iso3166Codes; private final Set<String> iso3166Codes;
private final String apiId; private final String apiId;
@ -73,10 +71,9 @@ public class BindProviderMetadataContextAndCredentialsTest {
@Inject @Inject
private ExpectedBindings(@Provider javax.inject.Provider<Context> backend, ProviderMetadata providerMetadata, private ExpectedBindings(@Provider javax.inject.Provider<Context> backend, ProviderMetadata providerMetadata,
@Provider Credentials creds, @Identity String identity, @Nullable @Credential String credential, @Provider Supplier<Credentials> creds, @Provider String providerId, @Iso3166 Set<String> iso3166Codes,
@Provider String providerId, @Iso3166 Set<String> iso3166Codes, @Api String apiId, @Api String apiId, @ApiVersion String apiVersion, @Nullable @BuildVersion String buildVersion,
@ApiVersion String apiVersion, @Nullable @BuildVersion String buildVersion, @Provider TypeToken<? extends Context> backendToken, FilterStringsBoundToInjectorByName filter) {
@Provider TypeToken<? extends Context> backendToken, FilterStringsBoundToInjectorByName filter) {
this.backend = backend; this.backend = backend;
assertEquals(backendToken, providerMetadata.getApiMetadata().getContext()); assertEquals(backendToken, providerMetadata.getApiMetadata().getContext());
this.providerMetadata = providerMetadata; this.providerMetadata = providerMetadata;
@ -86,11 +83,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
expected.putAll(providerMetadata.getApiMetadata().getDefaultProperties()); expected.putAll(providerMetadata.getApiMetadata().getDefaultProperties());
expected.putAll(providerMetadata.getDefaultProperties()); expected.putAll(providerMetadata.getDefaultProperties());
assertEquals(props, expected); assertEquals(props, expected);
this.creds = creds; this.creds = creds.get();
this.identity = identity;
assertEquals(identity, creds.identity);
this.credential = credential;
assertEquals(credential, creds.credential);
this.providerId = providerId; this.providerId = providerId;
assertEquals(providerId, providerMetadata.getId()); assertEquals(providerId, providerMetadata.getId());
this.iso3166Codes = iso3166Codes; this.iso3166Codes = iso3166Codes;
@ -110,12 +103,13 @@ public class BindProviderMetadataContextAndCredentialsTest {
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint( ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
Credentials creds = LoginCredentials.builder().user("user").password("password").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user")
.password("password").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
assertEquals(bindings.identity, "user"); assertEquals(bindings.creds.identity, "user");
assertEquals(bindings.credential, "password"); assertEquals(bindings.creds.credential, "password");
} }
@Test @Test
@ -123,12 +117,12 @@ public class BindProviderMetadataContextAndCredentialsTest {
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint( ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
assertEquals(bindings.identity, "user"); assertEquals(bindings.creds.identity, "user");
assertEquals(bindings.credential, null); assertEquals(bindings.creds.credential, null);
} }
@Test @Test
@ -138,7 +132,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build(); ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build();
md = md.toBuilder().apiMetadata(apiMd).build(); md = md.toBuilder().apiMetadata(apiMd).build();
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
@ -154,7 +148,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + ""); defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + "");
md = md.toBuilder().defaultProperties(defaultProps).build(); md = md.toBuilder().defaultProperties(defaultProps).build();
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
int session = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)).getInstance( int session = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)).getInstance(
Key.get(int.class, Names.named(Constants.PROPERTY_SESSION_INTERVAL))); Key.get(int.class, Names.named(Constants.PROPERTY_SESSION_INTERVAL)));