2
2
3
3
import java .time .Duration ;
4
4
import java .util .ArrayList ;
5
+ import java .util .Arrays ;
5
6
import java .util .List ;
6
7
import java .util .Locale ;
7
8
import java .util .UUID ;
9
+ import java .util .concurrent .TimeUnit ;
8
10
11
+ import org .awaitility .Awaitility ;
9
12
import org .junit .jupiter .api .extension .*;
13
+ import org .slf4j .Logger ;
14
+ import org .slf4j .LoggerFactory ;
10
15
11
16
import io .fabric8 .kubernetes .api .model .HasMetadata ;
12
17
import io .fabric8 .kubernetes .api .model .KubernetesResourceList ;
18
+ import io .fabric8 .kubernetes .api .model .NamespaceBuilder ;
13
19
import io .fabric8 .kubernetes .client .DefaultKubernetesClient ;
14
20
import io .fabric8 .kubernetes .client .KubernetesClient ;
15
21
import io .fabric8 .kubernetes .client .dsl .NonNamespaceOperation ;
@@ -26,7 +32,9 @@ public abstract class AbstractOperatorExtension implements HasKubernetesClient,
26
32
AfterAllCallback ,
27
33
AfterEachCallback {
28
34
29
- protected final KubernetesClient kubernetesClient ;
35
+ private static final Logger LOGGER = LoggerFactory .getLogger (AbstractOperatorExtension .class );
36
+
37
+ private final KubernetesClient kubernetesClient ;
30
38
protected final ConfigurationService configurationService ;
31
39
protected final List <HasMetadata > infrastructure ;
32
40
protected Duration infrastructureTimeout ;
@@ -55,22 +63,22 @@ protected AbstractOperatorExtension(
55
63
56
64
57
65
@ Override
58
- public void beforeAll (ExtensionContext context ) throws Exception {
66
+ public void beforeAll (ExtensionContext context ) {
59
67
beforeAllImpl (context );
60
68
}
61
69
62
70
@ Override
63
- public void beforeEach (ExtensionContext context ) throws Exception {
71
+ public void beforeEach (ExtensionContext context ) {
64
72
beforeEachImpl (context );
65
73
}
66
74
67
75
@ Override
68
- public void afterAll (ExtensionContext context ) throws Exception {
76
+ public void afterAll (ExtensionContext context ) {
69
77
afterAllImpl (context );
70
78
}
71
79
72
80
@ Override
73
- public void afterEach (ExtensionContext context ) throws Exception {
81
+ public void afterEach (ExtensionContext context ) {
74
82
afterEachImpl (context );
75
83
}
76
84
@@ -100,6 +108,7 @@ public <T extends HasMetadata> T replace(Class<T> type, T resource) {
100
108
return kubernetesClient .resources (type ).inNamespace (namespace ).replace (resource );
101
109
}
102
110
111
+ @ SuppressWarnings ("unchecked" )
103
112
public <T extends HasMetadata > boolean delete (Class <T > type , T resource ) {
104
113
return kubernetesClient .resources (type ).inNamespace (namespace ).delete (resource );
105
114
}
@@ -130,7 +139,20 @@ protected void beforeEachImpl(ExtensionContext context) {
130
139
}
131
140
}
132
141
133
- protected abstract void before (ExtensionContext context );
142
+ protected void before (ExtensionContext context ) {
143
+ LOGGER .info ("Initializing integration test in namespace {}" , namespace );
144
+
145
+ kubernetesClient
146
+ .namespaces ()
147
+ .create (new NamespaceBuilder ().withNewMetadata ().withName (namespace ).endMetadata ().build ());
148
+
149
+ kubernetesClient
150
+ .resourceList (infrastructure )
151
+ .createOrReplace ();
152
+ kubernetesClient
153
+ .resourceList (infrastructure )
154
+ .waitUntilReady (infrastructureTimeout .toMillis (), TimeUnit .MILLISECONDS );
155
+ }
134
156
135
157
protected void afterAllImpl (ExtensionContext context ) {
136
158
if (oneNamespacePerClass ) {
@@ -144,9 +166,32 @@ protected void afterEachImpl(ExtensionContext context) {
144
166
}
145
167
}
146
168
147
- protected abstract void after (ExtensionContext context );
169
+ protected void after (ExtensionContext context ) {
170
+ if (namespace != null ) {
171
+ if (preserveNamespaceOnError && context .getExecutionException ().isPresent ()) {
172
+ LOGGER .info ("Preserving namespace {}" , namespace );
173
+ } else {
174
+ kubernetesClient .resourceList (infrastructure ).delete ();
175
+ deleteOperator ();
176
+ LOGGER .info ("Deleting namespace {} and stopping operator" , namespace );
177
+ kubernetesClient .namespaces ().withName (namespace ).delete ();
178
+ if (waitForNamespaceDeletion ) {
179
+ LOGGER .info ("Waiting for namespace {} to be deleted" , namespace );
180
+ Awaitility .await ("namespace deleted" )
181
+ .pollInterval (50 , TimeUnit .MILLISECONDS )
182
+ .atMost (90 , TimeUnit .SECONDS )
183
+ .until (() -> kubernetesClient .namespaces ().withName (namespace ).get () == null );
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ protected void deleteOperator () {
190
+ // nothing to do by default: only needed if the operator is deployed to the cluster
191
+ }
148
192
149
- public static abstract class AbstractBuilder {
193
+ @ SuppressWarnings ("unchecked" )
194
+ public static abstract class AbstractBuilder <T extends AbstractBuilder <T >> {
150
195
protected ConfigurationService configurationService ;
151
196
protected final List <HasMetadata > infrastructure ;
152
197
protected Duration infrastructureTimeout ;
@@ -172,5 +217,41 @@ protected AbstractBuilder() {
172
217
"josdk.it.oneNamespacePerClass" ,
173
218
false );
174
219
}
220
+
221
+ public T preserveNamespaceOnError (boolean value ) {
222
+ this .preserveNamespaceOnError = value ;
223
+ return (T ) this ;
224
+ }
225
+
226
+ public T waitForNamespaceDeletion (boolean value ) {
227
+ this .waitForNamespaceDeletion = value ;
228
+ return (T ) this ;
229
+ }
230
+
231
+ public T oneNamespacePerClass (boolean value ) {
232
+ this .oneNamespacePerClass = value ;
233
+ return (T ) this ;
234
+ }
235
+
236
+ public T withConfigurationService (ConfigurationService value ) {
237
+ configurationService = value ;
238
+ return (T ) this ;
239
+ }
240
+
241
+ public T withInfrastructureTimeout (Duration value ) {
242
+ infrastructureTimeout = value ;
243
+ return (T ) this ;
244
+ }
245
+
246
+ public T withInfrastructure (List <HasMetadata > hm ) {
247
+ infrastructure .addAll (hm );
248
+ return (T ) this ;
249
+ }
250
+
251
+ public T withInfrastructure (HasMetadata ... hms ) {
252
+ infrastructure .addAll (Arrays .asList (hms ));
253
+ return (T ) this ;
254
+ }
255
+
175
256
}
176
257
}
0 commit comments