diff --git a/changelog/@unreleased/pr-384.v2.yml b/changelog/@unreleased/pr-384.v2.yml new file mode 100644 index 000000000..9c520edc8 --- /dev/null +++ b/changelog/@unreleased/pr-384.v2.yml @@ -0,0 +1,6 @@ +type: improvement +improvement: + description: |- + copy logs to circle even if there's an error initializing in `before` + links: + - https://github.com/palantir/docker-compose-rule/pull/384 diff --git a/docker-compose-junit-jupiter/src/test/java/com/palantir/docker/compose/DockerComposeExtensionTest.java b/docker-compose-junit-jupiter/src/test/java/com/palantir/docker/compose/DockerComposeExtensionTest.java new file mode 100644 index 000000000..2e10486b7 --- /dev/null +++ b/docker-compose-junit-jupiter/src/test/java/com/palantir/docker/compose/DockerComposeExtensionTest.java @@ -0,0 +1,69 @@ +/* + * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.docker.compose; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.palantir.docker.compose.configuration.DockerComposeFiles; +import com.palantir.docker.compose.connection.waiting.ClusterWait; +import com.palantir.docker.compose.events.EventConsumer; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.mockito.Mockito; + +public class DockerComposeExtensionTest { + + @Test + public void calls_after_only_once() { + AtomicInteger count = new AtomicInteger(); + DockerComposeExtension dockerComposeExtension = new DockerComposeExtension() { + @Override + public void before() { + throw new IllegalStateException("some error"); + } + + @Override + public void after() { + count.incrementAndGet(); + } + + @Override + public DockerComposeFiles files() { + return null; + } + + @Override + protected List clusterWaits() { + return null; + } + + @Override + protected List eventConsumers() { + return null; + } + }; + + ExtensionContext extensionContext = Mockito.mock(ExtensionContext.class); + assertThatThrownBy(() -> dockerComposeExtension.beforeAll(extensionContext)) + .isInstanceOf(IllegalStateException.class); + dockerComposeExtension.afterAll(extensionContext); + assertThat(count.get()).isEqualTo(1); + } +} diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/DockerComposeManager.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/DockerComposeManager.java index d6d746078..589d70f54 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/DockerComposeManager.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/DockerComposeManager.java @@ -76,6 +76,7 @@ public abstract class DockerComposeManager { public static final int DEFAULT_RETRY_ATTEMPTS = 2; private final RunRecorder runRecorder = RunRecorder.defaults(); + private boolean hasCalledAfterMethod; public DockerPort hostNetworkedPort(int port) { return new DockerPort(machine().getIp(), port, port); @@ -177,13 +178,19 @@ protected void setDescription(TestDescription testDescription) { } public void before() throws IOException, InterruptedException { - log.debug("Starting docker-compose cluster"); + try { + log.debug("Starting docker-compose cluster"); - runRecorder.before(() -> dockerCompose().config()); + runRecorder.before(() -> dockerCompose().config()); - pullBuildAndUp(); + pullBuildAndUp(); - emitEventsFor().waitingForServices(this::waitForServices); + emitEventsFor().waitingForServices(this::waitForServices); + } catch (RuntimeException e) { + after(); + hasCalledAfterMethod = true; + throw e; + } } private void pullBuildAndUp() throws IOException, InterruptedException { @@ -254,6 +261,10 @@ private void waitForAllClusterWaits(List allClusterWai } public void after() { + if (hasCalledAfterMethod) { + return; + } + try { emitEventsFor().shutdownStop(() -> shutdownStrategy().stop(this.dockerCompose())); diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/connection/Container.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/connection/Container.java index 1fa862ab0..6256680e8 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/connection/Container.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/connection/Container.java @@ -88,7 +88,8 @@ public DockerPort port(int internalPort) { .stream() .filter(port -> port.getInternalPort() == internalPort) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No internal port '" + internalPort + "' for container '" + containerName + "': " + portMappings)); + .orElseThrow(() -> new IllegalArgumentException("No internal port '" + internalPort + "' " + + "for container '" + containerName + "': " + portMappings.get())); } public void start() throws IOException, InterruptedException {