You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by io...@apache.org on 2011/11/05 15:44:15 UTC

svn commit: r1197966 - in /camel/trunk/components/camel-jclouds/src: main/java/org/apache/camel/component/jclouds/ test/java/org/apache/camel/component/jclouds/ test/resources/

Author: iocanel
Date: Sat Nov  5 14:44:14 2011
New Revision: 1197966

URL: http://svn.apache.org/viewvc?rev=1197966&view=rev
Log:
[CAMEL-4622] Added predicate support to compute producer, to support node ranges and filtering.

Modified:
    camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeEndpoint.java
    camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeProducer.java
    camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsConstants.java
    camel/trunk/components/camel-jclouds/src/test/java/org/apache/camel/component/jclouds/JcloudsSpringComputeTest.java
    camel/trunk/components/camel-jclouds/src/test/resources/compute-test.xml

Modified: camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeEndpoint.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeEndpoint.java?rev=1197966&r1=1197965&r2=1197966&view=diff
==============================================================================
--- camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeEndpoint.java (original)
+++ camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeEndpoint.java Sat Nov  5 14:44:14 2011
@@ -31,6 +31,7 @@ public class JcloudsComputeEndpoint exte
     private String hardwareId;
 
     private String operation;
+    private String nodeState;
     private String nodeId;
     private String group;
     private String user;
@@ -83,6 +84,14 @@ public class JcloudsComputeEndpoint exte
         this.operation = operation;
     }
 
+    public String getNodeState() {
+        return nodeState;
+    }
+
+    public void setNodeState(String nodeState) {
+        this.nodeState = nodeState;
+    }
+
     public String getNodeId() {
         return nodeId;
     }

Modified: camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeProducer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeProducer.java?rev=1197966&r1=1197965&r2=1197966&view=diff
==============================================================================
--- camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeProducer.java (original)
+++ camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsComputeProducer.java Sat Nov  5 14:44:14 2011
@@ -17,6 +17,7 @@
 package org.apache.camel.component.jclouds;
 
 import java.util.Set;
+import com.google.common.base.Predicate;
 import org.apache.camel.CamelException;
 import org.apache.camel.Exchange;
 import org.jclouds.compute.ComputeService;
@@ -26,10 +27,13 @@ import org.jclouds.compute.domain.ExecRe
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeState;
 import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.domain.internal.NodeMetadataImpl;
 import org.jclouds.compute.options.RunScriptOptions;
 import org.jclouds.domain.Credentials;
 
+
 public class JcloudsComputeProducer extends JcloudsProducer {
 
     private ComputeService computeService;
@@ -148,11 +152,8 @@ public class JcloudsComputeProducer exte
      * @throws CamelException
      */
     protected void destroyNode(Exchange exchange) throws CamelException {
-        String nodeId = getNodeId(exchange);
-        if (nodeId == null) {
-            throw new CamelException("Node id must be specific in the URI or as exchange property for the destroy node operation.");
-        }
-        computeService.destroyNode(nodeId);
+        Predicate<NodeMetadata> predicate = getNodePredicate(exchange);
+        computeService.destroyNodesMatching(predicate);
     }
 
     /**
@@ -162,7 +163,8 @@ public class JcloudsComputeProducer exte
      * @throws CamelException
      */
     protected void listNodes(Exchange exchange) throws CamelException {
-        Set<? extends ComputeMetadata> computeMetadatas = computeService.listNodes();
+        Predicate<ComputeMetadata> predicate = getComputePredicate(exchange);
+        Set<? extends ComputeMetadata> computeMetadatas = computeService.listNodesDetailsMatching(predicate);
         exchange.getOut().setBody(computeMetadatas);
     }
 
@@ -188,6 +190,73 @@ public class JcloudsComputeProducer exte
         exchange.getOut().setBody(hardwareProfiles);
     }
 
