brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [1/3] git commit: BrooklynEntityMirror: Mirror effectors of remote entity
Date Mon, 22 Sep 2014 15:16:18 GMT
Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 888afd075 -> d829990f4


BrooklynEntityMirror: Mirror effectors of remote entity

Parameter have Object types resulting in transparently passing the incoming data to the remote
effector.
Effectors' return is treated as plain string.


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

Branch: refs/heads/master
Commit: 0b269ba33816a34006827c9eb49c7a80f0e2a59c
Parents: c9fe10e
Author: Svetoslav Neykov <svetoslav.neykov@cloudsoftcorp.com>
Authored: Fri Sep 19 17:52:18 2014 +0300
Committer: Svetoslav Neykov <svetoslav.neykov@cloudsoftcorp.com>
Committed: Fri Sep 19 18:00:38 2014 +0300

----------------------------------------------------------------------
 .../brooklynnode/BrooklynEntityMirror.java      |  2 +
 .../brooklynnode/BrooklynEntityMirrorImpl.java  | 84 +++++++------------
 .../entity/brooklynnode/BrooklynNodeImpl.java   |  2 +-
 .../brooklynnode/EntityHttpClientImpl.java      | 54 +++++++++----
 .../brooklynnode/RemoteEffectorBuilder.java     | 85 ++++++++++++++++++++
 5 files changed, 153 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b269ba3/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirror.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirror.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirror.java
index 296287b..6cd8709 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirror.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirror.java
@@ -54,5 +54,7 @@ public interface BrooklynEntityMirror extends Entity {
         "Frequency to poll for client sensors", Duration.FIVE_SECONDS);
     
     public static final AttributeSensor<String> MIRROR_STATUS = Sensors.newStringSensor("brooklyn.mirror.monitoring_status");
+    
+    public EntityHttpClient http();
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b269ba3/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
index ae62f7b..7a25674 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorImpl.java
@@ -18,24 +18,21 @@
  */
 package brooklyn.entity.brooklynnode;
 
-import java.net.URI;
+import java.util.Collection;
 import java.util.Map;
 import java.util.concurrent.Callable;
 
 import javax.annotation.Nullable;
 
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.entity.Effector;
 import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.Attributes;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityDynamicType;
 import brooklyn.entity.basic.EntityFunctions;
 import brooklyn.entity.basic.Lifecycle;
-import brooklyn.entity.basic.ServiceStateLogic;
 import brooklyn.entity.effector.EffectorBody;
 import brooklyn.event.basic.Sensors;
 import brooklyn.event.feed.http.HttpFeed;
@@ -43,17 +40,12 @@ import brooklyn.event.feed.http.HttpPollConfig;
 import brooklyn.util.collections.Jsonya;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Functionals;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpTool.HttpClientBuilder;
 import brooklyn.util.http.HttpToolResponse;
 import brooklyn.util.net.Urls;
-import brooklyn.util.stream.Streams;
 import brooklyn.util.task.DynamicTasks;
 import brooklyn.util.task.Tasks;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Suppliers;
@@ -126,6 +118,20 @@ public class BrooklynEntityMirrorImpl extends AbstractEntity implements
Brooklyn
                         Suppliers.ofInstance("error contacting service")
                     ))))
             .build();
+
+        populateEffectors();
+    }
+
+    private void populateEffectors() {
+        HttpToolResponse result = http().get("/effectors");
+        Collection<?> cfgEffectors = new Gson().fromJson(result.getContentAsString(),
Collection.class);
+        Collection<Effector<String>> remoteEntityEffectors = RemoteEffectorBuilder.of(cfgEffectors);
+        EntityDynamicType mutableEntityType = getMutableEntityType();
+        for (Effector<String> eff : remoteEntityEffectors) {
+            //remote already started
+            if ("start".equals(eff.getName())) continue;
+            mutableEntityType.addEffector(eff);
+        }
     }
 
     protected void disconnectSensors() {
@@ -137,64 +143,30 @@ public class BrooklynEntityMirrorImpl extends AbstractEntity implements
Brooklyn
         disconnectSensors();
     }
 
