brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [02/16] git commit: HTTP API entity helpers
Date Fri, 19 Sep 2014 11:31:18 GMT
HTTP API entity helpers


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/58d648a0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/58d648a0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/58d648a0

Branch: refs/heads/master
Commit: 58d648a0d8acf27f91f5968f35b89366768a2968
Parents: 05e810f
Author: Svetoslav Neykov <svetoslav.neykov@cloudsoftcorp.com>
Authored: Fri Sep 12 19:02:55 2014 +0300
Committer: Svetoslav Neykov <svetoslav.neykov@cloudsoftcorp.com>
Committed: Wed Sep 17 15:40:39 2014 +0300

----------------------------------------------------------------------
 .../main/java/brooklyn/util/http/HttpTool.java  |  32 ++++-
 .../entity/brooklynnode/BrooklynNode.java       |   4 +-
 .../entity/brooklynnode/BrooklynNodeImpl.java   |  41 ++-----
 .../entity/brooklynnode/EntityHttpClient.java   |  60 ++++++++++
 .../brooklynnode/EntityHttpClientImpl.java      | 120 +++++++++++++++++++
 .../brooklynnode/SameBrooklynNodeImpl.java      |   5 +
 .../brooklynnode/DeployBlueprintTest.java       |  30 +++--
 7 files changed, 250 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/core/src/main/java/brooklyn/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java
index 61a5b7a..a81b928 100644
--- a/core/src/main/java/brooklyn/util/http/HttpTool.java
+++ b/core/src/main/java/brooklyn/util/http/HttpTool.java
@@ -24,17 +24,22 @@ import static com.google.common.base.Preconditions.checkState;
 import java.net.URI;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.http.ConnectionReuseStrategy;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.Credentials;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
 import org.apache.http.client.methods.HttpGet;
@@ -52,6 +57,7 @@ import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.entity.ByteArrayEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.params.BasicHttpParams;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
@@ -281,7 +287,24 @@ public class HttpTool {
             super(new HttpPost(uri));
         }
     }
-    
+
+    public static class HttpFormPostBuilder extends HttpRequestBuilder<HttpFormPostBuilder,
HttpPost> {
+        HttpFormPostBuilder(URI uri) {
+            super(new HttpPost(uri));
+        }
+
+        public HttpFormPostBuilder params(Map<String, String> params) {
+            if (params != null) {
+                Collection<NameValuePair> httpParams = new ArrayList<NameValuePair>(params.size());
+                for (Entry<String, String> param : params.entrySet()) {
+                    httpParams.add(new BasicNameValuePair(param.getKey(), param.getValue()));
+                }
+                req.setEntity(new UrlEncodedFormEntity(httpParams));
+            }
+            return self();
+        }
+    }
+
     public static class HttpPutBuilder extends HttpEntityEnclosingRequestBaseBuilder<HttpPutBuilder,