+
+    /**
+     * Returns the required {@ComputeMetadata} {@link Predicate} for the Exhcnage.
+     * The predicate can be used for filtering.
+     *
+     * @param exchange
+     * @return
+     */
+    public Predicate<ComputeMetadata> getComputePredicate(final Exchange exchange) {
+        final String nodeId = getNodeId(exchange);
+        final String imageId = getImageId(exchange);
+        final String group = getGroup(exchange);
+        final NodeState queryState = getNodeState(exchange);
+
+        Predicate<ComputeMetadata> predicate = new Predicate<ComputeMetadata>() {
+            public boolean apply(ComputeMetadata metadata) {
+                if (nodeId != null && !nodeId.equals(metadata.getId())) {
+                    return false;
+                }
+
+                //If NodeMetadata also delegate to Node predicate.
+                if (metadata instanceof NodeMetadataImpl) {
+                    Predicate<NodeMetadata> nodeMetadataPredicate = getNodePredicate(exchange);
+                    if (!nodeMetadataPredicate.apply((NodeMetadataImpl) metadata)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        };
+
+        return predicate;
+    }
+
+    /**
+     * Returns the required {@ComputeMetadata} {@link Predicate} for the Exhcnage.
+     * The predicate can be used for filtering.
+     *
+     * @param exchange
+     * @return
+     */
+    public Predicate<NodeMetadata> getNodePredicate(Exchange exchange) {
+        final String nodeId = getNodeId(exchange);
+        final String imageId = getImageId(exchange);
+        final String group = getGroup(exchange);
+        final NodeState queryState = getNodeState(exchange);
+
+        Predicate<NodeMetadata> predicate = new Predicate<NodeMetadata>() {
+            public boolean apply(NodeMetadata metadata) {
+                if (nodeId != null && !nodeId.equals(metadata.getId())) {
+                    return false;
+                }
+                if (imageId != null && !imageId.equals(metadata.getImageId())) {
+                    return false;
+                }
+                if (queryState != null && !queryState.equals(metadata.getState())) {
+                    return false;
+                }
+                if (group != null && !group.equals(metadata.getGroup())) {
+                    return false;
+                }
+                return true;
+            }
+        };
+        return predicate;
+    }
+
     /**
      * Retrieves the operation from the URI or from the exchange headers. The header will take precedence over the URI.
      *
@@ -204,6 +273,33 @@ public class JcloudsComputeProducer exte
     }
 
     /**
+     * Retrieves the node state from the URI or from the exchange headers. The header will take precedence over the URI.
+     *
+     * @param exchange
+     * @return
+     */
+    public NodeState getNodeState(Exchange exchange) {
+        NodeState nodeState = null;
+        String state = ((JcloudsComputeEndpoint) getEndpoint()).getNodeState();
+        if (state != null) {
+            nodeState = NodeState.valueOf(state);
+        }
+
+        if (exchange.getIn().getHeader(JcloudsConstants.NODE_STATE) != null) {
+            Object stateHeader = exchange.getIn().getHeader(JcloudsConstants.NODE_STATE);
+            if (stateHeader == null) {
+                nodeState = null;
+            } else if (stateHeader instanceof NodeState) {
+                nodeState = (NodeState) stateHeader;
+            } else {
+                nodeState = NodeState.valueOf(String.valueOf(stateHeader));
+            }
+        }
+        return nodeState;
+    }
+
+
+    /**
      * Retrieves the image id from the URI or from the exchange properties. The property will take precedence over the URI.
      *
      * @param exchange

Modified: camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsConstants.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsConstants.java?rev=1197966&r1=1197965&r2=1197966&view=diff
==============================================================================
--- camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsConstants.java (original)
+++ camel/trunk/components/camel-jclouds/src/main/java/org/apache/camel/component/jclouds/JcloudsConstants.java Sat Nov  5 14:44:14 2011
@@ -23,6 +23,8 @@ public final class JcloudsConstants {
     public static final String BLOB_NAME = "CamelJcloudsBlobName";
     public static final String CONTAINER_NAME = "CamelJcloudsContainerName";
 
+    public static final String NODE_STATE = "CamelJcloudsNodeState";
+
     public static final String OPERATION = "CamelJcloudsOperation";
     public static final String PUT = "CamelJcloudsPut";
     public static final String GET = "CamelJcloudsGet";

Modified: camel/trunk/components/camel-jclouds/src/test/java/org/apache/camel/component/jclouds/JcloudsSpringComputeTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jclouds/src/test/java/org/apache/camel/component/jclouds/JcloudsSpringComputeTest.java?rev=1197966&r1=1197965&r2=1197966&view=diff
==============================================================================
--- camel/trunk/components/camel-jclouds/src/test/java/org/apache/camel/component/jclouds/JcloudsSpringComputeTest.java (original)
+++ camel/trunk/components/camel-jclouds/src/test/java/org/apache/camel/component/jclouds/JcloudsSpringComputeTest.java Sat Nov  5 14:44:14 2011
@@ -27,7 +27,7 @@ import org.apache.camel.test.junit4.Came
 import org.jclouds.compute.domain.Hardware;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.NodeMetadata;
-import org.junit.BeforeClass;
+import org.junit.After;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.springframework.context.support.AbstractApplicationContext;
@@ -38,8 +38,9 @@ public class JcloudsSpringComputeTest ex
     @EndpointInject(uri = "mock:result")
     protected MockEndpoint result;
 
-    @BeforeClass
-    public static void setUpClass() throws Exception {
+    @After
+    public void tearDown() throws Exception {
+        template.sendBodyAndHeaders("direct:start", null, destroyHeaders(null, null));
     }
 
     @Override
@@ -49,7 +50,7 @@ public class JcloudsSpringComputeTest ex
 
     @Test
     public void testListImages() throws InterruptedException {
-        template.sendBodyAndHeader("direct:start", "Some message", JcloudsConstants.OPERATION, JcloudsConstants.LIST_IMAGES);
+        template.sendBodyAndHeader("direct:start", null, JcloudsConstants.OPERATION, JcloudsConstants.LIST_IMAGES);
         result.expectedMessageCount(1);
         result.assertIsSatisfied();
         List<Exchange> exchanges = result.getExchanges();
@@ -66,7 +67,7 @@ public class JcloudsSpringComputeTest ex
 
     @Test
     public void testListHardware() throws InterruptedException {
-        template.sendBodyAndHeader("direct:start", "Some message", JcloudsConstants.OPERATION, JcloudsConstants.LIST_HARDWARE);
+        template.sendBodyAndHeader("direct:start", null, JcloudsConstants.OPERATION, JcloudsConstants.LIST_HARDWARE);
         result.expectedMessageCount(1);
         result.assertIsSatisfied();
         List<Exchange> exchanges = result.getExchanges();
@@ -83,7 +84,7 @@ public class JcloudsSpringComputeTest ex
 
     @Test
     public void testListNodes() throws InterruptedException {
-        template.sendBodyAndHeader("direct:start", "Some message", JcloudsConstants.OPERATION, JcloudsConstants.LIST_NODES);
+        template.sendBodyAndHeader("direct:start", null, JcloudsConstants.OPERATION, JcloudsConstants.LIST_NODES);
         result.expectedMessageCount(1);
         result.assertIsSatisfied();
         List<Exchange> exchanges = result.getExchanges();
@@ -95,18 +96,64 @@ public class JcloudsSpringComputeTest ex
         }
     }
 
+    @Test
+    public void testCreateAndListNodes() throws InterruptedException {
+        template.sendBodyAndHeaders("direct:start", null, createHeaders("1", "default"));
+
+        template.sendBodyAndHeader("direct:start", null, JcloudsConstants.OPERATION, JcloudsConstants.LIST_NODES);
+        result.expectedMessageCount(2);
+        result.assertIsSatisfied();
+        List<Exchange> exchanges = result.getExchanges();
+        if (exchanges != null && !exchanges.isEmpty()) {
+            for (Exchange exchange : exchanges) {
+                Set nodeMetadatas = (Set) exchange.getIn().getBody();
+                assertEquals("Nodes should be 1", 1, nodeMetadatas.size());
+            }
+        }
+    }
+
 
     @Test
-    public void testCreateAndDestroyNode() throws InterruptedException {
-        Map<String, Object> createHeaders = new HashMap<String, Object>();
-        createHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.CREATE_NODE);
-        createHeaders.put(JcloudsConstants.IMAGE_ID, "1");
-        createHeaders.put(JcloudsConstants.GROUP, "default");
+    public void testCreateAndListWithPredicates() throws InterruptedException {
+        //Create a node for the default group
+        template.sendBodyAndHeaders("direct:start", null, createHeaders("1", "default"));
+
+        //Create a node for the group 'other'
+        template.sendBodyAndHeaders("direct:start", null, createHeaders("1", "other"));
+        template.sendBodyAndHeaders("direct:start", null, createHeaders("2", "other"));
+
+        template.sendBodyAndHeaders("direct:start", null, listNodeHeaders(null, "other", null));
+        template.sendBodyAndHeaders("direct:start", null, listNodeHeaders("3", "other", null));
+        template.sendBodyAndHeaders("direct:start", null, listNodeHeaders("3", "other", "RUNNING"));
 
-        Map<String, Object> destroyHeaders = new HashMap<String, Object>();
-        destroyHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.DESTROY_NODE);
+        result.expectedMessageCount(6);
+        result.assertIsSatisfied();
+        List<Exchange> exchanges = result.getExchanges();
 
-        template.sendBodyAndHeaders("direct:start", "Some message", createHeaders);
+        Exchange exchange = exchanges.get(3);
+        Set<NodeMetadata> nodeMetadatas = (Set<NodeMetadata>) exchange.getIn().getBody();
+        assertEquals("Nodes should be 2", 2, nodeMetadatas.size());
+        NodeMetadata nodeMetadata = nodeMetadatas.toArray(new NodeMetadata[0])[0];
+        assertEquals("other", nodeMetadata.getGroup());
+
+        exchange = exchanges.get(4);
+        nodeMetadatas = (Set<NodeMetadata>) exchange.getIn().getBody();
+        assertEquals("Nodes should be 1", 1, nodeMetadatas.size());
+        nodeMetadata = nodeMetadatas.toArray(new NodeMetadata[0])[0];
+        assertEquals("other", nodeMetadata.getGroup());
+        assertEquals("3", nodeMetadata.getId());
+
+        exchange = exchanges.get(5);
+        nodeMetadatas = (Set<NodeMetadata>) exchange.getIn().getBody();
+        assertEquals("Nodes should be 1", 1, nodeMetadatas.size());
+        nodeMetadata = nodeMetadatas.toArray(new NodeMetadata[0])[0];
+        assertEquals("other", nodeMetadata.getGroup());
+        assertEquals("3", nodeMetadata.getId());
+    }
+
+    @Test
+    public void testCreateAndDestroyNode() throws InterruptedException {
+        template.sendBodyAndHeaders("direct:start", null, createHeaders("1", "default"));
         result.expectedMessageCount(1);
         result.assertIsSatisfied();
         List<Exchange> exchanges = result.getExchanges();
@@ -117,8 +164,7 @@ public class JcloudsSpringComputeTest ex
 
                 for (Object obj : nodeMetadatas) {
                     NodeMetadata nodeMetadata = (NodeMetadata) obj;
-                    destroyHeaders.put(JcloudsConstants.NODE_ID, nodeMetadata.getId());
-                    template.sendBodyAndHeaders("direct:start", "Some message", destroyHeaders);
+                    template.sendBodyAndHeaders("direct:start", null, destroyHeaders(nodeMetadata.getId(), null));
                 }
             }
         }
@@ -128,24 +174,76 @@ public class JcloudsSpringComputeTest ex
     @Ignore("For now not possible to combine stub provider with ssh module, requird for runScript")
     @Test
     public void testRunScript() throws InterruptedException {
+        Map<String, Object> runScriptHeaders = new HashMap<String, Object>();
+        runScriptHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.RUN_SCRIPT);
+
+        Set<? extends NodeMetadata> nodeMetadatas = (Set<? extends NodeMetadata>) template.requestBodyAndHeaders("direct:in-out", null, createHeaders("1", "default"));
+        assertEquals("There should be a node running", 1, nodeMetadatas.size());
+        for (NodeMetadata nodeMetadata : nodeMetadatas) {
+            runScriptHeaders.put(JcloudsConstants.NODE_ID, nodeMetadata.getId());
+            template.requestBodyAndHeaders("direct:in-out", null, runScriptHeaders);
+            template.sendBodyAndHeaders("direct:in-out", null, destroyHeaders(nodeMetadata.getId(), null));
+        }
+    }
+
+
+    /**
+     * Returns a {@Map} with the create headers.
+     *
+     * @param imageId The imageId to use for creating the node.
+     * @param group   The group to be assigned to the node.
+     * @return
+     */
+    protected Map<String, Object> createHeaders(String imageId, String group) {
         Map<String, Object> createHeaders = new HashMap<String, Object>();
         createHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.CREATE_NODE);
-        createHeaders.put(JcloudsConstants.IMAGE_ID, "1");
-        createHeaders.put(JcloudsConstants.GROUP, "default");
+        createHeaders.put(JcloudsConstants.IMAGE_ID, imageId);
+        createHeaders.put(JcloudsConstants.GROUP, group);
+        return createHeaders;
+    }
 
-        Map<String, Object> runScriptHeaders = new HashMap<String, Object>();
-        runScriptHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.RUN_SCRIPT);
 
+    /**
+     * Returns a {@Map} with the destroy headers.
+     *
+     * @param nodeId The id of the node to destroy.
+     * @param group  The group of the node to destroy.
+     * @return
+     */
+    protected Map<String, Object> destroyHeaders(String nodeId, String group) {
         Map<String, Object> destroyHeaders = new HashMap<String, Object>();
         destroyHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.DESTROY_NODE);
+        if (nodeId != null) {
+            destroyHeaders.put(JcloudsConstants.NODE_ID, nodeId);
+        }
+        if (group != null) {
+            destroyHeaders.put(JcloudsConstants.GROUP, group);
+        }
+        return destroyHeaders;
+    }
 