+    @Override
+    public EntityHttpClient http() {
+        return new EntityHttpClientImpl(this, MIRRORED_ENTITY_URL);
+    }
+
     public static class RemoteEffector<T> extends EffectorBody<T> {
         public final String remoteEffectorName;
-        public final Function<byte[], T> resultParser;
+        public final Function<HttpToolResponse, T> resultParser;
         
         /** creates an effector implementation which POSTs to a remote effector endpoint,
optionally converting
          * the byte[] response (if resultParser is null then null is returned) */
-        public RemoteEffector(String remoteEffectorName, @Nullable Function<byte[],T>
resultParser) {
+        public RemoteEffector(String remoteEffectorName, @Nullable Function<HttpToolResponse,T>
resultParser) {
             this.remoteEffectorName = remoteEffectorName;
             this.resultParser = resultParser;
         }
 
         @Override
         public T call(ConfigBag parameters) {
-            String baseUri = Preconditions.checkNotNull(entity().getConfig(MIRRORED_ENTITY_URL),
"Cannot be invoked without an entity URL");
-            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();
-            
-            byte[] result = submit(client, URI.create(Urls.mergePaths(baseUri, "effectors",
Urls.encode(remoteEffectorName))), parameters.getAllConfig());
+            MutableMap<String, String> headers = MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE,
MediaType.JSON_UTF_8.toString());
+            byte[] httpBody = Jsonya.of(parameters.getAllConfig()).toString().getBytes();
+            String effectorUrl = Urls.mergePaths("effectors", Urls.encode(remoteEffectorName));
+            HttpToolResponse result = ((BrooklynEntityMirror)entity()).http().post(effectorUrl,
headers, httpBody);
             if (resultParser!=null) return resultParser.apply(result);
             else return null;
         }
-
-        @VisibleForTesting
-        public static byte[] submit(HttpClient client, URI uri, Map<String,Object>
args) {
-            HttpToolResponse result = null;
-            byte[] content;
-            try {
-                result = HttpTool.httpPost(client, uri, MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE,
MediaType.JSON_UTF_8.toString()), 
-                    Jsonya.of(args).toString().getBytes());
-                content = result.getContent();
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                throw new IllegalStateException("Invalid response invoking "+uri+": "+e,
e);
-            }
-            Tasks.addTagDynamically(BrooklynTaskTags.tagForStreamWeak("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());
-            }
-            return content;
-        }
-
-    }
-
-    public static class StopAndExpungeEffector extends RemoteEffector<Void> {
-        public StopAndExpungeEffector() {
-            super("stop", null);
-        }
-        @Override
-        public Void call(ConfigBag parameters) {
-            super.call(parameters);
-            Entities.unmanage(entity());
-            return null;
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b269ba3/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 78c9991..a956540 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/BrooklynNodeImpl.java
@@ -328,7 +328,7 @@ public class BrooklynNodeImpl extends SoftwareProcessImpl implements BrooklynNod
 
     @Override
     public EntityHttpClient http() {
-        return new EntityHttpClientImpl(this);
+        return new EntityHttpClientImpl(this, BrooklynNode.WEB_CONSOLE_URI);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b269ba3/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
index 76d2ede..3fa2b5d 100644
--- a/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/EntityHttpClientImpl.java
@@ -26,7 +26,12 @@ import org.apache.http.client.HttpClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.api.client.util.Preconditions;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
 import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.event.AttributeSensor;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.http.HttpTool;
@@ -35,8 +40,6 @@ import brooklyn.util.net.Urls;
 import brooklyn.util.stream.Streams;
 import brooklyn.util.task.Tasks;
 
-import com.google.common.base.Preconditions;
-
 public class EntityHttpClientImpl implements EntityHttpClient {
     private static final Logger LOG = LoggerFactory.getLogger(EntityHttpClientImpl.class);
 
@@ -44,36 +47,41 @@ public class EntityHttpClientImpl implements EntityHttpClient {
         public HttpToolResponse call(HttpClient client, URI uri);
     }
 
-    protected BrooklynNode node;
+    protected Entity entity;
+    protected AttributeSensor<?> urlSensor;
+    protected ConfigKey<?> urlConfig;
+
+    protected EntityHttpClientImpl(Entity entity, AttributeSensor<?> urlSensor) {
+        this.entity = entity;
+        this.urlSensor = urlSensor;
+    }
 
-    protected EntityHttpClientImpl(BrooklynNode node) {
-        this.node = node;
+    protected EntityHttpClientImpl(Entity entity, ConfigKey<?> urlConfig) {
+        this.entity = entity;
+        this.urlConfig = urlConfig;
     }
 
     @Override
     public HttpTool.HttpClientBuilder getHttpClientForBrooklynNode() {
-        URI baseUri = node.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
-        if (baseUri == null) {
-            return null;
-        }
+        String baseUrl = getEntityUrl();
         HttpTool.HttpClientBuilder builder = HttpTool.httpClientBuilder()
                 .trustAll()
                 .laxRedirect(true)
-                .uri(baseUri);
-        if (node.getConfig(BrooklynNode.MANAGEMENT_USER) != null) {
+                .uri(baseUrl);
+        if (entity.getConfig(BrooklynNode.MANAGEMENT_USER) != null) {
             UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
-                    node.getConfig(BrooklynNode.MANAGEMENT_USER),
-                    node.getConfig(BrooklynNode.MANAGEMENT_PASSWORD));
+                    entity.getConfig(BrooklynNode.MANAGEMENT_USER),
+                    entity.getConfig(BrooklynNode.MANAGEMENT_PASSWORD));
             builder.credentials(credentials);
         }
         return builder;
     }
 
     protected HttpToolResponse exec(String path, HttpCall httpCall) {
-        HttpClient client = Preconditions.checkNotNull(getHttpClientForBrooklynNode(), "No
address info for "+node)
-            .build();
-        URI baseUri = node.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
-        URI uri = URI.create(Urls.mergePaths(baseUri.toString(), path));
+        HttpClient client = Preconditions.checkNotNull(getHttpClientForBrooklynNode(), "No
address info for "+entity)
+                .build();
+        String baseUri = getEntityUrl();
+        URI uri = URI.create(Urls.mergePaths(baseUri, path));
 
         HttpToolResponse result;
         try {
@@ -120,4 +128,16 @@ public class EntityHttpClientImpl implements EntityHttpClient {
             }
         });
     }
+
+    protected String getEntityUrl() {
+        Preconditions.checkState(urlSensor == null ^ urlConfig == null, "Exactly one of urlSensor
and urlConfig should be non-null for entity " + entity);
+        Object url = null;
+        if (urlSensor != null) {
+            url = entity.getAttribute(urlSensor);
+        } else if (urlConfig != null) {
+            url = entity.getConfig(urlConfig);
+        }
+        Preconditions.checkNotNull(url, "URL sensor " + urlSensor + " for entity " + entity
+ " is empty");
+        return url.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b269ba3/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
b/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
new file mode 100644
index 0000000..eba3c1a
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/brooklynnode/RemoteEffectorBuilder.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import brooklyn.entity.Effector;
+import brooklyn.entity.brooklynnode.BrooklynEntityMirrorImpl.RemoteEffector;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.effector.Effectors.EffectorBuilder;
+import brooklyn.util.http.HttpToolResponse;
+
+import com.google.common.base.Function;
+
+public class RemoteEffectorBuilder {
+    private static class ResultParser implements Function<HttpToolResponse, String>
{
+        @Override
+        public String apply(HttpToolResponse input) {
+            return input.getContentAsString();
+        }
+    }
+
+    public static Collection<Effector<String>> of(Collection<?> cfgEffectors)
{
+        Collection<Effector<String>> effectors = new ArrayList<Effector<String>>();
+        for (Object objEff : cfgEffectors) {
+            Map<?, ?> cfgEff = (Map<?, ?>)objEff;
+//            String returnTypeName = (String)cfgEff.get("returnType");
+            String effName = (String)cfgEff.get("name");
+            String description = (String)cfgEff.get("description");
+
+//            Class<?> returnType = getType(returnTypeName);
+            EffectorBuilder<String> eff = Effectors.effector(String.class, effName);
+            Collection<?> params = (Collection<?>)cfgEff.get("parameters");
+
+            if (description != null) {
+                eff.description(description);
+            }
+
+            for (Object objParam : params) {
+                buildParam(eff, (Map<?, ?>)objParam);
+            }
+
+            eff.impl(new RemoteEffector<String>(effName, new ResultParser()));
+            effectors.add(eff.build());
+        }
+        return effectors;
+    }
+
+    private static void buildParam(EffectorBuilder<String> eff, Map<?, ?> cfgParam)
{
+//        String type = (String)cfgParam.get("type");
+        String name = (String)cfgParam.get("name");
+        String description = (String)cfgParam.get("description");
+        String defaultValue = (String)cfgParam.get("defaultValue");
+
+//        Class<?> paramType = getType(type);
+        eff.parameter(Object.class, name, description, defaultValue /*TypeCoercions.coerce(defaultValue,
paramType)*/);
+    }
+
+//    private static Class<?> getType(String type) {
+//        try {
+//            return Class.forName(type);
+//        } catch (ClassNotFoundException e) {
+//            return Object.class;
+//        }
+//    }
+
+}


Mime
View raw message