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 2015/03/19 15:07:28 UTC

[10/19] incubator-brooklyn git commit: Tests for the HA HOT state check for resource access

Tests for the HA HOT state check for resource access


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

Branch: refs/heads/master
Commit: cc95fa72092dd5d1be622bcac4769c9934821239
Parents: f2460a6
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Mar 5 15:07:53 2015 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Mar 19 16:01:29 2015 +0200

----------------------------------------------------------------------
 .../brooklyn/launcher/BrooklynWebServer.java    |   7 +-
 .../rest/filter/HaStateCheckResourceFilter.java |   3 -
 .../rest/util/ManagementContextProvider.java    |  33 ++++
 .../brooklyn/rest/BrooklynRestApiLauncher.java  |   4 +
 .../brooklyn/rest/resources/HaHotCheckTest.java |  82 ++++++++
 .../mocks/HighAvailabilityManagerMock.java      | 121 ++++++++++++
 .../testing/mocks/ManagementContextMock.java    | 189 +++++++++++++++++++
 .../rest/util/HaHotStateCheckClassResource.java |  38 ++++
 .../rest/util/HaHotStateCheckResource.java      |  44 +++++
 9 files changed, 517 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
index d469152..aaac004 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
@@ -60,9 +60,11 @@ import brooklyn.rest.BrooklynRestApi;
 import brooklyn.rest.BrooklynWebConfig;
 import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
 import brooklyn.rest.filter.HaMasterCheckFilter;
+import brooklyn.rest.filter.HaStateCheckResourceFilter;
 import brooklyn.rest.filter.LoggingFilter;
 import brooklyn.rest.filter.NoCacheFilter;
 import brooklyn.rest.filter.RequestTaggingFilter;
+import brooklyn.rest.util.ManagementContextProvider;
 import brooklyn.util.BrooklynNetworkUtils;
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.collections.MutableMap;
@@ -322,7 +324,7 @@ public class BrooklynWebServer {
         config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName());
         config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, ImmutableList.of(GZIPContentEncodingFilter.class, NoCacheFilter.class));
         // Checks if appropriate request given HA status
-        config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, brooklyn.rest.filter.HaStateCheckResourceFilter.class.getName());
+        config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, HaStateCheckResourceFilter.class.getName());
         // configure to match empty path, or any thing which looks like a file path with /assets/ and extension html, css, js, or png
         // and treat that as static content
         config.getProperties().put(ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX, "(/?|[^?]*/assets/[^?]+\\.[A-Za-z0-9_]+)");
@@ -332,6 +334,9 @@ public class BrooklynWebServer {
         FilterHolder filterHolder = new FilterHolder(new ServletContainer(config));
 
         context.addFilter(filterHolder, "/*", EnumSet.allOf(DispatcherType.class));
+
+        ManagementContext mgmt = (ManagementContext) context.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
+        config.getSingletons().add(new ManagementContextProvider(mgmt));
     }
 
     ContextHandlerCollectionHotSwappable handlers = new ContextHandlerCollectionHotSwappable();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/main/java/brooklyn/rest/filter/HaStateCheckResourceFilter.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaStateCheckResourceFilter.java b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaStateCheckResourceFilter.java
index d894252..86a5b9b 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/filter/HaStateCheckResourceFilter.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/filter/HaStateCheckResourceFilter.java
@@ -22,13 +22,11 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import javax.servlet.ServletContext;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import brooklyn.config.BrooklynServiceAttributes;
 import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ha.ManagementNodeState;
