diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DockerCliCommand.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DockerCliCommand.java index 0face26b499..feb2d8dd6aa 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DockerCliCommand.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DockerCliCommand.java @@ -184,7 +184,7 @@ abstract sealed class DockerCliCommand { static final class ComposeStart extends DockerCliCommand { ComposeStart(LogLevel logLevel) { - super(Type.DOCKER_COMPOSE, logLevel, Void.class, false, "start", "--detach", "--wait"); + super(Type.DOCKER_COMPOSE, logLevel, Void.class, false, "start"); } } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliCommandTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliCommandTests.java index c9174a859df..4ed1d983bd1 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliCommandTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliCommandTests.java @@ -88,7 +88,7 @@ class DockerCliCommandTests { DockerCliCommand command = new DockerCliCommand.ComposeStart(LogLevel.INFO); assertThat(command.getType()).isEqualTo(DockerCliCommand.Type.DOCKER_COMPOSE); assertThat(command.getLogLevel()).isEqualTo(LogLevel.INFO); - assertThat(command.getCommand()).containsExactly("start", "--detach", "--wait"); + assertThat(command.getCommand()).containsExactly("start"); assertThat(command.deserialize("[]")).isNull(); } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java new file mode 100644 index 00000000000..ee5efe52ebc --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java @@ -0,0 +1,131 @@ +/* + * Copyright 2012-2023 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. + * You may obtain a copy of the License at + * + * https://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.springframework.boot.docker.compose.core; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.time.Duration; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposeConfig; +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposeDown; +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposePs; +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposeStart; +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposeStop; +import org.springframework.boot.docker.compose.core.DockerCliCommand.ComposeUp; +import org.springframework.boot.docker.compose.core.DockerCliCommand.Inspect; +import org.springframework.boot.logging.LogLevel; +import org.springframework.boot.testsupport.process.DisabledIfProcessUnavailable; +import org.springframework.boot.testsupport.testcontainers.DisabledIfDockerUnavailable; +import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.FileCopyUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DockerCli}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + */ +@DisabledIfDockerUnavailable +@DisabledIfProcessUnavailable({ "docker", "compose" }) +class DockerCliIntegrationTests { + + @TempDir + private static Path tempDir; + + @Test + void runBasicCommand() { + DockerCli cli = new DockerCli(null, null, Collections.emptySet()); + List context = cli.run(new DockerCliCommand.Context()); + assertThat(context).isNotEmpty(); + } + + @Test + void runLifecycle() throws IOException { + File composeFile = createComposeFile(); + DockerCli cli = new DockerCli(null, DockerComposeFile.of(composeFile), Collections.emptySet()); + try { + // Verify that no services are running (this is a fresh compose project) + List ps = cli.run(new ComposePs()); + assertThat(ps).isEmpty(); + // List the config and verify that redis is there + DockerCliComposeConfigResponse config = cli.run(new ComposeConfig()); + assertThat(config.services()).containsOnlyKeys("redis"); + // Run up + cli.run(new ComposeUp(LogLevel.INFO)); + // Run ps and use id to run inspect on the id + ps = cli.run(new ComposePs()); + assertThat(ps).hasSize(1); + String id = ps.get(0).id(); + List inspect = cli.run(new Inspect(List.of(id))); + assertThat(inspect).isNotEmpty(); + assertThat(inspect.get(0).id()).isEqualTo(id); + // Run stop, then run ps and verify the services are stopped + cli.run(new ComposeStop(Duration.ofSeconds(10))); + ps = cli.run(new ComposePs()); + assertThat(ps).isEmpty(); + // Run start, verify that service is there, then run down and verify they are + // gone + cli.run(new ComposeStart(LogLevel.INFO)); + ps = cli.run(new ComposePs()); + assertThat(ps).hasSize(1); + cli.run(new ComposeDown(Duration.ofSeconds(10))); + ps = cli.run(new ComposePs()); + assertThat(ps).isEmpty(); + } + finally { + // Clean up in any case + quietComposeDown(cli); + } + } + + private static void quietComposeDown(DockerCli cli) { + try { + cli.run(new ComposeDown(Duration.ZERO)); + } + catch (RuntimeException ex) { + // Ignore + } + } + + private static File createComposeFile() throws IOException { + File composeFile = new ClassPathResource("redis-compose.yaml", DockerCliIntegrationTests.class).getFile(); + File tempComposeFile = Path.of(tempDir.toString(), composeFile.getName()).toFile(); + String composeFileContent; + try (FileReader reader = new FileReader(composeFile)) { + composeFileContent = FileCopyUtils.copyToString(reader); + } + composeFileContent = composeFileContent.replace("{imageName}", + DockerImageNames.redis().asCanonicalNameString()); + try (FileWriter writer = new FileWriter(tempComposeFile)) { + FileCopyUtils.copy(composeFileContent, writer); + } + return tempComposeFile; + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliTests.java deleted file mode 100644 index be801fb04d2..00000000000 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliTests.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2012-2023 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. - * You may obtain a copy of the License at - * - * https://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.springframework.boot.docker.compose.core; - -import java.util.Collections; -import java.util.List; - -import org.junit.jupiter.api.Test; - -import org.springframework.boot.testsupport.process.DisabledIfProcessUnavailable; -import org.springframework.boot.testsupport.testcontainers.DisabledIfDockerUnavailable; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link DockerCli}. - * - * @author Moritz Halbritter - * @author Andy Wilkinson - * @author Phillip Webb - */ -@DisabledIfDockerUnavailable -@DisabledIfProcessUnavailable({ "docker", "compose" }) -class DockerCliTests { - - @Test - void runBasicCommand() { - DockerCli cli = new DockerCli(null, null, Collections.emptySet()); - List context = cli.run(new DockerCliCommand.Context()); - assertThat(context).isNotEmpty(); - } - -} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractDockerComposeIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractDockerComposeIntegrationTests.java index b282af843d5..970d9cb9360 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractDockerComposeIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractDockerComposeIntegrationTests.java @@ -83,9 +83,14 @@ public abstract class AbstractDockerComposeIntegrationTests { private File transformedComposeFile(File composeFile, DockerImageName imageName) { File tempComposeFile = Path.of(tempDir.toString(), composeFile.getName()).toFile(); try { - String composeFileContent = FileCopyUtils.copyToString(new FileReader(composeFile)); + String composeFileContent; + try (FileReader reader = new FileReader(composeFile)) { + composeFileContent = FileCopyUtils.copyToString(reader); + } composeFileContent = composeFileContent.replace("{imageName}", imageName.asCanonicalNameString()); - FileCopyUtils.copy(composeFileContent, new FileWriter(tempComposeFile)); + try (FileWriter writer = new FileWriter(tempComposeFile)) { + FileCopyUtils.copy(composeFileContent, writer); + } } catch (IOException ex) { fail("Error transforming Docker compose file '" + composeFile + "' to '" + tempComposeFile + "': " diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractIntegrationTests.java deleted file mode 100644 index d2e081d88a7..00000000000 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/test/AbstractIntegrationTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012-2023 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. - * You may obtain a copy of the License at - * - * https://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.springframework.boot.docker.compose.service.connection.test; - -import org.springframework.boot.testsupport.testcontainers.DisabledIfDockerUnavailable; - -/** - * Abstract base class for integration tests. - * - * @author Moritz Halbritter - * @author Andy Wilkinson - */ -@DisabledIfDockerUnavailable -public abstract class AbstractIntegrationTests { - - //// @formatter:off - - /* - - @TempDir - static Path tempDir; - - private static List shutdownHandler; - - @BeforeAll - static void beforeAll() { - shutdownHandler = new ArrayList<>(); - } - - @AfterAll - static void afterAll() { - for (Runnable runnable : shutdownHandler) { - runnable.run(); - } - } - - @BeforeEach - void setUp() throws IOException { - createComposeYaml(); - } - - protected abstract InputStream getComposeContent(); - - protected final T runProvider(Class serviceConnectionClass) { - return runProvider(new MockEnvironment(), serviceConnectionClass); - } - - protected final T runProvider(MockEnvironment environment, - Class serviceConnectionClass) { - environment.setProperty("spring.dev-services.docker-compose.stop-mode", "down"); - DockerComposeListener dockerComposeListener = createProvider(environment); - GenericApplicationContext context = new GenericApplicationContext(); - context.setEnvironment(environment); - dockerComposeListener - .onApplicationEvent(new ApplicationPreparedEvent(new SpringApplication(), new String[0], context)); - context.refresh(); - T serviceConnection = context.getBean(serviceConnectionClass); - assertThat(serviceConnection.getOrigin()).isInstanceOf(DockerComposeOrigin.class); - return serviceConnection; - } - - private DockerComposeListener createProvider(Environment environment) { - return new DockerComposeListener(getClass().getClassLoader(), environment, null, null, null, tempDir, - new SpringApplicationShutdownHandlers() { - - @Override - public void add(Runnable action) { - shutdownHandler.add(action); - } - - @Override - public void remove(Runnable action) { - } - - }); - } - - private void createComposeYaml() throws IOException { - try (InputStream stream = getComposeContent()) { - byte[] content = stream.readAllBytes(); - Files.write(tempDir.resolve("compose.yaml"), content); - } - } - - */ - // @formatter:on - -} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/core/redis-compose.yaml b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/core/redis-compose.yaml new file mode 100644 index 00000000000..9511c464d9f --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/core/redis-compose.yaml @@ -0,0 +1,5 @@ +services: + redis: + image: '{imageName}' + ports: + - '6379'