-        Set<? extends NodeMetadata> nodeMetadatas = (Set<? extends NodeMetadata>) template.requestBodyAndHeaders("direct:in-out", "Some message", createHeaders);
-        assertEquals("There should be a node running", 1, nodeMetadatas.size());
-        for (NodeMetadata nodeMetadata : nodeMetadatas) {
-            runScriptHeaders.put(JcloudsConstants.NODE_ID, nodeMetadata.getId());
-            destroyHeaders.put(JcloudsConstants.NODE_ID, nodeMetadata.getId());
-            template.requestBodyAndHeaders("direct:in-out", "Some message", runScriptHeaders);
-            template.sendBodyAndHeaders("direct:in-out", "Some message", destroyHeaders);
+    /**
+     * Returns a {@Map} with the destroy headers.
+     *
+     * @param nodeId The id of the node to destroy.
+     * @param group  The group of the node to destroy.
+     * @return
+     */
+    protected Map<String, Object> listNodeHeaders(String nodeId, String group, Object state) {
+        Map<String, Object> listHeaders = new HashMap<String, Object>();
+        listHeaders.put(JcloudsConstants.OPERATION, JcloudsConstants.LIST_NODES);
+        if (nodeId != null) {
+            listHeaders.put(JcloudsConstants.NODE_ID, nodeId);
         }
+
+        if (group != null) {
+            listHeaders.put(JcloudsConstants.GROUP, group);
+        }
+
+        if (state != null) {
+            listHeaders.put(JcloudsConstants.NODE_STATE, state);
+        }
+
+        return listHeaders;
     }
 }

Modified: camel/trunk/components/camel-jclouds/src/test/resources/compute-test.xml
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-jclouds/src/test/resources/compute-test.xml?rev=1197966&r1=1197965&r2=1197966&view=diff
==============================================================================
--- camel/trunk/components/camel-jclouds/src/test/resources/compute-test.xml (original)
+++ camel/trunk/components/camel-jclouds/src/test/resources/compute-test.xml Sat Nov  5 14:44:14 2011
@@ -25,13 +25,13 @@
 
         <route>
             <from uri="direct:start"/>
-            <to uri="jclouds:compute:stub?operation=CamelJcloudsListImages"/>
+            <to uri="jclouds:compute:stub?operation=CamelJcloudsListImages&amp;nodeState=RUNNING"/>
             <to uri="mock:result"/>
         </route>
 
         <route>
             <from uri="direct:in-out"/>
-            <to uri="jclouds:compute:stub?operation=CamelJcloudsListImages"/>
+            <to uri="jclouds:compute:stub?operation=CamelJcloudsListImages&amp;nodeState=RUNNING"/>
         </route>
 
     </camelContext>