Skip to content

Commit ab28e5e

Browse files
committed
Merge pull request #47797 from nosan
* pr/47797: Polish "Add failure analysis for invalid Docker environments" Add failure analysis for invalid Docker environments Closes gh-47797
2 parents 784fd6c + 7c519ee commit ab28e5e

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.testcontainers.lifecycle;
18+
19+
import org.jspecify.annotations.Nullable;
20+
21+
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
22+
import org.springframework.boot.diagnostics.FailureAnalysis;
23+
import org.springframework.util.StringUtils;
24+
25+
/**
26+
* A {@code FailureAnalyzer} that performs analysis of failures caused by Testcontainers
27+
* not finding a valid Docker environment.
28+
*
29+
* @author Dmytro Nosan
30+
* @author Stephane Nicoll
31+
*/
32+
class DockerEnvironmentNotFoundFailureAnalyzer extends AbstractFailureAnalyzer<IllegalStateException> {
33+
34+
private static final String EXPECTED_MESSAGE = "Could not find a valid Docker environment";
35+
36+
private static final String DESCRIPTION = "Could not find a valid Docker environment for Testcontainers.";
37+
38+
private static final String ACTION = """
39+
- Ensure a Docker-compatible container engine is installed and running.
40+
- If running Testcontainers in CI, ensure the runner has access to the daemon, typically by using a mounted socket or a Docker-in-Docker setup.
41+
- Review the Testcontainers documentation for troubleshooting and advanced configuration options.
42+
""";
43+
44+
@Override
45+
protected @Nullable FailureAnalysis analyze(Throwable rootFailure, IllegalStateException cause) {
46+
if (StringUtils.hasText(cause.getMessage()) && cause.getMessage().contains(EXPECTED_MESSAGE)) {
47+
return new FailureAnalysis(DESCRIPTION, ACTION, cause);
48+
}
49+
return null;
50+
}
51+
52+
}

core/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleApplica
66
org.springframework.test.context.ContextCustomizerFactory=\
77
org.springframework.boot.testcontainers.service.connection.ServiceConnectionContextCustomizerFactory
88

9+
# Failure Analyzers
10+
org.springframework.boot.diagnostics.FailureAnalyzer=\
11+
org.springframework.boot.testcontainers.lifecycle.DockerEnvironmentNotFoundFailureAnalyzer
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.testcontainers.lifecycle;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.diagnostics.FailureAnalysis;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
/**
26+
* Tests for {@link DockerEnvironmentNotFoundFailureAnalyzer}.
27+
*
28+
* @author Dmytro Nosan
29+
*/
30+
class DockerEnvironmentNotFoundFailureAnalyzerTests {
31+
32+
private final DockerEnvironmentNotFoundFailureAnalyzer analyzer = new DockerEnvironmentNotFoundFailureAnalyzer();
33+
34+
@Test
35+
void shouldReturnFailureAnalysisWhenMessageMatches() {
36+
IllegalStateException cause = new IllegalStateException(
37+
"Could not find a valid Docker environment. Please see logs and check configuration");
38+
FailureAnalysis analysis = this.analyzer
39+
.analyze(new RuntimeException("Root", new RuntimeException("Intermediate", cause)));
40+
assertThat(analysis).isNotNull();
41+
assertThat(analysis.getDescription())
42+
.isEqualTo("Could not find a valid Docker environment for Testcontainers.");
43+
assertThat(analysis.getAction())
44+
.contains("Ensure a Docker-compatible container engine is installed and running");
45+
assertThat(analysis.getCause()).isSameAs(cause);
46+
}
47+
48+
@Test
49+
void shouldReturnNullWhenMessageDoesNotMatch() {
50+
FailureAnalysis analysis = this.analyzer.analyze(new IllegalStateException("Some message"));
51+
assertThat(analysis).isNull();
52+
}
53+
54+
@Test
55+
void shouldReturnNullWhenMessageIsNull() {
56+
FailureAnalysis analysis = this.analyzer.analyze(new IllegalStateException());
57+
assertThat(analysis).isNull();
58+
}
59+
60+
}

0 commit comments

Comments
 (0)