diff --git a/sandbox-apis/byon/pom.xml b/sandbox-apis/byon/pom.xml index 1c70b984bf..dd1741abc6 100644 --- a/sandbox-apis/byon/pom.xml +++ b/sandbox-apis/byon/pom.xml @@ -30,11 +30,10 @@ org.jclouds.api byon - jclouds example components for a standalone compute provider + jclouds bring your own node provider file://c:/test.txt - FIXME - FIXME + @@ -103,12 +102,8 @@ ${test.byon.endpoint} - test.byon.identity - ${test.byon.identity} - - - test.byon.credential - ${test.byon.credential} + test.byon.sudo-password + ${test.byon.sudo-password} diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/Node.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/Node.java index 7640ab5fe2..e5032843f6 100644 --- a/sandbox-apis/byon/src/main/java/org/jclouds/byon/Node.java +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/Node.java @@ -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 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 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 getTags() { Set tagSet = new HashSet(); 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(); } } diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java index 08c962061b..dc7cdb1cd1 100644 --- a/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java @@ -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 { - @Resource - protected Logger logger = Logger.NULL; + JCloudsNativeComputeServiceAdapterContextModule { public BYONComputeServiceContextModule() { super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class); } - @Provides - @Singleton - Supplier> provideNodeList(@Provider final URI uri) { - return new Supplier> (){ - @Override - public Map 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. of(); - } catch(IOException e) { - logger.error(e, "URI could not be read: %s", uri); - return ImmutableMap. of(); - } - - return config.nodes; - } - }; - } - + @SuppressWarnings("unchecked") @Provides @Singleton Supplier provideApi(Supplier> in) { return in; } + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>>() { + }).to(NodesParsedFromSupplier.class); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class); + // TODO make this somehow overridable via user request + bind(new TypeLiteral>>() { + }).to(NodesFromYaml.class); + } + } diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodeToNodeMetadata.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodeToNodeMetadata.java index e3f1492e43..078a2ede31 100644 --- a/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodeToNodeMetadata.java +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodeToNodeMetadata.java @@ -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 { 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. 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(); } diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYaml.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYaml.java new file mode 100644 index 0000000000..1dcfa29295 --- /dev/null +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYaml.java @@ -0,0 +1,88 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + * + *
+ * 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
+ * 
+ * + * @author Kelvin Kakugawa + */ +@Singleton +public class NodesFromYaml implements Function> { + + /** + * Type-safe config class for YAML + * + */ + public static class Config { + public Map nodes; + } + + @Override + public Map 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; + } +} \ No newline at end of file diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java index 96f3511a7b..f6bc145379 100644 --- a/sandbox-apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java @@ -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> 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 credentialStore) { + Map credentialStore) { throw new UnsupportedOperationException(); } @@ -81,11 +83,7 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda @Override public Iterable listLocations() { - Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); - Location region = new LocationImpl(LocationScope.REGION, providerName + "region", providerName + "region", - provider); - return ImmutableSet. of(new LocationImpl(LocationScope.ZONE, providerName + "zone", providerName - + "zone", region)); + return ImmutableSet. of(new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null)); } @Override diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java new file mode 100644 index 0000000000..1da7fd0ad0 --- /dev/null +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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> { + @Resource + protected Logger logger = Logger.NULL; + + private final Supplier supplier; + private final Function> parser; + + @Inject + NodesParsedFromSupplier(@Provider Supplier supplier, Function> parser) { + this.supplier = checkNotNull(supplier, "supplier"); + this.parser = checkNotNull(parser, "parser"); + } + + @Override + public Map get() { + Map nodes = parser.apply(supplier.get()); + checkState(nodes != null && nodes.size() > 0, "no nodes parsed from supplier: %s", supplier); + return nodes; + } + +} \ No newline at end of file diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesProperty.java b/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesProperty.java new file mode 100644 index 0000000000..b54fcceb21 --- /dev/null +++ b/sandbox-apis/byon/src/main/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesProperty.java @@ -0,0 +1,76 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + @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 + "]"; + } + +} \ No newline at end of file diff --git a/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceLiveTest.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceLiveTest.java new file mode 100644 index 0000000000..342ee3004c --- /dev/null +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceLiveTest.java @@ -0,0 +1,98 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. of( + new JschSshClientModule(), new Log4JLoggingModule()), contextProperties); + } + + public void testCanRunCommandAsCurrentUser() throws Exception { + Map responses = context.getComputeService().runScriptOnNodesMatching( + Predicates. alwaysTrue(), exec("id"), wrapInInitScript(false).runAsRoot(false)); + + for (Entry 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(); + } +} diff --git a/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONParseTest.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java similarity index 54% rename from sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONParseTest.java rename to sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java index 85366b33fb..c1655df4a7 100644 --- a/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONParseTest.java +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java @@ -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. 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 + . of(new JschSshClientModule()), props); assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint)); @SuppressWarnings("unchecked") Supplier> supplier = (Supplier>) context.getProviderSpecificContext() - .getApi(); + .getApi(); assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); + assertEquals(supplier.get(), ImmutableMap. 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.alwaysTrue(), "echo hello") -); + assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest.TEST1)); } finally { if (context != null) diff --git a/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java new file mode 100644 index 0000000000..e81941fb39 --- /dev/null +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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"))); + + } +} diff --git a/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java new file mode 100644 index 0000000000..12e20a9e7b --- /dev/null +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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("")); + } +} diff --git a/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/Config.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/NodesParsedFromSupplierTest.java similarity index 52% rename from sandbox-apis/byon/src/main/java/org/jclouds/byon/config/Config.java rename to sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/NodesParsedFromSupplierTest.java index 457e04d087..cfb036a1f8 100644 --- a/sandbox-apis/byon/src/main/java/org/jclouds/byon/config/Config.java +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/NodesParsedFromSupplierTest.java @@ -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 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(); + + } } diff --git a/sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesPropertyTest.java b/sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesPropertyTest.java new file mode 100644 index 0000000000..0ad987aa76 --- /dev/null +++ b/sandbox-apis/byon/src/test/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesPropertyTest.java @@ -0,0 +1,67 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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"))); + } +} diff --git a/sandbox-apis/byon/src/test/resources/log4j.xml b/sandbox-apis/byon/src/test/resources/log4j.xml index f7337defb9..32b6448af4 100755 --- a/sandbox-apis/byon/src/test/resources/log4j.xml +++ b/sandbox-apis/byon/src/test/resources/log4j.xml @@ -28,8 +28,8 @@ debug="false"> - - + + @@ -99,8 +99,8 @@ - - + + @@ -112,13 +112,9 @@ - - - - - - - + + + diff --git a/sandbox-apis/byon/src/test/resources/test1.yaml b/sandbox-apis/byon/src/test/resources/test1.yaml new file mode 100644 index 0000000000..4a611af553 --- /dev/null +++ b/sandbox-apis/byon/src/test/resources/test1.yaml @@ -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== \ No newline at end of file