| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.brooklyn.entity.proxy.nginx; |
| |
| import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEquals; |
| import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEventuallyEquals; |
| import static org.testng.Assert.assertFalse; |
| import static org.testng.Assert.assertNotEquals; |
| import static org.testng.Assert.assertTrue; |
| |
| import java.util.Map; |
| |
| import org.apache.brooklyn.api.entity.Entity; |
| import org.apache.brooklyn.api.entity.EntitySpec; |
| import org.apache.brooklyn.api.location.Location; |
| import org.apache.brooklyn.core.entity.EntityAsserts; |
| import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport; |
| import org.apache.brooklyn.core.test.entity.TestEntity; |
| import org.apache.brooklyn.entity.group.DynamicCluster; |
| import org.apache.brooklyn.entity.software.base.SoftwareProcess; |
| import org.apache.brooklyn.entity.webapp.JavaWebAppService; |
| import org.apache.brooklyn.entity.webapp.WebAppService; |
| import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server; |
| import org.apache.brooklyn.test.Asserts; |
| import org.apache.brooklyn.test.HttpTestUtils; |
| import org.apache.brooklyn.test.WebAppMonitor; |
| import org.apache.brooklyn.test.support.TestResourceUnavailableException; |
| import org.apache.brooklyn.util.time.Duration; |
| import org.apache.brooklyn.util.time.Time; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.testng.annotations.BeforeMethod; |
| import org.testng.annotations.Test; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Iterables; |
| /** |
| * Test the operation of the {@link NginxController} class. |
| */ |
| public class NginxIntegrationTest extends BrooklynAppLiveTestSupport { |
| private static final Logger log = LoggerFactory.getLogger(NginxIntegrationTest.class); |
| |
| private NginxController nginx; |
| private DynamicCluster serverPool; |
| private Location localLoc; |
| |
| @BeforeMethod(alwaysRun=true) |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| localLoc = mgmt.getLocationRegistry().getLocationManaged("localhost"); |
| } |
| |
| public String getTestWar() { |
| TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war"); |
| return "classpath://hello-world.war"; |
| } |
| |
| /** |
| * Test that the Nginx proxy starts up and sets SERVICE_UP correctly. |
| */ |
| @Test(groups = "Integration") |
| public void testWhenNoServersReturns404() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure("initialSize", 0) |
| .configure("memberSpec", EntitySpec.create(TestEntity.class))); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost")); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| EntityAsserts.assertAttributeEqualsEventually(nginx, SoftwareProcess.SERVICE_UP, true); |
| assertHttpStatusCodeEventuallyEquals(nginx.getAttribute(NginxController.ROOT_URL), 404); |
| } |
| |
| @Test(groups = "Integration") |
| public void testRestart() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure("initialSize", 0) |
| .configure("memberSpec", EntitySpec.create(TestEntity.class))); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost")); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| nginx.restart(); |
| |
| EntityAsserts.assertAttributeEqualsEventually(nginx, SoftwareProcess.SERVICE_UP, true); |
| assertHttpStatusCodeEventuallyEquals(nginx.getAttribute(NginxController.ROOT_URL), 404); |
| } |
| |
| /** |
| * Test that the Nginx proxy starts up and sets SERVICE_UP correctly. |
| */ |
| @Test(groups = "Integration") |
| public void testCanStartupAndShutdown() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class)) |
| .configure("initialSize", 1) |
| .configure(JavaWebAppService.ROOT_WAR, getTestWar())); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("portNumberSensor", WebAppService.HTTP_PORT)); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| // App-servers and nginx has started |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| for (Entity member : serverPool.getMembers()) { |
| assertTrue(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| assertTrue(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| }}); |
| |
| // URLs reachable |
| assertHttpStatusCodeEventuallyEquals(nginx.getAttribute(NginxController.ROOT_URL), 200); |
| for (Entity member : serverPool.getMembers()) { |
| assertHttpStatusCodeEventuallyEquals(member.getAttribute(WebAppService.ROOT_URL), 200); |
| } |
| |
| app.stop(); |
| |
| // Services have stopped |
| assertFalse(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| assertFalse(serverPool.getAttribute(SoftwareProcess.SERVICE_UP)); |
| for (Entity member : serverPool.getMembers()) { |
| assertFalse(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| } |
| |
| /** |
| * Test that the Nginx proxy starts up and sets SERVICE_UP correctly using the config file template. |
| */ |
| @Test(groups = "Integration") |
| public void testCanStartupAndShutdownUsingTemplate() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class)) |
| .configure("initialSize", 1) |
| .configure(JavaWebAppService.ROOT_WAR, getTestWar())); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("portNumberSensor", WebAppService.HTTP_PORT) |
| .configure("configTemplate", "classpath://org/apache/brooklyn/entity/proxy/nginx/server.conf")); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| // App-servers and nginx has started |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| for (Entity member : serverPool.getMembers()) { |
| assertTrue(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| assertTrue(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| }}); |
| |
| // URLs reachable |
| assertHttpStatusCodeEventuallyEquals(nginx.getAttribute(NginxController.ROOT_URL), 200); |
| for (Entity member : serverPool.getMembers()) { |
| assertHttpStatusCodeEventuallyEquals(member.getAttribute(WebAppService.ROOT_URL), 200); |
| } |
| |
| app.stop(); |
| |
| // Services have stopped |
| assertFalse(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| assertFalse(serverPool.getAttribute(SoftwareProcess.SERVICE_UP)); |
| for (Entity member : serverPool.getMembers()) { |
| assertFalse(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| } |
| |
| /** |
| * Test that the Nginx proxy works, serving all domains, if no domain is set |
| */ |
| @Test(groups = "Integration") |
| public void testDomainless() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class)) |
| .configure("initialSize", 1) |
| .configure(JavaWebAppService.ROOT_WAR, getTestWar())); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("portNumberSensor", WebAppService.HTTP_PORT)); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| // App-servers and nginx has started |
| EntityAsserts.assertAttributeEqualsEventually(serverPool, SoftwareProcess.SERVICE_UP, true); |
| for (Entity member : serverPool.getMembers()) { |
| EntityAsserts.assertAttributeEqualsEventually(member, SoftwareProcess.SERVICE_UP, true); |
| } |
| EntityAsserts.assertAttributeEqualsEventually(nginx, SoftwareProcess.SERVICE_UP, true); |
| |
| // URLs reachable |
| assertHttpStatusCodeEventuallyEquals(nginx.getAttribute(NginxController.ROOT_URL), 200); |
| for (Entity member : serverPool.getMembers()) { |
| assertHttpStatusCodeEventuallyEquals(member.getAttribute(WebAppService.ROOT_URL), 200); |
| } |
| |
| app.stop(); |
| |
| // Services have stopped |
| assertFalse(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| assertFalse(serverPool.getAttribute(SoftwareProcess.SERVICE_UP)); |
| for (Entity member : serverPool.getMembers()) { |
| assertFalse(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| } |
| |
| @Test(groups = "Integration") |
| public void testTwoNginxesGetDifferentPorts() { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure("initialSize", 0) |
| .configure("memberSpec", EntitySpec.create(TestEntity.class))); |
| |
| NginxController nginx1 = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("port", "14000+")); |
| |
| NginxController nginx2 = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("port", "14000+")); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| String url1 = nginx1.getAttribute(NginxController.ROOT_URL); |
| String url2 = nginx2.getAttribute(NginxController.ROOT_URL); |
| |
| assertTrue(url1.contains(":1400"), url1); |
| assertTrue(url2.contains(":1400"), url2); |
| assertNotEquals(url1, url2, "Two nginxs should listen on different ports, not both on "+url1); |
| |
| // Nginx has started |
| EntityAsserts.assertAttributeEqualsEventually(nginx1, SoftwareProcess.SERVICE_UP, true); |
| EntityAsserts.assertAttributeEqualsEventually(nginx2, SoftwareProcess.SERVICE_UP, true); |
| |
| // Nginx reachable (returning default 404) |
| assertHttpStatusCodeEventuallyEquals(url1, 404); |
| assertHttpStatusCodeEventuallyEquals(url2, 404); |
| } |
| |
| /** Test that site access does not fail even while nginx is reloaded */ |
| // FIXME test disabled -- reload isn't a problem, but #365 is |
| @Test(enabled = false, groups = "Integration") |
| public void testServiceContinuity() throws Exception { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class)) |
| .configure("initialSize", 1) |
| .configure(JavaWebAppService.ROOT_WAR, getTestWar())); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool)); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| for (Entity member : serverPool.getMembers()) { |
| assertHttpStatusCodeEquals(member.getAttribute(WebAppService.ROOT_URL), 200); |
| } |
| assertHttpStatusCodeEquals(nginx.getAttribute(WebAppService.ROOT_URL), 200); |
| }}); |
| |
| WebAppMonitor monitor = new WebAppMonitor(nginx.getAttribute(WebAppService.ROOT_URL)) |
| .logFailures(log) |
| .delayMillis(0); |
| Thread t = new Thread(monitor); |
| t.start(); |
| |
| try { |
| Thread.sleep(1*1000); |
| log.info("service continuity test, startup, "+monitor.getAttempts()+" requests made"); |
| monitor.assertAttemptsMade(10, "startup").assertNoFailures("startup").resetCounts(); |
| |
| for (int i=0; i<20; i++) { |
| nginx.reload(); |
| Thread.sleep(500); |
| log.info("service continuity test, iteration "+i+", "+monitor.getAttempts()+" requests made"); |
| monitor.assertAttemptsMade(10, "reloaded").assertNoFailures("reloaded").resetCounts(); |
| } |
| |
| } finally { |
| t.interrupt(); |
| } |
| |
| app.stop(); |
| |
| // Services have stopped |
| assertFalse(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| assertFalse(serverPool.getAttribute(SoftwareProcess.SERVICE_UP)); |
| for (Entity member : serverPool.getMembers()) { |
| assertFalse(member.getAttribute(SoftwareProcess.SERVICE_UP)); |
| } |
| } |
| |
| // FIXME test disabled -- issue #365 |
| /* |
| * This currently makes no assertions, but writes out the number of sequential reqs per sec |
| * supported with nginx and jboss. |
| * <p> |
| * jboss is (now) steady, at 6k+, since we close the connections in HttpTestUtils.getHttpStatusCode. |
| * but nginx still hits problems, after about 15k reqs, something is getting starved in nginx. |
| */ |
| @Test(enabled=false, groups = "Integration") |
| public void testContinuityNginxAndJboss() throws Exception { |
| serverPool = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) |
| .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class)) |
| .configure("initialSize", 1) |
| .configure(JavaWebAppService.ROOT_WAR, getTestWar())); |
| |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool)); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| final String nginxUrl = nginx.getAttribute(WebAppService.ROOT_URL); |
| |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| for (Entity member : serverPool.getMembers()) { |
| String jbossUrl = member.getAttribute(WebAppService.ROOT_URL); |
| assertHttpStatusCodeEquals(jbossUrl, 200); |
| } |
| assertHttpStatusCodeEquals(nginxUrl, 200); |
| }}); |
| |
| final String jbossUrl = Iterables.get(serverPool.getMembers(), 0).getAttribute(WebAppService.ROOT_URL); |
| |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| long lastReportTime = System.currentTimeMillis(); |
| int num = 0; |
| while (true) { |
| try { |
| num++; |
| int code = HttpTestUtils.getHttpStatusCode(nginxUrl); |
| if (code!=200) log.info("NGINX GOT: "+code); |
| else log.debug("NGINX GOT: "+code); |
| if (System.currentTimeMillis()>=lastReportTime+1000) { |
| log.info("NGINX DID "+num+" requests in last "+(System.currentTimeMillis()-lastReportTime)+"ms"); |
| num=0; |
| lastReportTime = System.currentTimeMillis(); |
| } |
| } catch (Exception e) { |
| log.info("NGINX GOT: "+e); |
| } |
| } |
| }}); |
| t.start(); |
| |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| long lastReportTime = System.currentTimeMillis(); |
| int num = 0; |
| while (true) { |
| try { |
| num++; |
| int code = HttpTestUtils.getHttpStatusCode(jbossUrl); |
| if (code!=200) log.info("JBOSS GOT: "+code); |
| else log.debug("JBOSS GOT: "+code); |
| if (System.currentTimeMillis()>=1000+lastReportTime) { |
| log.info("JBOSS DID "+num+" requests in last "+(System.currentTimeMillis()-lastReportTime)+"ms"); |
| num=0; |
| lastReportTime = System.currentTimeMillis(); |
| } |
| } catch (Exception e) { |
| log.info("JBOSS GOT: "+e); |
| } |
| } |
| }}); |
| t2.start(); |
| |
| t2.join(); |
| } |
| |
| /** |
| * Test that the Nginx proxy starts up and sets SERVICE_UP correctly. |
| */ |
| @Test(groups = "Integration") |
| public void testCanRestart() { |
| nginx = app.createAndManageChild(EntitySpec.create(NginxController.class) |
| .configure("serverPool", serverPool) |
| .configure("domain", "localhost") |
| .configure("portNumberSensor", WebAppService.HTTP_PORT)); |
| |
| app.start(ImmutableList.of(localLoc)); |
| |
| // App-servers and nginx has started |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| assertTrue(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| }}); |
| |
| log.info("started, will restart soon"); |
| Time.sleep(Duration.ONE_SECOND); |
| |
| nginx.restart(); |
| |
| Time.sleep(Duration.ONE_SECOND); |
| Asserts.succeedsEventually(new Runnable() { |
| public void run() { |
| assertTrue(nginx.getAttribute(SoftwareProcess.SERVICE_UP)); |
| }}); |
| log.info("restarted and got service up"); |
| } |
| |
| // public static void main(String[] args) { |
| // NginxIntegrationTest t = new NginxIntegrationTest(); |
| // t.setup(); |
| // t.testCanRestart(); |
| // t.shutdown(); |
| // } |
| |
| } |