@@ -110,7 +108,6 @@ public class HaStateCheckResourceFilter implements ResourceFilterFactory {
 
     @Override
     public List<ResourceFilter> create(AbstractMethod am) {
-        ManagementContext mgmt = (ManagementContext)servletContext.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
         return Collections.<ResourceFilter>singletonList(new MethodFilter(am, mgmt));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/main/java/brooklyn/rest/util/ManagementContextProvider.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/ManagementContextProvider.java b/usage/rest-server/src/main/java/brooklyn/rest/util/ManagementContextProvider.java
new file mode 100644
index 0000000..f964000
--- /dev/null
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/ManagementContextProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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.rest.util;
+
+import javax.ws.rs.core.Context;
+
+import brooklyn.management.ManagementContext;
+
+import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
+
+public class ManagementContextProvider extends SingletonTypeInjectableProvider<Context, ManagementContext> {
+
+    public ManagementContextProvider(ManagementContext instance) {
+        super(ManagementContext.class, instance);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java b/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
index 102f7dd..db54b40 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
@@ -54,6 +54,7 @@ import brooklyn.rest.filter.NoCacheFilter;
 import brooklyn.rest.filter.RequestTaggingFilter;
 import brooklyn.rest.security.provider.AnyoneSecurityProvider;
 import brooklyn.rest.security.provider.SecurityProvider;
+import brooklyn.rest.util.ManagementContextProvider;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.net.Networking;
 import brooklyn.util.text.WildcardGlobs;
@@ -339,6 +340,9 @@ public class BrooklynRestApiLauncher {
         // finally create this as a _filter_ which falls through to a web app or something (optionally)
         FilterHolder filterHolder = new FilterHolder(new ServletContainer(config));
         context.addFilter(filterHolder, "/*", EnumSet.allOf(DispatcherType.class));
+
+        ManagementContext mgmt = (ManagementContext) context.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
+        config.getSingletons().add(new ManagementContextProvider(mgmt));
     }
 
     private static void installBrooklynFilters(ServletContextHandler context, List<Class<? extends Filter>> filters) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/resources/HaHotCheckTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/HaHotCheckTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/HaHotCheckTest.java
new file mode 100644
index 0000000..b8e54ef
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/HaHotCheckTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.rest.resources;
+
+import static org.testng.Assert.assertEquals;
+
+import javax.ws.rs.core.MediaType;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.management.ha.HighAvailabilityManager;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.rest.filter.HaHotCheckResourceFilter;
+import brooklyn.rest.testing.BrooklynRestResourceTest;
+import brooklyn.rest.testing.mocks.ManagementContextMock;
+import brooklyn.rest.util.HaHotStateCheckClassResource;
+import brooklyn.rest.util.HaHotStateCheckResource;
+import brooklyn.rest.util.ManagementContextProvider;
+
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.core.ResourceConfig;
+
+public class HaHotCheckTest extends BrooklynRestResourceTest {
+
+    private ManagementContextMock mgmtMock;
+
+    @Override
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() throws Exception {
+        mgmtMock = new ManagementContextMock();
+        super.setUp();
+    }
+
+    @Override
+    protected void addBrooklynResources() {
+        config.getSingletons().add(new ManagementContextProvider(mgmtMock));
+        config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, HaHotCheckResourceFilter.class.getName());
+        addResource(new HaHotStateCheckResource());
+        addResource(new HaHotStateCheckClassResource());
+    }
+
+    @Test
+    public void testHaCheck() throws Exception {
+        HighAvailabilityManager ha = mgmtMock.getHighAvailabilityManager();
+        assertEquals(ha.getNodeState(), ManagementNodeState.MASTER);
+        testResourceFetch("/ha/method/ok", 200);
+        testResourceFetch("/ha/method/fail", 200);
+        testResourceFetch("/ha/class/fail", 200);
+
+        mgmtMock.setState(ManagementNodeState.STANDBY);
+        assertEquals(ha.getNodeState(), ManagementNodeState.STANDBY);
+
+        testResourceFetch("/ha/method/ok", 200);
+        testResourceFetch("/ha/method/fail", 403);
+        testResourceFetch("/ha/class/fail", 403);
+    }
+
+    private void testResourceFetch(String resource, int code) {
+        ClientResponse response = client().resource(resource)
+                .accept(MediaType.APPLICATION_JSON_TYPE)
+                .get(ClientResponse.class);
+        assertEquals(response.getStatus(), code);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/HighAvailabilityManagerMock.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/HighAvailabilityManagerMock.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/HighAvailabilityManagerMock.java
new file mode 100644
index 0000000..abc8e00
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/HighAvailabilityManagerMock.java
@@ -0,0 +1,121 @@
+/*
+ * 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.rest.testing.mocks;
+
+import java.util.Map;
+
+import brooklyn.management.ha.HighAvailabilityManager;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.ha.ManagementPlaneSyncRecord;
+import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+
+public class HighAvailabilityManagerMock implements HighAvailabilityManager {
+
+    private ManagementNodeState state = ManagementNodeState.MASTER;
+
+    public void setState(ManagementNodeState state) {
+        this.state = state;
+    }
+
+    private static RuntimeException fail() {
+        throw new UnsupportedOperationException("Mocked method not implemented");
+    }
+
+    @Override
+    public ManagementNodeState getNodeState() {
+        return state;
+    }
+
+    @Override
+    public long getLastStateChange() {
+        return 0;
+    }
+
+    @Override
+    public HighAvailabilityManager setPersister(ManagementPlaneSyncRecordPersister persister) {
+        throw fail();
+    }
+
+    @Override
+    public void disabled() {
+        throw fail();
+    }
+
+    @Override
+    public boolean isRunning() {
+        throw fail();
+    }
+
+    @Override
+    public void start(HighAvailabilityMode startMode) {
+        throw fail();
+    }
+
+    @Override
+    public void stop() {
+        throw fail();
+    }
+
+    @Override
+    public void changeMode(HighAvailabilityMode mode) {
+        throw fail();
+    }
+
+    @Override
+    public void setPriority(long priority) {
+        throw fail();
+    }
+
+    @Override
+    public long getPriority() {
+        throw fail();
+    }
+
+    @Override
+    public void publishClearNonMaster() {
+        throw fail();
+    }
+
+    @Override
+    public ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord() {
+        throw fail();
+    }
+
+    @Override
+    public ManagementPlaneSyncRecord getManagementPlaneSyncState() {
+        throw fail();
+    }
+
+    @Override
+    public ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean useLocalKnowledgeForThisNode) {
+        throw fail();
+    }
+
+    @Override
+    public ManagementPlaneSyncRecordPersister getPersister() {
+        throw fail();
+    }
+
+    @Override
+    public Map<String, Object> getMetrics() {
+        throw fail();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
new file mode 100644
index 0000000..6a29fed
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/ManagementContextMock.java
@@ -0,0 +1,189 @@
+/*
+ * 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.rest.testing.mocks;
+
+import java.net.URI;
+import java.util.Collection;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.catalog.BrooklynCatalog;
+import brooklyn.config.StringConfigMap;
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.drivers.EntityDriverManager;
+import brooklyn.entity.drivers.downloads.DownloadResolverManager;
+import brooklyn.entity.rebind.RebindManager;
+import brooklyn.location.LocationRegistry;
+import brooklyn.management.AccessController;
+import brooklyn.management.EntityManager;
+import brooklyn.management.ExecutionContext;
+import brooklyn.management.ExecutionManager;
+import brooklyn.management.LocationManager;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.SubscriptionContext;
+import brooklyn.management.SubscriptionManager;
+import brooklyn.management.entitlement.EntitlementManager;
+import brooklyn.management.ha.HighAvailabilityManager;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.util.guava.Maybe;
+
+public class ManagementContextMock implements ManagementContext {
+    private HighAvailabilityManagerMock haMock = new HighAvailabilityManagerMock();
+
+    public void setState(ManagementNodeState state) {
+        haMock.setState(state);
+    }
+
+    private static RuntimeException fail() {
+        throw new UnsupportedOperationException("Mocked method not implemented");
+    }
+
+    @Override
+    public HighAvailabilityManager getHighAvailabilityManager() {
+        return haMock;
+    }
+
+    @Override
+    public String getManagementPlaneId() {
+        throw fail();
+    }
+
+    @Override
+    public String getManagementNodeId() {
+        throw fail();
+    }
+
+    @Override
+    public Maybe<URI> getManagementNodeUri() {
+        throw fail();
+    }
+
+    @Override
+    public Collection<Application> getApplications() {
+        throw fail();
+    }
+
+    @Override
+    public EntityManager getEntityManager() {
+        throw fail();
+    }
+
+    @Override
+    public ExecutionManager getExecutionManager() {
+        throw fail();
+    }
+
+    @Override
+    public ExecutionContext getServerExecutionContext() {
+        throw fail();
+    }
+
+    @Override
+    public EntityDriverManager getEntityDriverManager() {
+        throw fail();
+    }
+
+    @Override
+    public DownloadResolverManager getEntityDownloadsManager() {
+        throw fail();
+    }
+
+    @Override
+    public SubscriptionManager getSubscriptionManager() {
+        throw fail();
+    }
+
+    @Override
+    public ExecutionContext getExecutionContext(Entity entity) {
+        throw fail();
+    }
+
+    @Override
+    public SubscriptionContext getSubscriptionContext(Entity entity) {
+        throw fail();
+    }
+
+    @Override
+    public RebindManager getRebindManager() {
+        throw fail();
+    }
+
+    @Override
+    public StringConfigMap getConfig() {
+        throw fail();
+    }
+
+    @Override
+    public boolean isRunning() {
+        throw fail();
+    }
+
+    @Override
+    public LocationRegistry getLocationRegistry() {
+        throw fail();
+    }
+
+    @Override
+    public BrooklynCatalog getCatalog() {
+        throw fail();
+    }
+
+    @Override
+    public LocationManager getLocationManager() {
+        throw fail();
+    }
+
+    @Override
+    public AccessController getAccessController() {
+        throw fail();
+    }
+
+    @Override
+    public void reloadBrooklynProperties() {
+        throw fail();
+
+    }
+
+    @Override
+    public void addPropertiesReloadListener(PropertiesReloadListener listener) {
+        throw fail();
+
+    }
+
+    @Override
+    public void removePropertiesReloadListener(PropertiesReloadListener listener) {
+        throw fail();
+    }
+
+    @Override
+    public EntitlementManager getEntitlementManager() {
+        throw fail();
+    }
+
+    @Override
+    public BrooklynObject lookup(String id) {
+        throw fail();
+    }
+
+    @Override
+    public <T extends BrooklynObject> T lookup(String id, Class<T> type) {
+        throw fail();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckClassResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckClassResource.java b/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckClassResource.java
new file mode 100644
index 0000000..0a288a5
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckClassResource.java
@@ -0,0 +1,38 @@
+/*
+ * 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.rest.util;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import brooklyn.rest.filter.HaHotStateRequired;
+
+@Path("/ha/class")
+@Produces(MediaType.APPLICATION_JSON)
+@HaHotStateRequired
+public class HaHotStateCheckClassResource {
+
+    @GET
+    @Path("fail")
+    public String fail() {
+        return "FAIL";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc95fa72/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckResource.java b/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckResource.java
new file mode 100644
index 0000000..86a8ee3
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/util/HaHotStateCheckResource.java
@@ -0,0 +1,44 @@
+/*
+ * 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.rest.util;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import brooklyn.rest.filter.HaHotStateRequired;
+
+@Path("/ha/method")
+@Produces(MediaType.APPLICATION_JSON)
+public class HaHotStateCheckResource {
+
+    @GET
+    @Path("ok")
+    public String ok() {
+        return "OK";
+    }
+
+    @GET
+    @Path("fail")
+    @HaHotStateRequired
+    public String fail() {
+        return "FAIL";
+    }
+}