whirr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tomwh...@apache.org
Subject svn commit: r1003381 - in /incubator/whirr/trunk: ./ cli/src/main/java/org/apache/whirr/cli/ cli/src/main/java/org/apache/whirr/cli/command/ cli/src/test/java/org/apache/whirr/cli/ cli/src/test/java/org/apache/whirr/cli/command/ core/src/main/java/org/...
Date Fri, 01 Oct 2010 04:07:36 GMT
Author: tomwhite
Date: Fri Oct  1 04:07:36 2010
New Revision: 1003381

URL: http://svn.apache.org/viewvc?rev=1003381&view=rev
Log:
WHIRR-73. Add a list command to the CLI.

Added:
    incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
  (with props)
    incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
  (with props)
Modified:
    incubator/whirr/trunk/CHANGES.txt
    incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java
    incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java
    incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Service.java
    incubator/whirr/trunk/services/cassandra/src/main/java/org/apache/whirr/service/cassandra/CassandraService.java
    incubator/whirr/trunk/services/zookeeper/src/main/java/org/apache/whirr/service/zookeeper/ZooKeeperService.java

Modified: incubator/whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/CHANGES.txt?rev=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/CHANGES.txt (original)
+++ incubator/whirr/trunk/CHANGES.txt Fri Oct  1 04:07:36 2010
@@ -6,6 +6,8 @@ Trunk (unreleased changes)
 
     WHIRR-100. Create a binary distribution of Whirr. (tomwhite)
 
+    WHIRR-73. Add a list command to the CLI. (tomwhite)
+
   IMPROVEMENTS
 
     WHIRR-89. Support maven 3 builds. (Adrian Cole via tomwhite)

Modified: 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=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java (original)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/Main.java Fri Oct  1 04:07:36
2010
@@ -18,6 +18,8 @@
 
 package org.apache.whirr.cli;
 
+import com.google.common.collect.Maps;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
@@ -28,11 +30,10 @@ import java.util.TreeSet;
 
 import org.apache.whirr.cli.command.DestroyClusterCommand;
 import org.apache.whirr.cli.command.LaunchClusterCommand;
+import org.apache.whirr.cli.command.ListClusterCommand;
 import org.apache.whirr.cli.command.VersionCommand;
 import org.apache.whirr.service.ServiceFactory;
 
-import com.google.common.collect.Maps;
-
 /**
  * The entry point for the Whirr CLI.
  */
@@ -51,31 +52,41 @@ public class Main {
   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());
-      }
-      out.println();
-      out.println("Available services:");
-      ServiceFactory serviceFactory = new ServiceFactory();
-      for (String serviceName :
-        new TreeSet<String>(serviceFactory.availableServices())) {
-        out.println("  " + serviceName);
-      }
+      printUsage(out);
       return -1;
     }
     Command command = commandMap.get(list.get(0));
+    if (command == null) {
+      err.printf("Unrecognized command '%s'\n", list.get(0));
+      err.println();
+      printUsage(err);
+      return -1;
+    }
     return command.run(in, out, err, list.subList(1, list.size()));
   }
