CLI better default, port/https control, and version reporting * adds config key for web-console port * adds CLI for https * port defaults to 8443+ if no port specified and using https * default if no CLI options is to show help and an error * some https test fixes * discovers and reports Brooklyn OSGi metadata in log, including git SHA1 (and `brooklyn info`)
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/d423522c Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/d423522c Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/d423522c Branch: refs/heads/master Commit: d423522cacf97c3fefa0df3c641718a49f9103a5 Parents: ec74489 Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Authored: Tue Jan 27 17:47:41 2015 +0000 Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Committed: Tue Jan 27 17:47:41 2015 +0000 ---------------------------------------------------------------------- .../src/main/java/brooklyn/BrooklynVersion.java | 222 +++++++++++++++---- .../main/java/brooklyn/util/http/HttpTool.java | 5 + .../test/java/brooklyn/BrooklynVersionTest.java | 49 +++- .../main/java/brooklyn/cli/AbstractMain.java | 14 +- usage/cli/src/main/java/brooklyn/cli/Main.java | 26 ++- .../cli/src/test/java/brooklyn/cli/CliTest.java | 2 +- .../brooklyn/cli/CloudExplorerLiveTest.java | 11 +- .../brooklyn/launcher/BrooklynLauncher.java | 15 +- .../brooklyn/launcher/BrooklynWebServer.java | 13 +- .../brooklyn/launcher/WebAppRunnerTest.java | 4 +- .../java/brooklyn/rest/BrooklynWebConfig.java | 7 +- .../brooklyn/rest/resources/ServerResource.java | 15 ++ .../provider/ExplicitUsersSecurityProvider.java | 2 + .../main/java/brooklyn/test/HttpTestUtils.java | 4 +- 14 files changed, 328 insertions(+), 61 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/main/java/brooklyn/BrooklynVersion.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java index 8ef6a61..3e7645a 100644 --- a/core/src/main/java/brooklyn/BrooklynVersion.java +++ b/core/src/main/java/brooklyn/BrooklynVersion.java @@ -19,80 +19,218 @@ package brooklyn; import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; import java.io.IOException; import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; +import java.util.jar.Attributes; + +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.osgi.Osgis; +import brooklyn.util.osgi.Osgis.ManifestHelper; +import brooklyn.util.text.Strings; + +/** + * Wraps the version of Brooklyn. + * <p> + * Also retrieves the SHA-1 from any OSGi bundle, and checks that the maven and osgi versions match. + */ public class BrooklynVersion { private static final Logger log = LoggerFactory.getLogger(BrooklynVersion.class); - private static final String VERSION_RESOURCE_FILE = "META-INF/maven/io.brooklyn/brooklyn-core/pom.properties"; - private static final String VERSION_PROPERTY_NAME = "version"; + private static final String MVN_VERSION_RESOURCE_FILE = "META-INF/maven/org.apache.brooklyn/brooklyn-core/pom.properties"; + private static final String MANIFEST_PATH = "META-INF/MANIFEST.MF"; + private static final String BROOKLYN_CORE_SYMBOLIC_NAME = "org.apache.brooklyn.core"; + + private static final String MVN_VERSION_PROPERTY_NAME = "version"; + private static final String OSGI_VERSION_PROPERTY_NAME = Attributes.Name.IMPLEMENTATION_VERSION.toString(); + private static final String OSGI_SHA1_PROPERTY_NAME = "Implementation-SHA-1"; + + private final static String VERSION_FROM_STATIC = "0.7.0-SNAPSHOT"; // BROOKLYN_VERSION + private static final AtomicReference<Boolean> IS_DEV_ENV = new AtomicReference<Boolean>(); + public static final BrooklynVersion INSTANCE = new BrooklynVersion(); + + private final Properties versionProperties = new Properties(); + + public BrooklynVersion() { + // we read the maven pom metadata and osgi metadata and make sure it's sensible + // everything is put into a single map for now (good enough, but should be cleaned up) + readPropertiesFromMavenResource(BrooklynVersion.class.getClassLoader()); + readPropertiesFromOsgiResource(BrooklynVersion.class.getClassLoader(), "org.apache.brooklyn.core"); + // TODO there is also build-metadata.properties used in ServerResource /v1/server/version endpoint + // see comments on that about folding it into this class instead - private final String versionFromClasspath; - // static useful when running from the IDE - // TODO is the classpath version ever useful? should we always use the static? - private final String versionFromStatic = "0.7.0-SNAPSHOT"; // BROOKLYN_VERSION - private final String version; + checkVersions(); + } - public BrooklynVersion() { - this.versionFromClasspath = readVersionPropertyFromClasspath(BrooklynVersion.class.getClassLoader()); - if (isValid(versionFromClasspath)) { - this.version = versionFromClasspath; - if (!this.version.equals(versionFromStatic)) { - // should always be the same, and we can drop classpath detection ... - log.warn("Version detected from classpath as "+versionFromClasspath+" (preferring that), but in code it is recorded as "+versionFromStatic); - } - } else { - this.version = versionFromStatic; - } + public void checkVersions() { + String mvnVersion = getVersionFromMavenProperties(); + if (mvnVersion!=null && !VERSION_FROM_STATIC.equals(mvnVersion)) { + throw new IllegalStateException("Version error: maven "+mvnVersion+" / code "+VERSION_FROM_STATIC); + } + + String osgiVersion = versionProperties.getProperty(OSGI_VERSION_PROPERTY_NAME); + // TODO does the OSGi version include other slightly differ gubbins/style ? + if (osgiVersion!=null && !VERSION_FROM_STATIC.equals(osgiVersion)) { + throw new IllegalStateException("Version error: osgi "+osgiVersion+" / code "+VERSION_FROM_STATIC); + } } - + + /** Returns version as inferred from classpath/osgi, if possible, or 0.0.0-SNAPSHOT. + * See also {@link #getVersionFromMavenProperties()} and {@link #getVersionFromOsgiManifest()}. + * @deprecated since 0.7.0, in favour of the more specific methods (and does anyone need that default value?) + */ + @Deprecated public String getVersionFromClasspath() { - return versionFromClasspath; + String v = getVersionFromMavenProperties(); + if (Strings.isNonBlank(v)) return v; + v = getVersionFromOsgiManifest(); + if (Strings.isNonBlank(v)) return v; + return "0.0.0-SNAPSHOT"; } - public String getVersion() { - return version; + @Nullable + public String getVersionFromMavenProperties() { + return versionProperties.getProperty(MVN_VERSION_PROPERTY_NAME); + } + + @Nullable + public String getVersionFromOsgiManifest() { + return versionProperties.getProperty(OSGI_VERSION_PROPERTY_NAME); } - public String getVersionFromStatic() { - return versionFromStatic; + @Nullable + /** SHA1 of the last commit to brooklyn at the time this build was made. + * For SNAPSHOT builds of course there may have been further non-committed changes. */ + public String getSha1FromOsgiManifest() { + return versionProperties.getProperty(OSGI_SHA1_PROPERTY_NAME); } - - public boolean isSnapshot() { - return (getVersion().indexOf("-SNAPSHOT")>=0); + + public String getVersion() { + return VERSION_FROM_STATIC; } - private static boolean isValid(String v) { - if (v==null) return false; - if (v.equals("0.0.0") || v.equals("0.0")) return false; - if (v.startsWith("0.0.0-") || v.startsWith("0.0-")) return false; - return true; + public boolean isSnapshot() { + return (getVersion().indexOf("-SNAPSHOT")>=0); } - - private String readVersionPropertyFromClasspath(ClassLoader resourceLoader) { - Properties versionProperties = new Properties(); + + private void readPropertiesFromMavenResource(ClassLoader resourceLoader) { try { - InputStream versionStream = resourceLoader.getResourceAsStream(VERSION_RESOURCE_FILE); - if (versionStream==null) return null; + InputStream versionStream = resourceLoader.getResourceAsStream(MVN_VERSION_RESOURCE_FILE); + if (versionStream==null) { + if (isDevelopmentEnvironment()) { + // allowed for dev env + log.trace("No maven resource file "+MVN_VERSION_RESOURCE_FILE+" available"); + } else { + log.warn("No maven resource file "+MVN_VERSION_RESOURCE_FILE+" available"); + } + return; + } versionProperties.load(checkNotNull(versionStream)); - } catch (IOException exception) { - throw new IllegalStateException(format("Unable to load version resource file '%s'", VERSION_RESOURCE_FILE), exception); + } catch (IOException e) { + log.warn("Error reading maven resource file "+MVN_VERSION_RESOURCE_FILE+": "+e, e); } - return checkNotNull(versionProperties.getProperty(VERSION_PROPERTY_NAME), VERSION_PROPERTY_NAME); + } + + /** reads properties from brooklyn-core's manifest */ + private void readPropertiesFromOsgiResource(ClassLoader resourceLoader, String symbolicName) { + Enumeration<URL> paths; + try { + paths = BrooklynVersion.class.getClassLoader().getResources(MANIFEST_PATH); + } catch (IOException e) { + // shouldn't happen + throw Exceptions.propagate(e); + } + while (paths.hasMoreElements()) { + URL u = paths.nextElement(); + try { + ManifestHelper mh = Osgis.ManifestHelper.forManifest(u.openStream()); + if (BROOKLYN_CORE_SYMBOLIC_NAME.equals(mh.getSymbolicName())) { + Attributes attrs = mh.getManifest().getMainAttributes(); + for (Object key: attrs.keySet()) { + // key is an Attribute.Name; toString converts to string + versionProperties.put(key.toString(), attrs.getValue(key.toString())); + } + return; + } + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + log.warn("Error reading OSGi manifest from "+u+" when determining version properties: "+e, e); + } + } + if (isDevelopmentEnvironment()) { + // allowed for dev env + log.trace("No OSGi manifest available to determine version properties"); + } else { + log.warn("No OSGi manifest available to determine version properties"); + } + } + + /** + * Returns whether this is a Brooklyn dev environment, + * specifically core/target/classes/ is on the classpath for the org.apache.brooklyn.core project. + * <p> + * In a packaged or library build of Brooklyn (normal usage) this should return false, + * and all OSGi components should be available. + */ + public static boolean isDevelopmentEnvironment() { + Boolean isDevEnv = IS_DEV_ENV.get(); + if (isDevEnv!=null) return isDevEnv; + synchronized (IS_DEV_ENV) { + isDevEnv = computeIsDevelopmentEnvironment(); + IS_DEV_ENV.set(isDevEnv); + return isDevEnv; + } + } + + private static boolean computeIsDevelopmentEnvironment() { + Enumeration<URL> paths; + try { + paths = BrooklynVersion.class.getClassLoader().getResources(MANIFEST_PATH); + } catch (IOException e) { + // shouldn't happen + throw Exceptions.propagate(e); + } + while (paths.hasMoreElements()) { + URL u = paths.nextElement(); + if (u.getPath().endsWith("core/target/classes/META-INF/MANIFEST.MF")) { + try { + ManifestHelper mh = Osgis.ManifestHelper.forManifest(u.openStream()); + if (BROOKLYN_CORE_SYMBOLIC_NAME.equals(mh.getSymbolicName())) { + log.debug("Brooklyn debug environment detected; core manifest is at: "+u); + return true; + } + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + log.warn("Error reading manifest to determine whether this is a development environment: "+e, e); + } + } + } + return false; + } + + public void logSummary() { + log.debug("Brooklyn version "+getVersion()+" (git SHA1 "+getSha1FromOsgiManifest()+")"); + } + + /** @deprecated since 0.7.0, redundant with {@link #get()} */ @Deprecated + public static String getVersionFromStatic() { + return VERSION_FROM_STATIC; } public static String get() { - return INSTANCE.version; + return getVersionFromStatic(); } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/main/java/brooklyn/util/http/HttpTool.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java index b57c157..a812cfc 100644 --- a/core/src/main/java/brooklyn/util/http/HttpTool.java +++ b/core/src/main/java/brooklyn/util/http/HttpTool.java @@ -65,6 +65,7 @@ import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.util.crypto.SslTrustUtils; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.net.URLParamEncoder; import brooklyn.util.text.Strings; @@ -80,6 +81,10 @@ public class HttpTool { private static final Logger LOG = LoggerFactory.getLogger(HttpTool.class); + /** Apache HTTP commons utility for trusting all. + * <p> + * For generic java HTTP usage, see {@link SslTrustUtils#trustAll(java.net.URLConnection)} + * and static constants in the same class. */ public static class TrustAllStrategy implements TrustStrategy { @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/core/src/test/java/brooklyn/BrooklynVersionTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/BrooklynVersionTest.java b/core/src/test/java/brooklyn/BrooklynVersionTest.java index ef9f9a6..887d8e4 100644 --- a/core/src/test/java/brooklyn/BrooklynVersionTest.java +++ b/core/src/test/java/brooklyn/BrooklynVersionTest.java @@ -19,18 +19,63 @@ package brooklyn; import static org.testng.Assert.assertEquals; + +import java.net.URL; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; import org.testng.annotations.Test; +import brooklyn.util.text.Strings; + public class BrooklynVersionTest { + private static final Logger log = LoggerFactory.getLogger(BrooklynVersionTest.class); + @Test public void testGetVersion() { - assertEquals(BrooklynVersion.get(), BrooklynVersion.INSTANCE.getVersionFromStatic()); + assertEquals(BrooklynVersion.get(), BrooklynVersion.INSTANCE.getVersion()); } @Test public void testGetHardcodedClasspathVersion() { - assertEquals(BrooklynVersion.INSTANCE.getVersionFromClasspath(), "0.0.0-SNAPSHOT"); + @SuppressWarnings("deprecation") + String v = BrooklynVersion.INSTANCE.getVersionFromClasspath(); + Assert.assertTrue(BrooklynVersion.get().equals(v) || "0.0.0-SNAPSHOT".equals(v), v); + } + + @Test + public void testGetFromMaven() { + String v = BrooklynVersion.INSTANCE.getVersionFromMavenProperties(); + Assert.assertTrue(v==null || BrooklynVersion.get().equals(v), v); + } + + @Test + public void testGetFromOsgi() { + String v = BrooklynVersion.INSTANCE.getVersionFromOsgiManifest(); + Assert.assertTrue(v==null || BrooklynVersion.get().equals(v), v); + } + + @Test + public void testGetOsgiSha1() { + String sha1 = BrooklynVersion.INSTANCE.getSha1FromOsgiManifest(); + log.info("sha1: "+sha1); + if (Strings.isNonBlank(sha1) || BrooklynVersion.isDevelopmentEnvironment()) + return; + // we might not have a SHA1 if it's a standalone source build; just log warn in that case + log.warn("This build does not have git SHA1 information."); + // (can't assert anything, except that sha1 lookup doesn't NPE) + } + + @Test + public void testDevEnv() { + URL sp = getClass().getClassLoader().getResource("brooklyn/config/sample.properties"); + if (sp==null) Assert.fail("Can't find test resources"); + + log.info("Test for dev env: "+"Dev env? "+BrooklynVersion.isDevelopmentEnvironment()+"; path "+sp); + Assert.assertEquals(sp.getPath().endsWith("classes/brooklyn/config/sample.properties"), BrooklynVersion.isDevelopmentEnvironment(), + "Dev env? "+BrooklynVersion.isDevelopmentEnvironment()+"; path "+sp); } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java index d2b9169..1378c82 100644 --- a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java +++ b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java @@ -165,10 +165,13 @@ public abstract class AbstractMain { System.out.println(BANNER); System.out.println("Version: " + BrooklynVersion.get()); + if (BrooklynVersion.INSTANCE.isSnapshot()) { + System.out.println("Git SHA1: " + BrooklynVersion.INSTANCE.getSha1FromOsgiManifest()); + } System.out.println("Website: http://brooklyn.incubator.apache.org"); System.out.println("Source: https://github.com/apache/incubator-brooklyn"); System.out.println(); - System.out.println("Copyright 2011-2014 The Apache Software Foundation."); + System.out.println("Copyright 2011-2015 The Apache Software Foundation."); System.out.println("Licensed under the Apache 2.0 License"); System.out.println(); @@ -176,6 +179,15 @@ public abstract class AbstractMain { } } + public static class DefaultInfoCommand extends InfoCommand { + @Override + public Void call() throws Exception { + super.call(); + System.out.println("ERROR: No command specified."); + System.out.println(); + throw new ParseException("No command specified."); + } + } /** method intended for overriding when the script filename is different * @return the name of the script the user has invoked */ http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/main/java/brooklyn/cli/Main.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java index 8b9480a..7a79721 100644 --- a/usage/cli/src/main/java/brooklyn/cli/Main.java +++ b/usage/cli/src/main/java/brooklyn/cli/Main.java @@ -31,11 +31,13 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import java.util.Collection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import brooklyn.BrooklynVersion; import brooklyn.catalog.BrooklynCatalog; import brooklyn.cli.CloudExplorer.BlobstoreGetBlobCommand; import brooklyn.cli.CloudExplorer.BlobstoreListContainerCommand; @@ -103,6 +105,8 @@ public class Main extends AbstractMain { public static final Logger log = LoggerFactory.getLogger(Main.class); public static void main(String... args) { + log.debug("Launching Brooklyn via CLI, with "+Arrays.toString(args)); + BrooklynVersion.INSTANCE.logSummary(); new Main().execCli(args); } @@ -207,9 +211,14 @@ public class Main extends AbstractMain { public String locations; @Option(name = { "-p", "--port" }, title = "port number", - description = "Specifies the port to be used by the Brooklyn Management Console") - public String port = "8081+"; + description = "Specifies the port to be used by the Brooklyn Management Console; " + + "default is 8081+ for http, 8443+ for https.") + public String port; + @Option(name = { "--https" }, + description = "Specifies that the server should start on https.") + public boolean useHttps = false; + @Option(name = { "-nc", "--noConsole" }, description = "Whether to start the web console") public boolean noConsole = false; @@ -519,12 +528,19 @@ public class Main extends AbstractMain { BrooklynLauncher launcher; launcher = BrooklynLauncher.newInstance(); launcher.localBrooklynPropertiesFile(localBrooklynProperties) - .webconsolePort(port) - .webconsole(!noConsole) .ignorePersistenceErrors(ignorePersistenceErrors) .ignoreWebErrors(ignoreWebErrors) .ignoreAppErrors(ignoreAppErrors) .locations(Strings.isBlank(locations) ? ImmutableList.<String>of() : JavaStringEscapes.unwrapJsonishListIfPossible(locations)); + + launcher.webconsole(!noConsole); + if (useHttps) { + // true sets it; false (not set) leaves it blank and falls back to config key + // (no way currently to override config key, but that could be added) + launcher.webconsoleHttps(useHttps); + } + launcher.webconsolePort(port); + if (noGlobalBrooklynProperties) { log.debug("Configuring to disable global brooklyn.properties"); launcher.globalBrooklynPropertiesFile(null); @@ -825,7 +841,7 @@ public class Main extends AbstractMain { protected CliBuilder<BrooklynCommand> cliBuilder() { CliBuilder<BrooklynCommand> builder = Cli.<BrooklynCommand>builder(cliScriptName()) .withDescription("Brooklyn Management Service") - .withDefaultCommand(InfoCommand.class) + .withDefaultCommand(DefaultInfoCommand.class) .withCommands( HelpCommand.class, InfoCommand.class, http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/test/java/brooklyn/cli/CliTest.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/test/java/brooklyn/cli/CliTest.java b/usage/cli/src/test/java/brooklyn/cli/CliTest.java index 8af432d..79e1b56 100644 --- a/usage/cli/src/test/java/brooklyn/cli/CliTest.java +++ b/usage/cli/src/test/java/brooklyn/cli/CliTest.java @@ -267,7 +267,7 @@ public class CliTest { assertTrue(details.contains("app=null"), details); assertTrue(details.contains("script=null"), details); assertTrue(details.contains("location=null"), details); - assertTrue(details.contains("port=8081"), details); + assertTrue(details.contains("port=null"), details); assertTrue(details.contains("noConsole=false"), details); assertTrue(details.contains("noConsoleSecurity=false"), details); assertTrue(details.contains("noShutdownOnExit=false"), details); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java b/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java index 3d3b140..6069f74 100644 --- a/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java +++ b/usage/cli/src/test/java/brooklyn/cli/CloudExplorerLiveTest.java @@ -21,6 +21,7 @@ package brooklyn.cli; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import io.airlift.command.Cli; +import io.airlift.command.ParseException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -28,6 +29,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.util.List; +import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; @@ -49,8 +51,13 @@ public class CloudExplorerLiveTest { } @Test - public void testNoArgsReturnsInfo() throws Exception { - call(new String[0]); + public void testNoArgsThrows() throws Exception { + try { + call(new String[0]); + Assert.fail("No args should fail"); + } catch (ParseException e) { + Assert.assertTrue(e.toString().contains("No command specified"), ""+e); + } } // A user running these tests might not have any instances; so don't assert that there will be one http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java index 64326c9..9cc8ea2 100644 --- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java +++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java @@ -144,6 +144,7 @@ public class BrooklynLauncher { private boolean startWebApps = true; private boolean startBrooklynNode = false; private PortRange port = null; + private Boolean useHttps = null; private InetAddress bindAddress = null; private InetAddress publicAddress = null; private Map<String,String> webApps = new LinkedHashMap<String,String>(); @@ -335,12 +336,13 @@ public class BrooklynLauncher { * As {@link #webconsolePort(PortRange)} taking a string range */ public BrooklynLauncher webconsolePort(String port) { + if (port==null) return webconsolePort((PortRange)null); return webconsolePort(PortRanges.fromString(port)); } /** * Specifies the port where the web console (and any additional webapps specified) will listen; - * default "8081+" (or "8443+" for https) being the first available >= 8081. + * default (null) means "8081+" being the first available >= 8081 (or "8443+" for https). */ public BrooklynLauncher webconsolePort(PortRange port) { this.port = port; @@ -348,6 +350,14 @@ public class BrooklynLauncher { } /** + * Specifies whether the webconsole should use https. + */ + public BrooklynLauncher webconsoleHttps(Boolean useHttps) { + this.useHttps = useHttps; + return this; + } + + /** * Specifies the NIC where the web console (and any additional webapps specified) will be bound; * default 0.0.0.0, unless no security is specified (e.g. users) in which case it is localhost. */ @@ -721,7 +731,8 @@ public class BrooklynLauncher { webServer = new BrooklynWebServer(webconsoleFlags, managementContext); webServer.setBindAddress(bindAddress); webServer.setPublicAddress(publicAddress); - webServer.setPort(port); + if (port!=null) webServer.setPort(port); + if (useHttps!=null) webServer.setHttpsEnabled(useHttps); webServer.putAttributes(brooklynProperties); if (skipSecurityFilter != Boolean.TRUE) { webServer.setSecurityFilter(BrooklynPropertiesSecurityFilter.class); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java index a2595cd..97e93b4 100644 --- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java +++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java @@ -212,6 +212,9 @@ public class BrooklynWebServer { } public BrooklynWebServer setPort(Object port) { + if (port==null) { + this.requestedPort = null; + } if (getActualPort()>0) throw new IllegalStateException("Can't set port after port has been assigned to server (using "+getActualPort()+")"); this.requestedPort = TypeCoercions.coerce(port, PortRange.class); @@ -223,6 +226,11 @@ public class BrooklynWebServer { return webappTempDir; } + public BrooklynWebServer setHttpsEnabled(Boolean httpsEnabled) { + this.httpsEnabled = httpsEnabled; + return this; + } + public boolean getHttpsEnabled() { if (httpsEnabled!=null) return httpsEnabled; httpsEnabled = managementContext.getConfig().getConfig(BrooklynWebConfig.HTTPS_REQUIRED); @@ -338,7 +346,10 @@ public class BrooklynWebServer { if (actualPort == -1){ PortRange portRange = requestedPort; if (portRange==null) { - portRange = getHttpsEnabled()? httpsPort : httpPort; + portRange = managementContext.getConfig().getConfig(BrooklynWebConfig.WEB_CONSOLE_PORT); + } + if (portRange==null) { + portRange = getHttpsEnabled() ? httpsPort : httpPort; } actualPort = LocalhostMachineProvisioningLocation.obtainPort(getAddress(), portRange); if (actualPort == -1) http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java index cc44db7..cc2af2b 100644 --- a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java +++ b/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java @@ -70,7 +70,7 @@ public class WebAppRunnerTest { Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") ); bigProps.put("attributes", attributes); - BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault(); + 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"); @@ -145,7 +145,7 @@ public class WebAppRunnerTest { TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war"); BrooklynLauncher launcher = BrooklynLauncher.newInstance() - .globalBrooklynPropertiesFile(null) + .brooklynProperties(BrooklynProperties.Factory.newEmpty()) .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider") .webapp("/hello", "hello-world.war") .start(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java index 67fd069..289837a 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/BrooklynWebConfig.java @@ -22,6 +22,7 @@ import brooklyn.config.ConfigKey; import brooklyn.config.ConfigMap; import brooklyn.config.ConfigPredicates; import brooklyn.entity.basic.ConfigKeys; +import brooklyn.location.PortRange; import brooklyn.rest.security.provider.DelegatingSecurityProvider; import brooklyn.rest.security.provider.ExplicitUsersSecurityProvider; @@ -67,7 +68,11 @@ public class BrooklynWebConfig { public final static ConfigKey<Boolean> HTTPS_REQUIRED = ConfigKeys.newBooleanConfigKey( BASE_NAME+".security.https.required", - "Whether HTTPS is required", false); + "Whether HTTPS is required; false here can be overridden by CLI option", false); + + public final static ConfigKey<PortRange> WEB_CONSOLE_PORT = ConfigKeys.newConfigKey(PortRange.class, + BASE_NAME+".port", + "Port/range for the web console to listen on; can be overridden by CLI option"); public final static ConfigKey<String> KEYSTORE_URL = ConfigKeys.newStringConfigKey( BASE_NAME+".security.keystore.url", http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java index eeed1b8..8eaf321 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java @@ -219,6 +219,21 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv @Override public VersionSummary getVersion() { + // TODO reconcile this with BrooklynVersion reading from the OSGi manifest + // @ahgittin / @sjcorbett to decide, is there need for this in addition to the OSGi manifest? + // TODO as part of this call should we have a strategy for reporting downstream builds in this call? + // for instance, we could look for + // * ALL "brooklyn-build-metadata.properties" files on the classpath + // * and/or ALL items on classpath with a custom header (eg "Brooklyn-OSGi-Feature-Name: My Project") in MANIFEST.MF + // i tend to favour the latter as MANIFEST.MF is already recognised; is there a reason to introduce a new file? + // whichever we do, i think: + // * "build-metadata.properties" is probably the wrong name + // * we should include brooklyn.version and a build timestamp in this file + // * the authority for brooklyn should probably be core rather than brooklyn-rest-server + + // TODO in version summary, maybe also have: + // features: [ { name: my-project, version: 0.1.0-SNAPSHOT, git-sha1: xxx }, ... ] + // osgi: [ /* similar metadata extracted from all active osgi bundles */ ] InputStream input = ResourceUtils.create().getResourceFromUrl("classpath://build-metadata.properties"); Properties properties = new Properties(); String gitSha1 = null, gitBranch = null; http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java b/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java index fc5e3c6..e09a42c 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/security/provider/ExplicitUsersSecurityProvider.java @@ -57,6 +57,8 @@ public class ExplicitUsersSecurityProvider extends AbstractSecurityProvider impl allowedUsers = new LinkedHashSet<String>(); String users = properties.getConfig(BrooklynWebConfig.USERS); if (users == null) { + // TODO unfortunately this is only activated *when* someone tries to log in + // (NB it seems like this class is not even instantiated until first log in) LOG.warn("REST has no users configured; no one will be able to log in!"); } else if ("*".equals(users)) { LOG.info("REST allowing any user (so long as valid password is set)"); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d423522c/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java ---------------------------------------------------------------------- diff --git a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java index ceee367..71eff35 100644 --- a/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java +++ b/usage/test-support/src/main/java/brooklyn/test/HttpTestUtils.java @@ -39,12 +39,12 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import brooklyn.util.collections.MutableMap; +import brooklyn.util.crypto.SslTrustUtils; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.stream.Streams; import brooklyn.util.time.Time; @@ -326,7 +326,7 @@ public class HttpTestUtils { public static String getContent(String url) { try { - return DefaultGroovyMethods.getText(new URL(url).openStream()); + return Streams.readFullyString(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream()); } catch (Exception e) { throw Throwables.propagate(e); }