Issue 452: backfilled tests and added sudo password

This commit is contained in:
Adrian Cole 2011-01-25 20:02:49 -08:00
parent d56bc68d1c
commit ec589e5180
16 changed files with 664 additions and 150 deletions

View File

@ -30,11 +30,10 @@
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId>
<name>jclouds example components for a standalone compute provider</name>
<name>jclouds bring your own node provider</name>
<properties>
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
<test.byon.identity>FIXME</test.byon.identity>
<test.byon.credential>FIXME</test.byon.credential>
<test.byon.sudo-password> </test.byon.sudo-password>
</properties>
<dependencies>
<dependency>
@ -103,12 +102,8 @@
<value>${test.byon.endpoint}</value>
</property>
<property>
<name>test.byon.identity</name>
<value>${test.byon.identity}</value>
</property>
<property>
<name>test.byon.credential</name>
<value>${test.byon.credential}</value>
<name>test.byon.sudo-password</name>
<value>${test.byon.sudo-password}</value>
</property>
</systemProperties>
</configuration>

View File

@ -24,28 +24,55 @@ import java.util.List;
import java.util.Set;
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
*/
public class Node {
// public due to snakeyaml
public Node() {
}
public Node(String id, String description, String hostname, String osArch, String osFamily, String osName,
String osVersion, String group, List<String> tags, String username, String credential, String sudo_password) {
this.id = id;
this.description = description;
this.hostname = hostname;
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 osArch;
public String osFamily;
public String osName;
public String osVersion;
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() {
return id;
}
public String getGroup() {
return group;
}
public String getDescription() {
return description;
}
@ -55,25 +82,25 @@ public class Node {
}
public String getOsArch() {
return osArch;
return os_arch;
}
public String getOsFamily() {
return osFamily;
return os_family;
}
public String getOsName() {
return osName;
return os_name;
}
public String getOsVersion() {
return osVersion;
return os_version;
}
public Set<String> getTags() {
Set<String> tagSet = new HashSet<String>();
for (String tag : tags)
tagSet.add(tag);
tagSet.add(tag);
return tagSet;
}
@ -90,6 +117,10 @@ public class Node {
return Objects.hashCode(id);
}
public String getSudoPassword() {
return sudo_password;
}
@Override
public boolean equals(Object that) {
if (that == null)
@ -99,9 +130,10 @@ public class Node {
@Override
public String toString() {
return Objects.toStringHelper(this).add("id", id).add("description", description).add("hostname", hostname)
.add("osArch", osArch).add("osFamily", osFamily).add("osName", osName).add("osVersion", osVersion)
.add("tags", tags).add("username", username).toString();
return Objects.toStringHelper(this).add("id", id).add("description", description).add("hostname", hostname).add(
"osArch", os_arch).add("osFamily", os_family).add("osName", os_name).add("osVersion", os_version).add(
"group", group).add("tags", tags).add("username", username).add("hasCredential", credential != null)
.add("hasSudoPassword", sudo_password != null).toString();
}
}

View File

@ -20,87 +20,54 @@
package org.jclouds.byon.config;
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.functions.NodesFromYaml;
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.concurrent.SingleThreaded;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@SuppressWarnings("rawtypes")
@SuppressWarnings( { "rawtypes", "unchecked" })
@SingleThreaded
public class BYONComputeServiceContextModule extends
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
@Resource
protected Logger logger = Logger.NULL;
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
public BYONComputeServiceContextModule() {
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
}
@Provides
@Singleton
Supplier<Map<String, Node>> provideNodeList(@Provider final URI uri) {
return new Supplier<Map<String, Node>> (){
@Override
public Map<String, Node> get() {
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;
try {
URL url = uri.toURL();
InputStream input = url.openStream();
config = (Config)yaml.load(input);
} catch(MalformedURLException e) {
logger.error(e, "URI is not a URL: %s", uri);
return ImmutableMap.<String, Node> of();
} catch(IOException e) {
logger.error(e, "URI could not be read: %s", uri);
return ImmutableMap.<String, Node> of();
}
return config.nodes;
}
};
}
@SuppressWarnings("unchecked")
@Provides
@Singleton
Supplier provideApi(Supplier<Map<String, Node>> 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);
}
}

View File

@ -32,13 +32,14 @@ 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.crypto.CryptoStreams;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -60,20 +61,19 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.ids(from.getId());
builder.name(from.getDescription());
builder.location(location.get());
builder.tag(Iterables.get(from.getTags(), 0));
builder
.operatingSystem(new OperatingSystemBuilder()
.arch(from.getOsArch())
.family(OsFamily.fromValue(from.getOsFamily()))
.name(from.getOsName())
.version(from.getOsVersion())
.description(from.getDescription())
.build());
builder.tag(from.getGroup());
// TODO add tags!
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).name(from.getOsName()).version(from.getOsVersion()).description(
from.getDescription()).build());
builder.state(NodeState.RUNNING);
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);
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();
}

