refactored ssh connections so that they can be shared across views

This commit is contained in:
Adrian Cole 2010-10-26 11:37:13 -07:00
parent c7c6e9eae1
commit b08abc6745
21 changed files with 335 additions and 148 deletions

View File

@ -37,12 +37,12 @@ import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.predicates.InstanceStateRunning; import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.InetSocketAddressConnect;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
import org.jclouds.scriptbuilder.ScriptBuilder; import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;

View File

@ -21,9 +21,11 @@ package org.jclouds.compute;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.internal.UtilsImpl; import org.jclouds.compute.internal.UtilsImpl;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
/** /**
@ -37,4 +39,9 @@ public interface Utils extends org.jclouds.rest.Utils {
@Nullable @Nullable
SshClient.Factory sshFactory(); SshClient.Factory sshFactory();
/**
* @return function that gets an ssh client for a node that is available via ssh.
*/
Function<NodeMetadata, SshClient> sshForNode();
} }

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections; import java.util.Collections;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.InitBuilder;
@ -32,6 +31,7 @@ import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.util.Utils;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -93,7 +93,7 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
String command; String command;
if (node.getCredentials().identity.equals("root")) { if (node.getCredentials().identity.equals("root")) {
command = "./" + init.getInstanceName() + " " + action; command = "./" + init.getInstanceName() + " " + action;
} else if (ComputeServiceUtils.isKeyAuth(node)) { } else if (Utils.isPrivateKeyCredential(node.getCredentials())) {
command = "sudo ./" + init.getInstanceName() + " " + action; command = "sudo ./" + init.getInstanceName() + " " + action;
} else { } else {
command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(), command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(),

View File

@ -34,10 +34,13 @@ import org.jclouds.compute.LoadBalancerService;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.ssh.SshClient;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -47,6 +50,7 @@ import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers; import com.google.inject.util.Providers;
/** /**
@ -58,6 +62,8 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
protected void configure() { protected void configure() {
install(new ComputeServiceTimeoutsModule()); install(new ComputeServiceTimeoutsModule());
bindLoadBalancerService(); bindLoadBalancerService();
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
}).to(CreateSshClientOncePortIsListeningOnNode.class);
} }
protected void bindLoadBalancerService() { protected void bindLoadBalancerService() {

View File

@ -30,9 +30,7 @@ import org.jclouds.compute.predicates.NodeTerminated;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
@ -50,7 +48,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
@Named("NODE_RUNNING") @Named("NODE_RUNNING")
protected Predicate<NodeMetadata> nodeRunning(NodeRunning stateRunning, Timeouts timeouts) { protected Predicate<NodeMetadata> nodeRunning(NodeRunning stateRunning, Timeouts timeouts) {
return timeouts.nodeRunning == 0 ? stateRunning : new RetryablePredicate<NodeMetadata>(stateRunning, return timeouts.nodeRunning == 0 ? stateRunning : new RetryablePredicate<NodeMetadata>(stateRunning,
timeouts.nodeRunning); timeouts.nodeRunning);
} }
@Provides @Provides
@ -58,7 +56,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
@Named("NODE_TERMINATED") @Named("NODE_TERMINATED")
protected Predicate<NodeMetadata> serverTerminated(NodeTerminated stateTerminated, Timeouts timeouts) { protected Predicate<NodeMetadata> serverTerminated(NodeTerminated stateTerminated, Timeouts timeouts) {
return timeouts.nodeTerminated == 0 ? stateTerminated : new RetryablePredicate<NodeMetadata>(stateTerminated, return timeouts.nodeTerminated == 0 ? stateTerminated : new RetryablePredicate<NodeMetadata>(stateTerminated,
timeouts.nodeTerminated); timeouts.nodeTerminated);
} }
@Provides @Provides
@ -66,13 +64,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
@Named("SCRIPT_COMPLETE") @Named("SCRIPT_COMPLETE")
protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning, Timeouts timeouts) { protected Predicate<CommandUsingClient> runScriptRunning(ScriptStatusReturnsZero stateRunning, Timeouts timeouts) {
return timeouts.scriptComplete == 0 ? not(stateRunning) : new RetryablePredicate<CommandUsingClient>( return timeouts.scriptComplete == 0 ? not(stateRunning) : new RetryablePredicate<CommandUsingClient>(
not(stateRunning), timeouts.scriptComplete); not(stateRunning), timeouts.scriptComplete);
}
@Provides
@Singleton
protected Predicate<IPSocket> socketTester(SocketOpen open, Timeouts timeouts) {
return timeouts.portOpen == 0 ? open : new RetryablePredicate<IPSocket>(open, timeouts.portOpen);
} }
@Override @Override

View File

@ -45,7 +45,7 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
private Credentials credentials; private Credentials credentials;
@Nullable @Nullable
private String tag; private String tag;
private int loginPort; private int loginPort = 22;
@Nullable @Nullable
private String imageId; private String imageId;
@Nullable @Nullable

View File

@ -0,0 +1,60 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
import org.jclouds.compute.util.ComputeServiceUtils;
import org.jclouds.net.IPSocket;
import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class CreateSshClientOncePortIsListeningOnNode implements Function<NodeMetadata, SshClient> {
@Inject(optional = true)
SshClient.Factory sshFactory;
private final RetryIfSocketNotYetOpen socketTester;
@Inject
public CreateSshClientOncePortIsListeningOnNode(RetryIfSocketNotYetOpen socketTester) {
this.socketTester = socketTester;
}
@Override
public SshClient apply(NodeMetadata node) {
checkState(sshFactory != null, "ssh requested, but no SshModule configured");
checkNotNull(node.getCredentials(), "credentials for node " + node.getName());
checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getName());
IPSocket socket = ComputeServiceUtils.findReachableSocketOnNode(socketTester, node, node.getLoginPort());
return sshFactory.create(socket, node.getCredentials());
}
}

View File

@ -26,14 +26,17 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.Utils; import org.jclouds.compute.Utils;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.HttpAsyncClient; import org.jclouds.rest.HttpAsyncClient;
import org.jclouds.rest.HttpClient; import org.jclouds.rest.HttpClient;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshClient.Factory; import org.jclouds.ssh.SshClient.Factory;
import com.google.common.base.Function;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -44,15 +47,15 @@ import com.google.inject.Inject;
public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Utils { public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Utils {
@Inject(optional = true) @Inject(optional = true)
private Factory sshFactory; private Factory sshFactory;
private final Function<NodeMetadata, SshClient> sshForNode;
@Inject @Inject
UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient, UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient, Crypto encryption,
Crypto encryption, DateService date, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, @Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, LoggerFactory loggerFactory,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, Function<NodeMetadata, SshClient> sshForNode) {
LoggerFactory loggerFactory) { super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, loggerFactory);
super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, this.sshForNode = sshForNode;
loggerFactory);
} }
@Override @Override
@ -65,4 +68,9 @@ public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Ut
return sshFactory; return sshFactory;
} }
@Override
public Function<NodeMetadata, SshClient> sshForNode() {
return sshForNode;
}
} }

View File

@ -0,0 +1,86 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.compute.predicates;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import com.google.common.base.Predicate;
/**
*
*
* Not singleton as seconds are mutable
*
* @author Adrian Cole
*
*/
public class RetryIfSocketNotYetOpen implements Predicate<IPSocket> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
private Logger logger = Logger.NULL;
private final SocketOpen socketTester;
private long seconds;
public RetryIfSocketNotYetOpen seconds(long seconds) {
this.seconds = seconds;
return this;
}
@Inject
public RetryIfSocketNotYetOpen(SocketOpen socketTester, Timeouts timeouts) {
this.socketTester = socketTester;
this.seconds = timeouts.portOpen;
}
public RetryIfSocketNotYetOpen(SocketOpen socketTester, Logger logger, long seconds) {
this.socketTester = socketTester;
this.logger = logger;
this.seconds = seconds;
}
@Override
public String toString() {
return "retryIfSocketNotYetOpen(" + seconds + ")";
}
@Override
public boolean apply(IPSocket socket) {
logger.debug(">> blocking on socket %s for %d seconds", socket, seconds);
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(socketTester, seconds, 1, TimeUnit.SECONDS);
boolean passed = tester.apply(socket);
if (passed)
logger.debug("<< socket %s opened", socket);
else
logger.warn("<< socket %s didn't open after %d seconds", socket, seconds);
return passed;
}
}

View File

@ -19,10 +19,15 @@
package org.jclouds.compute.util; package org.jclouds.compute.util;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.getStackTraceAsString; import static com.google.common.base.Throwables.getStackTraceAsString;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter; 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.size;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash; import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash;
import static org.jclouds.util.Utils.getSupportedProvidersOfType;
import java.net.URI; import java.net.URI;
import java.util.Formatter; import java.util.Formatter;
@ -33,6 +38,7 @@ import java.util.concurrent.Callable;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jclouds.compute.ComputeServiceContextBuilder; import org.jclouds.compute.ComputeServiceContextBuilder;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
@ -40,13 +46,15 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
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.predicates.RetryIfSocketNotYetOpen;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -212,13 +220,33 @@ public class ComputeServiceUtils {
void setConnection(SshClient ssh, Logger logger); void setConnection(SshClient ssh, Logger logger);
} }
public static boolean isKeyAuth(NodeMetadata createdNode) { public static Iterable<String> getSupportedProviders() {
return createdNode.getCredentials().credential != null return getSupportedProvidersOfType(ComputeServiceContextBuilder.class);
&& createdNode.getCredentials().credential.startsWith("-----BEGIN RSA PRIVATE KEY-----");
} }
public static Iterable<String> getSupportedProviders() { public static IPSocket findReachableSocketOnNode(RetryIfSocketNotYetOpen socketTester, final NodeMetadata node,
return Utils.getSupportedProvidersOfType(ComputeServiceContextBuilder.class); final int port) {
checkNodeHasIps(node);
IPSocket socket = null;
try {
socket = find(
transform(concat(node.getPublicAddresses(), node.getPrivateAddresses()),
new Function<String, IPSocket>() {
@Override
public IPSocket apply(String from) {
return new IPSocket(from, port);
}
}), socketTester);
} catch (NoSuchElementException e) {
throw new RuntimeException(String.format("could not connect to any ip address port %d on node %s", port, node));
}
return socket;
}
public static void checkNodeHasIps(NodeMetadata node) {
checkState(size(concat(node.getPublicAddresses(), node.getPrivateAddresses())) > 0,
"node does not have IP addresses configured: " + node);
} }
} }