HttpPut> {
         public HttpPutBuilder(URI uri) {
             super(new HttpPut(uri));
@@ -292,7 +315,7 @@ public class HttpTool {
         HttpGet req = new HttpGetBuilder(uri).headers(headers).build();
         return execAndConsume(httpClient, req);
     }
-    
+
     public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String>
headers, byte[] body) {
         HttpPost req = new HttpPostBuilder(uri).headers(headers).body(body).build();
         return execAndConsume(httpClient, req);
@@ -303,6 +326,11 @@ public class HttpTool {
         return execAndConsume(httpClient, req);
     }
 
+    public static HttpToolResponse httpPost(HttpClient httpClient, URI uri, Map<String,String>
headers, Map<String, String> params) {
+        HttpPost req = new HttpFormPostBuilder(uri).headers(headers).params(params).build();
+        return execAndConsume(httpClient, req);
+    }
+
     public static HttpToolResponse httpDelete(HttpClient httpClient, URI uri, Map<String,String>
headers) {
         HttpDelete req = new HttpDeleteBuilder(uri).headers(headers).build();
         return execAndConsume(httpClient, req);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
index 0290255..77e7214 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNode.java
@@ -222,5 +222,7 @@ public interface BrooklynNode extends SoftwareProcess, UsesJava {
     }
     
     public static Effector<String> DEPLOY_BLUEPRINT = DeployBlueprintEffector.DEPLOY_BLUEPRINT;
-    
+
+    public EntityHttpClient http();
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
index 5c29980..3475ef9 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
@@ -140,39 +140,14 @@ public class BrooklynNodeImpl extends SoftwareProcessImpl implements
BrooklynNod
             return (String)planRaw;
         }
         
-        protected String submitPlan(String plan) {
-            URI baseUri = Preconditions.checkNotNull(entity().getAttribute(WEB_CONSOLE_URI),
"Cannot be invoked until the web console URL is available");
-            HttpClientBuilder builder = HttpTool.httpClientBuilder()
-                .trustAll()
-                .laxRedirect(true)
-                .uri(baseUri);
-            if (entity().getConfig(MANAGEMENT_USER)!=null)
-                builder.credentials(new UsernamePasswordCredentials(entity().getConfig(MANAGEMENT_USER),
entity().getConfig(MANAGEMENT_PASSWORD)));
-            HttpClient client = builder.build();
-            
-            return submitPlan(client, baseUri, plan);
-        }
-
         @VisibleForTesting
         // Integration test for this in BrooklynNodeIntegrationTest in this project doesn't
use this method,
         // but a Unit test for this does, in DeployBlueprintTest -- but in the REST server
project (since it runs against local) 
-        public static String submitPlan(HttpClient client, URI baseUri, String plan) {
-            URI uri = URI.create(Urls.mergePaths(baseUri.toString(), "/v1/applications"));
-            
-            HttpToolResponse result = null;
-            byte[] content;
-            try {
-                result = HttpTool.httpPost(client, uri, MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE,
"application/yaml"), plan.getBytes());
-                content = result.getContent();
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                throw new IllegalStateException("Invalid response invoking "+uri+": "+e,
e);
-            }
-            Tasks.addTagDynamically(BrooklynTaskTags.tagForStream("http_response", Streams.byteArray(content)));
-            if (!HttpTool.isStatusCodeHealthy(result.getResponseCode())) {
-                log.warn("Invalid response invoking "+uri+": response code "+result.getResponseCode()+"\n"+result+":
"+new String(content));
-                throw new IllegalStateException("Invalid response invoking "+uri+": response
code "+result.getResponseCode());
-            }
+        public String submitPlan(String plan) {
+            MutableMap<String, String> headers = MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE,
"application/yaml");
+            HttpToolResponse result = ((BrooklynNode)entity()).http()
+                    .post("/v1/applications", headers, plan.getBytes());
+            byte[] content = result.getContent();
             return (String)new Gson().fromJson(new String(content), Map.class).get("entityId");
         }
     }
@@ -252,4 +227,10 @@ public class BrooklynNodeImpl extends SoftwareProcessImpl implements
BrooklynNod
         
         if (httpFeed != null) httpFeed.stop();
     }
+
+    @Override
+    public EntityHttpClient http() {
+        return new EntityHttpClientImpl(this);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
new file mode 100644
index 0000000..904c544
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClient.java
@@ -0,0 +1,60 @@
+/*
+ * 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 brooklyn.entity.brooklynnode;
+
+import java.util.Map;
+
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+
+/**
+ * Helpful methods for making HTTP requests to {@link BrooklynNode} entities.
+ */
+public interface EntityHttpClient {
+    /**
+     * @return An HTTP client builder configured to access the {@link
+     *         BrooklynNode#WEB_CONSOLE_URI web console URI} at the
+     *         given entity, or null if the entity has no URI.
+     */
+    public HttpTool.HttpClientBuilder getHttpClientForBrooklynNode();
+
+    /**
+     * Makes an HTTP GET to a Brooklyn node entity.
+     * @param path Relative path to resource on server, e.g v1/catalog
+     * @return The server's response
+     */
+    public HttpToolResponse get(String path);
+
+    /**
+     * Makes an HTTP POST to a Brooklyn node entity.
+     * @param path Relative path to resource on server, e.g v1/catalog
+     * @param body byte array of serialized JSON to attach to the request
+     * @return The server's response
+     */
+    public HttpToolResponse post(String path, Map<String, String> headers, byte[] body);
+
+    /**
+     * Makes an HTTP POST to a Brooklyn node entity.
+     * @param path Relative path to resource on server, e.g v1/catalog
+     * @param body byte array of serialized JSON to attach to the request
+     * @return The server's response
+     */
+    public HttpToolResponse post(String path, Map<String, String> headers, Map<String,
String> formParams);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
new file mode 100644
index 0000000..262c485
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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 brooklyn.entity.brooklynnode;
+
+import java.net.URI;
+import java.util.Map;
+
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.HttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.net.Urls;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.task.Tasks;
+
+public class EntityHttpClientImpl implements EntityHttpClient {
+    private static final Logger LOG = LoggerFactory.getLogger(EntityHttpClientImpl.class);
+
+    protected static interface HttpCall {
+        public HttpToolResponse call(HttpClient client, URI uri);
+    }
+
+    protected BrooklynNode node;
+
+    protected EntityHttpClientImpl(BrooklynNode node) {
+        this.node = node;
+    }
+
+    @Override
+    public HttpTool.HttpClientBuilder getHttpClientForBrooklynNode() {
+        URI baseUri = node.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
+        if (baseUri == null) {
+            return null;
+        }
+        HttpTool.HttpClientBuilder builder = HttpTool.httpClientBuilder()
+                .trustAll()
+                .laxRedirect(true)
+                .uri(baseUri);
+        if (node.getConfig(BrooklynNode.MANAGEMENT_USER) != null) {
+            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
+                    node.getConfig(BrooklynNode.MANAGEMENT_USER),
+                    node.getConfig(BrooklynNode.MANAGEMENT_PASSWORD));
+            builder.credentials(credentials);
+        }
+        return builder;
+    }
+
+    protected HttpToolResponse exec(String path, HttpCall httpCall) {
+        HttpClient client = getHttpClientForBrooklynNode().build();
+        URI baseUri = node.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
+        URI uri = URI.create(Urls.mergePaths(baseUri.toString(), path));
+
+        HttpToolResponse result;
+        try {
+            result = httpCall.call(client, uri);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Invalid response invoking " + uri + ": " + e,
e);
+        }
+        Tasks.addTagDynamically(BrooklynTaskTags.tagForStream("http_response", Streams.byteArray(result.getContent())));
+        if (!HttpTool.isStatusCodeHealthy(result.getResponseCode())) {
+            LOG.warn("Invalid response invoking {}: response code {}\n{}: {}",
+                    new Object[]{uri, result.getResponseCode(), result, new String(result.getContent())});
+            throw new IllegalStateException("Invalid response invoking " + uri + ": response
code " + result.getResponseCode());
+        }
+        return result;
+    }
+
+    @Override
+    public HttpToolResponse get(String path) {
+        return exec(path, new HttpCall() {
+            @Override
+            public HttpToolResponse call(HttpClient client, URI uri) {
+                return HttpTool.httpGet(client, uri, MutableMap.<String, String>of());
+            }
+        });
+    }
+
+    @Override
+    public HttpToolResponse post(String path, final Map<String, String> headers, final
byte[] body) {
+        return exec(path, new HttpCall() {
+            @Override
+            public HttpToolResponse call(HttpClient client, URI uri) {
+                return HttpTool.httpPost(client, uri, headers, body);
+            }
+        });
+    }
+
+    @Override
+    public HttpToolResponse post(String path, final Map<String, String> headers, final
Map<String, String> formParams) {
+        return exec(path, new HttpCall() {
+            @Override
+            public HttpToolResponse call(HttpClient client, URI uri) {
+                return HttpTool.httpPost(client, uri, headers, formParams);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/software/base/src/test/java/brooklyn/entity/brooklynnode/SameBrooklynNodeImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/brooklynnode/SameBrooklynNodeImpl.java
b/software/base/src/test/java/brooklyn/entity/brooklynnode/SameBrooklynNodeImpl.java
index 76e918c..198c257 100644
--- a/software/base/src/test/java/brooklyn/entity/brooklynnode/SameBrooklynNodeImpl.java
+++ b/software/base/src/test/java/brooklyn/entity/brooklynnode/SameBrooklynNodeImpl.java
@@ -83,4 +83,9 @@ public class SameBrooklynNodeImpl extends AbstractEntity implements BrooklynNode
         if (httpFeed != null) httpFeed.stop();
     }
 
+    @Override
+    public EntityHttpClient http() {
+        throw new UnsupportedOperationException();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/58d648a0/usage/rest-server/src/test/java/brooklyn/entity/brooklynnode/DeployBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/entity/brooklynnode/DeployBlueprintTest.java
b/usage/rest-server/src/test/java/brooklyn/entity/brooklynnode/DeployBlueprintTest.java
index d8214a4..42f0785 100644
--- a/usage/rest-server/src/test/java/brooklyn/entity/brooklynnode/DeployBlueprintTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/entity/brooklynnode/DeployBlueprintTest.java
@@ -22,42 +22,54 @@ import static org.testng.Assert.assertEquals;
 
 import java.net.URI;
 import java.util.List;
+import java.util.Map;
 
+import org.eclipse.jetty.server.Server;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.basic.BasicApplication;
-import brooklyn.entity.brooklynnode.BrooklynNodeImpl.DeployBlueprintEffectorBody;
-import brooklyn.event.feed.http.HttpValueFunctions;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.brooklynnode.BrooklynNode.DeployBlueprintEffector;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.feed.http.JsonFunctions;
+import brooklyn.management.EntityManager;
 import brooklyn.rest.BrooklynRestApiLauncherTestFixture;
 import brooklyn.test.HttpTestUtils;
 import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpTool;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 
 public class DeployBlueprintTest extends BrooklynRestApiLauncherTestFixture {
 
     private static final Logger log = LoggerFactory.getLogger(DeployBlueprintTest.class);
-    
+
+    Server server;
+
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
-        useServerForTest(newServer());
+        server = newServer();
+        useServerForTest(server);
     }
 
     @Test
     public void testStartsAppViaEffector() throws Exception {
         URI webConsoleUri = URI.create(getBaseUri());
-        
-        String id = DeployBlueprintEffectorBody.submitPlan(HttpTool.httpClientBuilder().build(),
webConsoleUri, 
-            "{ services: [ serviceType: \"java:"+BasicApplication.class.getName()+"\" ] }");
+
+        EntitySpec<BrooklynNode> spec = EntitySpec.create(BrooklynNode.class);
+        EntityManager mgr = getManagementContextFromJettyServerAttributes(server).getEntityManager();
+        BrooklynNode node = mgr.createEntity(spec);
+        ((EntityLocal)node).setAttribute(BrooklynNode.WEB_CONSOLE_URI, webConsoleUri);
+        mgr.manage(node);
+        Map<String, String> params = ImmutableMap.of(DeployBlueprintEffector.BLUEPRINT_CAMP_PLAN.getName(),
"{ services: [ serviceType: \"java:"+BasicApplication.class.getName()+"\" ] }");
+        String id = node.invoke(BrooklynNode.DEPLOY_BLUEPRINT, params).getUnchecked();
 
         log.info("got: "+id);
-        
+
         String apps = HttpTestUtils.getContent(webConsoleUri.toString()+"/v1/applications");
         List<String> appType = parseJsonList(apps, ImmutableList.of("spec", "type"),
String.class);
         assertEquals(appType, ImmutableList.of(BasicApplication.class.getName()));


Mime
View raw message