http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java new file mode 100644 index 0000000..66a9f67 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java @@ -0,0 +1,258 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynLauncher; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.Application; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.rebind.RebindTestUtils; +import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.management.ManagementContext; +import brooklyn.management.ha.HighAvailabilityMode; +import brooklyn.management.ha.ManagementPlaneSyncRecordPersister; +import brooklyn.management.internal.ManagementContextInternal; +import brooklyn.test.Asserts; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.test.entity.TestApplication; +import brooklyn.util.os.Os; +import brooklyn.util.time.Duration; + +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.common.io.Files; + +public class BrooklynLauncherHighAvailabilityTest { + + private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherHighAvailabilityTest.class); + + private static final Duration TIMEOUT = Duration.THIRTY_SECONDS; + + private BrooklynLauncher primary; + private BrooklynLauncher secondary; + private BrooklynLauncher tertiary; + private File persistenceDir; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + persistenceDir = Files.createTempDir(); + Os.deleteOnExitRecursively(persistenceDir); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (primary != null) primary.terminate(); + primary = null; + if (secondary != null) secondary.terminate(); + secondary = null; + if (tertiary != null) tertiary.terminate(); + tertiary = null; + if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir); + persistenceDir = null; + } + + @Test + public void testStandbyTakesOverWhenPrimaryTerminatedGracefully() throws Exception { + doTestStandbyTakesOver(true); + } + + @Test(invocationCount=10, groups="Integration") + /** test issues with termination and promotion; + * previously we got FileNotFound errors, though these should be fixed with + * the various PersistenceObjectStore prepare methods */ + public void testStandbyTakesOverWhenPrimaryTerminatedGracefullyManyTimes() throws Exception { + testStandbyTakesOverWhenPrimaryTerminatedGracefully(); + } + + @Test(groups="Integration") // because slow waiting for timeouts to promote standbys + public void testStandbyTakesOverWhenPrimaryFails() throws Exception { + doTestStandbyTakesOver(false); + } + + protected void doTestStandbyTakesOver(boolean stopGracefully) throws Exception { + log.info("STARTING standby takeover test"); + primary = BrooklynLauncher.newInstance(); + primary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.AUTO) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .haHeartbeatPeriod(Duration.millis(10)) + .haHeartbeatTimeout(Duration.millis(1000)) + .application(EntitySpec.create(TestApplication.class)) + .start(); + ManagementContext primaryManagementContext = primary.getServerDetails().getManagementContext(); + log.info("started mgmt primary "+primaryManagementContext); + + assertOnlyApp(primary.getServerDetails().getManagementContext(), TestApplication.class); + primaryManagementContext.getRebindManager().getPersister().waitForWritesCompleted(TIMEOUT); + + // Secondary will come up as standby + secondary = BrooklynLauncher.newInstance(); + secondary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.AUTO) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .haHeartbeatPeriod(Duration.millis(10)) + .haHeartbeatTimeout(Duration.millis(1000)) + .start(); + ManagementContext secondaryManagementContext = secondary.getServerDetails().getManagementContext(); + log.info("started mgmt secondary "+secondaryManagementContext); + + // TODO can assert it sees the apps read only +// assertNoApps(secondary.getServerDetails().getManagementContext()); + + // Terminate primary; expect secondary to take over + if (stopGracefully) { + ((ManagementContextInternal)primaryManagementContext).terminate(); + } else { + ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)primaryManagementContext).getHighAvailabilityManager().getPersister(); + planePersister.stop(); // can no longer write heartbeats + ((ManagementContextInternal)primaryManagementContext).terminate(); + } + + assertOnlyAppEventually(secondaryManagementContext, TestApplication.class); + + // Start tertiary (force up as standby) + tertiary = BrooklynLauncher.newInstance(); + tertiary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.STANDBY) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .haHeartbeatPeriod(Duration.millis(10)) + .haHeartbeatTimeout(Duration.millis(1000)) + .start(); + ManagementContext tertiaryManagementContext = tertiary.getServerDetails().getManagementContext(); + log.info("started mgmt tertiary "+primaryManagementContext); + + assertNoApps(tertiary.getServerDetails().getManagementContext()); + + // Terminate secondary; expect tertiary to take over + if (stopGracefully) { + ((ManagementContextInternal)secondaryManagementContext).terminate(); + } else { + ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)secondaryManagementContext).getHighAvailabilityManager().getPersister(); + planePersister.stop(); // can no longer write heartbeats + ((ManagementContextInternal)secondaryManagementContext).terminate(); + } + + assertOnlyAppEventually(tertiaryManagementContext, TestApplication.class); + } + + public void testHighAvailabilityMasterModeFailsIfAlreadyHasMaster() throws Exception { + primary = BrooklynLauncher.newInstance(); + primary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.AUTO) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .application(EntitySpec.create(TestApplication.class)) + .start(); + + try { + // Secondary will come up as standby + secondary = BrooklynLauncher.newInstance(); + secondary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.MASTER) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .start(); + fail(); + } catch (IllegalStateException e) { + // success + } + } + + @Test + public void testHighAvailabilityStandbyModeFailsIfNoExistingMaster() throws Exception { + try { + primary = BrooklynLauncher.newInstance(); + primary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.STANDBY) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .ignorePersistenceErrors(false) + .application(EntitySpec.create(TestApplication.class)) + .start(); + fail(); + } catch (IllegalStateException e) { + // success + } + } + + @Test + public void testHighAvailabilityHotStandbyModeFailsIfNoExistingMaster() throws Exception { + try { + primary = BrooklynLauncher.newInstance(); + primary.webconsole(false) + .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty())) + .highAvailabilityMode(HighAvailabilityMode.HOT_STANDBY) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)) + .ignorePersistenceErrors(false) + .application(EntitySpec.create(TestApplication.class)) + .start(); + fail(); + } catch (IllegalStateException e) { + // success + } + } + + private void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) { + assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications()); + assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications()); + } + + private void assertNoApps(ManagementContext managementContext) { + if (!managementContext.getApplications().isEmpty()) + log.warn("FAILED assertion (rethrowing), apps="+managementContext.getApplications()); + assertTrue(managementContext.getApplications().isEmpty(), "apps="+managementContext.getApplications()); + } + + private void assertOnlyAppEventually(final ManagementContext managementContext, final Class<? extends Application> expectedType) { + Asserts.succeedsEventually(new Runnable() { + @Override public void run() { + assertOnlyApp(managementContext, expectedType); + }}); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java new file mode 100644 index 0000000..48fb538 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java @@ -0,0 +1,116 @@ +/* + * 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.launcher; + +import java.io.File; +import java.util.List; + +import javax.annotation.Nullable; + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.io.Files; + +import org.apache.brooklyn.catalog.BrooklynCatalog; +import org.apache.brooklyn.catalog.CatalogItem; +import brooklyn.catalog.internal.CatalogInitialization; +import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.util.ResourceUtils; +import brooklyn.util.os.Os; + +public class BrooklynLauncherRebindCatalogTest { + + private static final String TEST_VERSION = "test-version"; + private static final String CATALOG_INITIAL = "classpath://rebind-test-catalog.bom"; + private static final String CATALOG_ADDITIONS = "rebind-test-catalog-additions.bom"; + private static final Iterable<String> EXPECTED_DEFAULT_IDS = ImmutableSet.of("one:" + TEST_VERSION, "two:" + TEST_VERSION); + private static final Iterable<String> EXPECTED_ADDED_IDS = ImmutableSet.of("three:" + TEST_VERSION, "four:" + TEST_VERSION); + + private List<BrooklynLauncher> launchers = Lists.newCopyOnWriteArrayList(); + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + for (BrooklynLauncher launcher : launchers) { + launcher.terminate(); + } + launchers.clear(); + } + + private BrooklynLauncher newLauncherForTests(String persistenceDir) { + CatalogInitialization catalogInitialization = new CatalogInitialization(CATALOG_INITIAL, false, null, false); + BrooklynLauncher launcher = BrooklynLauncher.newInstance() + .brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties()) + .catalogInitialization(catalogInitialization) + .persistMode(PersistMode.AUTO) + .persistenceDir(persistenceDir) + .webconsole(false); + launchers.add(launcher); + return launcher; + } + + @Test + public void testRebindDoesNotEffectCatalog() { + String persistenceDir = newTempPersistenceContainerName(); + + BrooklynLauncher launcher = newLauncherForTests(persistenceDir); + launcher.start(); + BrooklynCatalog catalog = launcher.getServerDetails().getManagementContext().getCatalog(); + + assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_DEFAULT_IDS); + + catalog.deleteCatalogItem("one", TEST_VERSION); + catalog.deleteCatalogItem("two", TEST_VERSION); + + Assert.assertEquals(Iterables.size(catalog.getCatalogItems()), 0); + + catalog.addItems(new ResourceUtils(this).getResourceAsString(CATALOG_ADDITIONS)); + + assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_ADDED_IDS); + + launcher.terminate(); + + BrooklynLauncher newLauncher = newLauncherForTests(persistenceDir); + newLauncher.start(); + assertCatalogConsistsOfIds(newLauncher.getServerDetails().getManagementContext().getCatalog().getCatalogItems(), EXPECTED_ADDED_IDS); + } + + private void assertCatalogConsistsOfIds(Iterable<CatalogItem<Object, Object>> catalogItems, Iterable<String> ids) { + Iterable<String> idsFromItems = Iterables.transform(catalogItems, new Function<CatalogItem<?,?>, String>() { + @Nullable + @Override + public String apply(CatalogItem<?, ?> catalogItem) { + return catalogItem.getCatalogItemId(); + } + }); + Assert.assertTrue(Iterables.elementsEqual(ids, idsFromItems), String.format("Expected %s, found %s", ids, idsFromItems)); + } + + protected String newTempPersistenceContainerName() { + File persistenceDirF = Files.createTempDir(); + Os.deleteOnExitRecursively(persistenceDirF); + return persistenceDirF.getAbsolutePath(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java new file mode 100644 index 0000000..bd804b6 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java @@ -0,0 +1,257 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynLauncher; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerConfig; +import brooklyn.entity.Application; +import brooklyn.entity.basic.EntityPredicates; +import brooklyn.entity.basic.StartableApplication; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore; +import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.entity.rebind.persister.PersistenceObjectStore; +import brooklyn.location.Location; +import brooklyn.management.ManagementContext; +import brooklyn.management.ha.HighAvailabilityMode; +import brooklyn.test.Asserts; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.test.entity.TestApplication; +import brooklyn.util.collections.MutableList; +import brooklyn.util.exceptions.FatalConfigurationRuntimeException; +import brooklyn.util.time.Duration; + +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public abstract class BrooklynLauncherRebindTestFixture { + + @SuppressWarnings("unused") + private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherRebindTestFixture.class); + + protected String persistenceDir; + protected String persistenceLocationSpec; + protected List<BrooklynLauncher> launchers = MutableList.of(); + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + persistenceDir = newTempPersistenceContainerName(); + } + + protected abstract String newTempPersistenceContainerName(); + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + for (BrooklynLauncher l: launchers) { + if (l.isStarted()) { + l.terminate(); + PersistenceObjectStore store = getPersistenceStore(l.getServerDetails().getManagementContext()); + if (store!=null) store.deleteCompletely(); + } + } + } + + protected BrooklynLauncher newLauncherBase() { + BrooklynLauncher l = BrooklynLauncher.newInstance() + .webconsole(false); + launchers.add(l); + return l; + } + protected BrooklynLauncher newLauncherDefault(PersistMode mode) { + return newLauncherBase() + .managementContext(newManagementContextForTests(null)) + .persistMode(mode) + .persistenceDir(persistenceDir) + .persistPeriod(Duration.millis(10)); + } + protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) { + if (props==null) + return new LocalManagementContextForTests(); + else + return new LocalManagementContextForTests(props); + } + + protected ManagementContext lastMgmt() { + return Iterables.getLast(launchers).getServerDetails().getManagementContext(); + } + + @Test + public void testRebindsToExistingApp() throws Exception { + populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig")); + + // Rebind to the app we just started last time + + newLauncherDefault(PersistMode.REBIND).start(); + + assertOnlyApp(lastMgmt(), TestApplication.class); + assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("myorig"), null), "apps="+lastMgmt().getApplications()); + } + + @Test + public void testRebindCanAddNewApps() throws Exception { + populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig")); + + // Rebind to the app we started last time + newLauncherDefault(PersistMode.REBIND) + .application(EntitySpec.create(TestApplication.class).displayName("mynew")) + .start(); + + // New app was added, and orig app was rebound + assertEquals(lastMgmt().getApplications().size(), 2, "apps="+lastMgmt().getApplications()); + assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("mynew"), null), "apps="+lastMgmt().getApplications()); + + // And subsequently can create new apps + StartableApplication app3 = lastMgmt().getEntityManager().createEntity( + EntitySpec.create(TestApplication.class).displayName("mynew2")); + app3.start(ImmutableList.<Location>of()); + } + + @Test + public void testAutoRebindsToExistingApp() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + + // Auto will rebind if the dir exists + newLauncherDefault(PersistMode.AUTO).start(); + + assertOnlyApp(lastMgmt(), TestApplication.class); + } + + @Test + public void testCleanDoesNotRebindToExistingApp() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + + // Auto will rebind if the dir exists + newLauncherDefault(PersistMode.CLEAN).start(); + + assertTrue(lastMgmt().getApplications().isEmpty(), "apps="+lastMgmt().getApplications()); + } + + @Test + public void testAutoRebindCreatesNewIfEmptyDir() throws Exception { + // Auto will rebind if the dir exists + newLauncherDefault(PersistMode.AUTO) + .application(EntitySpec.create(TestApplication.class)) + .start(); + + assertOnlyApp(lastMgmt(), TestApplication.class); + assertMementoContainerNonEmptyForTypeEventually("entities"); + } + + @Test + public void testRebindRespectsPersistenceDirSetInProperties() throws Exception { + String persistenceDir2 = newTempPersistenceContainerName(); + + BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault(); + brooklynProperties.put(BrooklynServerConfig.PERSISTENCE_DIR, persistenceDir2); + LocalManagementContextForTests mgmt = newManagementContextForTests(brooklynProperties); + + // Rebind to the app we started last time + newLauncherBase() + .persistMode(PersistMode.AUTO) + .persistPeriod(Duration.millis(10)) + .managementContext(mgmt) + .start(); + + checkPersistenceContainerNameIs(persistenceDir2); + } + + // assumes default persistence dir is rebindable + @Test(groups="Integration") + public void testRebindRespectsDefaultPersistenceDir() throws Exception { + newLauncherDefault(PersistMode.AUTO) + .persistenceDir((String)null) + .start(); + + checkPersistenceContainerNameIsDefault(); + } + + protected abstract void checkPersistenceContainerNameIsDefault(); + protected abstract void checkPersistenceContainerNameIs(String expected); + + @Test + public void testPersistenceFailsIfNoDir() throws Exception { + runRebindFails(PersistMode.REBIND, badContainerName(), "does not exist"); + } + + protected abstract String badContainerName(); + + @Test + public void testExplicitRebindFailsIfEmpty() throws Exception { + runRebindFails(PersistMode.REBIND, persistenceDir, "directory is empty"); + } + + protected void runRebindFails(PersistMode persistMode, String dir, String errmsg) throws Exception { + try { + newLauncherDefault(persistMode) + .persistenceDir(dir) + .start(); + } catch (FatalConfigurationRuntimeException e) { + if (!e.toString().contains(errmsg)) { + throw e; + } + } + } + + protected void populatePersistenceDir(String dir, EntitySpec<? extends StartableApplication> appSpec) throws Exception { + BrooklynLauncher launcher = newLauncherDefault(PersistMode.CLEAN) + .highAvailabilityMode(HighAvailabilityMode.MASTER) + .persistenceDir(dir) + .application(appSpec) + .start(); + launcher.terminate(); + assertMementoContainerNonEmptyForTypeEventually("entities"); + } + + protected void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) { + assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications()); + assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications()); + } + + protected void assertMementoContainerNonEmptyForTypeEventually(final String type) { + Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.TEN_SECONDS), new Runnable() { + @Override public void run() { + getPersistenceStore(lastMgmt()).listContentsWithSubPath(type); + }}); + } + + static PersistenceObjectStore getPersistenceStore(ManagementContext managementContext) { + if (managementContext==null) return null; + BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister(); + if (persister==null) return null; + return persister.getObjectStore(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java new file mode 100644 index 0000000..ee07f67 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java @@ -0,0 +1,154 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynLauncher; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertTrue; + +import java.io.File; + +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerPaths; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore; +import brooklyn.entity.rebind.persister.FileBasedObjectStore; +import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.management.ManagementContext; +import brooklyn.management.ha.HighAvailabilityMode; +import brooklyn.test.entity.TestApplication; +import brooklyn.util.javalang.JavaClassNames; +import brooklyn.util.os.Os; +import brooklyn.util.text.Identifiers; + +import com.google.common.base.Joiner; +import com.google.common.io.Files; + +public class BrooklynLauncherRebindTestToFiles extends BrooklynLauncherRebindTestFixture { + + protected String newTempPersistenceContainerName() { + File persistenceDirF = Files.createTempDir(); + Os.deleteOnExitRecursively(persistenceDirF); + return persistenceDirF.getAbsolutePath(); + } + + protected String badContainerName() { + return "/path/does/not/exist/"+Identifiers.makeRandomId(4); + } + + protected void checkPersistenceContainerNameIs(String expected) { + String expectedFqp = new File(Os.tidyPath(expected)).getAbsolutePath(); + assertEquals(getPersistenceDir(lastMgmt()).getAbsolutePath(), expectedFqp); + } + + static File getPersistenceDir(ManagementContext managementContext) { + BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister(); + FileBasedObjectStore store = (FileBasedObjectStore)persister.getObjectStore(); + return store.getBaseDir(); + } + + protected void checkPersistenceContainerNameIsDefault() { + String expected = BrooklynServerPaths.newMainPersistencePathResolver(BrooklynProperties.Factory.newEmpty()).location(null).dir(null).resolve(); + checkPersistenceContainerNameIs(expected); + } + + @Test + public void testPersistenceFailsIfIsFile() throws Exception { + File tempF = File.createTempFile("test-"+JavaClassNames.niceClassAndMethod(), ".not_dir"); + tempF.deleteOnExit(); + String tempFileName = tempF.getAbsolutePath(); + + try { + runRebindFails(PersistMode.AUTO, tempFileName, "must not be a file"); + runRebindFails(PersistMode.REBIND, tempFileName, "must not be a file"); + runRebindFails(PersistMode.CLEAN, tempFileName, "must not be a file"); + } finally { + new File(tempFileName).delete(); + } + } + + @Test + public void testPersistenceFailsIfNotWritable() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + new File(persistenceDir).setWritable(false); + try { + runRebindFails(PersistMode.AUTO, persistenceDir, "not writable"); + runRebindFails(PersistMode.REBIND, persistenceDir, "not writable"); + runRebindFails(PersistMode.CLEAN, persistenceDir, "not writable"); + } finally { + new File(persistenceDir).setWritable(true); + } + } + + @Test + public void testPersistenceFailsIfNotReadable() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + new File(persistenceDir).setReadable(false); + try { + runRebindFails(PersistMode.AUTO, persistenceDir, "not readable"); + runRebindFails(PersistMode.REBIND, persistenceDir, "not readable"); + runRebindFails(PersistMode.CLEAN, persistenceDir, "not readable"); + } finally { + new File(persistenceDir).setReadable(true); + } + } + + @Test(groups="Integration") + public void testCopyPersistedState() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + + File destinationDir = Files.createTempDir(); + String destination = destinationDir.getAbsolutePath(); + String destinationLocation = null; // i.e. file system, rather than object store + try { + // Auto will rebind if the dir exists + BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO) + .highAvailabilityMode(HighAvailabilityMode.MASTER) + .webconsole(false); + launcher.copyPersistedState(destination, destinationLocation); + launcher.terminate(); + + File entities = new File(Os.mergePaths(destination), "entities"); + assertTrue(entities.isDirectory(), "entities directory should exist"); + assertEquals(entities.listFiles().length, 1, "entities directory should contain one file (contained: "+ + Joiner.on(", ").join(entities.listFiles()) +")"); + + File nodes = new File(Os.mergePaths(destination, "nodes")); + assertTrue(nodes.isDirectory(), "nodes directory should exist"); + assertNotEquals(nodes.listFiles().length, 0, "nodes directory should not be empty"); + + // Should now have a usable copy in the destinationDir + // Auto will rebind if the dir exists + newLauncherDefault(PersistMode.AUTO) + .webconsole(false) + .persistenceDir(destinationDir) + .start(); + assertOnlyApp(lastMgmt(), TestApplication.class); + + } finally { + Os.deleteRecursively(destinationDir); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java new file mode 100644 index 0000000..b2aeaf9 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java @@ -0,0 +1,175 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynLauncher; +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerPaths; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore; +import brooklyn.entity.rebind.persister.PersistMode; +import brooklyn.entity.rebind.persister.jclouds.BlobStoreTest; +import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore; +import brooklyn.management.ManagementContext; +import brooklyn.mementos.BrooklynMementoRawData; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.test.entity.TestApplication; +import brooklyn.util.javalang.JavaClassNames; +import brooklyn.util.os.Os; +import brooklyn.util.text.Identifiers; + +@Test(groups="Live") +public class BrooklynLauncherRebindToCloudObjectStoreTest extends BrooklynLauncherRebindTestFixture { + + // FIXME BrooklynLauncherRebindToCloudObjectStoreTest.testCleanDoesNotRebindToExistingApp failed: + // apps=[Application[mDNfOA7w]] expected [true] but found [false] + // Should it really delete everything in the bucket?! Only if we can back up first! + + // FIXME brooklyn.util.exceptions.FatalRuntimeException: Error rebinding to persisted state: Writes not allowed in brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore@7d2f7563 + // at brooklyn.launcher.BrooklynLauncher.persistState(BrooklynLauncher.java:502) + // at brooklyn.launcher.BrooklynLauncherRebindToCloudObjectStoreTest.testCopyPersistedState(BrooklynLauncherRebindToCloudObjectStoreTest.java:144) + // Presumably a previous run wasn't tearing down properly, so it joined as a standby rather than being master?! + + { persistenceLocationSpec = BlobStoreTest.PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; } + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + persistenceDir = newTempPersistenceContainerName(); + } + + @Override + protected BrooklynLauncher newLauncherBase() { + return super.newLauncherBase().persistenceLocation(persistenceLocationSpec); + } + + protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) { + BrooklynProperties p2 = BrooklynProperties.Factory.newDefault(); + if (props!=null) p2.putAll(props); + return new LocalManagementContextForTests(p2); + } + + @Override + protected String newTempPersistenceContainerName() { + return "test-"+JavaClassNames.callerStackElement(0).getClassName()+"-"+Identifiers.makeRandomId(4); + } + + protected String badContainerName() { + return "container-does-not-exist-"+Identifiers.makeRandomId(4); + } + + protected void checkPersistenceContainerNameIs(String expected) { + assertEquals(getPersistenceContainerName(lastMgmt()), expected); + } + + static String getPersistenceContainerName(ManagementContext managementContext) { + BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister(); + JcloudsBlobStoreBasedObjectStore store = (JcloudsBlobStoreBasedObjectStore)persister.getObjectStore(); + return store.getContainerName(); + } + + protected void checkPersistenceContainerNameIsDefault() { + checkPersistenceContainerNameIs(BrooklynServerPaths.DEFAULT_PERSISTENCE_CONTAINER_NAME); + } + + @Override @Test(groups="Live") + public void testRebindsToExistingApp() throws Exception { + super.testRebindsToExistingApp(); + } + + @Override @Test(groups="Live") + public void testRebindCanAddNewApps() throws Exception { + super.testRebindCanAddNewApps(); + } + + @Override @Test(groups="Live") + public void testAutoRebindsToExistingApp() throws Exception { + super.testAutoRebindsToExistingApp(); + } + + // TODO Marked as work-in-progress because "clean" does not backup and then clean out the existing + // object store's bucket. Unclear what best behaviour there should be: should we really delete + // the data?! We better be confident about our backup! + @Override @Test(groups={"Live", "WIP"}) + public void testCleanDoesNotRebindToExistingApp() throws Exception { + super.testCleanDoesNotRebindToExistingApp(); + } + + @Override @Test(groups="Live") + public void testAutoRebindCreatesNewIfEmptyDir() throws Exception { + super.testAutoRebindCreatesNewIfEmptyDir(); + } + + @Override @Test(groups="Live") + public void testRebindRespectsPersistenceDirSetInProperties() throws Exception { + super.testRebindRespectsPersistenceDirSetInProperties(); + } + + @Override @Test(groups="Live") + public void testRebindRespectsDefaultPersistenceDir() throws Exception { + super.testRebindRespectsDefaultPersistenceDir(); + } + + @Override @Test(groups="Live") + public void testPersistenceFailsIfNoDir() throws Exception { + super.testPersistenceFailsIfNoDir(); + } + + @Override @Test(groups="Live") + public void testExplicitRebindFailsIfEmpty() throws Exception { + super.testExplicitRebindFailsIfEmpty(); + } + + // TODO Remove duplication from BrooklynLauncherRebindTestToFiles.testCopyPersistedState() + @Test(groups="Live") + public void testCopyPersistedState() throws Exception { + EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class); + populatePersistenceDir(persistenceDir, appSpec); + + String destinationDir = newTempPersistenceContainerName(); + String destinationLocation = persistenceLocationSpec; + try { + // Auto will rebind if the dir exists + BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO) + .webconsole(false) + .persistenceLocation(persistenceLocationSpec); + BrooklynMementoRawData memento = launcher.retrieveState(); + launcher.persistState(memento, destinationDir, destinationLocation); + launcher.terminate(); + + assertEquals(memento.getEntities().size(), 1, "entityMementos="+memento.getEntities().keySet()); + + // Should now have a usable copy in the destionationDir + // Auto will rebind if the dir exists + newLauncherDefault(PersistMode.AUTO) + .webconsole(false) + .persistenceDir(destinationDir) + .persistenceLocation(destinationLocation) + .start(); + assertOnlyApp(lastMgmt(), TestApplication.class); + + } finally { + Os.deleteRecursively(destinationDir); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java new file mode 100644 index 0000000..df295d8 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java @@ -0,0 +1,368 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynLauncher; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Properties; + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import brooklyn.catalog.internal.CatalogInitialization; +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerConfig; +import brooklyn.entity.Application; +import brooklyn.entity.basic.ApplicationBuilder; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.rebind.RebindTestUtils; +import brooklyn.location.Location; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.management.ManagementContext; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.management.internal.ManagementContextInternal; +import brooklyn.test.HttpTestUtils; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.test.entity.TestApplication; +import brooklyn.test.entity.TestApplicationImpl; +import brooklyn.test.entity.TestEntity; +import brooklyn.util.exceptions.FatalRuntimeException; +import brooklyn.util.io.FileUtil; +import brooklyn.util.net.Urls; +import brooklyn.util.os.Os; +import brooklyn.util.text.StringFunctions; +import brooklyn.util.text.Strings; + +import com.google.api.client.util.Preconditions; +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.io.Files; + +public class BrooklynLauncherTest { + + private BrooklynLauncher launcher; + private File persistenceDir; + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (launcher != null) launcher.terminate(); + if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir); + launcher = null; + } + + // Integration because takes a few seconds to start web-console + @Test(groups="Integration") + public void testStartsWebServerOnExpectectedPort() throws Exception { + launcher = newLauncherForTests(true) + .webconsolePort("10000+") + .start(); + + String webServerUrlStr = launcher.getServerDetails().getWebServerUrl(); + URI webServerUri = new URI(webServerUrlStr); + + assertEquals(launcher.getApplications(), ImmutableList.of()); + assertTrue(webServerUri.getPort() >= 10000 && webServerUri.getPort() < 10100, "port="+webServerUri.getPort()+"; uri="+webServerUri); + HttpTestUtils.assertUrlReachable(webServerUrlStr); + } + + // Integration because takes a few seconds to start web-console + @Test(groups="Integration") + public void testWebServerTempDirRespectsDataDirConfig() throws Exception { + String dataDirName = ".brooklyn-foo"+Strings.makeRandomId(4); + String dataDir = "~/"+dataDirName; + + launcher = newLauncherForTests(true) + .brooklynProperties(BrooklynServerConfig.MGMT_BASE_DIR, dataDir) + .start(); + + ManagementContext managementContext = launcher.getServerDetails().getManagementContext(); + String expectedTempDir = Os.mergePaths(Os.home(), dataDirName, "planes", managementContext.getManagementPlaneId(), managementContext.getManagementNodeId(), "jetty"); + + File webappTempDir = launcher.getServerDetails().getWebServer().getWebappTempDir(); + assertEquals(webappTempDir.getAbsolutePath(), expectedTempDir); + } + + @Test + public void testCanDisableWebServerStartup() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .start(); + + assertNull(launcher.getServerDetails().getWebServer()); + assertNull(launcher.getServerDetails().getWebServerUrl()); + Assert.assertTrue( ((ManagementContextInternal)launcher.getServerDetails().getManagementContext()).errors().isEmpty() ); + } + + @Test + public void testStartsAppInstance() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .application(new TestApplicationImpl()) + .start(); + + assertOnlyApp(launcher, TestApplication.class); + } + + @Test + public void testStartsAppFromSpec() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .application(EntitySpec.create(TestApplication.class)) + .start(); + + assertOnlyApp(launcher, TestApplication.class); + } + + @Test + public void testStartsAppFromBuilder() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) { + @Override protected void doBuild() { + }}) + .start(); + + assertOnlyApp(launcher, TestApplication.class); + } + + @Test + public void testStartsAppFromYAML() throws Exception { + String yaml = "name: example-app\n" + + "services:\n" + + "- serviceType: brooklyn.test.entity.TestEntity\n" + + " name: test-app"; + launcher = newLauncherForTests(true) + .webconsole(false) + .application(yaml) + .start(); + + assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications()); + Application app = Iterables.getOnlyElement(launcher.getApplications()); + assertEquals(app.getChildren().size(), 1, "children=" + app.getChildren()); + assertTrue(Iterables.getOnlyElement(app.getChildren()) instanceof TestEntity); + } + + @Test // may take 2s initializing location if running this test case alone, but noise if running suite + public void testStartsAppInSuppliedLocations() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .location("localhost") + .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) { + @Override protected void doBuild() { + }}) + .start(); + + Application app = Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class)); + assertOnlyLocation(app, LocalhostMachineProvisioningLocation.class); + } + + @Test + public void testUsesSuppliedManagementContext() throws Exception { + LocalManagementContext myManagementContext = LocalManagementContextForTests.newInstance(); + launcher = newLauncherForTests(false) + .webconsole(false) + .managementContext(myManagementContext) + .start(); + + assertSame(launcher.getServerDetails().getManagementContext(), myManagementContext); + } + + @Test + public void testUsesSuppliedBrooklynProperties() throws Exception { + BrooklynProperties props = LocalManagementContextForTests.builder(true).buildProperties(); + props.put("mykey", "myval"); + launcher = newLauncherForTests(false) + .webconsole(false) + .brooklynProperties(props) + .start(); + + assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval"); + } + + @Test + public void testUsesSupplementaryBrooklynProperties() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .brooklynProperties("mykey", "myval") + .start(); + + assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval"); + } + + @Test + public void testReloadBrooklynPropertiesRestoresProgrammaticProperties() throws Exception { + launcher = newLauncherForTests(true) + .webconsole(false) + .brooklynProperties("mykey", "myval") + .start(); + LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext(); + assertEquals(managementContext.getConfig().getFirst("mykey"), "myval"); + managementContext.getBrooklynProperties().put("mykey", "newval"); + assertEquals(managementContext.getConfig().getFirst("mykey"), "newval"); + managementContext.reloadBrooklynProperties(); + assertEquals(managementContext.getConfig().getFirst("mykey"), "myval"); + } + + @Test + public void testReloadBrooklynPropertiesFromFile() throws Exception { + File globalPropertiesFile = File.createTempFile("local-brooklyn-properties-test", ".properties"); + FileUtil.setFilePermissionsTo600(globalPropertiesFile); + try { + String property = "mykey=myval"; + Files.append(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8); + launcher = newLauncherForTests(false) + .webconsole(false) + .globalBrooklynPropertiesFile(globalPropertiesFile.getAbsolutePath()) + .start(); + LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext(); + assertEquals(managementContext.getConfig().getFirst("mykey"), "myval"); + property = "mykey=newval"; + Files.write(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8); + managementContext.reloadBrooklynProperties(); + assertEquals(managementContext.getConfig().getFirst("mykey"), "newval"); + } finally { + globalPropertiesFile.delete(); + } + } + + @Test(groups="Integration") + public void testChecksGlobalBrooklynPropertiesPermissionsX00() throws Exception { + File propsFile = File.createTempFile("testChecksGlobalBrooklynPropertiesPermissionsX00", ".properties"); + propsFile.setReadable(true, false); + try { + launcher = newLauncherForTests(false) + .webconsole(false) + .globalBrooklynPropertiesFile(propsFile.getAbsolutePath()) + .start(); + + Assert.fail("Should have thrown"); + } catch (FatalRuntimeException e) { + if (!e.toString().contains("Invalid permissions for file")) throw e; + } finally { + propsFile.delete(); + } + } + + @Test(groups="Integration") + public void testChecksLocalBrooklynPropertiesPermissionsX00() throws Exception { + File propsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00", ".properties"); + propsFile.setReadable(true, false); + try { + launcher = newLauncherForTests(false) + .webconsole(false) + .localBrooklynPropertiesFile(propsFile.getAbsolutePath()) + .start(); + + Assert.fail("Should have thrown"); + } catch (FatalRuntimeException e) { + if (!e.toString().contains("Invalid permissions for file")) throw e; + } finally { + propsFile.delete(); + } + } + + @Test(groups="Integration") + public void testStartsWithBrooklynPropertiesPermissionsX00() throws Exception { + File globalPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_global", ".properties"); + Files.write(getMinimalLauncherPropertiesString()+"key_in_global=1", globalPropsFile, Charset.defaultCharset()); + File localPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_local", ".properties"); + Files.write("key_in_local=2", localPropsFile, Charset.defaultCharset()); + FileUtil.setFilePermissionsTo600(globalPropsFile); + FileUtil.setFilePermissionsTo600(localPropsFile); + try { + launcher = newLauncherForTests(false) + .webconsole(false) + .localBrooklynPropertiesFile(localPropsFile.getAbsolutePath()) + .globalBrooklynPropertiesFile(globalPropsFile.getAbsolutePath()) + .start(); + assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_global"), "1"); + assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_local"), "2"); + } finally { + globalPropsFile.delete(); + localPropsFile.delete(); + } + } + + @Test // takes a bit of time because starts webapp, but also tests rest api so useful + public void testErrorsCaughtByApiAndRestApiWorks() throws Exception { + launcher = newLauncherForTests(true) + .catalogInitialization(new CatalogInitialization(null, false, null, false).addPopulationCallback(new Function<CatalogInitialization, Void>() { + @Override + public Void apply(CatalogInitialization input) { + throw new RuntimeException("deliberate-exception-for-testing"); + } + })) + .start(); + // such an error should be thrown, then caught in this calling thread + ManagementContext mgmt = launcher.getServerDetails().getManagementContext(); + Assert.assertFalse( ((ManagementContextInternal)mgmt).errors().isEmpty() ); + Assert.assertTrue( ((ManagementContextInternal)mgmt).errors().get(0).toString().contains("deliberate"), ""+((ManagementContextInternal)mgmt).errors() ); + HttpTestUtils.assertContentMatches( + Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/up"), + "true"); + HttpTestUtils.assertContentMatches( + Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/healthy"), + "false"); + // TODO test errors api? + } + + private BrooklynLauncher newLauncherForTests(boolean minimal) { + Preconditions.checkArgument(launcher==null, "can only be used if no launcher yet"); + BrooklynLauncher launcher = BrooklynLauncher.newInstance(); + if (minimal) + launcher.brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties()); + return launcher; + } + + private String getMinimalLauncherPropertiesString() throws IOException { + BrooklynProperties p1 = LocalManagementContextForTests.builder(true).buildProperties(); + Properties p = new Properties(); + p.putAll(Maps.transformValues(p1.asMapWithStringKeys(), StringFunctions.toStringFunction())); + Writer w = new StringWriter(); + p.store(w, "test"); + w.close(); + return w.toString()+"\n"; + } + + private void assertOnlyApp(BrooklynLauncher launcher, Class<? extends Application> expectedType) { + assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications()); + assertNotNull(Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+launcher.getApplications()); + } + + private void assertOnlyLocation(Application app, Class<? extends Location> expectedType) { + assertEquals(app.getLocations().size(), 1, "locs="+app.getLocations()); + assertNotNull(Iterables.find(app.getLocations(), Predicates.instanceOf(LocalhostMachineProvisioningLocation.class), null), "locs="+app.getLocations()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java new file mode 100644 index 0000000..9510754 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java @@ -0,0 +1,210 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynWebServer; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.io.File; +import java.io.FileInputStream; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLPeerUnverifiedException; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.DefaultHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.rest.BrooklynWebConfig; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.http.HttpTool; +import brooklyn.util.http.HttpToolResponse; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +public class BrooklynWebServerTest { + + public static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class); + + private BrooklynProperties brooklynProperties; + private BrooklynWebServer webServer; + private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList(); + + @BeforeMethod(alwaysRun=true) + public void setUp(){ + brooklynProperties = BrooklynProperties.Factory.newEmpty(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + for (LocalManagementContext managementContext : managementContexts) { + Entities.destroyAll(managementContext); + } + managementContexts.clear(); + if (webServer != null) webServer.stop(); + } + + private LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) { + LocalManagementContext result = new LocalManagementContextForTests(brooklynProperties); + managementContexts.add(result); + return result; + } + + @Test + public void verifyHttp() throws Exception { + webServer = new BrooklynWebServer(newManagementContext(brooklynProperties)); + try { + webServer.start(); + + HttpToolResponse response = HttpTool.execAndConsume(new DefaultHttpClient(), new HttpGet(webServer.getRootUrl())); + assertEquals(response.getResponseCode(), 200); + } finally { + webServer.stop(); + } + } + + @DataProvider(name="keystorePaths") + public Object[][] getKeystorePaths() { + return new Object[][] { + {getFile("server.ks")}, + {new File(getFile("server.ks")).toURI().toString()}, + {"classpath://server.ks"}}; + } + + @Test(dataProvider="keystorePaths") + public void verifyHttps(String keystoreUrl) throws Exception { + Map<String,?> flags = ImmutableMap.<String,Object>builder() + .put("httpsEnabled", true) + .put("keystoreUrl", keystoreUrl) + .put("keystorePassword", "password") + .build(); + webServer = new BrooklynWebServer(flags, newManagementContext(brooklynProperties)); + webServer.start(); + + try { + KeyStore keyStore = load("client.ks", "password"); + KeyStore trustStore = load("client.ts", "password"); + SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + HttpToolResponse response = HttpTool.execAndConsume( + HttpTool.httpClientBuilder() + .port(webServer.getActualPort()) + .https(true) + .socketFactory(socketFactory) + .build(), + new HttpGet(webServer.getRootUrl())); + assertEquals(response.getResponseCode(), 200); + } finally { + webServer.stop(); + } + } + + @Test + public void verifyHttpsFromConfig() throws Exception { + brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true); + brooklynProperties.put(BrooklynWebConfig.KEYSTORE_URL, getFile("server.ks")); + brooklynProperties.put(BrooklynWebConfig.KEYSTORE_PASSWORD, "password"); + verifyHttpsFromConfig(brooklynProperties); + } + + @Test + public void verifyHttpsCiphers() throws Exception { + brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true); + brooklynProperties.put(BrooklynWebConfig.TRANSPORT_PROTOCOLS, "XXX"); + brooklynProperties.put(BrooklynWebConfig.TRANSPORT_CIPHERS, "XXX"); + try { + verifyHttpsFromConfig(brooklynProperties); + fail("Expected to fail due to unsupported ciphers during connection negotiation"); + } catch (Exception e) { + assertTrue(Exceptions.getFirstThrowableOfType(e, SSLPeerUnverifiedException.class) != null || + Exceptions.getFirstThrowableOfType(e, SSLHandshakeException.class) != null, + "Expected to fail due to inability to negotiate"); + } + } + + private void verifyHttpsFromConfig(BrooklynProperties brooklynProperties) throws Exception { + webServer = new BrooklynWebServer(MutableMap.of(), newManagementContext(brooklynProperties)); + webServer.start(); + + try { + KeyStore keyStore = load("client.ks", "password"); + KeyStore trustStore = load("client.ts", "password"); + SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + + HttpToolResponse response = HttpTool.execAndConsume( + HttpTool.httpClientBuilder() + .port(webServer.getActualPort()) + .https(true) + .socketFactory(socketFactory) + .build(), + new HttpGet(webServer.getRootUrl())); + assertEquals(response.getResponseCode(), 200); + } finally { + webServer.stop(); + } + } + + private KeyStore load(String name, String password) throws Exception { + KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); + FileInputStream instream = new FileInputStream(new File(getFile(name))); + keystore.load(instream, password.toCharArray()); + return keystore; + } + + @Test + public void testGetFileFromUrl() throws Exception { + // On Windows will treat as relative paths + String url = "file:///tmp/special%40file%20with%20spaces"; + String file = "/tmp/special@file with spaces"; + assertEquals(getFile(new URL(url)), new File(file).getAbsolutePath()); + } + + private String getFile(String classpathResource) { + // this works because both IDE and Maven run tests with classes/resources on the file system + return getFile(getClass().getResource("/" + classpathResource)); + } + + private String getFile(URL url) { + try { + return new File(url.toURI()).getAbsolutePath(); + } catch (URISyntaxException e) { + throw Exceptions.propagate(e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java new file mode 100644 index 0000000..b2dfc5b --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java @@ -0,0 +1,31 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher; +import brooklyn.management.ManagementContext; +import brooklyn.test.entity.LocalManagementContextForTests; + +public class SimpleYamlLauncherForTests extends SimpleYamlLauncher { + + protected ManagementContext newManagementContext() { + return new LocalManagementContextForTests(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java new file mode 100644 index 0000000..3aa6334 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java @@ -0,0 +1,171 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.BrooklynWebServer; +import org.apache.brooklyn.launcher.BrooklynLauncher; +import org.apache.brooklyn.launcher.BrooklynServerDetails; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; + +import java.util.List; +import java.util.Map; + +import org.apache.brooklyn.test.TestResourceUnavailableException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.management.internal.ManagementContextInternal; +import brooklyn.test.HttpTestUtils; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.net.Networking; + +import com.google.common.collect.Lists; + + +/** + * These tests require the brooklyn.war to work. (Should be placed by maven build.) + */ +public class WebAppRunnerTest { + + public static final Logger log = LoggerFactory.getLogger(WebAppRunnerTest.class); + + List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList(); + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + for (LocalManagementContext managementContext : managementContexts) { + Entities.destroyAll(managementContext); + } + managementContexts.clear(); + } + + LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) { + LocalManagementContext result = new LocalManagementContext(brooklynProperties); + managementContexts.add(result); + return result; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + BrooklynWebServer createWebServer(Map properties) { + Map bigProps = MutableMap.copyOf(properties); + Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") ); + bigProps.put("attributes", attributes); + + BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty(); + brooklynProperties.putAll(bigProps); + brooklynProperties.put("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider"); + brooklynProperties.put("brooklyn.webconsole.security.https.required","false"); + return new BrooklynWebServer(bigProps, newManagementContext(brooklynProperties)); + } + + @Test + public void testStartWar1() throws Exception { + if (!Networking.isPortAvailable(8090)) + fail("Another process is using port 8090 which is required for this test."); + BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090)); + assertNotNull(server); + + try { + server.start(); + assertBrooklynEventuallyAt("http://localhost:8090/"); + } finally { + server.stop(); + } + } + + public static void assertBrooklynEventuallyAt(String url) { + HttpTestUtils.assertContentEventuallyContainsText(url, "Brooklyn Web Console"); + } + + @Test + public void testStartSecondaryWar() throws Exception { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war"); + + if (!Networking.isPortAvailable(8090)) + fail("Another process is using port 8090 which is required for this test."); + BrooklynWebServer server = createWebServer( + MutableMap.of("port", 8090, "war", "brooklyn.war", "wars", MutableMap.of("hello", "hello-world.war")) ); + assertNotNull(server); + + try { + server.start(); + + assertBrooklynEventuallyAt("http://localhost:8090/"); + HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello", + "This is the home page for a sample application"); + + } finally { + server.stop(); + } + } + + @Test + public void testStartSecondaryWarAfter() throws Exception { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war"); + + if (!Networking.isPortAvailable(8090)) + fail("Another process is using port 8090 which is required for this test."); + BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090, "war", "brooklyn.war")); + assertNotNull(server); + + try { + server.start(); + server.deploy("/hello", "hello-world.war"); + + assertBrooklynEventuallyAt("http://localhost:8090/"); + HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello", + "This is the home page for a sample application"); + + } finally { + server.stop(); + } + } + + @Test + public void testStartWithLauncher() throws Exception { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war"); + + BrooklynLauncher launcher = BrooklynLauncher.newInstance() + .brooklynProperties(BrooklynProperties.Factory.newEmpty()) + .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider") + .webapp("/hello", "hello-world.war") + .start(); + BrooklynServerDetails details = launcher.getServerDetails(); + + try { + details.getWebServer().deploy("/hello2", "hello-world.war"); + + assertBrooklynEventuallyAt(details.getWebServerUrl()); + HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello", "This is the home page for a sample application"); + HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello2", "This is the home page for a sample application"); + HttpTestUtils.assertHttpStatusCodeEventuallyEquals(details.getWebServerUrl()+"hello0", 404); + + } finally { + details.getWebServer().stop(); + ((ManagementContextInternal)details.getManagementContext()).terminate(); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java new file mode 100644 index 0000000..f383895 --- /dev/null +++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java @@ -0,0 +1,35 @@ +/* + * 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.launcher; + +import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher; + +public class YamlLauncher { + + public static void main(String[] args) { + SimpleYamlLauncher l = new SimpleYamlLauncher(); + l.setShutdownAppsOnExit(true); + + l.launchAppYaml("java-web-app-and-db-with-function.yaml"); +// l.launchAppYaml("java-web-app-and-memsql.yaml"); +// l.launchAppYaml("memsql.yaml"); +// l.launchAppYaml("classpath://mongo-blueprint.yaml"); + } + +}
