From 854cacdb4fb5f1d4d53bfac22848960ab75e2af3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 21 Jan 2016 14:39:39 +0000 Subject: [PATCH] Fix useStartStopDaemon in launch script and allow config via conf file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 5a1ee6eb added support for disabling use of start-stop-daemon via a placeholder in the default launch script. Unfortunately, that placeholder was subsequently broken in 81a47639. This commit reinstates the placeholder and adds tests to verify that all of the placeholders in the launch script can be replaced and that they have the required default values. Furthermore, it also allows the use of start-stop-daemon to be configured via USE_START_STOP_DAEMON in an app’s .conf file. This allows the configuration to be changed after the app has been built. Closes gh-4985 --- .../src/main/asciidoc/deployment.adoc | 8 +- .../launchscript/SysVinitLaunchScriptIT.java | 10 +++ ...-with-use-of-start-stop-daemon-disabled.sh | 7 ++ .../boot/loader/tools/launch.script | 5 +- .../tools/DefaultLaunchScriptTests.java | 82 ++++++++++++++++--- 5 files changed, 95 insertions(+), 17 deletions(-) create mode 100755 spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/launch-with-use-of-start-stop-daemon-disabled.sh diff --git a/spring-boot-docs/src/main/asciidoc/deployment.adoc b/spring-boot-docs/src/main/asciidoc/deployment.adoc index 9a1c64ca4e1..b5900837001 100644 --- a/spring-boot-docs/src/main/asciidoc/deployment.adoc +++ b/spring-boot-docs/src/main/asciidoc/deployment.adoc @@ -541,6 +541,10 @@ the default behavior in a script or on the command line: that the `stop\|start\|status\|restart` commands work, or to `run` if you just want to run the script in the foreground. +|`USE_START_STOP_DAEMON` +|If the `start-stop-daemon` command, when it's available, should be used to control the + process. Defaults to `true`. + |`PID_FOLDER` |The root name of the pid folder (`/var/run` by default). @@ -606,8 +610,8 @@ for Gradle and to `${project.name}` for Maven. |The `chkconfig` section of "`INIT INFO`". Defaults to `2345 99 01`. |`useStartStopDaemon` -|If the start-stop command should be used to control the process when it's available. - Defaults to `true`. +|If the `start-stop-daemon` command, when it's available, should be used to control the + process. Defaults to `true`. |=== diff --git a/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java b/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java index 69e50381903..22ab687d1ee 100644 --- a/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java +++ b/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/java/org/springframework/boot/launchscript/SysVinitLaunchScriptIT.java @@ -50,7 +50,10 @@ import org.junit.runners.Parameterized.Parameters; import org.springframework.boot.ansi.AnsiColor; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeThat; /** * Integration tests for Spring Boot's launch script on OSs that use SysVinit. @@ -188,6 +191,13 @@ public class SysVinitLaunchScriptIT { doLaunch("launch-with-multiple-java-opts.sh"); } + @Test + public void launchWithUseOfStartStopDaemonDisabled() throws Exception { + // CentOS doesn't have start-stop-daemon + assumeThat(this.os, is(not("CentOS"))); + doLaunch("launch-with-use-of-start-stop-daemon-disabled.sh"); + } + private void doLaunch(String script) throws Exception { assertThat(doTest(script), containsString("Launched")); } diff --git a/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/launch-with-use-of-start-stop-daemon-disabled.sh b/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/launch-with-use-of-start-stop-daemon-disabled.sh new file mode 100755 index 00000000000..75b98f69e82 --- /dev/null +++ b/spring-boot-integration-tests/spring-boot-launch-script-tests/src/test/resources/scripts/launch-with-use-of-start-stop-daemon-disabled.sh @@ -0,0 +1,7 @@ +source ./test-functions.sh +chmod -x $(type -p start-stop-daemon) +echo 'USE_START_STOP_DAEMON=false' > /spring-boot-app.conf +install_service +start_service +await_app +curl -s http://127.0.0.1:8080/ diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script b/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script index b7877fb0ef5..11f55304b42 100755 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script @@ -51,8 +51,9 @@ configfile="$(basename "${jarfile%.*}.conf")" ! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp" ! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp" -# Setup defaults +# Set up defaults [[ -z "$MODE" ]] && MODE="{{mode:auto}}" # modes are "auto", "service" or "run" +[[ -z "$USE_START_STOP_DAEMON" ]] && USE_START_STOP_DAEMON="{{useStartStopDaemon:true}}" # Create an identity for log/pid files if [[ -z "$identity" ]]; then @@ -146,7 +147,7 @@ do_start() { chown "$run_user" "$PID_FOLDER" chown "$run_user" "$pid_file" chown "$run_user" "$log_file" - if [ "${useStartStopDaemon:-true}" = true ] && type start-stop-daemon > /dev/null 2>&1; then + if [ $USE_START_STOP_DAEMON = true ] && type start-stop-daemon > /dev/null 2>&1; then arguments=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar $jarfile $RUN_ARGS "$@") start-stop-daemon --start --quiet \ --chuid "$run_user" \ diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java index 2e6c480555f..fec531b74ed 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/DefaultLaunchScriptTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,8 @@ package org.springframework.boot.loader.tools; import java.io.File; -import java.util.Properties; +import java.util.HashMap; +import java.util.Map; import org.junit.Rule; import org.junit.Test; @@ -33,6 +34,7 @@ import static org.junit.Assert.assertThat; * Tests for {@link DefaultLaunchScript}. * * @author Phillip Webb + * @author Andy Wilkinson */ public class DefaultLaunchScriptTests { @@ -44,6 +46,49 @@ public class DefaultLaunchScriptTests { DefaultLaunchScript script = new DefaultLaunchScript(null, null); String content = new String(script.toByteArray()); assertThat(content, containsString("Spring Boot Startup Script")); + } + + @Test + public void initInfoProvidesCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("initInfoProvides"); + } + + @Test + public void initInfoShortDescriptionCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("initInfoShortDescription"); + } + + @Test + public void initInfoDescriptionCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("initInfoDescription"); + } + + @Test + public void initInfoChkconfigCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("initInfoChkconfig"); + } + + @Test + public void modeCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("mode"); + } + + @Test + public void useStartStopDaemonCanBeReplaced() throws Exception { + assertThatPlaceholderCanBeReplaced("useStartStopDaemon"); + } + + @Test + public void defaultForUseStartStopDaemonIsTrue() throws Exception { + DefaultLaunchScript script = new DefaultLaunchScript(null, null); + String content = new String(script.toByteArray()); + assertThat(content, containsString("USE_START_STOP_DAEMON=\"true\"")); + } + + @Test + public void defaultForModeIsAuto() throws Exception { + DefaultLaunchScript script = new DefaultLaunchScript(null, null); + String content = new String(script.toByteArray()); assertThat(content, containsString("MODE=\"auto\"")); } @@ -60,10 +105,8 @@ public class DefaultLaunchScriptTests { public void expandVariables() throws Exception { File file = this.temporaryFolder.newFile(); FileCopyUtils.copy("h{{a}}ll{{b}}".getBytes(), file); - Properties properties = new Properties(); - properties.put("a", "e"); - properties.put("b", "o"); - DefaultLaunchScript script = new DefaultLaunchScript(file, properties); + DefaultLaunchScript script = new DefaultLaunchScript(file, + createProperties("a:e", "b:o")); String content = new String(script.toByteArray()); assertThat(content, equalTo("hello")); } @@ -72,10 +115,8 @@ public class DefaultLaunchScriptTests { public void expandVariablesMultiLine() throws Exception { File file = this.temporaryFolder.newFile(); FileCopyUtils.copy("h{{a}}l\nl{{b}}".getBytes(), file); - Properties properties = new Properties(); - properties.put("a", "e"); - properties.put("b", "o"); - DefaultLaunchScript script = new DefaultLaunchScript(file, properties); + DefaultLaunchScript script = new DefaultLaunchScript(file, + createProperties("a:e", "b:o")); String content = new String(script.toByteArray()); assertThat(content, equalTo("hel\nlo")); } @@ -93,9 +134,8 @@ public class DefaultLaunchScriptTests { public void expandVariablesWithDefaultsOverride() throws Exception { File file = this.temporaryFolder.newFile(); FileCopyUtils.copy("h{{a:e}}ll{{b:o}}".getBytes(), file); - Properties properties = new Properties(); - properties.put("a", "a"); - DefaultLaunchScript script = new DefaultLaunchScript(file, properties); + DefaultLaunchScript script = new DefaultLaunchScript(file, + createProperties("a:a")); String content = new String(script.toByteArray()); assertThat(content, equalTo("hallo")); } @@ -109,4 +149,20 @@ public class DefaultLaunchScriptTests { assertThat(content, equalTo("h{{a}}ll{{b}}")); } + private void assertThatPlaceholderCanBeReplaced(String placeholder) throws Exception { + DefaultLaunchScript script = new DefaultLaunchScript(null, + createProperties(placeholder + ":__test__")); + String content = new String(script.toByteArray()); + assertThat(content, containsString("__test__")); + } + + private Map createProperties(String... pairs) { + Map properties = new HashMap(); + for (String pair : pairs) { + String[] keyValue = pair.split(":"); + properties.put(keyValue[0], keyValue[1]); + } + return properties; + } + }