View File

@ -19,9 +19,12 @@
package org.jclouds.compute.util; package org.jclouds.compute.util;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.getRootCause;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Throwables.propagate;
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth; import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode;
import static org.jclouds.concurrent.FutureIterables.awaitCompletion; import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import java.util.List; import java.util.List;
@ -31,11 +34,11 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
@ -45,14 +48,13 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey; import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey;
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey; import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
@ -60,11 +62,8 @@ import org.jclouds.scriptbuilder.domain.StatementList;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -76,20 +75,20 @@ public class ComputeUtils {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject(optional = true) protected final Function<NodeMetadata, SshClient> sshFactory;
protected SshClient.Factory sshFactory;
protected final Predicate<CommandUsingClient> runScriptNotRunning; protected final Predicate<CommandUsingClient> runScriptNotRunning;
protected final Predicate<IPSocket> socketTester; protected final Provider<RetryIfSocketNotYetOpen> socketTester;
protected final ExecutorService executor; protected final ExecutorService executor;
protected final Predicate<NodeMetadata> nodeRunning; protected final Predicate<NodeMetadata> nodeRunning;
protected final GetNodeMetadataStrategy getNode; protected final GetNodeMetadataStrategy getNode;
protected final Timeouts timeouts; protected final Timeouts timeouts;
@Inject @Inject
public ComputeUtils(Predicate<IPSocket> socketTester, public ComputeUtils(Provider<RetryIfSocketNotYetOpen> socketTester, Function<NodeMetadata, SshClient> sshFactory,
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode, @Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.sshFactory = sshFactory;
this.nodeRunning = nodeRunning; this.nodeRunning = nodeRunning;
this.timeouts = timeouts; this.timeouts = timeouts;
this.getNode = getNode; this.getNode = getNode;
@ -101,7 +100,7 @@ public class ComputeUtils {
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options, public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes, Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
final Map<NodeMetadata, Exception> badNodes) { final Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, Future<Void>> responses = newHashMap();
for (final NodeMetadata node : runningNodes) { for (final NodeMetadata node : runningNodes) {
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
goodNodes, options))); goodNodes, options)));
@ -119,8 +118,7 @@ public class ComputeUtils {
logger.debug("<< options applied node(%s)", node1.getId()); logger.debug("<< options applied node(%s)", node1.getId());
goodNodes.add(node1); goodNodes.add(node1);
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), Throwables.getRootCause(e) logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
.getMessage());
badNodes.put(node, e); badNodes.put(node, e);
} }
return null; return null;
@ -133,13 +131,13 @@ public class ComputeUtils {
return node; return node;
if (nodeRunning.apply(node)) if (nodeRunning.apply(node))
node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())) node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())).credentials(node.getCredentials())
.credentials(node.getCredentials()).build(); .build();
else else
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(), "node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
timeouts.nodeRunning / 1000, node.getState())); timeouts.nodeRunning / 1000, node.getState()));
List<Statement> bootstrap = Lists.newArrayList(); List<Statement> bootstrap = newArrayList();
if (options.getRunScript() != null) if (options.getRunScript() != null)
bootstrap.add(options.getRunScript()); bootstrap.add(options.getRunScript());
if (options.getPublicKey() != null) if (options.getPublicKey() != null)
@ -151,14 +149,10 @@ public class ComputeUtils {
return node; return node;
} }
public void checkNodeHasPublicIps(NodeMetadata node) {
checkState(node.getPublicAddresses().size() > 0, "node does not have IP addresses configured: " + node);
}
public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) { public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) {
InitAndStartScriptOnNode callable = generateScript(node, runScript, options); InitAndStartScriptOnNode callable = generateScript(node, runScript, options);
ExecResponse response; ExecResponse response;
SshClient ssh = createSshClientOncePortIsListeningOnNode(node); SshClient ssh = sshFactory.apply(node);
try { try {
ssh.connect(); ssh.connect();
callable.setConnection(ssh, logger); callable.setConnection(ssh, logger);
@ -168,24 +162,11 @@ public class ComputeUtils {
ssh.disconnect(); ssh.disconnect();
} }
if (options.getPort() > 0) { if (options.getPort() > 0) {
checkNodeHasPublicIps(node); findReachableSocketOnNode(socketTester.get().seconds(options.getSeconds()), node, options.getPort());
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(),
Iterables.get(node.getPublicAddresses(), 0));
} }
return response; return response;
} }
public void blockUntilPortIsListeningOnPublicIp(int port, int seconds, String inetAddress) {
logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress, port, seconds);
RetryablePredicate<IPSocket> tester = new RetryablePredicate<IPSocket>(socketTester, seconds, 1, TimeUnit.SECONDS);
IPSocket socket = new IPSocket(inetAddress, port);
boolean passed = tester.apply(socket);
if (passed)
logger.debug("<< port %s:%d opened", inetAddress, port);
else
logger.warn("<< port %s:%d didn't open after %d seconds", inetAddress, port, seconds);
}
public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) { public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) {
return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(), return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(),
script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script, script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script,
@ -194,11 +175,7 @@ public class ComputeUtils {
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel, public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
@Nullable SshCallable<?> last) { @Nullable SshCallable<?> last) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); SshClient ssh = sshFactory.apply(node);
checkNodeHasPublicIps(node);
checkNotNull(node.getCredentials(), "credentials for node " + node.getName());
checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getName());
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
try { try {
ssh.connect(); ssh.connect();
return runTasksUsingSshClient(parallel, last, ssh); return runTasksUsingSshClient(parallel, last, ssh);
@ -210,8 +187,8 @@ public class ComputeUtils {
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last, private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
SshClient ssh) { SshClient ssh) {
Map<SshCallable<?>, Object> responses = Maps.newHashMap(); Map<SshCallable<?>, Object> responses = newHashMap();
if (Iterables.size(parallel) > 0) { if (size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh)); responses.putAll(runCallablesUsingSshClient(parallel, ssh));
} }
if (last != null) { if (last != null) {
@ -219,24 +196,15 @@ public class ComputeUtils {
try { try {
responses.put(last, last.call()); responses.put(last, last.call());
} catch (Exception e) { } catch (Exception e) {
Throwables.propagate(e); propagate(e);
} }
} }
return responses; return responses;
} }
public SshClient createSshClientOncePortIsListeningOnNode(NodeMetadata node) {
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22);
socketTester.apply(socket);
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().identity,
node.getCredentials().credential.getBytes()) : sshFactory.create(socket, node.getCredentials().identity,
node.getCredentials().credential);
return ssh;
}
// TODO refactor // TODO refactor
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) { private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
Map<SshCallable<?>, Future<?>> parallelResponses = Maps.newHashMap(); Map<SshCallable<?>, Future<?>> parallelResponses = newHashMap();
for (SshCallable<?> callable : parallel) { for (SshCallable<?> callable : parallel) {
callable.setConnection(ssh, logger); callable.setConnection(ssh, logger);
@ -252,14 +220,14 @@ public class ComputeUtils {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) { public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap(); Map<SshCallable<?>, T> actualResponses = newHashMap();
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) { for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
try { try {
actualResponses.put(entry.getKey(), (T) entry.getValue().get()); actualResponses.put(entry.getKey(), (T) entry.getValue().get());
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw Throwables.propagate(e); throw propagate(e);
} catch (ExecutionException e) { } catch (ExecutionException e) {
throw Throwables.propagate(e); throw propagate(e);
} }
} }
return actualResponses; return actualResponses;

View File

@ -564,20 +564,7 @@ public abstract class BaseComputeServiceLiveTest {
} }
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException { protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException {
IPSocket socket = new IPSocket(get(node.getPublicAddresses(), 0), 22); SshClient ssh = context.utils().sshForNode().apply(node);
socketTester.apply(socket); // TODO add transitionTo option that accepts
// a socket conection
// state.
SshClient ssh = (node.getCredentials().credential != null && !node.getCredentials().credential
.startsWith("-----BEGIN RSA PRIVATE KEY-----")) ? context.utils().sshFactory()
.create(socket, node.getCredentials().identity, node.getCredentials().credential) : context
.utils()
.sshFactory()
.create(
socket,
node.getCredentials().identity,
node.getCredentials().credential != null ? node.getCredentials().credential.getBytes() : keyPair.get(
"private").getBytes());
try { try {
ssh.connect(); ssh.connect();
ExecResponse hello = ssh.exec("echo hello"); ExecResponse hello = ssh.exec("echo hello");

View File

@ -19,7 +19,6 @@
package org.jclouds.compute; package org.jclouds.compute;
import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.reportMatcher; import static org.easymock.EasyMock.reportMatcher;
@ -41,6 +40,7 @@ import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
@ -120,15 +120,14 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
SshClient client4 = createMock(SshClient.class); SshClient client4 = createMock(SshClient.class);
SshClient client5 = createMock(SshClient.class); SshClient client5 = createMock(SshClient.class);
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1) expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn(
.atLeastOnce(); client1);
runScriptAndService(client1, 1); runScriptAndService(client1, 1);
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "romeo")).andThrow( expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn(
client2).times(2);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
new SshException("Auth fail")); new SshException("Auth fail"));
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2)
.atLeastOnce();
client2.connect(); client2.connect();
try { try {
runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
@ -138,32 +137,32 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
} }
client2.disconnect(); client2.disconnect();
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3) expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn(
.atLeastOnce(); client3).times(2);
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4) expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn(
.atLeastOnce(); client4).times(2);
expect(factory.create(new IPSocket("144.175.1.5", 22), "root", "password5")).andReturn(client5) expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn(
.atLeastOnce(); client5).times(2);
runScriptAndInstallSsh(client3, "bootstrap", 3); runScriptAndInstallSsh(client3, "bootstrap", 3);
runScriptAndInstallSsh(client4, "bootstrap", 4); runScriptAndInstallSsh(client4, "bootstrap", 4);
runScriptAndInstallSsh(client5, "bootstrap", 5); runScriptAndInstallSsh(client5, "bootstrap", 5);
expect( expect(
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private") factory.create(eq(new IPSocket("144.175.1.1", 22)),
.getBytes()))).andReturn(client1).atLeastOnce(); eq(new Credentials("root", keyPair.get("private"))))).andReturn(client1);
expect( expect(
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair.get("private") factory.create(eq(new IPSocket("144.175.1.2", 22)),
.getBytes()))).andReturn(client2).atLeastOnce(); eq(new Credentials("root", keyPair.get("private"))))).andReturn(client2);
expect( expect(
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair.get("private") factory.create(eq(new IPSocket("144.175.1.3", 22)),
.getBytes()))).andReturn(client3).atLeastOnce(); eq(new Credentials("root", keyPair.get("private"))))).andReturn(client3);
expect( expect(
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private") factory.create(eq(new IPSocket("144.175.1.4", 22)),
.getBytes()))).andReturn(client4).atLeastOnce(); eq(new Credentials("root", keyPair.get("private"))))).andReturn(client4);
expect( expect(
factory.create(eq(new IPSocket("155.175.1.5", 22)), eq("root"), aryEq(keyPair.get("private") factory.create(eq(new IPSocket("144.175.1.5", 22)),
.getBytes()))).andReturn(client5).atLeastOnce(); eq(new Credentials("root", keyPair.get("private"))))).andReturn(client5);
helloAndJava(client2); helloAndJava(client2);
helloAndJava(client3); helloAndJava(client3);

