You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whirr.apache.org by to...@apache.org on 2010/09/01 23:37:58 UTC
svn commit: r991712 - in /incubator/whirr/trunk: ./
cli/src/test/java/org/apache/whirr/cli/command/
core/src/main/java/org/apache/whirr/service/
services/cassandra/src/test/resources/
services/hadoop/src/main/java/org/apache/whirr/service/hadoop/ servi...
Author: tomwhite
Date: Wed Sep 1 21:37:57 2010
New Revision: 991712
URL: http://svn.apache.org/viewvc?rev=991712&view=rev
Log:
WHIRR-70. decouple keypairs from the files that hold them. Contributed by Adrian Cole.
Modified:
incubator/whirr/trunk/CHANGES.txt
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java
incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java
incubator/whirr/trunk/services/cassandra/src/test/resources/whirr-cassandra-test.properties
incubator/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopProxy.java
incubator/whirr/trunk/services/hadoop/src/test/resources/whirr-hadoop-test.properties
incubator/whirr/trunk/services/zookeeper/src/test/resources/whirr-zookeeper-test.properties
incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence
Modified: incubator/whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/CHANGES.txt?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/CHANGES.txt (original)
+++ incubator/whirr/trunk/CHANGES.txt Wed Sep 1 21:37:57 2010
@@ -55,6 +55,8 @@ Trunk (unreleased changes)
WHIRR-77. Document and implement release process. (tomwhite)
+ WHIRR-70. decouple keypairs from the files that hold them. (Adrian Cole via tomwhite)
+
BUG FIXES
WHIRR-50. Cassandra POM should depend on top-level. (tomwhite)
Modified: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java (original)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java Wed Sep 1 21:37:57 2010
@@ -25,9 +25,11 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.common.io.Files;
import com.google.inject.internal.Lists;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.PrintStream;
import java.util.Collections;
@@ -75,12 +77,23 @@ public class DestroyClusterCommandTest {
DestroyClusterCommand command = new DestroyClusterCommand(factory);
+ File privateKeyFile = File.createTempFile("private", "key");
+ privateKeyFile.deleteOnExit();
+ Files.write("-----BEGIN RSA PRIVATE KEY-----".getBytes(),
+ privateKeyFile);
+
+ File publicKeyFile = File.createTempFile("public", "key");
+ publicKeyFile.deleteOnExit();
+ Files.write("ssh-rsa".getBytes(), publicKeyFile);
+
int rc = command.run(null, out, null, Lists.newArrayList(
"--service-name", "test-service",
"--cluster-name", "test-cluster",
"--provider", "rackspace",
"--identity", "myusername", "--credential", "mypassword",
- "--secret-key-file", "secret-key"));
+ "--private-key-file", privateKeyFile.getAbsolutePath(),
+ "--public-key-file", publicKeyFile.getAbsolutePath()
+ ));
assertThat(rc, is(0));
@@ -90,7 +103,8 @@ public class DestroyClusterCommandTest {
expectedClusterSpec.setIdentity("myusername");
expectedClusterSpec.setCredential("mypassword");
expectedClusterSpec.setClusterName("test-cluster");
- expectedClusterSpec.setSecretKeyFile("secret-key");
+ expectedClusterSpec.setPrivateKey(privateKeyFile);
+ expectedClusterSpec.setPublicKey(publicKeyFile);
verify(factory).create("test-service");
Modified: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java (original)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java Wed Sep 1 21:37:57 2010
@@ -28,9 +28,12 @@ import static org.mockito.Mockito.verify
import static org.mockito.Mockito.when;
import com.google.common.collect.Sets;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
import com.google.inject.internal.Lists;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.PrintStream;
import java.util.Collections;
@@ -82,13 +85,24 @@ public class LaunchClusterCommandTest {
LaunchClusterCommand command = new LaunchClusterCommand(factory);
+ File privateKeyFile = File.createTempFile("private", "key");
+ privateKeyFile.deleteOnExit();
+ Files.write("-----BEGIN RSA PRIVATE KEY-----".getBytes(),
+ privateKeyFile);
+
+ File publicKeyFile = File.createTempFile("public", "key");
+ publicKeyFile.deleteOnExit();
+ Files.write("ssh-rsa".getBytes(), publicKeyFile);
+
int rc = command.run(null, out, null, Lists.newArrayList(
"--service-name", "test-service",
"--cluster-name", "test-cluster",
"--instance-templates", "1 role1+role2,2 role3",
"--provider", "rackspace",
"--identity", "myusername", "--credential", "mypassword",
- "--secret-key-file", "secret-key"));
+ "--private-key-file", privateKeyFile.getAbsolutePath(),
+ "--public-key-file", publicKeyFile.getAbsolutePath()
+ ));
assertThat(rc, is(0));
@@ -102,7 +116,8 @@ public class LaunchClusterCommandTest {
expectedClusterSpec.setIdentity("myusername");
expectedClusterSpec.setCredential("mypassword");
expectedClusterSpec.setClusterName("test-cluster");
- expectedClusterSpec.setSecretKeyFile("secret-key");
+ expectedClusterSpec.setPrivateKey(privateKeyFile);
+ expectedClusterSpec.setPublicKey(publicKeyFile);
verify(factory).create("test-service");
Modified: incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java (original)
+++ incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java Wed Sep 1 21:37:57 2010
@@ -18,7 +18,11 @@
package org.apache.whirr.service;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.http.Payloads.newStringPayload;
+import static org.jclouds.http.Payloads.newFilePayload;
+import static org.jclouds.util.Utils.toStringAndClose;
import com.google.common.base.Charsets;
import com.google.common.base.Objects;
@@ -32,7 +36,9 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
+import org.jclouds.http.Payload;
/**
* This class represents the specification of a cluster. It is used to describe
@@ -47,7 +53,8 @@ public class ClusterSpec {
CREDENTIAL(String.class, false),
IDENTITY(String.class, false),
CLUSTER_NAME(String.class, false),
- SECRET_KEY_FILE(String.class, false),
+ PUBLIC_KEY_FILE(String.class, false),
+ PRIVATE_KEY_FILE(String.class, false),
CLIENT_CIDRS(String.class, true);
private Class<?> type;
@@ -136,11 +143,17 @@ public class ClusterSpec {
private String identity;
private String credential;
private String clusterName;
- private String secretKeyFile;
+ private Payload privateKey;
+ private Payload publicKey;
private List<String> clientCidrs = Lists.newArrayList();
private Configuration config = new PropertiesConfiguration();
- public static ClusterSpec fromConfiguration(Configuration config) {
+ /**
+ *
+ * @throws ConfigurationException if the public or private key cannot be read.
+ */
+ public static ClusterSpec fromConfiguration(Configuration config)
+ throws ConfigurationException {
ClusterSpec spec = new ClusterSpec();
spec.setServiceName(config.getString(Property.SERVICE_NAME.getConfigName()));
spec.setInstanceTemplates(InstanceTemplate.parse(
@@ -150,7 +163,20 @@ public class ClusterSpec {
config.getString(Property.IDENTITY.getConfigName()), Property.IDENTITY));
spec.setCredential(config.getString(Property.CREDENTIAL.getConfigName()));
spec.setClusterName(config.getString(Property.CLUSTER_NAME.getConfigName()));
- spec.setSecretKeyFile(config.getString(Property.SECRET_KEY_FILE.getConfigName()));
+ try {
+ String privateKeyPath = config.getString(
+ Property.PRIVATE_KEY_FILE.getConfigName());
+ if (privateKeyPath != null)
+ spec.setPrivateKey(new File(privateKeyPath));
+ String publicKeyPath = config.getString(Property.PUBLIC_KEY_FILE.
+ getConfigName());
+ publicKeyPath = publicKeyPath == null && privateKeyPath != null ?
+ privateKeyPath + ".pub" : publicKeyPath;
+ if (publicKeyPath != null)
+ spec.setPublicKey(new File(publicKeyPath));
+ } catch (IOException e) {
+ throw new ConfigurationException("error reading key from file", e);
+ }
spec.setClientCidrs(config.getList(Property.CLIENT_CIDRS.getConfigName()));
spec.config = config;
return spec;
@@ -188,8 +214,25 @@ public class ClusterSpec {
public String getClusterName() {
return clusterName;
}
- public String getSecretKeyFile() {
- return secretKeyFile;
+ public Payload getPrivateKey() {
+ return privateKey;
+ }
+ public Payload getPublicKey() {
+ return publicKey;
+ }
+ /**
+ * @see #getPrivateKey
+ * @throws IOException if the payload cannot be read
+ */
+ public String readPrivateKey() throws IOException {
+ return toStringAndClose(getPrivateKey().getContent());
+ }
+ /**
+ * @see #getPublicKey
+ * @throws IOException if the payload cannot be read
+ */
+ public String readPublicKey() throws IOException {
+ return toStringAndClose(getPublicKey().getContent());
}
public List<String> getClientCidrs() {
return clientCidrs;
@@ -219,8 +262,50 @@ public class ClusterSpec {
this.clusterName = clusterName;
}
- public void setSecretKeyFile(String secretKeyFile) {
- this.secretKeyFile = secretKeyFile;
+ /**
+ * The rsa public key which is authorized to login to your on the cloud nodes.
+ *
+ * @param publicKey
+ */
+ public void setPublicKey(String publicKey) {
+ checkArgument(checkNotNull(publicKey, "publicKey").startsWith("ssh-rsa"),
+ "key should start with ssh-rsa");
+ this.publicKey = newStringPayload(publicKey);
+ }
+
+ /**
+ *
+ * @throws IOException
+ * if there is a problem reading the file
+ * @see #setPublicKey(String)
+ */
+ public void setPublicKey(File publicKey) throws IOException {
+ this.publicKey = newFilePayload(checkNotNull(publicKey,
+ "publicKey"));
+ }
+
+ /**
+ * The rsa private key which is used as the login identity on the cloud
+ * nodes.
+ *
+ * @param privateKey
+ */
+ public void setPrivateKey(String privateKey) {
+ checkArgument(checkNotNull(privateKey, "privateKey")
+ .startsWith("-----BEGIN RSA PRIVATE KEY-----"),
+ "key should start with -----BEGIN RSA PRIVATE KEY-----");
+ this.privateKey = newStringPayload(privateKey);
+ }
+
+ /**
+ *
+ * @throws IOException
+ * if there is a problem reading the file
+ * @see #setPrivateKey(String)
+ */
+ public void setPrivateKey(File privateKey) throws IOException {
+ this.privateKey = newFilePayload(
+ checkNotNull(privateKey, "privateKey"));
}
public void setClientCidrs(List<String> clientCidrs) {
@@ -232,15 +317,7 @@ public class ClusterSpec {
public Configuration getConfiguration() {
return config;
}
-
- public String readPrivateKey() throws IOException {
- return Files.toString(new File(getSecretKeyFile()), Charsets.UTF_8);
- }
- public String readPublicKey() throws IOException {
- return Files.toString(new File(getSecretKeyFile() + ".pub"), Charsets.UTF_8);
- }
-
public boolean equals(Object o) {
if (o instanceof ClusterSpec) {
ClusterSpec that = (ClusterSpec) o;
@@ -250,7 +327,6 @@ public class ClusterSpec {
&& Objects.equal(identity, that.identity)
&& Objects.equal(credential, that.credential)
&& Objects.equal(clusterName, that.clusterName)
- && Objects.equal(secretKeyFile, that.secretKeyFile)
&& Objects.equal(clientCidrs, that.clientCidrs);
}
return false;
@@ -258,8 +334,8 @@ public class ClusterSpec {
public int hashCode() {
return Objects.hashCode(instanceTemplates, serviceName,
- provider, identity, credential, clusterName, secretKeyFile,
- clientCidrs);
+ provider, identity, credential, clusterName, publicKey,
+ privateKey, clientCidrs);
}
public String toString() {
@@ -270,7 +346,8 @@ public class ClusterSpec {
.add("identity", identity)
.add("credential", credential)
.add("clusterName", clusterName)
- .add("secretKeyFile", secretKeyFile)
+ .add("publicKey", publicKey)
+ .add("privateKey", privateKey)
.add("clientCidrs", clientCidrs)
.toString();
}
Modified: incubator/whirr/trunk/services/cassandra/src/test/resources/whirr-cassandra-test.properties
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/cassandra/src/test/resources/whirr-cassandra-test.properties?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/services/cassandra/src/test/resources/whirr-cassandra-test.properties (original)
+++ incubator/whirr/trunk/services/cassandra/src/test/resources/whirr-cassandra-test.properties Wed Sep 1 21:37:57 2010
@@ -21,4 +21,4 @@ whirr.instance-templates=2 cassandra
whirr.provider=ec2
whirr.identity=${sys:whirr.test.identity}
whirr.credential=${sys:whirr.test.credential}
-whirr.secret-key-file=${sys:user.home}/.ssh/id_rsa
+whirr.private-key-file=${sys:user.home}/.ssh/id_rsa
Modified: incubator/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopProxy.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopProxy.java?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopProxy.java (original)
+++ incubator/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopProxy.java Wed Sep 1 21:37:57 2010
@@ -18,13 +18,18 @@
package org.apache.whirr.service.hadoop;
+import static com.google.common.base.Preconditions.checkState;
+
import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.whirr.service.ClusterSpec;
import com.google.common.collect.Iterables;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
public class HadoopProxy {
@@ -40,11 +45,19 @@ public class HadoopProxy {
public void start() throws IOException {
// jsch doesn't support SOCKS-based dynamic port forwarding, so we need to shell out...
// TODO: Use static port forwarding instead?
- String identityFile = clusterSpec.getSecretKeyFile();
+ checkState(clusterSpec.getPrivateKey() != null, "privateKey is needed");
+ File identity;
+ if (clusterSpec.getPrivateKey().getRawContent() instanceof File) {
+ identity = File.class.cast(clusterSpec.getPrivateKey().getRawContent());
+ } else {
+ identity = File.createTempFile("hadoop", "key");
+ identity.deleteOnExit();
+ Files.write(ByteStreams.toByteArray(clusterSpec.getPrivateKey().getContent()), identity);
+ }
String user = Iterables.get(cluster.getInstances(), 0).getLoginCredentials().account;
String server = cluster.getNamenodePublicAddress().getHostName();
String[] command = new String[] { "ssh",
- "-i", identityFile,
+ "-i", identity.getAbsolutePath(),
"-o", "ConnectTimeout=10",
"-o", "ServerAliveInterval=60",
"-o", "StrictHostKeyChecking=no",
Modified: incubator/whirr/trunk/services/hadoop/src/test/resources/whirr-hadoop-test.properties
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/hadoop/src/test/resources/whirr-hadoop-test.properties?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/services/hadoop/src/test/resources/whirr-hadoop-test.properties (original)
+++ incubator/whirr/trunk/services/hadoop/src/test/resources/whirr-hadoop-test.properties Wed Sep 1 21:37:57 2010
@@ -21,4 +21,4 @@ whirr.instance-templates=1 jt+nn,1 dn+tt
whirr.provider=ec2
whirr.identity=${sys:whirr.test.identity}
whirr.credential=${sys:whirr.test.credential}
-whirr.secret-key-file=${sys:user.home}/.ssh/id_rsa
+whirr.private-key-file=${sys:user.home}/.ssh/id_rsa
Modified: incubator/whirr/trunk/services/zookeeper/src/test/resources/whirr-zookeeper-test.properties
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/zookeeper/src/test/resources/whirr-zookeeper-test.properties?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/services/zookeeper/src/test/resources/whirr-zookeeper-test.properties (original)
+++ incubator/whirr/trunk/services/zookeeper/src/test/resources/whirr-zookeeper-test.properties Wed Sep 1 21:37:57 2010
@@ -21,4 +21,4 @@ whirr.instance-templates=2 zk
whirr.provider=ec2
whirr.identity=${sys:whirr.test.identity}
whirr.credential=${sys:whirr.test.credential}
-whirr.secret-key-file=${sys:user.home}/.ssh/id_rsa
+whirr.private-key-file=${sys:user.home}/.ssh/id_rsa
Modified: incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence?rev=991712&r1=991711&r2=991712&view=diff
==============================================================================
--- incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence (original)
+++ incubator/whirr/trunk/src/site/confluence/configuration-guide.confluence Wed Sep 1 21:37:57 2010
@@ -33,7 +33,7 @@ h2. Comparison
| {{cloud-provider}} | {{provider}} | |
| none | {{identity}} | Specified using environment variables for Python. E.g. {{AWS\_ACCESS\_KEY\_ID}}, {{RACKSPACE\_KEY}} |
| none | {{credential}} | Specified using environment variables for Python. E.g. {{AWS\_ACCESS\_KEY\_ID}}, {{RACKSPACE\_SECRET}} |
-| {{private-key-file}} | {{secret-key-file}} | |
+| {{private-key-file}} | {{private-key-file}} | |
| {{client-cidr}} | {{client-cidrs}} | Python {{client-cidr}} option may be repeated multiple times, whereas Java {{client-cidrs}} contains comma-separated CIDRs. |
| {{public-key}} | none | Based on secret key in Java (add {{.pub}}). |
| {{image-id}} | none | Need to add to Java. Along with more flexible image matching (pattern, OS, arch). See jclouds TemplateBuilder. |