blob: fe5eda69d2d0173b741a29d12e8b3f6b13d595be [file] [log] [blame]
/*
* 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 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.net.URI;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.internal.BrooklynProperties;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.server.BrooklynServerConfig;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.core.test.entity.TestApplicationImpl;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.launcher.common.BrooklynPropertiesFactoryHelperTest;
import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.util.http.HttpAsserts;
import org.apache.brooklyn.util.http.HttpTool;
import org.apache.brooklyn.util.http.HttpToolResponse;
import org.apache.brooklyn.util.io.FileUtil;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.text.Strings;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;
public class BrooklynLauncherTest {
private BrooklynLauncher launcher;
@AfterMethod(alwaysRun=true)
public void tearDown() throws Exception {
if (launcher != null) launcher.terminate();
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+")
.installSecurityFilter(false)
.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);
HttpAsserts.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);
}
// Integration because takes a few seconds to start web-console
@Test(groups="Integration")
public void testStartsWebServerWithoutAuthentication() throws Exception {
launcher = newLauncherForTests(true)
.start();
String uri = launcher.getServerDetails().getWebServerUrl();
HttpToolResponse response = HttpTool.execAndConsume(HttpTool.httpClientBuilder().build(), new HttpGet(uri));
assertEquals(response.getResponseCode(), 200);
}
// Integration because takes a few seconds to start web-console
@Test(groups="Integration")
public void testStartsWebServerWithCredentials() throws Exception {
launcher = newLauncherForTests(true)
.webconsolePort("10000+")
.brooklynProperties(BrooklynWebConfig.USERS, "myname")
.brooklynProperties(BrooklynWebConfig.PASSWORD_FOR_USER("myname"), "mypassword")
.start();
String uri = launcher.getServerDetails().getWebServerUrl();
HttpToolResponse response = HttpTool.execAndConsume(HttpTool.httpClientBuilder().build(), new HttpGet(uri));
assertEquals(response.getResponseCode(), 401);
HttpToolResponse response2 = HttpTool.execAndConsume(
HttpTool.httpClientBuilder()
.uri(uri)
.credentials(new UsernamePasswordCredentials("myname", "mypassword"))
.build(),
new HttpGet(uri));
assertEquals(response2.getResponseCode(), 200);
}
@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(EntitySpec.create(TestApplicationImpl.class))
.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
@SuppressWarnings("deprecation")
public void testStartsAppFromBuilder() throws Exception {
launcher = newLauncherForTests(true)
.webconsole(false)
.application(new org.apache.brooklyn.core.entity.factory.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: org.apache.brooklyn.core.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(EntitySpec.create(TestApplication.class))
.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(BrooklynPropertiesFactoryHelperTest.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(BrooklynPropertiesFactoryHelperTest.getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
managementContext.reloadBrooklynProperties();
assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
} finally {
globalPropertiesFile.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");
}
}))
.installSecurityFilter(false)
.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() );
HttpAsserts.assertContentMatches(
Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/up"),
"true");
HttpAsserts.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 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());
}
}