View File

@ -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;
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.byon.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Inject;
@ -52,15 +54,15 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Inject
public BYONComputeServiceAdapter(Supplier<Map<String, Node>> nodes, NodeToNodeMetadata converter,
@org.jclouds.location.Provider String providerName) {
this.nodes = nodes;
this.converter = converter;
this.providerName = providerName;
@org.jclouds.location.Provider String providerName) {
this.nodes = checkNotNull(nodes, "nodes");
this.converter = checkNotNull(converter, "converter");
this.providerName = checkNotNull(providerName, "providerName");
}
@Override
public NodeMetadata runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
Map<String, Credentials> credentialStore) {
throw new UnsupportedOperationException();
}
@ -81,11 +83,7 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override
public Iterable<Location> listLocations() {
Location provider = 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));
return ImmutableSet.<Location> of(new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null));
}
@Override

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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();
}
}

View File

@ -25,66 +25,47 @@ import java.net.URI;
import java.util.Map;
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.ComputeServiceContextFactory;
import org.testng.annotations.BeforeClass;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
//TODO: REMOVE
import com.google.common.base.Predicates;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BYONParseTest {
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");
endpoint = System.getProperty("test." + provider + ".endpoint", "file:///Users/kelvin/pg/jclouds/sandbox-apis/byon/src/test/resources/config.yaml");
// NOTE you may not care about identity/credential
// identity = System.getProperty("test." + provider + ".identity", "FIXME_IDENTITY");
identity = System.getProperty("test." + provider + ".identity", "kelvin");
// credential = System.getProperty("test." + provider + ".credential", "FIXME_CREDENTIAL");
credential = System.getProperty("test." + provider + ".credential", "~/.ssh/id_rsa");
}
public class BYONComputeServiceTest {
@Test
public void testNodesParse() throws Exception {
ComputeServiceContext context = null;
try {
Properties contextProperties = new Properties();
contextProperties.setProperty("byon.endpoint", endpoint);
context = new ComputeServiceContextFactory().createContext("byon", identity, credential,
ImmutableSet.<Module> of(new JschSshClientModule()), contextProperties);
String endpoint = "file://" + getClass().getResource("/test1.yaml").getPath();
Properties props = new Properties();
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));
@SuppressWarnings("unchecked")
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
.getApi();
.getApi();
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
context.getComputeService().listNodes();
//TODO: REMOVE
System.out.println(
context.getComputeService().runScriptOnNodesMatching(Predicates.<NodeMetadata>alwaysTrue(), "echo hello")
);
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest.TEST1));
} finally {
if (context != null)

View File

@ -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")));
}
}

View File

@ -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(""));
}
}

View File

@ -17,17 +17,31 @@
* ====================================================================
*/
package org.jclouds.byon.config;
package org.jclouds.byon.suppliers;
import java.util.Map;
import org.jclouds.byon.functions.NodesFromYaml;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import org.jclouds.byon.Node;
import com.google.common.base.Suppliers;
/**
* Type-safe config class for YAML
*
* @author Kelvin Kakugawa
*
* @author Adrian Cole
*/
public class Config {
public Map<String, Node> nodes;
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();
}
}

View File

@ -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")));
}
}

View File

@ -28,8 +28,8 @@
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-ssh.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
@ -99,8 +99,8 @@
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="SSHFILE" />
</appender>
<!-- ================ -->
@ -112,13 +112,9 @@
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
<category name="jclouds.ssh">
<priority value="TRACE" />
<appender-ref ref="ASYNCSSH" />
</category>
<category name="jclouds.compute">

View File

@ -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==