mirror of https://github.com/apache/jclouds.git
Merge remote branch 'upstream/master'
This commit is contained in:
commit
abc59149fc
|
@ -19,13 +19,11 @@
|
||||||
|
|
||||||
package org.jclouds.cloudfiles;
|
package org.jclouds.cloudfiles;
|
||||||
|
|
||||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
|
||||||
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.openstack.OpenStackAuthAsyncClient;
|
|
||||||
import org.jclouds.openstack.swift.SwiftPropertiesBuilder;
|
import org.jclouds.openstack.swift.SwiftPropertiesBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +37,6 @@ public class CloudFilesPropertiesBuilder extends SwiftPropertiesBuilder {
|
||||||
Properties properties = super.defaultProperties();
|
Properties properties = super.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_REGIONS, "US");
|
properties.setProperty(PROPERTY_REGIONS, "US");
|
||||||
properties.setProperty(PROPERTY_ENDPOINT, "https://auth.api.rackspacecloud.com");
|
properties.setProperty(PROPERTY_ENDPOINT, "https://auth.api.rackspacecloud.com");
|
||||||
properties.setProperty(PROPERTY_API_VERSION, OpenStackAuthAsyncClient.VERSION);
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
|
|
||||||
package org.jclouds.openstack.swift;
|
package org.jclouds.openstack.swift;
|
||||||
|
|
||||||
|
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.PropertiesBuilder;
|
import org.jclouds.PropertiesBuilder;
|
||||||
|
import org.jclouds.openstack.OpenStackAuthAsyncClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds properties used in CloudFiles Connections
|
* Builds properties used in CloudFiles Connections
|
||||||
|
@ -37,6 +39,7 @@ public class SwiftPropertiesBuilder extends PropertiesBuilder {
|
||||||
Properties properties = super.defaultProperties();
|
Properties properties = super.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
properties.setProperty(PROPERTY_REGIONS, "DEFAULT");
|
||||||
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
|
properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-");
|
||||||
|
properties.setProperty(PROPERTY_API_VERSION, OpenStackAuthAsyncClient.VERSION);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.callables;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.options.RunScriptOptions;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
|
import org.jclouds.ssh.ExecResponse;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class RunScriptOnNodeUsingSsh implements RunScriptOnNode {
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
protected final Function<NodeMetadata, SshClient> sshFactory;
|
||||||
|
protected final NodeMetadata node;
|
||||||
|
protected final Statement statement;
|
||||||
|
protected final boolean runAsRoot;
|
||||||
|
|
||||||
|
protected SshClient ssh;
|
||||||
|
|
||||||
|
@AssistedInject
|
||||||
|
public RunScriptOnNodeUsingSsh(Function<NodeMetadata, SshClient> sshFactory, @Assisted NodeMetadata node,
|
||||||
|
@Assisted Statement statement, @Assisted RunScriptOptions options) {
|
||||||
|
this.sshFactory = checkNotNull(sshFactory, "sshFactory");
|
||||||
|
this.node = checkNotNull(node, "node");
|
||||||
|
this.statement = checkNotNull(statement, "statement");
|
||||||
|
this.runAsRoot = options.shouldRunAsRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExecResponse call() {
|
||||||
|
checkState(ssh != null, "please call init() before invoking call");
|
||||||
|
try {
|
||||||
|
ssh.connect();
|
||||||
|
ExecResponse returnVal;
|
||||||
|
String command = (runAsRoot) ? execAsRoot(statement.render(OsFamily.UNIX)) : execScriptAsDefaultUser(statement
|
||||||
|
.render(OsFamily.UNIX));
|
||||||
|
returnVal = runCommand(command);
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
logger.trace("<< %s[%s]", statement, returnVal);
|
||||||
|
else
|
||||||
|
logger.debug("<< %s(%d)", statement, returnVal.getExitCode());
|
||||||
|
return returnVal;
|
||||||
|
} finally {
|
||||||
|
if (ssh != null)
|
||||||
|
ssh.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RunScriptOnNode init() {
|
||||||
|
ssh = sshFactory.apply(node);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExecResponse runCommand(String command) {
|
||||||
|
ExecResponse returnVal;
|
||||||
|
logger.debug(">> running [%s] as %s@%s", command.replace(node.getAdminPassword() != null ? node
|
||||||
|
.getAdminPassword() : "XXXXX", "XXXXX"), ssh.getUsername(), ssh.getHostAddress());
|
||||||
|
returnVal = ssh.exec(command);
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public String execAsRoot(String command) {
|
||||||
|
if (node.getCredentials().identity.equals("root")) {
|
||||||
|
} else if (node.getAdminPassword() != null) {
|
||||||
|
command = String.format("echo '%s'|sudo -S %s", node.getAdminPassword(), command);
|
||||||
|
} else {
|
||||||
|
command = "sudo " + command;
|
||||||
|
}
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String execScriptAsDefaultUser(String command) {
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeMetadata getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Objects.toStringHelper(this).add("node", node).add("name", statement).add("runAsRoot", runAsRoot)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||||
import org.jclouds.compute.callables.RunScriptOnNodeAsInitScriptUsingSsh;
|
import org.jclouds.compute.callables.RunScriptOnNodeAsInitScriptUsingSsh;
|
||||||
import org.jclouds.compute.callables.RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete;
|
import org.jclouds.compute.callables.RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete;
|
||||||
|
import org.jclouds.compute.callables.RunScriptOnNodeUsingSsh;
|
||||||
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;
|
||||||
|
@ -81,11 +82,12 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
bind(new TypeLiteral<Function<TemplateOptions, Statement>>() {
|
bind(new TypeLiteral<Function<TemplateOptions, Statement>>() {
|
||||||
}).to(TemplateOptionsToStatement.class);
|
}).to(TemplateOptionsToStatement.class);
|
||||||
|
|
||||||
install(new FactoryModuleBuilder().implement(RunScriptOnNode.class, Names.named("blocking"),
|
install(new FactoryModuleBuilder().implement(RunScriptOnNode.class, Names.named("direct"),
|
||||||
|
RunScriptOnNodeUsingSsh.class).implement(RunScriptOnNode.class, Names.named("blocking"),
|
||||||
RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete.class).implement(RunScriptOnNode.class,
|
RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete.class).implement(RunScriptOnNode.class,
|
||||||
Names.named("nonblocking"), RunScriptOnNodeAsInitScriptUsingSsh.class).build(
|
Names.named("nonblocking"), RunScriptOnNodeAsInitScriptUsingSsh.class).build(
|
||||||
RunScriptOnNodeFactoryImpl.Factory.class));
|
RunScriptOnNodeFactoryImpl.Factory.class));
|
||||||
|
|
||||||
bind(RunScriptOnNode.Factory.class).to(RunScriptOnNodeFactoryImpl.class);
|
bind(RunScriptOnNode.Factory.class).to(RunScriptOnNodeFactoryImpl.class);
|
||||||
|
|
||||||
install(new FactoryModuleBuilder().implement(new TypeLiteral<Callable<Void>>() {
|
install(new FactoryModuleBuilder().implement(new TypeLiteral<Callable<Void>>() {
|
||||||
|
@ -103,11 +105,14 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
|
|
||||||
static interface Factory {
|
static interface Factory {
|
||||||
|
|
||||||
|
@Named("direct")
|
||||||
|
RunScriptOnNode exec(NodeMetadata node, Statement script, RunScriptOptions options);
|
||||||
|
|
||||||
@Named("blocking")
|
@Named("blocking")
|
||||||
RunScriptOnNode blockOnComplete(NodeMetadata node, Statement script, RunScriptOptions options);
|
RunScriptOnNode backgroundAndBlockOnComplete(NodeMetadata node, Statement script, RunScriptOptions options);
|
||||||
|
|
||||||
@Named("nonblocking")
|
@Named("nonblocking")
|
||||||
RunScriptOnNode dontBlockOnComplete(NodeMetadata node, Statement script, RunScriptOptions options);
|
RunScriptOnNode background(NodeMetadata node, Statement script, RunScriptOptions options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Factory factory;
|
private final Factory factory;
|
||||||
|
@ -122,8 +127,9 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
checkNotNull(node, "node");
|
checkNotNull(node, "node");
|
||||||
checkNotNull(runScript, "runScript");
|
checkNotNull(runScript, "runScript");
|
||||||
checkNotNull(options, "options");
|
checkNotNull(options, "options");
|
||||||
return options.shouldBlockOnComplete() ? factory.blockOnComplete(node, runScript, options) : factory
|
return !options.shouldWrapInInitScript() ? factory.exec(node, runScript, options)
|
||||||
.dontBlockOnComplete(node, runScript, options);
|
: (options.shouldBlockOnComplete() ? factory.backgroundAndBlockOnComplete(node, runScript, options)
|
||||||
|
: factory.background(node, runScript, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class CreateSshClientOncePortIsListeningOnNode implements Function<NodeMe
|
||||||
checkState(sshFactory != null, "ssh requested, but no SshModule configured");
|
checkState(sshFactory != null, "ssh requested, but no SshModule configured");
|
||||||
checkNotNull(node.getCredentials(), "no credentials found for node %s", node.getId());
|
checkNotNull(node.getCredentials(), "no credentials found for node %s", node.getId());
|
||||||
checkNotNull(node.getCredentials().identity, "no login identity found for node %s", node.getId());
|
checkNotNull(node.getCredentials().identity, "no login identity found for node %s", node.getId());
|
||||||
checkNotNull(node.getCredentials().credential, "no credential found for $s on node %s", node
|
checkNotNull(node.getCredentials().credential, "no credential found for %s on node %s", node
|
||||||
.getCredentials().identity, node.getId());
|
.getCredentials().identity, node.getId());
|
||||||
IPSocket socket = ComputeServiceUtils.findReachableSocketOnNode(socketTester, node, node.getLoginPort());
|
IPSocket socket = ComputeServiceUtils.findReachableSocketOnNode(socketTester, node, node.getLoginPort());
|
||||||
return sshFactory.create(socket, node.getCredentials());
|
return sshFactory.create(socket, node.getCredentials());
|
||||||
|
|
|
@ -118,6 +118,7 @@ public class RunScriptOptions {
|
||||||
protected Credentials overridingCredentials;
|
protected Credentials overridingCredentials;
|
||||||
protected boolean runAsRoot = true;
|
protected boolean runAsRoot = true;
|
||||||
protected boolean blockOnComplete = true;
|
protected boolean blockOnComplete = true;
|
||||||
|
protected boolean wrapInInitScript = true;
|
||||||
|
|
||||||
public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) {
|
public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) {
|
||||||
checkNotNull(overridingCredentials, "overridingCredentials");
|
checkNotNull(overridingCredentials, "overridingCredentials");
|
||||||
|
@ -142,6 +143,20 @@ public class RunScriptOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default true
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @param wrapInInitScript
|
||||||
|
* if the command is long-running, use this option to ensure it is wrapInInitScripted
|
||||||
|
* properly. (ex. have jclouds wrap it an init script, nohup, etc)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public RunScriptOptions wrapInInitScript(boolean wrapInInitScript) {
|
||||||
|
this.wrapInInitScript = wrapInInitScript;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public RunScriptOptions blockOnComplete(boolean blockOnComplete) {
|
public RunScriptOptions blockOnComplete(boolean blockOnComplete) {
|
||||||
this.blockOnComplete = blockOnComplete;
|
this.blockOnComplete = blockOnComplete;
|
||||||
return this;
|
return this;
|
||||||
|
@ -198,6 +213,15 @@ public class RunScriptOptions {
|
||||||
return blockOnComplete;
|
return blockOnComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to wait until the script has completed. By default, true.
|
||||||
|
*
|
||||||
|
* @return value
|
||||||
|
*/
|
||||||
|
public boolean shouldWrapInInitScript() {
|
||||||
|
return wrapInInitScript;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
public static RunScriptOptions nameTask(String name) {
|
public static RunScriptOptions nameTask(String name) {
|
||||||
|
@ -220,6 +244,11 @@ public class RunScriptOptions {
|
||||||
return options.blockOnComplete(value);
|
return options.blockOnComplete(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RunScriptOptions wrapInInitScript(boolean value) {
|
||||||
|
RunScriptOptions options = new RunScriptOptions();
|
||||||
|
return options.wrapInInitScript(value);
|
||||||
|
}
|
||||||
|
|
||||||
public static RunScriptOptions blockOnPort(int port, int seconds) {
|
public static RunScriptOptions blockOnPort(int port, int seconds) {
|
||||||
RunScriptOptions options = new RunScriptOptions();
|
RunScriptOptions options = new RunScriptOptions();
|
||||||
return options.blockOnPort(port, seconds);
|
return options.blockOnPort(port, seconds);
|
||||||
|
@ -230,7 +259,8 @@ public class RunScriptOptions {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[overridingCredentials=" + (overridingCredentials != null) + ", port:seconds=" + port + ":" + seconds
|
return "[overridingCredentials=" + (overridingCredentials != null) + ", port:seconds=" + port + ":" + seconds
|
||||||
+ ", runAsRoot=" + runAsRoot + ", blockOnComplete=" + blockOnComplete + "]";
|
+ ", runAsRoot=" + runAsRoot + ", blockOnComplete=" + blockOnComplete + ", wrapInInitScript=" + wrapInInitScript
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
@ -76,6 +77,7 @@ import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.predicates.SocketOpen;
|
import org.jclouds.predicates.SocketOpen;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
import org.jclouds.ssh.ExecResponse;
|
import org.jclouds.ssh.ExecResponse;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.ssh.SshException;
|
import org.jclouds.ssh.SshException;
|
||||||
|
@ -236,6 +238,12 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
assert getRootCause(e).getMessage().contains("Auth fail") : e;
|
assert getRootCause(e).getMessage().contains("Auth fail") : e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Entry<? extends NodeMetadata, ExecResponse> response : client.runScriptOnNodesMatching(
|
||||||
|
runningWithTag(tag), Statements.exec("echo hello"), overrideCredentialsWith(good).wrapInInitScript(false))
|
||||||
|
.entrySet())
|
||||||
|
assert response.getValue().getOutput().trim().equals("hello") : response.getKey() + ": "
|
||||||
|
+ response.getValue();
|
||||||
|
|
||||||
runScriptWithCreds(tag, os, good);
|
runScriptWithCreds(tag, os, good);
|
||||||
|
|
||||||
checkNodes(nodes, tag);
|
checkNodes(nodes, tag);
|
||||||
|
|
|
@ -106,48 +106,55 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
SshClient client5 = createMock(SshClient.class);
|
SshClient client5 = createMock(SshClient.class);
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn(
|
expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn(
|
||||||
client1);
|
client1);
|
||||||
runScriptAndService(client1, 1);
|
runScriptAndService(client1, 1);
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn(
|
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn(
|
||||||
client2).times(2);
|
client2).times(3);
|
||||||
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
|
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
|
||||||
new SshException("Auth fail"));
|
new SshException("Auth fail"));
|
||||||
|
|
||||||
|
// run script without backgrounding
|
||||||
|
client2.connect();
|
||||||
|
expect(client2.exec("echo hello\n")).andReturn(new ExecResponse("hello\n", "", 0));
|
||||||
|
client2.disconnect();
|
||||||
|
|
||||||
client2.connect();
|
client2.connect();
|
||||||
try {
|
try {
|
||||||
runScript(client2, "runScriptWithCreds", Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
runScript(client2, "runScriptWithCreds",
|
||||||
.getResourceAsStream("/runscript.sh")), 2);
|
Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
||||||
|
.getResourceAsStream("/runscript.sh")), 2);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
client2.disconnect();
|
client2.disconnect();
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn(
|
expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn(
|
||||||
client3).times(2);
|
client3).times(2);
|
||||||
expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn(
|
expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn(
|
||||||
client4).times(2);
|
client4).times(2);
|
||||||
expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn(
|
expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn(
|
||||||
client5).times(2);
|
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)),
|
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq(new Credentials("root", keyPair
|
||||||
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client1);
|
.get("private"))))).andReturn(client1);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.2", 22)),
|
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq(new Credentials("root", keyPair
|
||||||
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client2);
|
.get("private"))))).andReturn(client2);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.3", 22)),
|
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq(new Credentials("root", keyPair
|
||||||
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client3);
|
.get("private"))))).andReturn(client3);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.4", 22)),
|
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq(new Credentials("root", keyPair
|
||||||
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client4);
|
.get("private"))))).andReturn(client4);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.5", 22)),
|
factory.create(eq(new IPSocket("144.175.1.5", 22)), eq(new Credentials("root", keyPair
|
||||||
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client5);
|
.get("private"))))).andReturn(client5);
|
||||||
|
|
||||||
helloAndJava(client2);
|
helloAndJava(client2);
|
||||||
helloAndJava(client3);
|
helloAndJava(client3);
|
||||||
|
@ -169,7 +176,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
|
|
||||||
try {
|
try {
|
||||||
runScript(client, "jboss", Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
runScript(client, "jboss", Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
||||||
.getResourceAsStream("/initscript_with_jboss.sh")), nodeId);
|
.getResourceAsStream("/initscript_with_jboss.sh")), nodeId);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
@ -183,7 +190,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
|
|
||||||
try {
|
try {
|
||||||
runScript(client, scriptName, Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
runScript(client, scriptName, Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
|
||||||
.getResourceAsStream("/initscript_with_java.sh")), nodeId);
|
.getResourceAsStream("/initscript_with_java.sh")), nodeId);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +243,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
public void testAssignability() throws Exception {
|
public void testAssignability() throws Exception {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
RestContext<ConcurrentMap<String, NodeMetadata>, ConcurrentMap<String, NodeMetadata>> stubContext = new ComputeServiceContextFactory()
|
RestContext<ConcurrentMap<String, NodeMetadata>, ConcurrentMap<String, NodeMetadata>> stubContext = new ComputeServiceContextFactory()
|
||||||
.createContext(provider, identity, credential).getProviderSpecificContext();
|
.createContext(provider, identity, credential).getProviderSpecificContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PayloadEquals implements IArgumentMatcher, Serializable {
|
private static class PayloadEquals implements IArgumentMatcher, Serializable {
|
||||||
|
@ -283,7 +290,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
return false;
|
return false;
|
||||||
PayloadEquals other = (PayloadEquals) o;
|
PayloadEquals other = (PayloadEquals) o;
|
||||||
return this.expected == null && other.expected == null || this.expected != null
|
return this.expected == null && other.expected == null || this.expected != null
|
||||||
&& this.expected.equals(other.expected);
|
&& this.expected.equals(other.expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -371,7 +378,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
super.testListNodes();
|
super.testListNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
|
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
|
||||||
public void testDestroyNodes() {
|
public void testDestroyNodes() {
|
||||||
super.testDestroyNodes();
|
super.testDestroyNodes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,10 @@
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>org.jclouds.api</groupId>
|
<groupId>org.jclouds.api</groupId>
|
||||||
<artifactId>byon</artifactId>
|
<artifactId>byon</artifactId>
|
||||||
<name>jclouds example components for a standalone compute provider</name>
|
<name>jclouds bring your own node provider</name>
|
||||||
<properties>
|
<properties>
|
||||||
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
|
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
|
||||||
<test.byon.identity>FIXME</test.byon.identity>
|
<test.byon.sudo-password> </test.byon.sudo-password>
|
||||||
<test.byon.credential>FIXME</test.byon.credential>
|
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -74,6 +73,11 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
@ -98,12 +102,8 @@
|
||||||
<value>${test.byon.endpoint}</value>
|
<value>${test.byon.endpoint}</value>
|
||||||
</property>
|
</property>
|
||||||
<property>
|
<property>
|
||||||
<name>test.byon.identity</name>
|
<name>test.byon.sudo-password</name>
|
||||||
<value>${test.byon.identity}</value>
|
<value>${test.byon.sudo-password}</value>
|
||||||
</property>
|
|
||||||
<property>
|
|
||||||
<name>test.byon.credential</name>
|
|
||||||
<value>${test.byon.credential}</value>
|
|
||||||
</property>
|
</property>
|
||||||
</systemProperties>
|
</systemProperties>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -19,31 +19,60 @@
|
||||||
|
|
||||||
package org.jclouds.byon;
|
package org.jclouds.byon;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This would be replaced with the real java object related to the underlying server
|
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class Node {
|
public class Node {
|
||||||
private String id;
|
// public due to snakeyaml
|
||||||
private String description;
|
public Node() {
|
||||||
private String hostname;
|
}
|
||||||
private String osArch;
|
|
||||||
private String osFamily;
|
public Node(String id, String description, String hostname, String osArch, String osFamily, String osName,
|
||||||
private String osName;
|
String osVersion, String group, List<String> tags, String username, String credential, String sudo_password) {
|
||||||
private String osVersion;
|
this.id = id;
|
||||||
private Set<String> tags;
|
this.description = description;
|
||||||
private String username;
|
this.hostname = hostname;
|
||||||
private String credential;
|
this.os_arch = osArch;
|
||||||
|
this.os_family = osFamily;
|
||||||
|
this.os_name = osName;
|
||||||
|
this.os_version = osVersion;
|
||||||
|
this.group = group;
|
||||||
|
this.tags = ImmutableList.copyOf(tags);
|
||||||
|
this.username = username;
|
||||||
|
this.credential = credential;
|
||||||
|
this.sudo_password = sudo_password;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public due to snakeyaml
|
||||||
|
public String id;
|
||||||
|
public String description;
|
||||||
|
public String hostname;
|
||||||
|
public String os_arch;
|
||||||
|
public String os_family;
|
||||||
|
public String os_name;
|
||||||
|
public String os_version;
|
||||||
|
public String group;
|
||||||
|
public List<String> tags;
|
||||||
|
public String username;
|
||||||
|
public String credential;
|
||||||
|
public String sudo_password;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
@ -53,23 +82,26 @@ public class Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOsArch() {
|
public String getOsArch() {
|
||||||
return osArch;
|
return os_arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOsFamily() {
|
public String getOsFamily() {
|
||||||
return osFamily;
|
return os_family;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOsName() {
|
public String getOsName() {
|
||||||
return osName;
|
return os_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOsVersion() {
|
public String getOsVersion() {
|
||||||
return osVersion;
|
return os_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getTags() {
|
public Set<String> getTags() {
|
||||||
return tags;
|
Set<String> tagSet = new HashSet<String>();
|
||||||
|
for (String tag : tags)
|
||||||
|
tagSet.add(tag);
|
||||||
|
return tagSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
|
@ -85,6 +117,10 @@ public class Node {
|
||||||
return Objects.hashCode(id);
|
return Objects.hashCode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSudoPassword() {
|
||||||
|
return sudo_password;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object that) {
|
public boolean equals(Object that) {
|
||||||
if (that == null)
|
if (that == null)
|
||||||
|
@ -94,9 +130,10 @@ public class Node {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Objects.toStringHelper(this).add("id", id).add("description", description).add("hostname", hostname)
|
return Objects.toStringHelper(this).add("id", id).add("description", description).add("hostname", hostname).add(
|
||||||
.add("osArch", osArch).add("osFamily", osFamily).add("osName", osName).add("osVersion", osVersion)
|
"osArch", os_arch).add("osFamily", os_family).add("osName", os_name).add("osVersion", os_version).add(
|
||||||
.add("tags", tags).add("username", username).toString();
|
"group", group).add("tags", tags).add("username", username).add("hasCredential", credential != null)
|
||||||
|
.add("hasSudoPassword", sudo_password != null).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,52 +19,55 @@
|
||||||
|
|
||||||
package org.jclouds.byon.config;
|
package org.jclouds.byon.config;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.byon.Node;
|
import org.jclouds.byon.Node;
|
||||||
|
import org.jclouds.byon.functions.NodesFromYaml;
|
||||||
import org.jclouds.byon.internal.BYONComputeServiceAdapter;
|
import org.jclouds.byon.internal.BYONComputeServiceAdapter;
|
||||||
|
import org.jclouds.byon.suppliers.NodesParsedFromSupplier;
|
||||||
|
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
|
||||||
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
|
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
|
||||||
import org.jclouds.concurrent.SingleThreaded;
|
import org.jclouds.concurrent.SingleThreaded;
|
||||||
import org.jclouds.location.Provider;
|
import org.jclouds.location.Provider;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings( { "rawtypes", "unchecked" })
|
||||||
@SingleThreaded
|
@SingleThreaded
|
||||||
public class BYONComputeServiceContextModule extends
|
public class BYONComputeServiceContextModule extends
|
||||||
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
|
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
|
||||||
|
|
||||||
public BYONComputeServiceContextModule() {
|
public BYONComputeServiceContextModule() {
|
||||||
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
|
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@SuppressWarnings("unchecked")
|
||||||
@Singleton
|
|
||||||
Supplier<Map<String, Node>> provideNodeList(@Provider URI uri) {
|
|
||||||
return new Supplier<Map<String, Node>> (){
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Node> get() {
|
|
||||||
// TODO parse uri into list, using yaml or something
|
|
||||||
return ImmutableMap.<String, Node> of();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Supplier provideApi(Supplier<Map<String, Node>> in) {
|
Supplier provideApi(Supplier<Map<String, Node>> in) {
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
bind(new TypeLiteral<Supplier<Map<String, Node>>>() {
|
||||||
|
}).to(NodesParsedFromSupplier.class);
|
||||||
|
bind(new TypeLiteral<Supplier<InputStream>>() {
|
||||||
|
}).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class);
|
||||||
|
// TODO make this somehow overridable via user request
|
||||||
|
bind(new TypeLiteral<Function<InputStream, Map<String, Node>>>() {
|
||||||
|
}).to(NodesFromYaml.class);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,14 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.compute.domain.OperatingSystemBuilder;
|
import org.jclouds.compute.domain.OperatingSystemBuilder;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -60,16 +61,19 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
|
||||||
builder.ids(from.getId());
|
builder.ids(from.getId());
|
||||||
builder.name(from.getDescription());
|
builder.name(from.getDescription());
|
||||||
builder.location(location.get());
|
builder.location(location.get());
|
||||||
builder.tag(Iterables.get(from.getTags(), 0));
|
builder.tag(from.getGroup());
|
||||||
builder
|
// TODO add tags!
|
||||||
.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch())
|
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family(
|
||||||
.family(OsFamily.fromValue(from.getOsFamily())).name(from.getOsName()).version(from.getOsVersion())
|
OsFamily.fromValue(from.getOsFamily())).name(from.getOsName()).version(from.getOsVersion()).description(
|
||||||
.build());
|
from.getDescription()).build());
|
||||||
builder.state(NodeState.RUNNING);
|
builder.state(NodeState.RUNNING);
|
||||||
builder.publicAddresses(ImmutableSet.<String> of(from.getHostname()));
|
builder.publicAddresses(ImmutableSet.<String> of(from.getHostname()));
|
||||||
Credentials creds = new Credentials(from.getUsername(), from.getCredential());
|
Credentials creds = new Credentials(from.getUsername(), new String(CryptoStreams.base64(from.getCredential()),
|
||||||
|
Charsets.UTF_8));
|
||||||
builder.credentials(creds);
|
builder.credentials(creds);
|
||||||
credentialStore.put(from.getId(), creds);
|
if (from.getSudoPassword() != null)
|
||||||
|
builder.adminPassword(new String(CryptoStreams.base64(from.getSudoPassword()), Charsets.UTF_8));
|
||||||
|
credentialStore.put("node#" + from.getId(), creds);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.byon.Node;
|
||||||
|
import org.yaml.snakeyaml.Loader;
|
||||||
|
import org.yaml.snakeyaml.TypeDescription;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the following syntax.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* nodes:
|
||||||
|
* cluster-1:
|
||||||
|
* id: cluster-1
|
||||||
|
* description: xyz
|
||||||
|
* hostname: cluster-1.mydomain.com
|
||||||
|
* os_arch: x86
|
||||||
|
* os_family: linux
|
||||||
|
* os_name: redhat
|
||||||
|
* os_version: 5.3
|
||||||
|
* group: hadoop
|
||||||
|
* tags:
|
||||||
|
* - vanilla
|
||||||
|
* username: kelvin
|
||||||
|
* credential: password_or_rsa_in_base64
|
||||||
|
* sudo_password: password_in_base64
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Kelvin Kakugawa
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class NodesFromYaml implements Function<InputStream, Map<String, Node>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-safe config class for YAML
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class Config {
|
||||||
|
public Map<String, Node> nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Node> apply(InputStream source) {
|
||||||
|
Constructor constructor = new Constructor(Config.class);
|
||||||
|
|
||||||
|
TypeDescription nodeDesc = new TypeDescription(Node.class);
|
||||||
|
nodeDesc.putListPropertyType("tags", String.class);
|
||||||
|
constructor.addTypeDescription(nodeDesc);
|
||||||
|
|
||||||
|
TypeDescription configDesc = new TypeDescription(Config.class);
|
||||||
|
configDesc.putMapPropertyType("nodes", String.class, Node.class);
|
||||||
|
constructor.addTypeDescription(configDesc);
|
||||||
|
|
||||||
|
Yaml yaml = new Yaml(new Loader(constructor));
|
||||||
|
Config config = (Config) yaml.load(source);
|
||||||
|
checkState(config != null, "missing nodes: collection");
|
||||||
|
return config.nodes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.jclouds.byon.internal;
|
package org.jclouds.byon.internal;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -52,15 +54,15 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BYONComputeServiceAdapter(Supplier<Map<String, Node>> nodes, NodeToNodeMetadata converter,
|
public BYONComputeServiceAdapter(Supplier<Map<String, Node>> nodes, NodeToNodeMetadata converter,
|
||||||
@org.jclouds.location.Provider String providerName) {
|
@org.jclouds.location.Provider String providerName) {
|
||||||
this.nodes = nodes;
|
this.nodes = checkNotNull(nodes, "nodes");
|
||||||
this.converter = converter;
|
this.converter = checkNotNull(converter, "converter");
|
||||||
this.providerName = providerName;
|
this.providerName = checkNotNull(providerName, "providerName");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
|
public NodeMetadata runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +83,7 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<Location> listLocations() {
|
public Iterable<Location> listLocations() {
|
||||||
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
return ImmutableSet.<Location> of(new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null));
|
||||||
Location region = new LocationImpl(LocationScope.REGION, providerName + "region", providerName + "region",
|
|
||||||
provider);
|
|
||||||
return ImmutableSet.<Location> of(new LocationImpl(LocationScope.ZONE, providerName + "zone", providerName
|
|
||||||
+ "zone", region));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.byon.Node;
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class NodesParsedFromSupplier implements Supplier<Map<String, Node>> {
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Supplier<InputStream> supplier;
|
||||||
|
private final Function<InputStream, Map<String, Node>> parser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
NodesParsedFromSupplier(@Provider Supplier<InputStream> supplier, Function<InputStream, Map<String, Node>> parser) {
|
||||||
|
this.supplier = checkNotNull(supplier, "supplier");
|
||||||
|
this.parser = checkNotNull(parser, "parser");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Node> get() {
|
||||||
|
Map<String, Node> nodes = parser.apply(supplier.get());
|
||||||
|
checkState(nodes != null && nodes.size() > 0, "no nodes parsed from supplier: %s", supplier);
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import org.jclouds.location.Provider;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SupplyFromProviderURIOrNodesProperty implements Supplier<InputStream> {
|
||||||
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
private final URI url;
|
||||||
|
|
||||||
|
@Inject(optional = true)
|
||||||
|
@Named("byon.nodes")
|
||||||
|
@VisibleForTesting
|
||||||
|
String nodes;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SupplyFromProviderURIOrNodesProperty(@Provider URI url) {
|
||||||
|
this.url = checkNotNull(url, "url");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream get() {
|
||||||
|
if (nodes != null)
|
||||||
|
return Strings2.toInputStream(nodes);
|
||||||
|
try {
|
||||||
|
return url.toURL().openStream();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e, "URI could not be read: %s", url);
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[url=" + url + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon;
|
||||||
|
|
||||||
|
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
|
||||||
|
import static org.jclouds.crypto.CryptoStreams.base64;
|
||||||
|
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
import org.jclouds.compute.ComputeTestUtils;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.ssh.ExecResponse;
|
||||||
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
|
import org.testng.annotations.AfterClass;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live")
|
||||||
|
public class BYONComputeServiceLiveTest {
|
||||||
|
|
||||||
|
private ComputeServiceContext context;
|
||||||
|
|
||||||
|
@BeforeClass(groups = "live")
|
||||||
|
public void setup() throws FileNotFoundException, IOException {
|
||||||
|
Properties contextProperties = new Properties();
|
||||||
|
|
||||||
|
StringBuilder nodes = new StringBuilder();
|
||||||
|
nodes.append("nodes:\n");
|
||||||
|
nodes.append(" mymachine:\n");
|
||||||
|
nodes.append(" id: mymachine\n");
|
||||||
|
nodes.append(" description: my local machine\n");
|
||||||
|
nodes.append(" hostname: localhost\n");
|
||||||
|
nodes.append(" os_arch: ").append(System.getProperty("os.arch")).append("\n");
|
||||||
|
nodes.append(" os_family: ").append(OsFamily.UNIX).append("\n");
|
||||||
|
nodes.append(" os_name: ").append(System.getProperty("os.name")).append("\n");
|
||||||
|
nodes.append(" os_version: ").append(System.getProperty("os.version")).append("\n");
|
||||||
|
nodes.append(" group: ").append("ssh").append("\n");
|
||||||
|
nodes.append(" tags:\n");
|
||||||
|
nodes.append(" - local\n");
|
||||||
|
nodes.append(" username: ").append(System.getProperty("user.name")).append("\n");
|
||||||
|
nodes.append(" credential: ").append(base64(ComputeTestUtils.setupKeyPair().get("private").getBytes()))
|
||||||
|
.append("\n");
|
||||||
|
|
||||||
|
contextProperties.setProperty("byon.nodes", nodes.toString());
|
||||||
|
|
||||||
|
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet.<Module> of(
|
||||||
|
new JschSshClientModule(), new Log4JLoggingModule()), contextProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCanRunCommandAsCurrentUser() throws Exception {
|
||||||
|
Map<? extends NodeMetadata, ExecResponse> responses = context.getComputeService().runScriptOnNodesMatching(
|
||||||
|
Predicates.<NodeMetadata> alwaysTrue(), exec("id"), wrapInInitScript(false).runAsRoot(false));
|
||||||
|
|
||||||
|
for (Entry<? extends NodeMetadata, ExecResponse> response : responses.entrySet())
|
||||||
|
assert response.getValue().getOutput().trim().contains(System.getProperty("user.name")) : response.getKey()
|
||||||
|
+ ": " + response.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass(groups = "live")
|
||||||
|
public void close() throws FileNotFoundException, IOException {
|
||||||
|
if (context != null)
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,12 +25,15 @@ import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.byon.functions.NodeToNodeMetadataTest;
|
||||||
|
import org.jclouds.byon.functions.NodesFromYamlTest;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
@ -39,39 +42,30 @@ import com.google.inject.Module;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live")
|
@Test(groups = "live")
|
||||||
public class BYONParseTest {
|
public class BYONComputeServiceTest {
|
||||||
private String provider = "byon";
|
|
||||||
private String endpoint;
|
|
||||||
private String identity;
|
|
||||||
private String credential;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
protected void setupCredentials() {
|
|
||||||
endpoint = System.getProperty("test." + provider + ".endpoint", "file://c:/test.txt");
|
|
||||||
// NOTE you may not care about identity/credential
|
|
||||||
identity = System.getProperty("test." + provider + ".identity", "FIXME_IDENTITY");
|
|
||||||
credential = System.getProperty("test." + provider + ".credential", "FIXME_CREDENTIAL");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNodesParse() {
|
public void testNodesParse() throws Exception {
|
||||||
ComputeServiceContext context = null;
|
ComputeServiceContext context = null;
|
||||||
try {
|
try {
|
||||||
Properties contextProperties = new Properties();
|
String endpoint = "file://" + getClass().getResource("/test1.yaml").getPath();
|
||||||
contextProperties.setProperty("byon.endpoint", endpoint);
|
|
||||||
context = new ComputeServiceContextFactory().createContext("byon", identity, credential,
|
Properties props = new Properties();
|
||||||
ImmutableSet.<Module> of(), contextProperties);
|
props.setProperty("byon.endpoint", endpoint);
|
||||||
|
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet
|
||||||
|
.<Module> of(new JschSshClientModule()), props);
|
||||||
|
|
||||||
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
|
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
|
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
|
||||||
.getApi();
|
.getApi();
|
||||||
|
|
||||||
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
|
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
|
||||||
|
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.id,
|
||||||
|
NodesFromYamlTest.TEST1));
|
||||||
|
|
||||||
// TODO verify that the node list corresponds correctly to the content at endpoint
|
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest.TEST1));
|
||||||
context.getComputeService().listNodes();
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (context != null)
|
if (context != null)
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.domain.OperatingSystemBuilder;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LocationScope;
|
||||||
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NodeToNodeMetadataTest {
|
||||||
|
public static final Location location = new LocationImpl(LocationScope.PROVIDER, "byon", "byon", null);
|
||||||
|
|
||||||
|
public static final NodeMetadata TEST1 = new NodeMetadataBuilder().ids("first").tag("hadoop").name("xyz").location(
|
||||||
|
location).state(NodeState.RUNNING).operatingSystem(
|
||||||
|
new OperatingSystemBuilder().name("redhat").family(OsFamily.RHEL).arch("x86").version("5.3").description(
|
||||||
|
"xyz").build()).publicAddresses(ImmutableSet.of("firsthost")).credentials(
|
||||||
|
new Credentials("myUser", "fancyfoot")).adminPassword("sudo").build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNodesParse() throws Exception {
|
||||||
|
|
||||||
|
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
|
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(location), credentialStore);
|
||||||
|
|
||||||
|
assertEquals(parser.apply(NodesFromYamlTest.TEST1), TEST1);
|
||||||
|
assertEquals(credentialStore, ImmutableMap.of("node#first", new Credentials("myUser", "fancyfoot")));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.jclouds.byon.Node;
|
||||||
|
import org.jclouds.crypto.CryptoStreams;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NodesFromYamlTest {
|
||||||
|
|
||||||
|
public static final Node TEST1 = new Node("cluster-1", "xyz", "cluster-1.mydomain.com", "x86", "rhel", "redhat",
|
||||||
|
"5.3", "hadoop", ImmutableList.of("vanilla"), "myUser", CryptoStreams.base64("fancyfoot".getBytes()),
|
||||||
|
CryptoStreams.base64("sudo".getBytes()));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNodesParse() throws Exception {
|
||||||
|
|
||||||
|
InputStream is = getClass().getResourceAsStream("/test1.yaml");
|
||||||
|
NodesFromYaml parser = new NodesFromYaml();
|
||||||
|
|
||||||
|
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
|
public void testMustParseSomething() throws Exception {
|
||||||
|
new NodesFromYaml().apply(Strings2.toInputStream(""));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.suppliers;
|
||||||
|
|
||||||
|
import org.jclouds.byon.functions.NodesFromYaml;
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NodesParsedFromSupplierTest {
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
|
public void testMustParseSomething() throws Exception {
|
||||||
|
|
||||||
|
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYaml()).get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCanParseSomething() throws Exception {
|
||||||
|
|
||||||
|
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n first:\n")),
|
||||||
|
new NodesFromYaml()).get();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.byon.suppliers;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.util.Strings2;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class SupplyFromProviderURIOrNodesPropertyTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromURI() throws Exception {
|
||||||
|
|
||||||
|
String path = getClass().getResource("/test1.yaml").getPath();
|
||||||
|
SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://"
|
||||||
|
+ path));
|
||||||
|
|
||||||
|
assertEquals(Strings2.toStringAndClose(supplier.get()), Strings2.toStringAndClose(getClass().getResourceAsStream(
|
||||||
|
"/test1.yaml")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromProperty() throws Exception {
|
||||||
|
|
||||||
|
SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://bar"));
|
||||||
|
supplier.nodes = Strings2.toStringAndClose(getClass().getResourceAsStream("/test1.yaml"));
|
||||||
|
|
||||||
|
assertEquals(Strings2.toStringAndClose(supplier.get()), Strings2.toStringAndClose(getClass().getResourceAsStream(
|
||||||
|
"/test1.yaml")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSupplyMultipleTimes() throws Exception {
|
||||||
|
String path = getClass().getResource("/test1.yaml").getPath();
|
||||||
|
SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://"
|
||||||
|
+ path));
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
assertEquals(Strings2.toStringAndClose(supplier.get()), Strings2.toStringAndClose(getClass()
|
||||||
|
.getResourceAsStream("/test1.yaml")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,8 +28,8 @@
|
||||||
debug="false">
|
debug="false">
|
||||||
|
|
||||||
<!-- A time/date based rolling appender -->
|
<!-- A time/date based rolling appender -->
|
||||||
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||||
<param name="File" value="target/test-data/jclouds-wire.log" />
|
<param name="File" value="target/test-data/jclouds-ssh.log" />
|
||||||
<param name="Append" value="true" />
|
<param name="Append" value="true" />
|
||||||
|
|
||||||
<!-- Rollover at midnight each day -->
|
<!-- Rollover at midnight each day -->
|
||||||
|
@ -99,8 +99,8 @@
|
||||||
<appender-ref ref="FILE" />
|
<appender-ref ref="FILE" />
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
|
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
|
||||||
<appender-ref ref="WIREFILE" />
|
<appender-ref ref="SSHFILE" />
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- ================ -->
|
<!-- ================ -->
|
||||||
|
@ -112,13 +112,9 @@
|
||||||
<appender-ref ref="ASYNC" />
|
<appender-ref ref="ASYNC" />
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="jclouds.headers">
|
<category name="jclouds.ssh">
|
||||||
<priority value="DEBUG" />
|
<priority value="TRACE" />
|
||||||
<appender-ref ref="ASYNCWIRE" />
|
<appender-ref ref="ASYNCSSH" />
|
||||||
</category>
|
|
||||||
<category name="jclouds.wire">
|
|
||||||
<priority value="DEBUG" />
|
|
||||||
<appender-ref ref="ASYNCWIRE" />
|
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="jclouds.compute">
|
<category name="jclouds.compute">
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
nodes:
|
||||||
|
cluster-1:
|
||||||
|
id: cluster-1
|
||||||
|
description: xyz
|
||||||
|
hostname: cluster-1.mydomain.com
|
||||||
|
os_arch: x86
|
||||||
|
os_family: rhel
|
||||||
|
os_name: redhat
|
||||||
|
os_version: 5.3
|
||||||
|
group: hadoop
|
||||||
|
tags:
|
||||||
|
- vanilla
|
||||||
|
username: myUser
|
||||||
|
credential: ZmFuY3lmb290
|
||||||
|
sudo_password: c3Vkbw==
|
Loading…
Reference in New Issue