This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new bfe0677f24 Change config/sensor to return 200, 204, or 404. Tidy other
API documentation bits.
bfe0677f24 is described below
commit bfe0677f247d15f47f20bb86fa23e1b2b9db87f1
Author: Alex Heneveld <[email protected]>
AuthorDate: Mon Jun 17 13:22:39 2024 +0100
Change config/sensor to return 200, 204, or 404. Tidy other API
documentation bits.
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 204, message = "No Content. The config is
known, but unset."),
@ApiResponse(code = 404, message = "Could not find application,
entity or config key"),
The behavior is now as above. 404 is returned if the sensor (or config) is
not defined, and 204 if it is defined but unset.
200 with null or empty string is only returned if the sensor/config is
explictly set as such.
Additionally, some discrepancies where Accepted was used instead of Created
or sometimes OK has been fixed,
and OK is returned in some places where ACCEPTED or CREATED had been where
it makes more sense to do so.
---
.../org/apache/brooklyn/rest/api/ActivityApi.java | 3 ++-
.../apache/brooklyn/rest/api/ApplicationApi.java | 2 +-
.../org/apache/brooklyn/rest/api/BundleApi.java | 9 ++++---
.../org/apache/brooklyn/rest/api/CatalogApi.java | 4 +--
.../org/apache/brooklyn/rest/api/EffectorApi.java | 5 ++--
.../org/apache/brooklyn/rest/api/EntityApi.java | 16 ++++++------
.../apache/brooklyn/rest/api/EntityConfigApi.java | 10 +++++---
.../org/apache/brooklyn/rest/api/LogoutApi.java | 7 +++---
.../org/apache/brooklyn/rest/api/ScriptApi.java | 2 +-
.../org/apache/brooklyn/rest/api/SensorApi.java | 9 ++++---
.../org/apache/brooklyn/rest/api/ServerApi.java | 14 +++++------
.../org/apache/brooklyn/rest/domain/ApiError.java | 15 +++++++++++
.../brooklyn/rest/resources/EffectorResource.java | 7 +++++-
.../rest/resources/EntityConfigResource.java | 20 +++++++++++++--
.../brooklyn/rest/resources/SensorResource.java | 29 +++++++++++++++++++---
.../brooklyn/rest/util/EntityAttributesUtils.java | 21 ++++++++++++++++
.../brooklyn/rest/util/WebResourceUtils.java | 14 +++++++----
.../rest/resources/ApplicationResourceTest.java | 4 +--
.../rest/resources/EffectorResourceTest.java | 6 ++---
.../rest/resources/SensorResourceTest.java | 7 ++++--
.../entity/brooklynnode/DeployBlueprintTest.java | 5 ++--
21 files changed, 152 insertions(+), 57 deletions(-)
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ActivityApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ActivityApi.java
index aabc2d2bd5..8679528957 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ActivityApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ActivityApi.java
@@ -44,7 +44,8 @@ public interface ActivityApi {
@Path("/{task}")
@ApiOperation(value = "Fetch task details", response =
org.apache.brooklyn.rest.domain.TaskSummary.class)
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
+ @ApiResponse(code = 200, message = "OK. The task is completed and
details are returned."),
+ @ApiResponse(code = 202, message = "Accepted. The task is still
running but it is not permitted to wait any longer so current details are
returned."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find task"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
index bd9ed5b473..e3f9f2e6fa 100644
---
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
+++
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ApplicationApi.java
@@ -384,7 +384,7 @@ public interface ApplicationApi {
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
+ @ApiResponse(code = 202, message = "Accepted. The application is
submitted for deletion."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application not found"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
index 033533b5ac..b9c8103942 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
@@ -247,7 +247,8 @@ public interface BundleApi {
@Consumes("application/deprecated-yaml")
@ApiOperation(value = "(deprecated; use same endpoint accepting optional
format)", hidden = true, response = BundleInstallationRestResult.class)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK. The bundle is already
installed."),
+ @ApiResponse(code = 201, message = "Created. The bundle has been
installed."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
@@ -266,7 +267,8 @@ public interface BundleApi {
@Consumes({"application/deprecated-zip"})
@ApiOperation(value = "(deprecated; use same endpoint accepting optional
format)", hidden = true, response = BundleInstallationRestResult.class)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK. The bundle is already
installed."),
+ @ApiResponse(code = 201, message = "Created. The bundle has been
installed."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
@@ -291,7 +293,8 @@ public interface BundleApi {
+ "a ZIP/JAR containing a catalog.bom and optional other
items",
response = BundleInstallationRestResult.class)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Catalog items added
successfully"),
+ @ApiResponse(code = 200, message = "OK. The bundle is already
installed."),
+ @ApiResponse(code = 201, message = "Created. The bundle has been
installed."),
@ApiResponse(code = 400, message = "Error processing the given
archive, or the catalog.bom is invalid"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
index 89993f8d11..3fb25bb17b 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
@@ -155,8 +155,8 @@ public interface CatalogApi {
+ "with a message, bundle, and code.",
response = String.class)
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
- @ApiResponse(code = 201, message = "Catalog items added
successfully"),
+ @ApiResponse(code = 200, message = "OK. The bundle is already
installed."),
+ @ApiResponse(code = 201, message = "Created. The bundle has been
installed."),
@ApiResponse(code = 400, message = "Error processing the given
archive, or the catalog.bom is invalid"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EffectorApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EffectorApi.java
index ca76932aa6..56fb0bd704 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EffectorApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EffectorApi.java
@@ -68,11 +68,12 @@ public interface EffectorApi {
@ApiOperation(value = "Trigger an effector",
notes="Returns the return value (status 200) if it completes, or
an activity task ID (status 202) if it times out", response = String.class)
@ApiResponses(value = {
- @ApiResponse(code = 202, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK. The effector run. The
result is returned."),
+ @ApiResponse(code = 202, message = "Accepted. The effector is
running. The task object is returned."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find application,
entity or effector"),
- @ApiResponse(code = 500, message = "Internal Server Error")
+ @ApiResponse(code = 500, message = "Internal Server Error. The
effector may have returned an error.")
})
@Consumes({MediaType.APPLICATION_JSON,
MediaType.APPLICATION_FORM_URLENCODED})
public Response invoke(
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityApi.java
index b1871c7af4..c952e7815b 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityApi.java
@@ -114,7 +114,7 @@ public interface EntityApi {
"text/yaml", "text/x-yaml", "application/yaml",
MediaType.APPLICATION_JSON})
@Path("/{entity}/children")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 201, message = "Created"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
@@ -166,7 +166,7 @@ public interface EntityApi {
@Path("/{entity}/activities/{task}")
@ApiOperation(value = "Fetch task details", response =
org.apache.brooklyn.rest.domain.TaskSummary.class)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find application,
entity or task"),
@@ -224,7 +224,7 @@ public interface EntityApi {
@Path("/{entity}/tag/add")
@ApiOperation(value = "Add a tag on this entity")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
@@ -239,7 +239,7 @@ public interface EntityApi {
@Path("/{entity}/tag/delete")
@ApiOperation(value = "Delete a tag on this entity, returning whether the
tag was found (and deleted)")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
@@ -254,7 +254,7 @@ public interface EntityApi {
@Path("/{entity}/tag/upsert/{tagKey}")
@ApiOperation(value = "Inserts a tag which is a single-key map with the
given key (path parameter) and value (post body), removing any existing tag
matching the key")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
@@ -286,7 +286,7 @@ public interface EntityApi {
value = "Rename an entity"
)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Undefined application or
entity"),
@@ -304,7 +304,7 @@ public interface EntityApi {
response = org.apache.brooklyn.rest.domain.TaskSummary.class
)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 202, message = "Accepted. The entity is
submitted for expunging."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
@@ -476,7 +476,7 @@ public interface EntityApi {
"text/yaml", "text/x-yaml", "application/yaml",
MediaType.APPLICATION_JSON})
@Path("/{entity}/workflows")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application or entity
missing"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java
index 4168c0766f..f3f2c9c35b 100644
---
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java
+++
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java
@@ -96,10 +96,11 @@ public interface EntityConfigApi {
@Path("/{config}")
@ApiOperation(value = "Fetch config value (json)", response = Object.class)
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
+ @ApiResponse(code = 200, message = "OK. The sensor value is
returned."),
+ @ApiResponse(code = 204, message = "No Content. The sensor is
known, but unset."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
- @ApiResponse(code = 404, message = "Could not find application,
entity or config key"),
+ @ApiResponse(code = 404, message = "Application, entity, or config
not found"),
@ApiResponse(code = 500, message = "Internal Server Error")
})
@Produces(MediaType.APPLICATION_JSON)
@@ -128,6 +129,7 @@ public interface EntityConfigApi {
@ApiOperation(value = "Fetch config value (text/plain)", response =
String.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK"),
+ @ApiResponse(code = 204, message = "No Content. The config is
known, but unset."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find application,
entity or config key"),
@@ -156,7 +158,7 @@ public interface EntityConfigApi {
@POST
@ApiOperation(value = "Manually set multiple config values")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find application or
entity"),
@@ -177,7 +179,7 @@ public interface EntityConfigApi {
@Path("/{config}")
@ApiOperation(value = "Manually set a config value")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Could not find application,
entity or config key"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/LogoutApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/LogoutApi.java
index e3cc4e9e7d..6d7937df3e 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/LogoutApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/LogoutApi.java
@@ -33,7 +33,7 @@ public interface LogoutApi {
@POST
@ApiOperation(value = "Logout and clean session")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -56,9 +56,8 @@ public interface LogoutApi {
@Path("/unauthorize")
@ApiOperation(value = "Return UNAUTHORIZED 401 response, but without
disabling the session [deprecated in favour of /logout query parameter]")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
@ApiResponse(code = 400, message = "Bad Request"),
- @ApiResponse(code = 401, message = "Unauthorized"),
+ @ApiResponse(code = 401, message = "Unauthorized. Normal
response."),
@ApiResponse(code = 500, message = "Internal Server Error")
})
Response unAuthorize();
@@ -69,7 +68,7 @@ public interface LogoutApi {
@Path("/{user}")
@ApiOperation(value = "Logout and clean session if matching user logged in
(deprecated; username should now be omitted)")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ScriptApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ScriptApi.java
index f0b11b0764..91bc18cd94 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ScriptApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ScriptApi.java
@@ -48,7 +48,7 @@ public interface ScriptApi {
@ApiOperation(value = "Execute a groovy script",
response = org.apache.brooklyn.rest.domain.SensorSummary.class)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/SensorApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/SensorApi.java
index 5f1970908a..03abc82502 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/SensorApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/SensorApi.java
@@ -91,7 +91,8 @@ public interface SensorApi {
@ApiOperation(value = "Fetch sensor value (json)", response = Object.class)
@Produces({MediaType.APPLICATION_JSON})
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "OK"),
+ @ApiResponse(code = 200, message = "OK. The sensor value is
returned."),
+ @ApiResponse(code = 204, message = "No Content. The sensor is
known, but unset."),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
@@ -142,7 +143,7 @@ public interface SensorApi {
@POST
@ApiOperation(value = "Manually set multiple sensor values")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
@@ -161,7 +162,7 @@ public interface SensorApi {
@Path("/{sensor}")
@ApiOperation(value = "Manually set a sensor value")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
@@ -181,7 +182,7 @@ public interface SensorApi {
@Path("/{sensor}")
@ApiOperation(value = "Manually clear a sensor value")
@ApiResponses(value = {
- @ApiResponse(code = 200, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 404, message = "Application, entity, or sensor
not found"),
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ServerApi.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ServerApi.java
index a805bca22a..d90e32d2c0 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ServerApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/ServerApi.java
@@ -59,7 +59,7 @@ public interface ServerApi {
@Path("/properties/reload")
@ApiOperation(value = "Reload brooklyn.properties")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -71,7 +71,7 @@ public interface ServerApi {
@ApiOperation(value = "Terminate this Brooklyn server instance")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 204, message = "No Content"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -204,7 +204,7 @@ public interface ServerApi {
@ApiOperation(value = "Changes the HA state of this management node")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -229,7 +229,7 @@ public interface ServerApi {
@Path("/ha/states/clear")
@ApiOperation(value = "Clears HA node information for non-master nodes;
active nodes will repopulate and other records will be erased")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -242,7 +242,7 @@ public interface ServerApi {
@ApiOperation(value = "Clears HA node information for a particular
non-master node; other nodes will repopulate and selected node will be erased",
consumes = MediaType.APPLICATION_FORM_URLENCODED)
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -267,7 +267,7 @@ public interface ServerApi {
@ApiOperation(value = "Sets the HA node priority for MASTER failover")
@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
@@ -296,7 +296,7 @@ public interface ServerApi {
@Consumes
@ApiOperation(value = "Imports a persistence export to a file-based store,
moving catalog items, locations and managed applications (merged with the
current persistence).")
@ApiResponses(value = {
- @ApiResponse(code = 201, message = "Accepted"),
+ @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 401, message = "Unauthorized"),
@ApiResponse(code = 500, message = "Internal Server Error")
diff --git
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
index be72f07bd4..cc9b70ed5e 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
@@ -23,11 +23,14 @@ import static
com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
import org.apache.brooklyn.util.text.Strings;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -210,4 +213,16 @@ public class ApiError implements Serializable {
", error=" + error +
'}';
}
+
+ public WebApplicationException throwWebApplicationException() {
+ throw throwWebApplicationException(null);
+ }
+
+ public WebApplicationException throwWebApplicationException(@Nullable
Throwable exception) {
+ throw new WebApplicationException(
+ exception==null ? new Throwable(this.toString()) :
+ message==null ? exception :
+ new PropagatedRuntimeException(message,
exception),
+ this.asJsonResponse());
+ }
}
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
index ba6eda643c..8431c7951c 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.rest.resources;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
+import javax.ws.rs.core.Response.Status;
import org.apache.brooklyn.api.effector.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.mgmt.Task;
@@ -96,18 +97,22 @@ public class EffectorResource extends
AbstractBrooklynRestResource implements Ef
try {
Object result;
+ boolean stillRunning;
if (timeout == null || timeout.isEmpty() ||
"never".equalsIgnoreCase(timeout)) {
result = t.get();
+ stillRunning = false;
} else {
long timeoutMillis = "always".equalsIgnoreCase(timeout) ? 0 :
Time.parseElapsedTime(timeout);
try {
if (timeoutMillis == 0) throw new TimeoutException();
result = t.get(timeoutMillis, TimeUnit.MILLISECONDS);
+ stillRunning = false;
} catch (TimeoutException e) {
result = TaskTransformer.taskSummary(t,
ui.getBaseUriBuilder(), resolving(null), null);
+ stillRunning = true;
}
}
- return
Response.status(Response.Status.ACCEPTED).entity(result).build();
+ return Response.status(stillRunning ? Response.Status.ACCEPTED :
Status.OK).entity(result).build();
} catch (Exception e) {
throw Exceptions.propagate(e);
}
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
index dc5a3714c4..438b0f66ce 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
@@ -21,12 +21,14 @@ package org.apache.brooklyn.rest.resources;
import io.swagger.annotations.ApiParam;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.Callable;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.QueryParam;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.sensor.Sensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.BasicConfigKey;
import org.apache.brooklyn.core.config.Sanitizer;
@@ -44,6 +46,7 @@ import org.apache.brooklyn.rest.transform.ConfigTransformer;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
@@ -191,8 +194,21 @@ public class EntityConfigResource extends
AbstractBrooklynRestResource implement
Entitlements.getEntitlementContext().user(), entity,
ck.getName());
}
- Object value = ((EntityInternal)entity).config().getRaw(ck).orNull();
- return
resolving(value).preferJson(preferJson).asJerseyOutermostReturnValue(true)
+ Maybe<Object> valueM = ((EntityInternal)entity).config().getRaw(ck);
+ if (valueM.isAbsent()) {
+ Set<ConfigKey<?>> configDefinition = ((EntityInternal)
entity).config().findKeysDeclared(x -> x.getName().equals(configKeyName));
+
+ // could do this...
+// // if sensor is defined, but value unavailable, return 424
+// if (sensorInMap) return WebResourceUtils.dependencyFailed("Value
specified but not resolvable.");
+ // cf sensors
+
+ if (!configDefinition.isEmpty()) return
WebResourceUtils.noContent("Value specified but not resolvable.");
+ // if sensor is not defined, return 404
+ throw WebResourceUtils.notFound("Config '%s' not known",
configKeyName);
+
+ }
+ return
resolving(valueM.get()).preferJson(preferJson).asJerseyOutermostReturnValue(true)
.useDisplayHints(useDisplayHints)
.skipResolution(skipResolution)
.suppressIfSecret(ck.getName(), suppressSecrets)
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index e79d037301..25bdacf6dd 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.rest.util.EntityAttributesUtils;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
@@ -120,9 +121,30 @@ public class SensorResource extends
AbstractBrooklynRestResource implements Sens
throw WebResourceUtils.forbidden("User '%s' is not authorized to
see entity '%s' sensor '%s'",
Entitlements.getEntitlementContext().user(), entity,
sensor.getName());
}
-
- Object value = EntityAttributesUtils.tryGetAttribute(entity, sensor);
- return
resolving(value).preferJson(preferJson).asJerseyOutermostReturnValue(true).useDisplayHints(useDisplayHints).raw(raw).context(entity).immediately(true).renderAs(sensor)
+
+ Maybe<?> vm = EntityAttributesUtils.getAttributeMaybe(entity, sensor);
+ if (vm.isAbsent()) {
+ Sensor<?> sensorDefinition = ((EntityInternal)
entity).getMutableEntityType().getSensor(sensorName);
+
+// boolean sensorInMap = ((EntityInternal)
entity).sensors().getAll().keySet().stream().anyMatch(k ->
k.getName().equals(sensorName));
+ // if sensor is defined, but value unavailable, return 424
+
+ // if sensor defined, but not set, retun 204
+ if (vm!=EntityAttributesUtils.SENSOR_NOT_SET) {
+// // could support 424, but that would probably be done below;
this is raw, so any error is low level
+// return WebResourceUtils.dependencyFailed("Value specified
but not resolvable.");
+ vm.get();
+ }
+
+ if (sensorDefinition!=null &&
vm==EntityAttributesUtils.SENSOR_NOT_SET) {
+ return WebResourceUtils.noContent("No value for sensor");
+ }
+
+ // if sensor is not defined, return 404
+ throw WebResourceUtils.notFound("Sensor '%s' not known",
sensorName);
+
+ }
+ return
resolving(vm.get()).preferJson(preferJson).asJerseyOutermostReturnValue(true).useDisplayHints(useDisplayHints).raw(raw).context(entity).immediately(true).renderAs(sensor)
.suppressIfSecret(sensorName, suppressSecrets).resolve();
}
@@ -190,6 +212,7 @@ public class SensorResource extends
AbstractBrooklynRestResource implements Sens
if (log.isDebugEnabled())
log.debug("REST user "+Entitlements.getEntitlementContext()+"
deleting sensor "+sensorName);
((EntityInternal)entity).sensors().remove(sensor);
+ ((EntityInternal)entity).getMutableEntityType().removeSensor(sensor);
}
}
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/EntityAttributesUtils.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/EntityAttributesUtils.java
index 68a266e4f3..6649ba4105 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/EntityAttributesUtils.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/EntityAttributesUtils.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.rest.util;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,4 +47,24 @@ public class EntityAttributesUtils {
}
return attribute;
}
+
+ public static final Maybe SENSOR_NOT_SET = Maybe.absent("Sensor is unset");
+
+ /** returns {@link #SENSOR_NOT_SET} if not defined; equals check can be
done to compare that with a different error */
+ public static <T> Maybe<T> getAttributeMaybe(Entity entity,
AttributeSensor<T> sensor) {
+ T attribute = null;
+ try {
+ attribute = entity.getAttribute(sensor);
+ if (attribute==null) {
+ if (!entity.sensors().getAll().keySet().stream().anyMatch(sn
-> sn.getName().equals(sensor.getName()))) {
+ return SENSOR_NOT_SET;
+ }
+ }
+ } catch (Exception exception) {
+ Exceptions.propagateIfFatal(exception);
+ LOG.warn("Error retrieving sensor " + sensor + " for " + entity +
" (ignoring): " + exception);
+ return Maybe.absent(exception);
+ }
+ return Maybe.ofAllowingNull(attribute);
+ }
}
diff --git
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
index cef552b4e3..090ebd9dea 100644
---
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
+++
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
@@ -86,11 +86,7 @@ public class WebResourceUtils {
: ApiError.builder().message(fullMsg==null ? "" : fullMsg))
.errorCode(status).build();
// including a Throwable is the only way to include a message with the
WebApplicationException - ugly!
- throw new WebApplicationException(
- exception==null ? new Throwable(apiError.toString()) :
- suppliedMsg==null ? exception :
- new PropagatedRuntimeException(suppliedMsg, exception),
- apiError.asJsonResponse());
+ throw apiError.throwWebApplicationException(exception);
}
/** @throws WebApplicationException With code 500 internal server error */
@@ -133,6 +129,14 @@ public class WebResourceUtils {
return
throwWebApplicationException(Response.Status.PRECONDITION_FAILED, format, args);
}
+ public static WebApplicationException dependencyFailed(String message) {
+ return
ApiError.builder().message(message).errorCode(424).build().throwWebApplicationException();
+ }
+
+ public static WebApplicationException noContent(String message) {
+ return
ApiError.builder().message(message).errorCode(204).build().throwWebApplicationException();
+ }
+
public final static Map<String,com.google.common.net.MediaType>
IMAGE_FORMAT_MIME_TYPES = ImmutableMap.<String,
com.google.common.net.MediaType>builder()
.put("jpg", com.google.common.net.MediaType.JPEG)
.put("jpeg", com.google.common.net.MediaType.JPEG)
diff --git
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
index 6c2ac33d91..0ffb66eeae 100644
---
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
+++
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/ApplicationResourceTest.java
@@ -609,7 +609,7 @@ public class ApplicationResourceTest extends
BrooklynRestResourceTest {
.type(MediaType.APPLICATION_JSON_TYPE)
.post(ImmutableMap.of("param1", "foo", "param2", 4));
- assertEquals(response.getStatus(),
Response.Status.ACCEPTED.getStatusCode());
+ assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
String result = response.readEntity(String.class);
assertEquals(result, "foo4");
@@ -625,7 +625,7 @@ public class ApplicationResourceTest extends
BrooklynRestResourceTest {
.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
.post(data);
- assertEquals(response.getStatus(),
Response.Status.ACCEPTED.getStatusCode());
+ assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
String result = response.readEntity(String.class);
assertEquals(result, "foo4");
diff --git
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/EffectorResourceTest.java
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/EffectorResourceTest.java
index a8d3cdf680..dba54257cb 100644
---
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/EffectorResourceTest.java
+++
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/EffectorResourceTest.java
@@ -76,7 +76,7 @@ public class EffectorResourceTest extends
BrooklynRestResourceTest {
Response response = client().path(path)
.accept(MediaType.APPLICATION_JSON)
.post(null);
- assertEquals(response.getStatus(), 202);
+ assertEquals(response.getStatus(), 200);
Asserts.succeedsEventually(() ->
assertTrue(entity.getCallHistory().contains("myEffector")));
}
@@ -100,7 +100,7 @@ public class EffectorResourceTest extends
BrooklynRestResourceTest {
.accept(MediaType.APPLICATION_JSON)
.header("Content-Type", MediaType.APPLICATION_JSON)
.post("{\"arg\": \"myval\"}");
- assertEquals(response.getStatus(), 202);
+ assertEquals(response.getStatus(), 200);
String responseBody = response.readEntity(String.class);
assertTrue(entity.getCallHistory().contains("identityEffector"));
@@ -118,7 +118,7 @@ public class EffectorResourceTest extends
BrooklynRestResourceTest {
.header("Content-Type", MediaType.APPLICATION_JSON)
.post("{\"duration\": \"50ms\"}");
Duration runDuration = Duration.of(stopwatch);
- assertEquals(response.getStatus(), 202);
+ assertEquals(response.getStatus(), 200);
assertTrue(entity.getCallHistory().contains("sleepEffector"));
assertTrue(runDuration.isLongerThan(Duration.millis(40)),
"runDuration="+runDuration);
diff --git
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceTest.java
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceTest.java
index 23dbdcb79b..ac4d87e28f 100644
---
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceTest.java
+++
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/SensorResourceTest.java
@@ -313,8 +313,11 @@ public class SensorResourceTest extends
BrooklynRestResourceTest {
.delete();
assertEquals(response.getStatus(),
Response.Status.NO_CONTENT.getStatusCode());
- String value = client().path(SENSORS_ENDPOINT + "/" +
SENSOR_NAME).accept(MediaType.TEXT_PLAIN_TYPE).get(String.class);
- assertEquals(value, "");
+ Response r = client().path(SENSORS_ENDPOINT + "/" +
SENSOR_NAME).accept(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(r.getStatus(), 404); // not defined
+
+ r = client().path(SENSORS_ENDPOINT + "/" +
RestMockSimpleEntity.SAMPLE_SENSOR.getName()).accept(MediaType.TEXT_PLAIN_TYPE).get();
+ assertEquals(r.getStatus(), 204); // defined but no value
} finally { addAmphibianSensor(entity); }
}
diff --git
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
index 4d1d3b6821..aeab1dd0fc 100644
---
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
+++
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/test/entity/brooklynnode/DeployBlueprintTest.java
@@ -81,8 +81,9 @@ public class DeployBlueprintTest extends
BrooklynRestResourceTest {
List<String> appType = parseJsonList(apps, ImmutableList.of("spec",
"type"), String.class);
assertEquals(appType,
ImmutableList.of(BasicApplication.class.getName()));
- String status =
HttpTool.getContentUnsafe(getEndpointAddress()+"/applications/"+id+"/entities/"+id+"/sensors/service.status");
- log.info("STATUS: "+status);
+ // status was empty, at least for a short while; now throws 404
+// String status =
HttpTool.getContentUnsafe(getEndpointAddress()+"/applications/"+id+"/entities/"+id+"/sensors/service.status");
+// log.info("STATUS: "+status);
}
private <T> List<T> parseJsonList(String json, List<String> elements,
Class<T> clazz) {