You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2017/09/19 15:07:29 UTC

[3/5] brooklyn-server git commit: Adds FunctionSensor (for yaml FunctionFeed)

Adds FunctionSensor (for yaml FunctionFeed)

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/3ef6742d
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/3ef6742d
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/3ef6742d

Branch: refs/heads/master
Commit: 3ef6742d002a7be6ac5f483c339e7a3aa344d440
Parents: 001730b
Author: Aled Sage <al...@gmail.com>
Authored: Fri Sep 15 09:11:45 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Sep 15 18:56:41 2017 +0100

----------------------------------------------------------------------
 .../camp/brooklyn/FunctionSensorYamlTest.java   | 89 +++++++++++++++++++
 .../core/sensor/function/FunctionSensor.java    | 91 ++++++++++++++++++++
 .../sensor/function/FunctionSensorTest.java     | 77 +++++++++++++++++
 3 files changed, 257 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3ef6742d/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/FunctionSensorYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/FunctionSensorYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/FunctionSensorYamlTest.java
new file mode 100644
index 0000000..14402ec
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/FunctionSensorYamlTest.java
@@ -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.brooklyn.camp.brooklyn;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.sensor.function.FunctionSensor;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+public class FunctionSensorYamlTest extends AbstractYamlRebindTest {
+    private static final Logger log = LoggerFactory.getLogger(FunctionSensorYamlTest.class);
+
+    final static AttributeSensor<String> SENSOR_STRING = Sensors.newStringSensor("aString");
+    final static String TARGET_TYPE = "java.lang.String";
+
+    public static class MyCallable implements Callable<Object> {
+        public static AtomicReference<Object> val = new AtomicReference<>();
+
+        @Override public Object call() throws Exception {
+            return val.get();
+        }
+    }
+
+    @Test
+    public void testFunctionSensor() throws Exception {
+        MyCallable.val.set("first");
+        
+        Entity app = createAndStartApplication(
+            "services:",
+            "- type: " + TestEntity.class.getName(),
+            "  brooklyn.config:",
+            "    onbox.base.dir.skipResolution: true",
+            "  brooklyn.initializers:",
+            "  - type: "+FunctionSensor.class.getName(),
+            "    brooklyn.config:",
+            "      "+FunctionSensor.SENSOR_PERIOD.getName()+": 100ms",
+            "      "+FunctionSensor.SENSOR_NAME.getName()+": " + SENSOR_STRING.getName(),
+            "      "+FunctionSensor.SENSOR_TYPE.getName()+": " + TARGET_TYPE,
+            "      "+FunctionSensor.FUNCTION.getName()+":",
+            "        $brooklyn:object:",
+            "          type: "+MyCallable.class.getName());
+        waitForApplicationTasks(app);
+        Entity entity = Iterables.getOnlyElement(app.getChildren());
+
+        EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "first");
+        
+        MyCallable.val.set("second");
+        EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "second");
+        
+        // Rebind, and confirm that it resumes polling
+        Application newApp = rebind();
+        Entity newEntity = Iterables.getOnlyElement(newApp.getChildren());
+
+        MyCallable.val.set("third");
+        EntityAsserts.assertAttributeEqualsEventually(newEntity, SENSOR_STRING, "third");
+    }
+
+    @Override
+    protected Logger getLogger() {
+        return log;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3ef6742d/core/src/main/java/org/apache/brooklyn/core/sensor/function/FunctionSensor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/function/FunctionSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/function/FunctionSensor.java
new file mode 100644
index 0000000..cc77f02
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/function/FunctionSensor.java
@@ -0,0 +1,91 @@
+/*
+ * 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.brooklyn.core.sensor.function;
+
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.effector.AddSensor;
+import org.apache.brooklyn.core.entity.EntityInitializers;
+import org.apache.brooklyn.feed.function.FunctionFeed;
+import org.apache.brooklyn.feed.function.FunctionPollConfig;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Functions;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Configurable {@link org.apache.brooklyn.api.entity.EntityInitializer} which adds a function sensor feed.
+ * This calls the function periodically, to compute the sensor's value.
+ *
+ * @see FunctionFeed
+ */
+@Beta
+public final class FunctionSensor<T> extends AddSensor<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FunctionSensor.class);
+
+    public static final ConfigKey<Boolean> SUPPRESS_DUPLICATES = ConfigKeys.newBooleanConfigKey(
+            "suppressDuplicates", 
+            "Whether to publish the sensor value again, if it is the same as the previous value",
+            Boolean.FALSE);
+    
+    public static final ConfigKey<Callable<?>> FUNCTION = ConfigKeys.newConfigKey(
+            new TypeToken<Callable<?>>() {},
+            "function",
+            "The callable to be executed periodically",
+            null);
+    
+    public FunctionSensor(final ConfigBag params) {
+        super(params);
+    }
+
+    @Override
+    public void apply(final EntityLocal entity) {
+        super.apply(entity);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Adding HTTP JSON sensor {} to {}", name, entity);
+        }
+
+        final ConfigBag allConfig = ConfigBag.newInstanceCopying(this.params).putAll(params);
+        
+        final Callable<?> function = EntityInitializers.resolve(allConfig, FUNCTION);
+        final Boolean suppressDuplicates = EntityInitializers.resolve(allConfig, SUPPRESS_DUPLICATES);
+
+        FunctionPollConfig<?, T> pollConfig = new FunctionPollConfig<Object, T>(sensor)
+                .callable(function)
+                .onSuccess(TypeCoercions.function((Class<T>)sensor.getType()))
+                .onFailureOrException(Functions.constant((T) null))
+                .suppressDuplicates(Boolean.TRUE.equals(suppressDuplicates))
+                .period(period);
+
+        FunctionFeed feed = FunctionFeed.builder().entity(entity)
+                .poll(pollConfig)
+                .build();
+
+        entity.addFeed(feed);
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3ef6742d/core/src/test/java/org/apache/brooklyn/core/sensor/function/FunctionSensorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/function/FunctionSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/function/FunctionSensorTest.java
new file mode 100644
index 0000000..3d554bd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/sensor/function/FunctionSensorTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.brooklyn.core.sensor.function;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.time.Duration;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class FunctionSensorTest extends BrooklynAppUnitTestSupport {
+    final static AttributeSensor<String> SENSOR_STRING = Sensors.newStringSensor("aString");
+    final static String STRING_TARGET_TYPE = "java.lang.String";
+
+    TestEntity entity;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        super.setUp();
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        app.start(ImmutableList.<Location>of());
+    }
+
+    @Test
+    public void testFunction() throws Exception {
+        AtomicReference<String> val = new AtomicReference<String>("first");
+        Callable<String> callable = new Callable<String>() {
+            @Override public String call() throws Exception {
+                return val.get();
+            }
+        };
+        
+        FunctionSensor<Integer> initializer = new FunctionSensor<Integer>(ConfigBag.newInstance()
+                .configure(FunctionSensor.SENSOR_PERIOD, Duration.millis(10))
+                .configure(FunctionSensor.SENSOR_NAME, SENSOR_STRING.getName())
+                .configure(FunctionSensor.SENSOR_TYPE, STRING_TARGET_TYPE)
+                .configure(FunctionSensor.FUNCTION, callable));
+        initializer.apply(entity);
+        entity.sensors().set(Attributes.SERVICE_UP, true);
+        
+        initializer.apply(entity);
+        entity.sensors().set(Attributes.SERVICE_UP, true);
+
+        EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "first");
+        
+        val.set("second");
+        EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "second");
+    }
+}