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/08/17 18:53:12 UTC
svn commit: r986393 - in /incubator/whirr/trunk: ./ cli/ cli/src/
cli/src/main/ cli/src/main/java/ cli/src/main/java/org/
cli/src/main/java/org/apache/ cli/src/main/java/org/apache/whirr/
cli/src/main/java/org/apache/whirr/cli/ cli/src/main/java/org/ap...
Author: tomwhite
Date: Tue Aug 17 16:53:11 2010
New Revision: 986393
URL: http://svn.apache.org/viewvc?rev=986393&view=rev
Log:
WHIRR-33. Add a CLI.
Added:
incubator/whirr/trunk/cli/
incubator/whirr/trunk/cli/pom.xml (with props)
incubator/whirr/trunk/cli/src/
incubator/whirr/trunk/cli/src/main/
incubator/whirr/trunk/cli/src/main/java/
incubator/whirr/trunk/cli/src/main/java/org/
incubator/whirr/trunk/cli/src/main/java/org/apache/
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java (with props)
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java (with props)
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java (with props)
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java (with props)
incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java (with props)
incubator/whirr/trunk/cli/src/test/
incubator/whirr/trunk/cli/src/test/java/
incubator/whirr/trunk/cli/src/test/java/org/
incubator/whirr/trunk/cli/src/test/java/org/apache/
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java (with props)
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java (with props)
incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java (with props)
Modified:
incubator/whirr/trunk/CHANGES.txt
incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Cluster.java
incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterSpec.java
incubator/whirr/trunk/pom.xml
Modified: incubator/whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/CHANGES.txt?rev=986393&r1=986392&r2=986393&view=diff
==============================================================================
--- incubator/whirr/trunk/CHANGES.txt (original)
+++ incubator/whirr/trunk/CHANGES.txt Tue Aug 17 16:53:11 2010
@@ -6,6 +6,8 @@ Trunk (unreleased changes)
NEW FEATURES
+ WHIRR-33. Add a CLI. (tomwhite)
+
IMPROVEMENTS
WHIRR-2. Import initial Java source code. (tomwhite)
Added: incubator/whirr/trunk/cli/pom.xml
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/pom.xml?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/pom.xml (added)
+++ incubator/whirr/trunk/cli/pom.xml Tue Aug 17 16:53:11 2010
@@ -0,0 +1,184 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.whirr</groupId>
+ <artifactId>whirr</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <groupId>org.apache.whirr</groupId>
+ <artifactId>whirr-cli</artifactId>
+ <packaging>jar</packaging>
+ <version>0.1.0-SNAPSHOT</version>
+ <name>Whirr CLI</name>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>whirr-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>whirr-cassandra</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>whirr-hadoop</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>whirr-zookeeper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-aws</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-enterprise</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-jsch</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-log4j</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jclouds</groupId>
+ <artifactId>jclouds-rackspace</artifactId>
+ <version>1.0-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.8.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>zookeeper</artifactId>
+ <version>3.3.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.15</version>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.jms</groupId>
+ <artifactId>jms</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.jdmk</groupId>
+ <artifactId>jmxtools</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.jmx</groupId>
+ <artifactId>jmxri</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sf.jopt-simple</groupId>
+ <artifactId>jopt-simple</artifactId>
+ <version>3.2</version>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>1.4</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <finalName>whirr-cli-${project.version}</finalName>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <mainClass>org.apache.whirr.cli.Main</mainClass>
+ </transformer>
+ </transformers>
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <repositories>
+ <repository>
+ <id>jclouds</id>
+ <url>http://jclouds.googlecode.com/svn/repo</url>
+ </repository>
+ </repositories>
+</project>
Propchange: incubator/whirr/trunk/cli/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java (added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli;
+
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
+/**
+ * A CLI command.
+ */
+public abstract class Command {
+
+ private String name;
+ private String description;
+
+ public Command(String name, String description) {
+ this.name = name;
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public abstract int run(InputStream in, PrintStream out, PrintStream err,
+ List<String> args) throws Exception;
+
+}
Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Command.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java (added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.whirr.cli.command.DestroyClusterCommand;
+import org.apache.whirr.cli.command.LaunchClusterCommand;
+
+import com.google.common.collect.Maps;
+
+/**
+ * The entry point for the Whirr CLI.
+ */
+public class Main {
+
+ private Map<String, Command> commandMap = Maps.newLinkedHashMap();
+ private int maxLen = 0;
+
+ Main(Command... commands) throws IOException {
+ for (Command command : commands) {
+ commandMap.put(command.getName(), command);
+ maxLen = Math.max(maxLen, command.getName().length());
+ }
+ }
+
+ int run(InputStream in, PrintStream out, PrintStream err,
+ List<String> list) throws Exception {
+ if (list.isEmpty()) {
+ out.println("Usage: whirr COMMAND [ARGS]");
+ out.println("where COMMAND may be one of:");
+ out.println();
+ for (Command command : commandMap.values()) {
+ out.printf("%" + maxLen + "s %s\n", command.getName(),
+ command.getDescription());
+ }
+ return -1;
+ }
+ Command command = commandMap.get(list.get(0));
+ return command.run(in, out, err, list.subList(1, list.size()));
+ }
+
+ public static void main(String... args) throws Exception {
+ Main main = new Main(
+ new LaunchClusterCommand(),
+ new DestroyClusterCommand()
+ );
+ int rc = main.run(System.in, System.out, System.err, Arrays.asList(args));
+ System.exit(rc);
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java (added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli.command;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Arrays;
+import java.util.List;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+import org.apache.whirr.cli.Command;
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.ServiceFactory;
+import org.apache.whirr.service.ClusterSpec.InstanceTemplate;
+
+/**
+ * An abstract command for interacting with clusters.
+ */
+public abstract class ClusterSpecCommand extends Command {
+
+ protected ServiceFactory factory;
+
+ protected OptionParser parser = new OptionParser();
+ protected OptionSpec<String> cloudProvider = parser.accepts("cloud-provider")
+ .withRequiredArg().defaultsTo("ec2").ofType(String.class);
+ protected OptionSpec<String> cloudIdentity = parser.accepts("cloud-identity")
+ .withRequiredArg().ofType(String.class);
+ protected OptionSpec<String> cloudCredential = parser.accepts("cloud-credential")
+ .withRequiredArg().ofType(String.class);
+ protected OptionSpec<String> secretKeyFile = parser.accepts("secret-key-file")
+ .withRequiredArg()
+ .defaultsTo(System.getProperty("user.home") + "/.ssh/id_rsa")
+ .ofType(String.class);
+
+ public ClusterSpecCommand(String name, String description, ServiceFactory factory) {
+ super(name, description);
+ this.factory = factory;
+ }
+
+ protected ClusterSpec getClusterSpec(OptionSet optionSet,
+ InstanceTemplate... instanceTemplates) {
+ return getClusterSpec(optionSet, Arrays.asList(instanceTemplates));
+ }
+
+ protected ClusterSpec getClusterSpec(OptionSet optionSet,
+ List<InstanceTemplate> instanceTemplates) {
+ ClusterSpec clusterSpec = new ClusterSpec(instanceTemplates);
+ clusterSpec.setProvider(optionSet.valueOf(cloudProvider));
+ clusterSpec.setIdentity(checkNotNull(optionSet.valueOf(cloudIdentity),
+ "cloud-identity"));
+ clusterSpec.setCredential(optionSet.valueOf(cloudCredential));
+ clusterSpec.setSecretKeyFile(optionSet.valueOf(secretKeyFile));
+ return clusterSpec;
+ }
+
+}
Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ClusterSpecCommand.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java (added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli.command;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+
+/**
+ * A command to destroy a running cluster (terminate and cleanup).
+ */
+public class DestroyClusterCommand extends ClusterSpecCommand {
+
+ public DestroyClusterCommand() throws IOException {
+ this(new ServiceFactory());
+ }
+
+ public DestroyClusterCommand(ServiceFactory factory) {
+ super("destroy-cluster", "Terminate and cleanup resources for a running cluster.", factory);
+ }
+
+ @Override
+ public int run(InputStream in, PrintStream out, PrintStream err,
+ List<String> args) throws Exception {
+
+ OptionSet optionSet = parser.parse(args.toArray(new String[0]));
+
+ List<String> nonOptionArguments = optionSet.nonOptionArguments();
+ if (nonOptionArguments.size() < 2) {
+ printUsage(parser, err);
+ return -1;
+ }
+ String serviceName = nonOptionArguments.get(0);
+ ClusterSpec clusterSpec = getClusterSpec(optionSet);
+ clusterSpec.setClusterName(nonOptionArguments.get(1));
+
+ Service service = factory.create(serviceName);
+ service.destroyCluster(clusterSpec);
+ return 0;
+ }
+
+ private void printUsage(OptionParser parser, PrintStream stream) throws IOException {
+ stream.println("Usage: whirr destroy-cluster [OPTIONS] <service-name> <cluster-name>");
+ stream.println();
+ parser.printHelpOn(stream);
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/DestroyClusterCommand.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java (added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli.command;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.Set;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+import org.apache.whirr.service.Cluster;
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+import org.apache.whirr.service.ClusterSpec.InstanceTemplate;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Sets;
+import com.google.inject.internal.Lists;
+
+/**
+ * A command to launch a new cluster.
+ */
+public class LaunchClusterCommand extends ClusterSpecCommand {
+
+ public LaunchClusterCommand() throws IOException {
+ this(new ServiceFactory());
+ }
+
+ public LaunchClusterCommand(ServiceFactory factory) {
+ super("launch-cluster", "Launch a new cluster running a service.", factory);
+ }
+
+ @Override
+ public int run(InputStream in, PrintStream out, PrintStream err,
+ List<String> args) throws Exception {
+
+ OptionSet optionSet = parser.parse(args.toArray(new String[0]));
+
+ List<String> nonOptionArguments = optionSet.nonOptionArguments();
+ if (nonOptionArguments.size() < 4) {
+ printUsage(parser, err);
+ return -1;
+ }
+
+ final int nonTemplateArgumentsSize = 2;
+
+ if ((nonOptionArguments.size() - nonTemplateArgumentsSize) % 2 == 1) {
+ printUsage(parser, err);
+ return -1;
+ }
+
+ List<InstanceTemplate> templates = Lists.newArrayList();
+ for (int i = 0; i < (nonOptionArguments.size() - 1) / 2; i++) {
+ int number = Integer.parseInt(nonOptionArguments.get(2 * i + nonTemplateArgumentsSize));
+ String rolesString = nonOptionArguments.get(2 * i + nonTemplateArgumentsSize + 1);
+ Set<String> roles = Sets.newHashSet(Splitter.on("+").split(rolesString));
+ templates.add(new InstanceTemplate(number, roles));
+ }
+ ClusterSpec clusterSpec = getClusterSpec(optionSet, templates);
+ String serviceName = nonOptionArguments.get(0);
+ clusterSpec.setClusterName(nonOptionArguments.get(1));
+
+ Service service = factory.create(serviceName);
+ Cluster cluster = service.launchCluster(clusterSpec);
+ out.printf("Started cluster of %s instances\n",
+ cluster.getInstances().size());
+ out.println(cluster);
+ return 0;
+ }
+
+ private void printUsage(OptionParser parser, PrintStream stream) throws IOException {
+ stream.println("Usage: whirr launch-cluster [OPTIONS] <service-name> " +
+ "<cluster-name> <num> <roles> [<num> <roles>]*");
+ stream.println();
+ parser.printHelpOn(stream);
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/LaunchClusterCommand.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java?rev=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java (added)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.inject.internal.Lists;
+
+public class MainTest {
+
+ static class TestCommand extends Command {
+ public TestCommand() {
+ super("test-command", "test description");
+ }
+
+ @Override
+ public int run(InputStream in, PrintStream out, PrintStream err,
+ List<String> args) throws Exception {
+ return 0;
+ }
+ }
+
+ @Test
+ public void testNoArgs() throws Exception {
+ Main main = new Main(new TestCommand());
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ PrintStream out = new PrintStream(bytes);
+ int rc = main.run(null, out, null, Collections.<String>emptyList());
+ assertThat(rc, is(-1));
+ assertThat(bytes.toString(), containsString("Usage: whirr COMMAND"));
+ assertThat(bytes.toString(), containsString("test-command test description"));
+ }
+
+ @Test
+ public void testCommand() throws Exception {
+ Command command = mock(Command.class);
+ when(command.getName()).thenReturn("mock-command");
+ Main main = new Main(command);
+ main.run(null, null, null, Lists.newArrayList("mock-command", "arg1", "arg2"));
+ verify(command).run(null, null, null, Lists.newArrayList("arg1", "arg2"));
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: 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=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java (added)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli.command;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.matchers.StringContains;
+
+import com.google.inject.internal.Lists;
+
+public class DestroyClusterCommandTest {
+
+ private ByteArrayOutputStream outBytes;
+ private PrintStream out;
+ private ByteArrayOutputStream errBytes;
+ private PrintStream err;
+
+ @Before
+ public void setUp() {
+ outBytes = new ByteArrayOutputStream();
+ out = new PrintStream(outBytes);
+ errBytes = new ByteArrayOutputStream();
+ err = new PrintStream(errBytes);
+ }
+
+ @Test
+ public void testNoArgs() throws Exception {
+ DestroyClusterCommand command = new DestroyClusterCommand();
+ int rc = command.run(null, null, err, Collections.<String>emptyList());
+ assertThat(rc, is(-1));
+ assertThat(errBytes.toString(), containsUsageString());
+ }
+
+ private Matcher<String> containsUsageString() {
+ return StringContains.containsString("Usage: whirr destroy-cluster " +
+ "[OPTIONS] <service-name> <cluster-name>");
+ }
+
+ @Test
+ public void testAllOptions() throws Exception {
+
+ ServiceFactory factory = mock(ServiceFactory.class);
+ Service service = mock(Service.class);
+ when(factory.create((String) any())).thenReturn(service);
+
+ DestroyClusterCommand command = new DestroyClusterCommand(factory);
+
+ int rc = command.run(null, out, null, Lists.newArrayList(
+ "--cloud-provider", "rackspace",
+ "--cloud-identity", "myusername", "--cloud-credential", "mypassword",
+ "--secret-key-file", "secret-key",
+ "test-service", "test-cluster"));
+
+ assertThat(rc, is(0));
+
+ ClusterSpec expectedClusterSpec = new ClusterSpec();
+ expectedClusterSpec.setProvider("rackspace");
+ expectedClusterSpec.setIdentity("myusername");
+ expectedClusterSpec.setCredential("mypassword");
+ expectedClusterSpec.setClusterName("test-cluster");
+ expectedClusterSpec.setSecretKeyFile("secret-key");
+
+ verify(factory).create("test-service");
+
+ verify(service).destroyCluster(expectedClusterSpec);
+
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/DestroyClusterCommandTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: 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=986393&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java (added)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java Tue Aug 17 16:53:11 2010
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.whirr.cli.command;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+
+import org.apache.whirr.cli.command.LaunchClusterCommand;
+import org.apache.whirr.service.Cluster;
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.matchers.StringContains;
+
+import com.google.common.collect.Sets;
+import com.google.inject.internal.Lists;
+
+public class LaunchClusterCommandTest {
+
+ private ByteArrayOutputStream outBytes;
+ private PrintStream out;
+ private ByteArrayOutputStream errBytes;
+ private PrintStream err;
+
+ @Before
+ public void setUp() {
+ outBytes = new ByteArrayOutputStream();
+ out = new PrintStream(outBytes);
+ errBytes = new ByteArrayOutputStream();
+ err = new PrintStream(errBytes);
+ }
+ @Test
+ public void testNoArgs() throws Exception {
+ LaunchClusterCommand command = new LaunchClusterCommand();
+ int rc = command.run(null, null, err, Collections.<String>emptyList());
+ assertThat(rc, is(-1));
+ assertThat(errBytes.toString(), containsUsageString());
+ }
+
+ @Test
+ public void testMissingNumberAndRoles() throws Exception {
+ LaunchClusterCommand command = new LaunchClusterCommand();
+ int rc = command.run(null, null, err, Lists.newArrayList("test-service",
+ "test-cluster"));
+ assertThat(rc, is(-1));
+ assertThat(errBytes.toString(), containsUsageString());
+ }
+
+ @Test
+ public void testMissingRoles() throws Exception {
+ LaunchClusterCommand command = new LaunchClusterCommand();
+ int rc = command.run(null, null, err, Lists.newArrayList("test-service",
+ "test-cluster", "1", "role1+role2", "2"));
+ assertThat(rc, is(-1));
+ assertThat(errBytes.toString(), containsUsageString());
+ }
+
+ private Matcher<String> containsUsageString() {
+ return StringContains.containsString("Usage: whirr launch-cluster " +
+ "[OPTIONS] <service-name> <cluster-name> <num> <roles> [<num> <roles>]*");
+ }
+
+ @Test
+ public void testAllOptions() throws Exception {
+
+ ServiceFactory factory = mock(ServiceFactory.class);
+ Service service = mock(Service.class);
+ Cluster cluster = mock(Cluster.class);
+ when(factory.create((String) any())).thenReturn(service);
+ when(service.launchCluster((ClusterSpec) any())).thenReturn(cluster);
+
+ LaunchClusterCommand command = new LaunchClusterCommand(factory);
+
+ int rc = command.run(null, out, null, Lists.newArrayList(
+ "--cloud-provider", "rackspace",
+ "--cloud-identity", "myusername", "--cloud-credential", "mypassword",
+ "--secret-key-file", "secret-key",
+ "test-service", "test-cluster", "1", "role1+role2", "2", "role3"));
+
+ assertThat(rc, is(0));
+
+ ClusterSpec expectedClusterSpec = new ClusterSpec(
+ new ClusterSpec.InstanceTemplate(1, Sets.newHashSet("role1", "role2")),
+ new ClusterSpec.InstanceTemplate(2, Sets.newHashSet("role3"))
+ );
+ expectedClusterSpec.setProvider("rackspace");
+ expectedClusterSpec.setIdentity("myusername");
+ expectedClusterSpec.setCredential("mypassword");
+ expectedClusterSpec.setClusterName("test-cluster");
+ expectedClusterSpec.setSecretKeyFile("secret-key");
+
+ verify(factory).create("test-service");
+
+ verify(service).launchCluster(expectedClusterSpec);
+
+ assertThat(outBytes.toString(), containsString("Started cluster of 0 instances"));
+
+ }
+}
Propchange: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/LaunchClusterCommandTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Cluster.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Cluster.java?rev=986393&r1=986392&r2=986393&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Cluster.java (original)
+++ incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Cluster.java Tue Aug 17 16:53:11 2010
@@ -25,6 +25,8 @@ import java.util.Set;
import org.jclouds.domain.Credentials;
+import com.google.common.base.Objects;
+
/**
* This class represents a real cluster of {@link Instances}.
*
@@ -66,6 +68,14 @@ public class Cluster {
return privateAddress;
}
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("roles", roles)
+ .add("publicAddress", publicAddress)
+ .add("privateAddress", privateAddress)
+ .toString();
+ }
+
}
private Set<Instance> instances;
@@ -86,5 +96,12 @@ public class Cluster {
public Properties getConfiguration() {
return configuration;
}
+
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("instances", instances)
+ .add("configuration", configuration)
+ .toString();
+ }
}
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=986393&r1=986392&r2=986393&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 Tue Aug 17 16:53:11 2010
@@ -19,6 +19,7 @@
package org.apache.whirr.service;
import com.google.common.base.Charsets;
+import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
@@ -62,6 +63,26 @@ public class ClusterSpec {
return numberOfInstances;
}
+ public boolean equals(Object o) {
+ if (o instanceof InstanceTemplate) {
+ InstanceTemplate that = (InstanceTemplate) o;
+ return Objects.equal(numberOfInstances, that.numberOfInstances)
+ && Objects.equal(roles, that.roles);
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(numberOfInstances, roles);
+ }
+
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("numberOfInstances", numberOfInstances)
+ .add("roles", roles)
+ .toString();
+ }
+
}
private Properties configuration;
@@ -158,4 +179,37 @@ public class ClusterSpec {
return Files.toString(new File(getSecretKeyFile() + ".pub"), Charsets.UTF_8);
}
+ public boolean equals(Object o) {
+ if (o instanceof ClusterSpec) {
+ ClusterSpec that = (ClusterSpec) o;
+ return Objects.equal(configuration, that.configuration)
+ && Objects.equal(instanceTemplates, that.instanceTemplates)
+ && Objects.equal(serviceName, that.serviceName)
+ && Objects.equal(provider, that.provider)
+ && Objects.equal(identity, that.identity)
+ && Objects.equal(credential, that.credential)
+ && Objects.equal(clusterName, that.clusterName)
+ && Objects.equal(secretKeyFile, that.secretKeyFile);
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(configuration, instanceTemplates, serviceName,
+ provider, identity, credential, clusterName, secretKeyFile);
+ }
+
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("configuration", configuration)
+ .add("instanceTemplates", instanceTemplates)
+ .add("serviceName", serviceName)
+ .add("provider", provider)
+ .add("identity", identity)
+ .add("credential", credential)
+ .add("clusterName", clusterName)
+ .add("secretKeyFile", secretKeyFile)
+ .toString();
+ }
+
}
Modified: incubator/whirr/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/pom.xml?rev=986393&r1=986392&r2=986393&view=diff
==============================================================================
--- incubator/whirr/trunk/pom.xml (original)
+++ incubator/whirr/trunk/pom.xml Tue Aug 17 16:53:11 2010
@@ -25,6 +25,7 @@
<modules>
<module>build-tools</module>
+ <module>cli</module>
<module>core</module>
<module>services/cassandra</module>
<module>services/hadoop</module>