-
+  
+  private void printUsage(PrintStream stream) {
+    stream.println("Usage: whirr COMMAND [ARGS]");
+    stream.println("where COMMAND may be one of:");
+    stream.println();
+    for (Command command : commandMap.values()) {
+      stream.printf("%" + maxLen + "s  %s\n", command.getName(),
+          command.getDescription());
+    }
+    stream.println();
+    stream.println("Available services:");
+    ServiceFactory serviceFactory = new ServiceFactory();
+    for (String serviceName : new TreeSet<String>(
+        serviceFactory.availableServices())) {
+      stream.println("  " + serviceName);
+    }
+  }
   public static void main(String... args) throws Exception {
     Main main = new Main(
         new VersionCommand(),
         new LaunchClusterCommand(),
-        new DestroyClusterCommand()
+        new DestroyClusterCommand(),
+        new ListClusterCommand()
     );
     int rc = main.run(System.in, System.out, System.err, Arrays.asList(args));
     System.exit(rc);

Added: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java?rev=1003381&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
(added)
+++ incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
Fri Oct  1 04:07:36 2010
@@ -0,0 +1,89 @@
+/**
+ * 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 com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+
+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.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+import org.jclouds.compute.domain.NodeMetadata;
+
+/**
+ * A command to list the nodes in a cluster.
+ */
+public class ListClusterCommand extends AbstractClusterSpecCommand {
+
+  public ListClusterCommand() throws IOException {
+    this(new ServiceFactory());
+  }
+
+  public ListClusterCommand(ServiceFactory factory) {
+    super("list-cluster", "List the nodes in a 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]));
+
+    if (!optionSet.nonOptionArguments().isEmpty()) {
+      printUsage(parser, err);
+      return -1;
+    }
+    try {
+      ClusterSpec clusterSpec = getClusterSpec(optionSet);
+
+      Service service = factory.create(clusterSpec.getServiceName());
+      Set<? extends NodeMetadata> nodes = service.getNodes(clusterSpec);
+      for (NodeMetadata node : nodes) {
+        out.println(Joiner.on('\t').join(node.getId(), node.getImageId(),
+            getFirstAddress(node.getPublicAddresses()),
+            getFirstAddress(node.getPrivateAddresses()),
+            node.getState(), node.getLocation().getId()));
+      }
+      return 0;
+    } catch (IllegalArgumentException e) {
+      err.println(e.getMessage());
+      printUsage(parser, err);
+      return -1;
+    }
+  }
+  
+  private String getFirstAddress(Set<String> addresses) {
+    return addresses.isEmpty() ? "" : Iterables.get(addresses, 0);
+  }
+
+  private void printUsage(OptionParser parser, PrintStream stream) throws IOException {
+    stream.println("Usage: whirr list-cluster [OPTIONS]");
+    stream.println();
+    parser.printHelpOn(stream);
+  }
+}

Propchange: incubator/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 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=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java (original)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MainTest.java Fri Oct  1
04:07:36 2010
@@ -61,6 +61,16 @@ public class MainTest {
   }
   
   @Test
+  public void testUnrecognizedCommand() throws Exception {
+    Main main = new Main(new TestCommand());
+    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+    PrintStream err = new PrintStream(bytes);
+    int rc = main.run(null, null, err, Lists.newArrayList("bogus-command"));
+    assertThat(rc, is(-1));
+    assertThat(bytes.toString(), containsString("Unrecognized command 'bogus-command'"));
+  }
+  
+  @Test
   public void testCommand() throws Exception {
     Command command = mock(Command.class);
     when(command.getName()).thenReturn("mock-command");

Added: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java?rev=1003381&view=auto
==============================================================================
--- incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
(added)
+++ incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
Fri Oct  1 04:07:36 2010
@@ -0,0 +1,115 @@
+/**
+ * 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 com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.whirr.service.ClusterSpec;
+import org.apache.whirr.service.Service;
+import org.apache.whirr.service.ServiceFactory;
+import org.hamcrest.Matcher;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeState;
+import org.jclouds.compute.domain.internal.NodeMetadataImpl;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.domain.internal.LocationImpl;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.matchers.StringContains;
+
+public class ListClusterCommandTest {
+
+  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 testInsufficientOptions() throws Exception {
+    ListClusterCommand command = new ListClusterCommand();
+    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 list-cluster [OPTIONS]");
+  }
+  
+  @Test
+  public void testAllOptions() throws Exception {
+    
+    ServiceFactory factory = mock(ServiceFactory.class);
+    Service service = mock(Service.class);
+    when(factory.create((String) any())).thenReturn(service);
+    NodeMetadata node1 = new NodeMetadataImpl(null, "name1", "id1",
+        new LocationImpl(LocationScope.PROVIDER, "location-id1",
+            "location-desc1", null),
+        null, Collections.<String,String>emptyMap(), null, null, "image-id",
+        null, NodeState.RUNNING,
+        Lists.newArrayList("100.0.0.1"),
+        Lists.newArrayList("10.0.0.1"), null);
+    NodeMetadata node2 = new NodeMetadataImpl(null, "name2", "id2",
+        new LocationImpl(LocationScope.PROVIDER, "location-id2",
+            "location-desc2", null),
+        null, Collections.<String,String>emptyMap(), null, null, "image-id",
+        null, NodeState.RUNNING,
+        Lists.newArrayList("100.0.0.2"),
+        Lists.newArrayList("10.0.0.2"), null);
+    when(service.getNodes((ClusterSpec) any())).thenReturn(
+        (Set) Sets.newLinkedHashSet(Lists.newArrayList(node1, node2)));
+    
+    ListClusterCommand command = new ListClusterCommand(factory);
+    
+    int rc = command.run(null, out, null, Lists.newArrayList(
+        "--service-name", "test-service",
+        "--cluster-name", "test-cluster",
+        "--identity", "myusername"));
+    
+    assertThat(rc, is(0));
+    
+    assertThat(outBytes.toString(), is(
+      "id1\timage-id\t100.0.0.1\t10.0.0.1\tRUNNING\tlocation-id1\n" +
+      "id2\timage-id\t100.0.0.2\t10.0.0.2\tRUNNING\tlocation-id2\n"));
+    
+    verify(factory).create("test-service");
+    
+  }
+}

Propchange: incubator/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Service.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Service.java?rev=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Service.java (original)
+++ incubator/whirr/trunk/core/src/main/java/org/apache/whirr/service/Service.java Fri Oct
 1 04:07:36 2010
@@ -20,9 +20,15 @@ package org.apache.whirr.service;
 
 import static org.jclouds.compute.predicates.NodePredicates.withTag;
 
+import com.google.common.base.Predicate;
+
 import java.io.IOException;
+import java.util.Set;
 
 import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeState;
 
 /**
  * This class represents a service that a client wants to use. This class is
@@ -58,5 +64,32 @@ public abstract class Service {
       ComputeServiceContextBuilder.build(clusterSpec).getComputeService();
     computeService.destroyNodesMatching(withTag(clusterSpec.getClusterName()));
   }
+  
+  public Set<? extends NodeMetadata> getNodes(ClusterSpec clusterSpec)
+    throws IOException {
+    ComputeService computeService =
+      ComputeServiceContextBuilder.build(clusterSpec).getComputeService();
+    return computeService.listNodesDetailsMatching(
+        runningWithTag(clusterSpec.getClusterName()));
+  }
+  
+  public static Predicate<ComputeMetadata> runningWithTag(final String tag) {
+    return new Predicate<ComputeMetadata>() {
+      @Override
+      public boolean apply(ComputeMetadata computeMetadata) {
+        // Not all list calls return NodeMetadata (e.g. VCloud)
+        if (computeMetadata instanceof NodeMetadata) {
+          NodeMetadata nodeMetadata = (NodeMetadata) computeMetadata;
+          return tag.equals(nodeMetadata.getTag())
+            && nodeMetadata.getState() == NodeState.RUNNING;
+        }
+        return false;
+      }
+      @Override
+      public String toString() {
+        return "runningWithTag(" + tag + ")";
+      }
+    };
+  }
 
 }

Modified: incubator/whirr/trunk/services/cassandra/src/main/java/org/apache/whirr/service/cassandra/CassandraService.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/cassandra/src/main/java/org/apache/whirr/service/cassandra/CassandraService.java?rev=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/services/cassandra/src/main/java/org/apache/whirr/service/cassandra/CassandraService.java
(original)
+++ incubator/whirr/trunk/services/cassandra/src/main/java/org/apache/whirr/service/cassandra/CassandraService.java
Fri Oct  1 04:07:36 2010
@@ -21,7 +21,6 @@ package org.apache.whirr.service.cassand
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.whirr.service.RunUrlBuilder.runUrls;
 import static org.jclouds.compute.options.TemplateOptions.Builder.runScript;
-import static org.jclouds.compute.predicates.NodePredicates.runningWithTag;
 import static org.jclouds.io.Payloads.newStringPayload;
 
 import com.google.common.base.Function;
@@ -55,6 +54,7 @@ import org.jclouds.compute.RunScriptOnNo
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.predicates.NodePredicates;
 import org.jclouds.io.Payload;
 import org.jclouds.ssh.ExecResponse;
 
@@ -115,7 +115,8 @@ public class CassandraService extends Se
     try {
       Map<? extends NodeMetadata, ExecResponse> responses = computeService
           .runScriptOnNodesMatching(
-              runningWithTag(clusterSpec.getClusterName()), configureScript);
+            NodePredicates.runningWithTag(clusterSpec.getClusterName()),
+              configureScript);
       assert responses.size() > 0 : "no nodes matched "
           + clusterSpec.getClusterName();
     } catch (RunScriptOnNodesException e) {

Modified: incubator/whirr/trunk/services/zookeeper/src/main/java/org/apache/whirr/service/zookeeper/ZooKeeperService.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/services/zookeeper/src/main/java/org/apache/whirr/service/zookeeper/ZooKeeperService.java?rev=1003381&r1=1003380&r2=1003381&view=diff
==============================================================================
--- incubator/whirr/trunk/services/zookeeper/src/main/java/org/apache/whirr/service/zookeeper/ZooKeeperService.java
(original)
+++ incubator/whirr/trunk/services/zookeeper/src/main/java/org/apache/whirr/service/zookeeper/ZooKeeperService.java
Fri Oct  1 04:07:36 2010
@@ -21,7 +21,6 @@ package org.apache.whirr.service.zookeep
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.whirr.service.RunUrlBuilder.runUrls;
 import static org.jclouds.compute.options.TemplateOptions.Builder.runScript;
-import static org.jclouds.compute.predicates.NodePredicates.runningWithTag;
 import static org.jclouds.io.Payloads.newStringPayload;
 
 import com.google.common.base.Function;
@@ -53,6 +52,7 @@ import org.jclouds.compute.RunScriptOnNo
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.predicates.NodePredicates;
 import org.jclouds.io.Payload;
 
 public class ZooKeeperService extends Service {
@@ -107,7 +107,8 @@ public class ZooKeeperService extends Se
     Payload configureScript = newStringPayload(runUrls(clusterSpec.getRunUrlBase(),
       "apache/zookeeper/post-configure " + servers));
     try {
-      computeService.runScriptOnNodesMatching(runningWithTag(clusterSpec.getClusterName()),
configureScript);
+      computeService.runScriptOnNodesMatching(NodePredicates.runningWithTag(
+          clusterSpec.getClusterName()), configureScript);
     } catch (RunScriptOnNodesException e) {
       // TODO: retry
       throw new IOException(e);



Mime
View raw message