Integration tests for resource accessibility with regard to the HA state

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

Branch: refs/heads/master
Commit: 5a757750783b1f6f79068e8d6f6ebb7d1121ee83
Parents: 86cf35f
Author: Svetoslav Neykov <[email protected]>
Authored: Fri Mar 6 14:02:31 2015 +0200
Committer: Svetoslav Neykov <[email protected]>
Committed: Thu Mar 19 16:01:29 2015 +0200

----------------------------------------------------------------------
 .../brooklyn/rest/BrooklynRestApiLauncher.java  |  12 +-
 .../test/java/brooklyn/rest/HaHotCheckTest.java |  82 +++++++
 .../brooklyn/rest/HaMasterCheckFilterTest.java  | 221 +++++++++++++++++++
 .../brooklyn/rest/resources/HaHotCheckTest.java |  82 -------
 4 files changed, 312 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5a757750/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 5baf2d2..cb7b29d 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/BrooklynRestApiLauncher.java
@@ -104,6 +104,7 @@ public class BrooklynRestApiLauncher {
     private ManagementContext mgmt;
     private ContextHandler customContext;
     private boolean deployJsgui = true;
+    private boolean disableHighAvailability = true;
 
     protected BrooklynRestApiLauncher() {}
 
@@ -151,6 +152,11 @@ public class BrooklynRestApiLauncher {
         this.deployJsgui = false;
         return this;
     }
+    
+    public BrooklynRestApiLauncher disableHighAvailability(boolean value) {
+        this.disableHighAvailability = value;
+        return this;
+    }
 
     public Server start() {
         if (this.mgmt == null) {
@@ -198,7 +204,7 @@ public class BrooklynRestApiLauncher {
             ((LocalManagementContext) 
mgmt).setBaseClassPathForScanning(ClasspathHelper.forJavaClassPath());
         }
 
-        return startServer(mgmt, context, summary);
+        return startServer(mgmt, context, summary, disableHighAvailability);
     }
 
     private ContextHandler filterContextHandler(ManagementContext mgmt) {
@@ -254,7 +260,7 @@ public class BrooklynRestApiLauncher {
 
     /** starts a server, on all NICs if security is configured,
      * otherwise (no security) only on loopback interface */
-    public static Server startServer(ManagementContext mgmt, ContextHandler 
context, String summary) {
+    public static Server startServer(ManagementContext mgmt, ContextHandler 
context, String summary, boolean disableHighAvailability) {
         // TODO this repeats code in BrooklynLauncher / WebServer. should 
merge the two paths.
         boolean secure = mgmt != null && 
!BrooklynWebConfig.hasNoSecurityOptions(mgmt.getConfig());
         if (secure) {
@@ -266,7 +272,7 @@ public class BrooklynRestApiLauncher {
                 
((BrooklynProperties)mgmt.getConfig()).put(BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME,
 AnyoneSecurityProvider.class.getName());
             }
         }
-        if (mgmt != null)
+        if (mgmt != null && disableHighAvailability)
             mgmt.getHighAvailabilityManager().disabled();
         InetSocketAddress bindLocation = new InetSocketAddress(
                 secure ? Networking.ANY_NIC : Networking.LOOPBACK,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5a757750/usage/rest-server/src/test/java/brooklyn/rest/HaHotCheckTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/HaHotCheckTest.java 
b/usage/rest-server/src/test/java/brooklyn/rest/HaHotCheckTest.java
new file mode 100644
index 0000000..224cda6
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/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;
+
+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() {
+        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/5a757750/usage/rest-server/src/test/java/brooklyn/rest/HaMasterCheckFilterTest.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-server/src/test/java/brooklyn/rest/HaMasterCheckFilterTest.java 
b/usage/rest-server/src/test/java/brooklyn/rest/HaMasterCheckFilterTest.java
new file mode 100644
index 0000000..55452c8
--- /dev/null
+++ b/usage/rest-server/src/test/java/brooklyn/rest/HaMasterCheckFilterTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import io.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+
+import java.io.File;
+import java.net.URI;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.http.client.HttpClient;
+import org.eclipse.jetty.server.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicApplication;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.management.EntityManager;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.rest.security.provider.AnyoneSecurityProvider;
+import brooklyn.test.Asserts;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.os.Os;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+
+public class HaMasterCheckFilterTest extends 
BrooklynRestApiLauncherTestFixture {
+    private static final Logger LOG = 
LoggerFactory.getLogger(HaMasterCheckFilterTest.class);
+    private static final Duration TIMEOUT = Duration.THIRTY_SECONDS;
+
+    private File mementoDir;
+    private ManagementContext writeMgmt;
+    private ManagementContext readMgmt;
+    private String appId;
+    private Server server;
+    private HttpClient client;
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        server.stop();
+        Entities.destroyAll(writeMgmt);
+        Entities.destroyAll(readMgmt);
+        Os.deleteRecursively(mementoDir);
+    }
+
+    @Test(groups = "Integration")
+    public void testEntitiesExistOnMasterPromotion() throws Exception {
+        initHaCluster(HighAvailabilityMode.AUTO, HighAvailabilityMode.AUTO);
+        stopWriteNode();
+        assertEntityExists(new ReturnCodeCheck());
+        assertReadIsMaster();
+    }
+
+    @Test(groups = "Integration")
+    public void testEntitiesExistOnHotStandbyAndPromotion() throws Exception {
+        initHaCluster(HighAvailabilityMode.AUTO, 
HighAvailabilityMode.HOT_STANDBY);
+        assertEntityExists(new ReturnCodeCheck());
+        stopWriteNode();
+        assertEntityExists(new ReturnCodeAndNodeState());
+        assertReadIsMaster();
+    }
+
+    @Test(groups = "Integration")
+    public void testEntitiesExistOnHotBackup() throws Exception {
+        initHaCluster(HighAvailabilityMode.AUTO, 
HighAvailabilityMode.HOT_BACKUP);
+        Asserts.continually(
+                ImmutableMap.<String,Object>of(
+                        "timeout", Duration.THIRTY_SECONDS,
+                        "period", Duration.ZERO),
+                new ReturnCodeSupplier(),
+                Predicates.or(Predicates.equalTo(200), 
Predicates.equalTo(403)));
+    }
+
+    private HttpClient getClient(Server server) {
+        HttpClient client = HttpTool.httpClientBuilder()
+                .uri(getBaseUri(server))
+                .build();
+        return client;
+    }
+
+    private int getAppResponseCode() {
+        HttpToolResponse response = HttpTool.httpGet(
+                client, URI.create(getBaseUri(server) + "/v1/applications/" + 
appId),
+                ImmutableMap.<String,String>of());
+        return response.getResponseCode();
+    }
+
+    private String createApp(ManagementContext mgmt) {
+        EntityManager entityMgr = mgmt.getEntityManager();
+        Entity app = 
entityMgr.createEntity(EntitySpec.create(BasicApplication.class));
+        entityMgr.manage(app);
+        return app.getId();
+    }
+
+    private ManagementContext createManagementContext(File mementoDir, 
HighAvailabilityMode mode) {
+        ManagementContext mgmt = 
RebindTestUtils.managementContextBuilder(mementoDir, 
getClass().getClassLoader())
+                .persistPeriodMillis(1)
+                .forLive(false)
+                .emptyCatalog(true)
+                .buildUnstarted();
+
+        mgmt.getHighAvailabilityManager().start(mode);
+
+        new BrooklynCampPlatformLauncherNoServer()
+            .useManagementContext(mgmt)
+            .launch();
+
+        return mgmt;
+    }
+
+    private void initHaCluster(HighAvailabilityMode writeMode, 
HighAvailabilityMode readMode) throws InterruptedException, TimeoutException {
+        mementoDir = Os.newTempDir(getClass());
+
+        writeMgmt = createManagementContext(mementoDir, writeMode);
+        appId = createApp(writeMgmt);
+        
writeMgmt.getRebindManager().getPersister().waitForWritesCompleted(TIMEOUT);
+
+        readMgmt = createManagementContext(mementoDir, readMode);
+
+        server = useServerForTest(BrooklynRestApiLauncher.launcher()
+                .managementContext(readMgmt)
+                .securityProvider(AnyoneSecurityProvider.class)
+                .forceUseOfDefaultCatalogWithJavaClassPath(true)
+                .withoutJsgui()
+                .disableHighAvailability(false)
+                .start());
+        client = getClient(server);
+    }
+
+    private void assertEntityExists(Callable<Boolean> c) {
+        assertTrue(Asserts.succeedsEventually(c), "Unexpected code returned");
+    }
+
+    private void assertReadIsMaster() {
+//        Asserts.eventually(new NodeStateSupplier(readMgmt), 
Predicates.equalTo(ManagementNodeState.MASTER));
+        assertEquals(readMgmt.getHighAvailabilityManager().getNodeState(), 
ManagementNodeState.MASTER);
+    }
+
+    private void stopWriteNode() {
+        writeMgmt.getHighAvailabilityManager().stop();
+    }
+
+    private class ReturnCodeCheck implements Callable<Boolean> {
+        @Override
+        public Boolean call() {
+            int retCode = getAppResponseCode();
+            if (retCode == 200) {
+                return true;
+            } else if (retCode == 403) {
+                throw new RuntimeException("Not ready, response " + retCode);
+            } else {
+                LOG.error("Unexpected return code " + retCode);
+                return false;
+            }
+        }
+    }
+
+    private class ReturnCodeAndNodeState extends ReturnCodeCheck {
+        @Override
+        public Boolean call() {
+            Boolean ret = super.call();
+            if (ret) {
+                ManagementNodeState state = 
readMgmt.getHighAvailabilityManager().getNodeState();
+                if (state != ManagementNodeState.MASTER) {
+                    throw new RuntimeException("Not master yet " + state);
+                }
+            }
+            return ret;
+        }
+    }
+
+    private class ReturnCodeSupplier implements Supplier<Integer> {
+        @Override
+        public Integer get() {
+            return getAppResponseCode();
+        }
+    }
+
+    private static class NodeStateSupplier implements 
Supplier<ManagementNodeState> {
+        private ManagementContext node;
+        public NodeStateSupplier(ManagementContext node) {
+            this.node = node;
+        }
+
+        @Override
+        public ManagementNodeState get() {
+            return node.getHighAvailabilityManager().getNodeState();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5a757750/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
deleted file mode 100644
index b8e54ef..0000000
--- 
a/usage/rest-server/src/test/java/brooklyn/rest/resources/HaHotCheckTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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);
-    }
-
-}

Reply via email to