You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/12/15 17:57:32 UTC

[5/9] incubator-brooklyn git commit: REST API support for setting multiple sensors or config with a map

REST API support for setting multiple sensors or config with a map


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

Branch: refs/heads/master
Commit: 25dccf0fed5186bd78b3090282a9e897dd7715a5
Parents: 7c0e0bd
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Nov 28 09:21:17 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Dec 12 13:54:55 2014 +0000

----------------------------------------------------------------------
 .../java/brooklyn/rest/api/EntityConfigApi.java | 18 +++-
 .../main/java/brooklyn/rest/api/SensorApi.java  | 14 +++
 .../rest/resources/EntityConfigResource.java    | 27 +++++-
 .../brooklyn/rest/resources/SensorResource.java | 21 +++++
 .../resources/EntityConfigResourceTest.java     | 93 ++++++++++++++++----
 .../rest/resources/SensorResourceTest.java      | 16 ++++
 6 files changed, 169 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
index 76dd25d..7c576bf 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
@@ -104,6 +104,22 @@ public interface EntityConfigApi {
   );
 
   @POST
+  @ApiOperation(value = "Manually set multiple config values")
+  @ApiErrors(value = {
+      @ApiError(code = 404, reason = "Could not find application or entity")
+  })
+  public void setFromMap(
+      @ApiParam(value = "Application ID or name", required = true)
+      @PathParam("application") final String application,
+      @ApiParam(value = "Entity ID or name", required = true)
+      @PathParam("entity") final String entityToken,
+      @ApiParam(value = "Apply the config to all pre-existing descendants", required = false)
+      @QueryParam("recurse") @DefaultValue("false") final Boolean recurse,
+      @ApiParam(value = "Map of config key names to values", required = true)
+      Map<?,?> newValues
+  ) ;
+
+  @POST
   @Path("/{config}")
   @ApiOperation(value = "Manually set a config value")
   @ApiErrors(value = {
@@ -117,7 +133,7 @@ public interface EntityConfigApi {
           @ApiParam(value = "Config key name", required = true)
           @PathParam("config") String configName,
           @ApiParam(value = "Apply the config to all pre-existing descendants", required = false)
-          @QueryParam("raw") @DefaultValue("false") final Boolean recurse,
+          @QueryParam("recurse") @DefaultValue("false") final Boolean recurse,
           @ApiParam(value = "Value to set")
           Object newValue
   ) ;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
index 349da5a..982aa52 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
@@ -109,6 +109,20 @@ public interface SensorApi {
   ) ;
 
   @POST
+  @ApiOperation(value = "Manually set multiple sensor values")
+  @ApiErrors(value = {
+      @ApiError(code = 404, reason = "Could not find application or entity")
+  })
+  public void setFromMap(
+      @ApiParam(value = "Application ID or name", required = true)
+      @PathParam("application") final String application,
+      @ApiParam(value = "Entity ID or name", required = true)
+      @PathParam("entity") final String entityToken,
+      @ApiParam(value = "Map of sensor names to values", required = true)
+      Map<?,?> newValues
+  ) ;
+
+  @POST
   @Path("/{sensor}")
   @ApiOperation(value = "Manually set a sensor value")
   @ApiErrors(value = {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
index e5e2aac..66c1ef7 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
@@ -89,7 +89,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
   
   @Override
   public String getPlain(String application, String entityToken, String configKeyName, Boolean raw) {
-      return Strings.toString(get(true, application, entityToken, configKeyName, raw));
+      return Strings.toString(get(false, application, entityToken, configKeyName, raw));
   }
 
     public Object get(boolean preferJson, String application, String entityToken, String configKeyName, Boolean raw) {
@@ -110,6 +110,31 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
 
   @SuppressWarnings({ "rawtypes", "unchecked" })
   @Override
+  public void setFromMap(String application, String entityToken, Boolean recurse, Map<?, ?> newValues) {
+      final EntityLocal entity = brooklyn().getEntity(application, entityToken);
+      if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
+          throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+              Entitlements.getEntitlementContext().user(), entity);
+      }
+
+      if (LOG.isDebugEnabled())
+          LOG.debug("REST user "+Entitlements.getEntitlementContext()+" setting configs "+newValues);
+      for (Map.Entry<?,?> entry: newValues.entrySet()) {
+          String configName = Strings.toString(entry.getKey());
+          Object newValue = entry.getValue();
+          
+          ConfigKey ck = findConfig(entity, configName);
+          ((EntityInternal) entity).setConfig(ck, TypeCoercions.coerce(newValue, ck.getTypeToken()));
+          if (Boolean.TRUE.equals(recurse)) {
+              for (Entity e2: Entities.descendants(entity, Predicates.alwaysTrue(), false)) {
+                  ((EntityInternal) e2).setConfig(ck, newValue);
+              }
+          }
+      }
+  }
+  
+  @SuppressWarnings({ "rawtypes", "unchecked" })
+  @Override
   public void set(String application, String entityToken, String configName, Boolean recurse, Object newValue) {
       final EntityLocal entity = brooklyn().getEntity(application, entityToken);
       if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
index fedd60d..987a995 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
@@ -38,6 +38,7 @@ import brooklyn.rest.api.SensorApi;
 import brooklyn.rest.domain.SensorSummary;
 import brooklyn.rest.transform.SensorTransformer;
 import brooklyn.rest.util.WebResourceUtils;
+import brooklyn.util.text.Strings;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
@@ -103,7 +104,27 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
         if (s instanceof AttributeSensor) return (AttributeSensor<?>) s;
         return new BasicAttributeSensor<Object>(Object.class, name);
     }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public void setFromMap(String application, String entityToken, Map<?, ?> newValues) {
+        final EntityLocal entity = brooklyn().getEntity(application, entityToken);
+        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
+            throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
+                Entitlements.getEntitlementContext().user(), entity);
+        }
 
+        if (log.isDebugEnabled())
+            log.debug("REST user "+Entitlements.getEntitlementContext()+" setting sensors "+newValues);
+        for (Map.Entry<?,?> entry: newValues.entrySet()) {
+            String sensorName = Strings.toString(entry.getKey());
+            Object newValue = entry.getValue();
+            
+            AttributeSensor sensor = findSensor(entity, sensorName);
+            entity.setAttribute(sensor, newValue);
+        }
+    }
+    
     @SuppressWarnings({ "rawtypes", "unchecked" })
     @Override
     public void set(String application, String entityToken, String sensorName, Object newValue) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-server/src/test/java/brooklyn/rest/resources/EntityConfigResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/EntityConfigResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/EntityConfigResourceTest.java
index 1f18f60..af8ca5d 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/EntityConfigResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/EntityConfigResourceTest.java
@@ -18,11 +18,33 @@
  */
 package brooklyn.rest.resources;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityPredicates;
 import brooklyn.rest.domain.ApplicationSpec;
 import brooklyn.rest.domain.EntityConfigSummary;
 import brooklyn.rest.domain.EntitySpec;
 import brooklyn.rest.testing.BrooklynRestResourceTest;
 import brooklyn.rest.testing.mocks.RestMockSimpleEntity;
+import brooklyn.util.collections.MutableMap;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableMap;
@@ -30,26 +52,13 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.GenericType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import javax.annotation.Nullable;
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
 
 @Test(singleThreaded = true)
 public class EntityConfigResourceTest extends BrooklynRestResourceTest {
     
     private final static Logger log = LoggerFactory.getLogger(EntityConfigResourceTest.class);
-    private URI application;
+    private URI applicationUri;
+    private EntityInternal entity;
 
     @BeforeClass(alwaysRun = true)
     @Override
@@ -65,9 +74,11 @@ public class EntityConfigResourceTest extends BrooklynRestResourceTest {
         ClientResponse response = clientDeploy(simpleSpec);
         int status = response.getStatus();
         assertTrue(status >= 200 && status <= 299, "expected HTTP Response of 2xx but got " + status);
-        application = response.getLocation();
+        applicationUri = response.getLocation();
         log.debug("Built app: application");
-        waitForApplicationToBeRunning(application);
+        waitForApplicationToBeRunning(applicationUri);
+        
+        entity = (EntityInternal) Iterables.find(getManagementContext().getEntityManager().getEntities(), EntityPredicates.displayNameEqualTo("simple-ent"));
     }
 
     @Test
@@ -106,11 +117,57 @@ public class EntityConfigResourceTest extends BrooklynRestResourceTest {
     }
 
     @Test
-    public void testGet() throws Exception {
+    public void testGetJson() throws Exception {
         String configValue = client().resource(
                 URI.create("/v1/applications/simple-app/entities/simple-ent/config/install.version"))
+                .accept(MediaType.APPLICATION_JSON_TYPE)
                 .get(String.class);
         assertEquals(configValue, "\"1.0.0\"");
     }
 
+    @Test
+    public void testGetPlain() throws Exception {
+        String configValue = client().resource(
+                URI.create("/v1/applications/simple-app/entities/simple-ent/config/install.version"))
+                .accept(MediaType.TEXT_PLAIN_TYPE)
+                .get(String.class);
+        assertEquals(configValue, "1.0.0");
+    }
+
+    @Test
+    public void testSet() throws Exception {
+        try {
+            String uri = "/v1/applications/simple-app/entities/simple-ent/config/"+
+                RestMockSimpleEntity.SAMPLE_CONFIG.getName();
+            ClientResponse response = client().resource(uri)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .post(ClientResponse.class, "\"hello world\"");
+            assertEquals(response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+
+            assertEquals(entity.getConfig(RestMockSimpleEntity.SAMPLE_CONFIG), "hello world");
+            
+            String value = client().resource(uri).accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
+            assertEquals(value, "\"hello world\"");
+
+        } finally { entity.setConfig(RestMockSimpleEntity.SAMPLE_CONFIG, RestMockSimpleEntity.SAMPLE_CONFIG.getDefaultValue()); }
+    }
+
+    @Test
+    public void testSetFromMap() throws Exception {
+        try {
+            String uri = "/v1/applications/simple-app/entities/simple-ent/config";
+            ClientResponse response = client().resource(uri)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .post(ClientResponse.class, MutableMap.of(
+                    RestMockSimpleEntity.SAMPLE_CONFIG.getName(), "hello world"));
+            assertEquals(response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+
+            assertEquals(entity.getConfig(RestMockSimpleEntity.SAMPLE_CONFIG), "hello world");
+            
+            String value = client().resource(uri+"/"+RestMockSimpleEntity.SAMPLE_CONFIG.getName()).accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
+            assertEquals(value, "\"hello world\"");
+
+        } finally { entity.setConfig(RestMockSimpleEntity.SAMPLE_CONFIG, RestMockSimpleEntity.SAMPLE_CONFIG.getDefaultValue()); }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/25dccf0f/usage/rest-server/src/test/java/brooklyn/rest/resources/SensorResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/SensorResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/SensorResourceTest.java
index bb80035..6d074c0 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/SensorResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/SensorResourceTest.java
@@ -41,6 +41,7 @@ import brooklyn.rest.domain.EntitySpec;
 import brooklyn.rest.testing.BrooklynRestResourceTest;
 import brooklyn.rest.testing.mocks.RestMockSimpleEntity;
 import brooklyn.test.HttpTestUtils;
+import brooklyn.util.collections.MutableMap;
 import brooklyn.util.stream.Streams;
 import brooklyn.util.text.StringFunctions;
 
@@ -233,12 +234,27 @@ public class SensorResourceTest extends BrooklynRestResourceTest {
                 .post(ClientResponse.class, 67890);
             assertEquals(response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
 
+            assertEquals(entity.getAttribute(SENSOR), (Integer)67890);
+            
             String value = client().resource(SENSORS_ENDPOINT + "/" + SENSOR_NAME).accept(MediaType.TEXT_PLAIN_TYPE).get(String.class);
             assertEquals(value, "67890 frogs");
 
         } finally { addAmphibianSensor(entity); }
     }
 
+    @Test
+    public void testSetFromMap() throws Exception {
+        try {
+            ClientResponse response = client().resource(SENSORS_ENDPOINT)
+                .type(MediaType.APPLICATION_JSON_TYPE)
+                .post(ClientResponse.class, MutableMap.of(SENSOR_NAME, 67890));
+            assertEquals(response.getStatus(), Response.Status.NO_CONTENT.getStatusCode());
+            
+            assertEquals(entity.getAttribute(SENSOR), (Integer)67890);
+
+        } finally { addAmphibianSensor(entity); }
+    }
+    
     /** Check we can delete a value */
     @Test
     public void testDelete() throws Exception {