View File

@ -17,7 +17,7 @@
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.ssh.jsch.predicates; package org.jclouds.predicates;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -29,7 +29,6 @@ import javax.inject.Singleton;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.SocketOpen;
import com.google.inject.Inject; import com.google.inject.Inject;

View File

@ -58,6 +58,8 @@ import javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.jclouds.PropertiesBuilder; import org.jclouds.PropertiesBuilder;
import org.jclouds.crypto.Pems;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.RestContextBuilder; import org.jclouds.rest.RestContextBuilder;
@ -246,15 +248,14 @@ public class Utils {
} }
/** /**
* Encode the given string with the given encoding, if possible. If the * Encode the given string with the given encoding, if possible. If the encoding fails with
* encoding fails with {@link UnsupportedEncodingException}, log a warning * {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
* and fall back to the system's default encoding. * encoding.
* *
* @param str * @param str
* what to encode * what to encode
* @param charsetName * @param charsetName
* the name of a supported {@link java.nio.charset.Charset * the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
* </code>charset<code>}
* @return properly encoded String. * @return properly encoded String.
*/ */
public static byte[] encodeString(String str, String charsetName) { public static byte[] encodeString(String str, String charsetName) {
@ -268,10 +269,9 @@ public class Utils {
} }
/** /**
* Encode the given string with the UTF-8 encoding, the sane default. In the * Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
* very unlikely event the encoding fails with * the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
* {@link UnsupportedEncodingException}, log a warning and fall back to the * the system's default encoding.
* system's default encoding.
* *
* @param str * @param str
* what to encode * what to encode
@ -322,8 +322,7 @@ public class Utils {
} }
/** /**
* Will throw an exception if the argument is null or empty. Accepts a custom * Will throw an exception if the argument is null or empty. Accepts a custom error message.
* error message.
* *
* @param nullableString * @param nullableString
* string to verify. Can be null or empty. * string to verify. Can be null or empty.
@ -335,8 +334,8 @@ public class Utils {
} }
/** /**
* Gets a set of supported providers. Idea stolen from pallets * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* (supported-clouds). Uses rest.properties to populate the set. * rest.properties to populate the set.
* *
*/ */
public static Iterable<String> getSupportedProviders() { public static Iterable<String> getSupportedProviders() {
@ -344,8 +343,8 @@ public class Utils {
} }
/** /**
* Gets a set of supported providers. Idea stolen from pallets * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* (supported-clouds). Uses rest.properties to populate the set. * rest.properties to populate the set.
* *
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -468,4 +467,24 @@ public class Utils {
} }
return modules; return modules;
} }
public static boolean isPrivateKeyCredential(Credentials credentials) {
return credentials != null
&& credentials.credential != null
&& (credentials.credential.startsWith(Pems.PRIVATE_PKCS1_MARKER) || credentials.credential
.startsWith(Pems.PRIVATE_PKCS8_MARKER));
}
public static Credentials overrideCredentialsIfSupplied(Credentials defaultCredentials,
@Nullable Credentials overridingCredentials) {
if (overridingCredentials == null)
return defaultCredentials;
String identity = overridingCredentials.identity != null ? overridingCredentials.identity : checkNotNull(
defaultCredentials, "defaultCredentials").identity;
String credential = overridingCredentials.credential != null ? overridingCredentials.credential : checkNotNull(
defaultCredentials, "defaultCredentials").credential;
return new Credentials(identity, credential);
}
} }

View File

@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.domain.Credentials;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -42,6 +43,33 @@ import com.google.inject.spi.Message;
@Test(groups = "unit", testName = "jclouds.UtilsTest") @Test(groups = "unit", testName = "jclouds.UtilsTest")
public class UtilsTest { public class UtilsTest {
public void testOverridingCredentialsWhenOverridingIsNull() {
Credentials defaultCredentials = new Credentials("foo", "bar");
Credentials overridingCredentials = null;
assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), defaultCredentials);
}
public void testOverridingCredentialsWhenOverridingLoginIsNull() {
Credentials defaultCredentials = new Credentials("foo", "bar");
Credentials overridingCredentials = new Credentials(null, "baz");
assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials(
"foo", "baz"));
}
public void testOverridingCredentialsWhenOverridingCredentialIsNull() {
Credentials defaultCredentials = new Credentials("foo", "bar");
Credentials overridingCredentials = new Credentials("fooble", null);
assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials(
"fooble", "bar"));
}
public void testOverridingCredentialsWhenOverridingCredentialsAreNull() {
Credentials defaultCredentials = new Credentials("foo", "bar");
Credentials overridingCredentials = new Credentials(null, null);
assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials(
"foo", "bar"));
}
public void testGetCause() { public void testGetCause() {
AuthorizationException aex = createMock(AuthorizationException.class); AuthorizationException aex = createMock(AuthorizationException.class);
Message message = new Message(ImmutableList.of(), "test", aex); Message message = new Message(ImmutableList.of(), "test", aex);

View File

@ -59,11 +59,11 @@ import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.InetSocketAddressConnect;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.jsch.JschSshClient; import org.jclouds.ssh.jsch.JschSshClient;
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
import org.testng.SkipException; import org.testng.SkipException;
import org.testng.TestException; import org.testng.TestException;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;

View File

@ -117,7 +117,7 @@ public class RackspaceAuthenticationRestModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
@CloudFiles @CloudFiles
protected URI provideStorageUrl(AuthenticationResponse response) { protected URI providestroageUrl(AuthenticationResponse response) {
return response.getStorageUrl(); return response.getStorageUrl();
} }

View File

@ -139,7 +139,7 @@ public interface RimuHostingAsyncClient {
ListenableFuture<ServerInfo> restartServer(@PathParam("id") Long id); ListenableFuture<ServerInfo> restartServer(@PathParam("id") Long id);
/** /**
* @see RimuHostingClient#destoryServer * @see RimuHostingClient#destroyServer
*/ */
@DELETE @DELETE
@Path("/orders/order-{id}-blah/vps") @Path("/orders/order-{id}-blah/vps")

View File

@ -20,7 +20,6 @@
package org.jclouds.tools.ant.taskdefs.compute; package org.jclouds.tools.ant.taskdefs.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores; import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
@ -45,6 +44,7 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.util.Utils;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
@ -212,7 +212,7 @@ public class ComputeTask extends Task {
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getProviderId()); getProject().setProperty(nodeElement.getIdproperty(), createdNode.getProviderId());
if (nodeElement.getHostproperty() != null) if (nodeElement.getHostproperty() != null)
getProject().setProperty(nodeElement.getHostproperty(), ipOrEmptyString(createdNode.getPublicAddresses())); getProject().setProperty(nodeElement.getHostproperty(), ipOrEmptyString(createdNode.getPublicAddresses()));
if (nodeElement.getPasswordproperty() != null && !isKeyAuth(createdNode)) if (nodeElement.getPasswordproperty() != null && !Utils.isPrivateKeyCredential(createdNode.getCredentials()))
getProject().setProperty(nodeElement.getPasswordproperty(), createdNode.getCredentials().credential); getProject().setProperty(nodeElement.getPasswordproperty(), createdNode.getCredentials().credential);
if (nodeElement.getUsernameproperty() != null) if (nodeElement.getUsernameproperty() != null)
getProject().setProperty(nodeElement.getUsernameproperty(), createdNode.getCredentials().identity); getProject().setProperty(nodeElement.getUsernameproperty(), createdNode.getCredentials().identity);

View File

@ -35,11 +35,11 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.net.IPSocket; import org.jclouds.net.IPSocket;
import org.jclouds.predicates.InetSocketAddressConnect;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshClient.Factory; import org.jclouds.ssh.SshClient.Factory;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;