Change DockerComposeProperties shut down default to stop
Closes gh-35239
This commit is contained in:
@@ -33,35 +33,35 @@ import org.springframework.boot.logging.LogLevel;
|
||||
public interface DockerCompose {
|
||||
|
||||
/**
|
||||
* Timeout duration used to request a forced shutdown.
|
||||
* Timeout duration used to request a forced stop.
|
||||
*/
|
||||
Duration FORCE_SHUTDOWN = Duration.ZERO;
|
||||
Duration FORCE_STOP = Duration.ZERO;
|
||||
|
||||
/**
|
||||
* Run {@code docker compose up} to startup services. Waits until all contains are
|
||||
* started and healthy.
|
||||
* Run {@code docker compose up} to create and start services. Waits until all
|
||||
* contains are started and healthy.
|
||||
* @param logLevel the log level used to report progress
|
||||
*/
|
||||
void up(LogLevel logLevel);
|
||||
|
||||
/**
|
||||
* Run {@code docker compose down} to shut down any running services.
|
||||
* @param timeout the amount of time to wait or {@link #FORCE_SHUTDOWN} to shut down
|
||||
* without waiting.
|
||||
* Run {@code docker compose down} to stop and remove any running services.
|
||||
* @param timeout the amount of time to wait or {@link #FORCE_STOP} to stop without
|
||||
* waiting.
|
||||
*/
|
||||
void down(Duration timeout);
|
||||
|
||||
/**
|
||||
* Run {@code docker compose start} to startup services. Waits until all contains are
|
||||
* Run {@code docker compose start} to start services. Waits until all containers are
|
||||
* started and healthy.
|
||||
* @param logLevel the log level used to report progress
|
||||
*/
|
||||
void start(LogLevel logLevel);
|
||||
|
||||
/**
|
||||
* Run {@code docker compose stop} to shut down any running services.
|
||||
* @param timeout the amount of time to wait or {@link #FORCE_SHUTDOWN} to shut down
|
||||
* without waiting.
|
||||
* Run {@code docker compose stop} to stop any running services.
|
||||
* @param timeout the amount of time to wait or {@link #FORCE_STOP} to stop without
|
||||
* waiting.
|
||||
*/
|
||||
void stop(Duration timeout);
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.docker.compose.core.DockerCompose;
|
||||
import org.springframework.boot.docker.compose.core.DockerComposeFile;
|
||||
import org.springframework.boot.docker.compose.core.RunningService;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties.Shutdown;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties.Startup;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties.Start;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties.Stop;
|
||||
import org.springframework.boot.docker.compose.readiness.ServiceReadinessChecks;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -89,30 +89,30 @@ class DockerComposeLifecycleManager {
|
||||
: new ServiceReadinessChecks(this.classLoader, applicationContext.getEnvironment(), binder);
|
||||
}
|
||||
|
||||
void startup() {
|
||||
void start() {
|
||||
if (!this.properties.isEnabled()) {
|
||||
logger.trace("Docker compose support not enabled");
|
||||
logger.trace("Docker Compose support not enabled");
|
||||
return;
|
||||
}
|
||||
if (this.skipCheck.shouldSkip(this.classLoader, this.properties.getSkip())) {
|
||||
logger.trace("Docker compose support skipped");
|
||||
logger.trace("Docker Compose support skipped");
|
||||
return;
|
||||
}
|
||||
DockerComposeFile composeFile = getComposeFile();
|
||||
Set<String> activeProfiles = this.properties.getProfiles().getActive();
|
||||
DockerCompose dockerCompose = getDockerCompose(composeFile, activeProfiles);
|
||||
if (!dockerCompose.hasDefinedServices()) {
|
||||
logger.warn(LogMessage.format("No services defined in docker compose file '%s' with active profiles %s",
|
||||
logger.warn(LogMessage.format("No services defined in Docker Compose file '%s' with active profiles %s",
|
||||
composeFile, activeProfiles));
|
||||
return;
|
||||
}
|
||||
LifecycleManagement lifecycleManagement = this.properties.getLifecycleManagement();
|
||||
Startup startup = this.properties.getStartup();
|
||||
Shutdown shutdown = this.properties.getShutdown();
|
||||
if (lifecycleManagement.shouldStartup() && !dockerCompose.hasRunningServices()) {
|
||||
startup.getCommand().applyTo(dockerCompose, startup.getLogLevel());
|
||||
if (lifecycleManagement.shouldShutdown()) {
|
||||
this.shutdownHandlers.add(() -> shutdown.getCommand().applyTo(dockerCompose, shutdown.getTimeout()));
|
||||
Start start = this.properties.getStart();
|
||||
Stop stop = this.properties.getStop();
|
||||
if (lifecycleManagement.shouldStart() && !dockerCompose.hasRunningServices()) {
|
||||
start.getCommand().applyTo(dockerCompose, start.getLogLevel());
|
||||
if (lifecycleManagement.shouldStop()) {
|
||||
this.shutdownHandlers.add(() -> stop.getCommand().applyTo(dockerCompose, stop.getTimeout()));
|
||||
}
|
||||
}
|
||||
List<RunningService> runningServices = new ArrayList<>(dockerCompose.getRunningServices());
|
||||
@@ -124,7 +124,7 @@ class DockerComposeLifecycleManager {
|
||||
protected DockerComposeFile getComposeFile() {
|
||||
DockerComposeFile composeFile = (this.properties.getFile() != null)
|
||||
? DockerComposeFile.of(this.properties.getFile()) : DockerComposeFile.find(this.workingDirectory);
|
||||
logger.info(LogMessage.format("Found docker compose file '%s'", composeFile));
|
||||
logger.info(LogMessage.format("Found Docker Compose file '%s'", composeFile));
|
||||
return composeFile;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class DockerComposeListener implements ApplicationListener<ApplicationPreparedEv
|
||||
Binder binder = Binder.get(applicationContext.getEnvironment());
|
||||
DockerComposeProperties properties = DockerComposeProperties.get(binder);
|
||||
Set<ApplicationListener<?>> eventListeners = event.getSpringApplication().getListeners();
|
||||
createDockerComposeLifecycleManager(applicationContext, binder, properties, eventListeners).startup();
|
||||
createDockerComposeLifecycleManager(applicationContext, binder, properties, eventListeners).start();
|
||||
}
|
||||
|
||||
protected DockerComposeLifecycleManager createDockerComposeLifecycleManager(
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* Configuration properties for the 'docker compose'.
|
||||
* Configuration properties for Docker Compose.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
@@ -61,12 +61,12 @@ public class DockerComposeProperties {
|
||||
/**
|
||||
* Start configuration.
|
||||
*/
|
||||
private final Startup startup = new Startup();
|
||||
private final Start start = new Start();
|
||||
|
||||
/**
|
||||
* Stop configuration.
|
||||
*/
|
||||
private final Shutdown shutdown = new Shutdown();
|
||||
private final Stop stop = new Stop();
|
||||
|
||||
/**
|
||||
* Profiles configuration.
|
||||
@@ -107,12 +107,12 @@ public class DockerComposeProperties {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Startup getStartup() {
|
||||
return this.startup;
|
||||
public Start getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public Shutdown getShutdown() {
|
||||
return this.shutdown;
|
||||
public Stop getStop() {
|
||||
return this.stop;
|
||||
}
|
||||
|
||||
public Profiles getProfiles() {
|
||||
@@ -128,25 +128,25 @@ public class DockerComposeProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup properties.
|
||||
* Start properties.
|
||||
*/
|
||||
public static class Startup {
|
||||
public static class Start {
|
||||
|
||||
/**
|
||||
* Command used to start docker compose.
|
||||
*/
|
||||
private StartupCommand command = StartupCommand.UP;
|
||||
private StartCommand command = StartCommand.UP;
|
||||
|
||||
/**
|
||||
* Log level for output.
|
||||
*/
|
||||
private LogLevel logLevel = LogLevel.INFO;
|
||||
|
||||
public StartupCommand getCommand() {
|
||||
public StartCommand getCommand() {
|
||||
return this.command;
|
||||
}
|
||||
|
||||
public void setCommand(StartupCommand command) {
|
||||
public void setCommand(StartCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@@ -161,25 +161,25 @@ public class DockerComposeProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown properties.
|
||||
* Stop properties.
|
||||
*/
|
||||
public static class Shutdown {
|
||||
public static class Stop {
|
||||
|
||||
/**
|
||||
* Command used to stop docker compose.
|
||||
*/
|
||||
private ShutdownCommand command = ShutdownCommand.DOWN;
|
||||
private StopCommand command = StopCommand.STOP;
|
||||
|
||||
/**
|
||||
* Timeout for stopping docker compose. Use '0' for forced stop.
|
||||
* Timeout for stopping Docker Compose. Use '0' for forced stop.
|
||||
*/
|
||||
private Duration timeout = Duration.ofSeconds(10);
|
||||
|
||||
public ShutdownCommand getCommand() {
|
||||
public StopCommand getCommand() {
|
||||
return this.command;
|
||||
}
|
||||
|
||||
public void setCommand(ShutdownCommand command) {
|
||||
public void setCommand(StopCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* {@link ApplicationEvent} published when docker compose {@link RunningService} instances
|
||||
* are available. This event is published from the {@link ApplicationPreparedEvent} that
|
||||
* performs the docker compose startup.
|
||||
* {@link ApplicationEvent} published when Docker Compose {@link RunningService} instances
|
||||
* are available. This event is published from the {@link ApplicationPreparedEvent}
|
||||
* listener that starts Docker Compose.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.boot.SpringApplicationAotProcessor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Checks if docker compose support should be skipped.
|
||||
* Checks if Docker Compose support should be skipped.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.springframework.boot.docker.compose.lifecycle;
|
||||
|
||||
/**
|
||||
* Docker compose lifecycle management.
|
||||
* Docker Compose lifecycle management.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
@@ -27,43 +27,43 @@ package org.springframework.boot.docker.compose.lifecycle;
|
||||
public enum LifecycleManagement {
|
||||
|
||||
/**
|
||||
* Don't start or stop docker compose.
|
||||
* Don't start or stop Docker Compose.
|
||||
*/
|
||||
NONE(false, false),
|
||||
|
||||
/**
|
||||
* Only start docker compose if it's not running.
|
||||
* Start Docker Compose if it's not running.
|
||||
*/
|
||||
START_ONLY(true, false),
|
||||
|
||||
/**
|
||||
* Start and stop docker compose if it's not running.
|
||||
* Start Docker Compose if it's not running and stop it when the JVM exits.
|
||||
*/
|
||||
START_AND_STOP(true, true);
|
||||
|
||||
private final boolean startup;
|
||||
private final boolean start;
|
||||
|
||||
private final boolean shutdown;
|
||||
private final boolean stop;
|
||||
|
||||
LifecycleManagement(boolean startup, boolean shutdown) {
|
||||
this.startup = startup;
|
||||
this.shutdown = shutdown;
|
||||
LifecycleManagement(boolean start, boolean stop) {
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether docker compose should be started.
|
||||
* @return whether docker compose should be started
|
||||
* Return whether Docker Compose should be started.
|
||||
* @return whether Docker Compose should be started
|
||||
*/
|
||||
boolean shouldStartup() {
|
||||
return this.startup;
|
||||
boolean shouldStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether docker compose should be stopped.
|
||||
* @return whether docker compose should be stopped
|
||||
* Return whether Docker Compose should be stopped.
|
||||
* @return whether Docker Compose should be stopped
|
||||
*/
|
||||
boolean shouldShutdown() {
|
||||
return this.shutdown;
|
||||
boolean shouldStop() {
|
||||
return this.stop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,28 +22,28 @@ import org.springframework.boot.docker.compose.core.DockerCompose;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
|
||||
/**
|
||||
* Command used to startup docker compose.
|
||||
* Command used to start Docker Compose.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public enum StartupCommand {
|
||||
public enum StartCommand {
|
||||
|
||||
/**
|
||||
* Startup using {@code docker compose up}.
|
||||
* Start using {@code docker compose up}.
|
||||
*/
|
||||
UP(DockerCompose::up),
|
||||
|
||||
/**
|
||||
* Startup using {@code docker compose start}.
|
||||
* Start using {@code docker compose start}.
|
||||
*/
|
||||
START(DockerCompose::start);
|
||||
|
||||
private final BiConsumer<DockerCompose, LogLevel> action;
|
||||
|
||||
StartupCommand(BiConsumer<DockerCompose, LogLevel> action) {
|
||||
StartCommand(BiConsumer<DockerCompose, LogLevel> action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@@ -22,28 +22,28 @@ import java.util.function.BiConsumer;
|
||||
import org.springframework.boot.docker.compose.core.DockerCompose;
|
||||
|
||||
/**
|
||||
* Command used to shut down docker compose.
|
||||
* Command used to stop Docker Compose.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public enum ShutdownCommand {
|
||||
public enum StopCommand {
|
||||
|
||||
/**
|
||||
* Shutdown using {@code docker compose down}.
|
||||
* Stop using {@code docker compose down}.
|
||||
*/
|
||||
DOWN(DockerCompose::down),
|
||||
|
||||
/**
|
||||
* Shutdown using {@code docker compose stop}.
|
||||
* Stop using {@code docker compose stop}.
|
||||
*/
|
||||
STOP(DockerCompose::stop);
|
||||
|
||||
private final BiConsumer<DockerCompose, Duration> action;
|
||||
|
||||
ShutdownCommand(BiConsumer<DockerCompose, Duration> action) {
|
||||
StopCommand(BiConsumer<DockerCompose, Duration> action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lifecycle management for docker compose with the context of a Spring application.
|
||||
* Lifecycle management for Docker Compose with the context of a Spring application.
|
||||
*/
|
||||
package org.springframework.boot.docker.compose.lifecycle;
|
||||
|
||||
@@ -103,32 +103,32 @@ class DockerComposeLifecycleManagerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenEnabledFalseDoesNotStart() {
|
||||
void startWhenEnabledFalseDoesNotStart() {
|
||||
this.properties.setEnabled(false);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
assertThat(listener.getEvent()).isNull();
|
||||
then(this.dockerCompose).should(never()).hasDefinedServices();
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenInTestDoesNotStart() {
|
||||
void startWhenInTestDoesNotStart() {
|
||||
given(this.skipCheck.shouldSkip(any(), any())).willReturn(true);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
assertThat(listener.getEvent()).isNull();
|
||||
then(this.dockerCompose).should(never()).hasDefinedServices();
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenHasNoDefinedServicesDoesNothing() {
|
||||
void startWhenHasNoDefinedServicesDoesNothing() {
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
assertThat(listener.getEvent()).isNull();
|
||||
then(this.dockerCompose).should().hasDefinedServices();
|
||||
then(this.dockerCompose).should(never()).up(any());
|
||||
@@ -138,27 +138,27 @@ class DockerComposeLifecycleManagerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenLifecycleStartAndStopAndHasNoRunningServicesDoesStartupAndShutdown() {
|
||||
void startWhenLifecycleStartAndStopAndHasNoRunningServicesDoesUpAndStop() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_AND_STOP);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should().up(any());
|
||||
then(this.dockerCompose).should(never()).start(any());
|
||||
then(this.dockerCompose).should().down(any());
|
||||
then(this.dockerCompose).should(never()).stop(any());
|
||||
then(this.dockerCompose).should().stop(any());
|
||||
then(this.dockerCompose).should(never()).down(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenLifecycleStartAndStopAndHasRunningServicesDoesNoStartupOrShutdown() {
|
||||
void startWhenLifecycleStartAndStopAndHasRunningServicesDoesNothing() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_AND_STOP);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should(never()).up(any());
|
||||
@@ -168,12 +168,12 @@ class DockerComposeLifecycleManagerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenLifecycleNoneDoesNoStartupOrShutdown() {
|
||||
void startWhenLifecycleNoneDoesNothing() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.NONE);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should(never()).up(any());
|
||||
@@ -183,12 +183,12 @@ class DockerComposeLifecycleManagerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenLifecycleStartOnlyDoesStartupAndNoShutdown() {
|
||||
void startWhenLifecycleStartOnlyDoesOnlyStart() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_ONLY);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should().up(any());
|
||||
@@ -199,97 +199,97 @@ class DockerComposeLifecycleManagerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenStartupCommandStartDoesStartupUsingStartAndShutdown() {
|
||||
void startWhenStartCommandStartDoesStartAndStop() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_AND_STOP);
|
||||
this.properties.getStartup().setCommand(StartupCommand.START);
|
||||
this.properties.getStart().setCommand(StartCommand.START);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should(never()).up(any());
|
||||
then(this.dockerCompose).should().start(any());
|
||||
then(this.dockerCompose).should().down(any());
|
||||
then(this.dockerCompose).should(never()).stop(any());
|
||||
then(this.dockerCompose).should().stop(any());
|
||||
then(this.dockerCompose).should(never()).down(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenShutdownCommandStopDoesStartupAndShutdownUsingStop() {
|
||||
void startWhenStopCommandDownDoesStartAndDown() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_AND_STOP);
|
||||
this.properties.getShutdown().setCommand(ShutdownCommand.STOP);
|
||||
this.properties.getStop().setCommand(StopCommand.DOWN);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should().up(any());
|
||||
then(this.dockerCompose).should(never()).start(any());
|
||||
then(this.dockerCompose).should(never()).down(any());
|
||||
then(this.dockerCompose).should().stop(any());
|
||||
then(this.dockerCompose).should(never()).stop(any());
|
||||
then(this.dockerCompose).should().down(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenHasShutdownTimeoutUsesDuration() {
|
||||
void startWhenHasStopTimeoutUsesDuration() {
|
||||
this.properties.setLifecycleManagement(LifecycleManagement.START_AND_STOP);
|
||||
Duration timeout = Duration.ofDays(1);
|
||||
this.properties.getShutdown().setTimeout(timeout);
|
||||
this.properties.getStop().setTimeout(timeout);
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
this.lifecycleManager.startup();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
then(this.dockerCompose).should().down(timeout);
|
||||
then(this.dockerCompose).should().stop(timeout);
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWhenHasIgnoreLabelIgnoresService() {
|
||||
void startWhenHasIgnoreLabelIgnoresService() {
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices(Map.of("org.springframework.boot.ignore", "true"));
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices(Map.of("org.springframework.boot.ignore", "true"));
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
assertThat(listener.getEvent()).isNotNull();
|
||||
assertThat(listener.getEvent().getRunningServices()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupWaitsUntilReady() {
|
||||
void startWaitsUntilReady() {
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
this.shutdownHandlers.run();
|
||||
then(this.serviceReadinessChecks).should().waitUntilReady(this.runningServices);
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupGetsDockerComposeWithActiveProfiles() {
|
||||
void startGetsDockerComposeWithActiveProfiles() {
|
||||
this.properties.getProfiles().setActive(Set.of("my-profile"));
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
assertThat(this.activeProfiles).containsExactly("my-profile");
|
||||
}
|
||||
|
||||
@Test
|
||||
void startupPublishesEvent() {
|
||||
void startPublishesEvent() {
|
||||
EventCapturingListener listener = new EventCapturingListener();
|
||||
this.eventListeners.add(listener);
|
||||
setupRunningServices();
|
||||
this.lifecycleManager.startup();
|
||||
setUpRunningServices();
|
||||
this.lifecycleManager.start();
|
||||
DockerComposeServicesReadyEvent event = listener.getEvent();
|
||||
assertThat(event).isNotNull();
|
||||
assertThat(event.getSource()).isEqualTo(this.applicationContext);
|
||||
assertThat(event.getRunningServices()).isEqualTo(this.runningServices);
|
||||
}
|
||||
|
||||
private void setupRunningServices() {
|
||||
setupRunningServices(Collections.emptyMap());
|
||||
private void setUpRunningServices() {
|
||||
setUpRunningServices(Collections.emptyMap());
|
||||
}
|
||||
|
||||
private void setupRunningServices(Map<String, String> labels) {
|
||||
private void setUpRunningServices(Map<String, String> labels) {
|
||||
given(this.dockerCompose.hasDefinedServices()).willReturn(true);
|
||||
given(this.dockerCompose.hasRunningServices()).willReturn(true);
|
||||
RunningService runningService = mock(RunningService.class);
|
||||
|
||||
@@ -53,7 +53,7 @@ class DockerComposeListenerTests {
|
||||
ApplicationPreparedEvent event = new ApplicationPreparedEvent(application, new String[0], context);
|
||||
listener.onApplicationEvent(event);
|
||||
assertThat(listener.getManager()).isNotNull();
|
||||
then(listener.getManager()).should().startup();
|
||||
then(listener.getManager()).should().start();
|
||||
}
|
||||
|
||||
static class TestDockerComposeListener extends DockerComposeListener {
|
||||
|
||||
@@ -44,9 +44,9 @@ class DockerComposePropertiesTests {
|
||||
assertThat(properties.getFile()).isNull();
|
||||
assertThat(properties.getLifecycleManagement()).isEqualTo(LifecycleManagement.START_AND_STOP);
|
||||
assertThat(properties.getHost()).isNull();
|
||||
assertThat(properties.getStartup().getCommand()).isEqualTo(StartupCommand.UP);
|
||||
assertThat(properties.getShutdown().getCommand()).isEqualTo(ShutdownCommand.DOWN);
|
||||
assertThat(properties.getShutdown().getTimeout()).isEqualTo(Duration.ofSeconds(10));
|
||||
assertThat(properties.getStart().getCommand()).isEqualTo(StartCommand.UP);
|
||||
assertThat(properties.getStop().getCommand()).isEqualTo(StopCommand.STOP);
|
||||
assertThat(properties.getStop().getTimeout()).isEqualTo(Duration.ofSeconds(10));
|
||||
assertThat(properties.getProfiles().getActive()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -56,18 +56,18 @@ class DockerComposePropertiesTests {
|
||||
source.put("spring.docker.compose.file", "my-compose.yml");
|
||||
source.put("spring.docker.compose.lifecycle-management", "start-only");
|
||||
source.put("spring.docker.compose.host", "myhost");
|
||||
source.put("spring.docker.compose.startup.command", "start");
|
||||
source.put("spring.docker.compose.shutdown.command", "stop");
|
||||
source.put("spring.docker.compose.shutdown.timeout", "5s");
|
||||
source.put("spring.docker.compose.start.command", "start");
|
||||
source.put("spring.docker.compose.stop.command", "down");
|
||||
source.put("spring.docker.compose.stop.timeout", "5s");
|
||||
source.put("spring.docker.compose.profiles.active", "myprofile");
|
||||
Binder binder = new Binder(new MapConfigurationPropertySource(source));
|
||||
DockerComposeProperties properties = DockerComposeProperties.get(binder);
|
||||
assertThat(properties.getFile()).isEqualTo(new File("my-compose.yml"));
|
||||
assertThat(properties.getLifecycleManagement()).isEqualTo(LifecycleManagement.START_ONLY);
|
||||
assertThat(properties.getHost()).isEqualTo("myhost");
|
||||
assertThat(properties.getStartup().getCommand()).isEqualTo(StartupCommand.START);
|
||||
assertThat(properties.getShutdown().getCommand()).isEqualTo(ShutdownCommand.STOP);
|
||||
assertThat(properties.getShutdown().getTimeout()).isEqualTo(Duration.ofSeconds(5));
|
||||
assertThat(properties.getStart().getCommand()).isEqualTo(StartCommand.START);
|
||||
assertThat(properties.getStop().getCommand()).isEqualTo(StopCommand.DOWN);
|
||||
assertThat(properties.getStop().getTimeout()).isEqualTo(Duration.ofSeconds(5));
|
||||
assertThat(properties.getProfiles().getActive()).containsExactly("myprofile");
|
||||
}
|
||||
|
||||
|
||||
@@ -31,32 +31,32 @@ class LifecycleManagementTests {
|
||||
|
||||
@Test
|
||||
void shouldStartupWhenNone() {
|
||||
assertThat(LifecycleManagement.NONE.shouldStartup()).isFalse();
|
||||
assertThat(LifecycleManagement.NONE.shouldStart()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldShutdownWhenNone() {
|
||||
assertThat(LifecycleManagement.NONE.shouldShutdown()).isFalse();
|
||||
assertThat(LifecycleManagement.NONE.shouldStop()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldStartupWhenStartOnly() {
|
||||
assertThat(LifecycleManagement.START_ONLY.shouldStartup()).isTrue();
|
||||
assertThat(LifecycleManagement.START_ONLY.shouldStart()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldShutdownWhenStartOnly() {
|
||||
assertThat(LifecycleManagement.START_ONLY.shouldShutdown()).isFalse();
|
||||
assertThat(LifecycleManagement.START_ONLY.shouldStop()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldStartupWhenStartAndStop() {
|
||||
assertThat(LifecycleManagement.START_AND_STOP.shouldStartup()).isTrue();
|
||||
assertThat(LifecycleManagement.START_AND_STOP.shouldStart()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldShutdownWhenStartAndStop() {
|
||||
assertThat(LifecycleManagement.START_AND_STOP.shouldShutdown()).isTrue();
|
||||
assertThat(LifecycleManagement.START_AND_STOP.shouldStop()).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,25 +25,25 @@ import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link StartupCommand}.
|
||||
* Tests for {@link StartCommand}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class StartupCommandTests {
|
||||
class StartCommandTests {
|
||||
|
||||
private DockerCompose dockerCompose = mock(DockerCompose.class);
|
||||
|
||||
@Test
|
||||
void applyToWhenUp() {
|
||||
StartupCommand.UP.applyTo(this.dockerCompose, LogLevel.INFO);
|
||||
StartCommand.UP.applyTo(this.dockerCompose, LogLevel.INFO);
|
||||
then(this.dockerCompose).should().up(LogLevel.INFO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyToWhenStart() {
|
||||
StartupCommand.START.applyTo(this.dockerCompose, LogLevel.INFO);
|
||||
StartCommand.START.applyTo(this.dockerCompose, LogLevel.INFO);
|
||||
then(this.dockerCompose).should().start(LogLevel.INFO);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@ import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link ShutdownCommand}.
|
||||
* Tests for {@link StopCommand}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ShutdownCommandTests {
|
||||
class StopCommandTests {
|
||||
|
||||
private DockerCompose dockerCompose = mock(DockerCompose.class);
|
||||
|
||||
@@ -40,13 +40,13 @@ class ShutdownCommandTests {
|
||||
|
||||
@Test
|
||||
void applyToWhenDown() {
|
||||
ShutdownCommand.DOWN.applyTo(this.dockerCompose, this.duration);
|
||||
StopCommand.DOWN.applyTo(this.dockerCompose, this.duration);
|
||||
then(this.dockerCompose).should().down(this.duration);
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyToWhenStart() {
|
||||
ShutdownCommand.STOP.applyTo(this.dockerCompose, this.duration);
|
||||
StopCommand.STOP.applyTo(this.dockerCompose, this.duration);
|
||||
then(this.dockerCompose).should().stop(this.duration);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class AbstractDockerComposeIntegrationTests {
|
||||
private final Resource composeResource;
|
||||
|
||||
@AfterAll
|
||||
static void shutdown() {
|
||||
static void shutDown() {
|
||||
SpringApplicationShutdownHandlers shutdownHandlers = SpringApplication.getShutdownHandlers();
|
||||
((Runnable) shutdownHandlers).run();
|
||||
}
|
||||
|
||||
@@ -169,17 +169,17 @@ TIP: You can also provide your own `ServiceReadinessCheck` implementations and r
|
||||
|
||||
[[features.docker-compose.lifecycle]]
|
||||
=== Controlling the Docker Compose Lifecycle
|
||||
By default Spring Boot calls `docker compose up` when your application starts and `docker compose down` when it's shutdown.
|
||||
By default Spring Boot calls `docker compose up` when your application starts and `docker compose stop` when it's shut down.
|
||||
If you prefer to have different lifecycle management you can use the configprop:spring.docker.compose.lifecycle-management[] property.
|
||||
|
||||
The following values are supported:
|
||||
|
||||
* `none` - Do not start or stop Docker Compose
|
||||
* `start-only` - Start Docker Compose on application startup and leave it running
|
||||
* `start-and-stop` - Start Docker Compose on application startup and stop it on application shutdown
|
||||
* `start-only` - Start Docker Compose when the application starts and leave it running
|
||||
* `start-and-stop` - Start Docker Compose whe the application starts and stop it when the JVM exits
|
||||
|
||||
In addition you can use the configprop:spring.docker.compose.startup.command[] property to change if `docker up` or `docker start` is used.
|
||||
The configprop:spring.docker.compose.shutdown.command[] allows you to configure if `docker down` or `docker stop` is used.
|
||||
In addition you can use the configprop:spring.docker.compose.start.command[] property to change whether `docker compose up` or `docker compose start` is used.
|
||||
The configprop:spring.docker.compose.stop.command[] allows you to configure if `docker compose down` or `docker compose stop` is used.
|
||||
|
||||
The following example shows how lifecycle management can be configured:
|
||||
|
||||
@@ -189,10 +189,10 @@ The following example shows how lifecycle management can be configured:
|
||||
docker:
|
||||
compose:
|
||||
lifecycle-management: start-and-stop
|
||||
startup:
|
||||
start:
|
||||
command: start
|
||||
shutdown:
|
||||
command: stop
|
||||
stop:
|
||||
command: down
|
||||
timeout: 1m
|
||||
----
|
||||
|
||||
|
||||
Reference in New Issue
Block a user