1
1
/*
2
- * Copyright 2012-2024 the original author or authors.
2
+ * Copyright 2012-2025 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .boot .docker .compose .service .connection .test ;
18
18
19
19
import java .io .IOException ;
20
+ import java .nio .charset .StandardCharsets ;
20
21
import java .nio .file .Files ;
21
22
import java .nio .file .Path ;
22
23
import java .util .LinkedHashMap ;
39
40
import org .springframework .context .annotation .Configuration ;
40
41
import org .springframework .core .io .ClassPathResource ;
41
42
import org .springframework .core .io .Resource ;
43
+ import org .springframework .util .FileSystemUtils ;
42
44
43
45
import static org .assertj .core .api .Assertions .fail ;
44
46
45
47
/**
46
48
* {@link Extension} for {@link DockerComposeTest @DockerComposeTest}.
47
49
*
48
50
* @author Andy Wilkinson
51
+ * @author Moritz Halbritter
49
52
*/
50
53
class DockerComposeTestExtension implements BeforeTestExecutionCallback , AfterTestExecutionCallback , ParameterResolver {
51
54
52
55
private static final Namespace NAMESPACE = Namespace .create (DockerComposeTestExtension .class );
53
56
54
- private static final String STORE_KEY_COMPOSE_FILE = "compose-file " ;
57
+ private static final String STORE_KEY_WORKSPACE = "workspace " ;
55
58
56
59
private static final String STORE_KEY_APPLICATION_CONTEXT = "application-context" ;
57
60
58
61
@ Override
59
62
public void beforeTestExecution (ExtensionContext context ) throws Exception {
60
- Path transformedComposeFile = prepareComposeFile (context );
61
63
Store store = context .getStore (NAMESPACE );
62
- store .put (STORE_KEY_COMPOSE_FILE , transformedComposeFile );
64
+ Path workspace = Files .createTempDirectory ("DockerComposeTestExtension-" );
65
+ store .put (STORE_KEY_WORKSPACE , workspace );
63
66
try {
64
- SpringApplication application = prepareApplication (transformedComposeFile );
67
+ Path composeFile = prepareComposeFile (workspace , context );
68
+ SpringApplication application = prepareApplication (composeFile );
65
69
store .put (STORE_KEY_APPLICATION_CONTEXT , application .run ());
66
70
}
67
71
catch (Exception ex ) {
@@ -70,33 +74,33 @@ public void beforeTestExecution(ExtensionContext context) throws Exception {
70
74
}
71
75
}
72
76
73
- private Path prepareComposeFile (ExtensionContext context ) {
77
+ private Path prepareComposeFile (Path workspace , ExtensionContext context ) {
74
78
DockerComposeTest dockerComposeTest = context .getRequiredTestMethod ().getAnnotation (DockerComposeTest .class );
75
79
TestImage image = dockerComposeTest .image ();
76
80
Resource composeResource = new ClassPathResource (dockerComposeTest .composeFile (),
77
81
context .getRequiredTestClass ());
78
- return transformedComposeFile (composeResource , image );
82
+ return transformedComposeFile (workspace , composeResource , image );
79
83
}
80
84
81
- private Path transformedComposeFile (Resource composeFileResource , TestImage image ) {
85
+ private Path transformedComposeFile (Path workspace , Resource composeFileResource , TestImage image ) {
82
86
try {
83
- Path composeFile = composeFileResource .getFile (). toPath ( );
84
- Path transformedComposeFile = Files . createTempFile ( " " , "-" + composeFile . getFileName () .toString ());
85
- String transformedContent = Files . readString ( composeFile ). replace ( "{imageName}" , image . toString () );
86
- Files .writeString (transformedComposeFile , transformedContent );
87
- return transformedComposeFile ;
87
+ String template = composeFileResource .getContentAsString ( StandardCharsets . UTF_8 );
88
+ String content = template . replace ( "{imageName} " , image .toString ());
89
+ Path composeFile = workspace . resolve ( "compose.yaml" );
90
+ Files .writeString (composeFile , content );
91
+ return composeFile ;
88
92
}
89
93
catch (IOException ex ) {
90
- fail ("Error transforming Docker compose file '" + composeFileResource + "': " + ex .getMessage ());
94
+ fail ("Error transforming Docker compose file '" + composeFileResource + "': " + ex .getMessage (), ex );
95
+ return null ;
91
96
}
92
- return null ;
93
97
}
94
98
95
- private SpringApplication prepareApplication (Path transformedComposeFile ) {
99
+ private SpringApplication prepareApplication (Path composeFile ) {
96
100
SpringApplication application = new SpringApplication (Config .class );
97
101
Map <String , Object > properties = new LinkedHashMap <>();
98
102
properties .put ("spring.docker.compose.skip.in-tests" , "false" );
99
- properties .put ("spring.docker.compose.file" , transformedComposeFile );
103
+ properties .put ("spring.docker.compose.file" , composeFile );
100
104
properties .put ("spring.docker.compose.stop.command" , "down" );
101
105
application .setDefaultProperties (properties );
102
106
return application ;
@@ -110,18 +114,18 @@ public void afterTestExecution(ExtensionContext context) throws Exception {
110
114
private void cleanUp (ExtensionContext context ) throws Exception {
111
115
Store store = context .getStore (NAMESPACE );
112
116
runShutdownHandlers ();
113
- deleteComposeFile (store );
117
+ deleteWorkspace (store );
114
118
}
115
119
116
120
private void runShutdownHandlers () {
117
121
SpringApplicationShutdownHandlers shutdownHandlers = SpringApplication .getShutdownHandlers ();
118
122
((Runnable ) shutdownHandlers ).run ();
119
123
}
120
124
121
- private void deleteComposeFile (Store store ) throws IOException {
122
- Path composeFile = store .get (STORE_KEY_COMPOSE_FILE , Path . class );
123
- if (composeFile != null ) {
124
- Files . delete ( composeFile );
125
+ private void deleteWorkspace (Store store ) throws IOException {
126
+ Path workspace = ( Path ) store .get (STORE_KEY_WORKSPACE );
127
+ if (workspace != null ) {
128
+ FileSystemUtils . deleteRecursively ( workspace );
125
129
}
126
130
}
127
131
0 commit comments