9
9
import java .net .MalformedURLException ;
10
10
import java .net .URL ;
11
11
import java .time .Duration ;
12
- import java .util .ArrayList ;
13
12
import java .util .List ;
14
13
import java .util .Optional ;
15
- import java .util .concurrent .TimeUnit ;
16
14
import java .util .function .Function ;
17
15
import java .util .stream .Collectors ;
18
16
28
26
import com .dajudge .kindcontainer .KubernetesImageSpec ;
29
27
import com .dajudge .kindcontainer .KubernetesVersionEnum ;
30
28
31
- import io .fabric8 .kubernetes .api .model .Endpoints ;
32
29
import io .fabric8 .kubernetes .api .model .HasMetadata ;
33
- import io .fabric8 .kubernetes .api .model .Node ;
34
- import io .fabric8 .kubernetes .api .model .Pod ;
35
- import io .fabric8 .kubernetes .api .model .ReplicationController ;
36
- import io .fabric8 .kubernetes .api .model .apps .Deployment ;
37
- import io .fabric8 .kubernetes .api .model .apps .ReplicaSet ;
38
- import io .fabric8 .kubernetes .api .model .apps .StatefulSet ;
39
30
import io .fabric8 .kubernetes .client .Config ;
40
31
import io .fabric8 .kubernetes .client .KubernetesClient ;
41
32
import io .fabric8 .kubernetes .client .KubernetesClientBuilder ;
42
33
import io .quarkus .deployment .Feature ;
43
34
import io .quarkus .deployment .IsDevServicesSupportedByLaunchMode ;
35
+ import io .quarkus .deployment .IsDevelopment ;
36
+ import io .quarkus .deployment .IsTest ;
44
37
import io .quarkus .deployment .annotations .BuildProducer ;
45
38
import io .quarkus .deployment .annotations .BuildStep ;
46
39
import io .quarkus .deployment .annotations .BuildSteps ;
47
- import io .quarkus .deployment .annotations .Produce ;
40
+ import io .quarkus .deployment .annotations .ExecutionTime ;
41
+ import io .quarkus .deployment .annotations .Record ;
48
42
import io .quarkus .deployment .builditem .DevServicesComposeProjectBuildItem ;
49
43
import io .quarkus .deployment .builditem .DevServicesResultBuildItem ;
50
44
import io .quarkus .deployment .builditem .DevServicesSharedNetworkBuildItem ;
51
45
import io .quarkus .deployment .builditem .DockerStatusBuildItem ;
52
46
import io .quarkus .deployment .builditem .LaunchModeBuildItem ;
53
- import io .quarkus .deployment .builditem .ServiceStartBuildItem ;
54
47
import io .quarkus .deployment .dev .devservices .DevServicesConfig ;
55
48
import io .quarkus .devservices .common .ComposeLocator ;
56
49
import io .quarkus .devservices .common .ConfigureUtil ;
57
50
import io .quarkus .devservices .common .ContainerLocator ;
58
51
import io .quarkus .kubernetes .client .runtime .internal .KubernetesClientBuildConfig ;
52
+ import io .quarkus .kubernetes .client .runtime .internal .KubernetesClusterFixtures ;
59
53
import io .quarkus .kubernetes .client .runtime .internal .KubernetesDevServicesBuildTimeConfig ;
60
54
import io .quarkus .kubernetes .client .runtime .internal .KubernetesDevServicesBuildTimeConfig .Flavor ;
61
55
import io .quarkus .kubernetes .client .spi .KubernetesDevServiceInfoBuildItem ;
@@ -69,7 +63,7 @@ public class DevServicesKubernetesProcessor {
69
63
static final int KUBERNETES_PORT = 6443 ;
70
64
private static final String KUBERNETES_CLIENT_DEVSERVICES_OVERRIDE_KUBECONFIG = "quarkus.kubernetes-client.devservices.override-kubeconfig" ;
71
65
private static final Logger log = Logger .getLogger (DevServicesKubernetesProcessor .class );
72
- static final String KUBERNETES_CLIENT_MASTER_URL = "quarkus.kubernetes-client.api-server-url" ;
66
+ static final String KUBERNETES_CLIENT_API_SERVER_URL = "quarkus.kubernetes-client.api-server-url" ;
73
67
private static final String DEFAULT_MASTER_URL_ENDING_WITH_SLASH = Config .DEFAULT_MASTER_URL + "/" ;
74
68
private static final ContainerLocator KubernetesContainerLocator = locateContainerWithLabels (KUBERNETES_PORT ,
75
69
DEV_SERVICE_LABEL );
@@ -135,8 +129,9 @@ public String getContainerId() {
135
129
.startable (() -> container )
136
130
.configProvider (
137
131
StartableKubernetesContainer .getKubernetesClientConfigFromRunningContainerKubeConfig ())
138
- .postStartHook (unused -> log .info (
139
- "Dev Services for Kubernetes started. Other Quarkus applications in dev mode will find the cluster automatically." ))
132
+ .postStartHook (started -> log .infof (
133
+ "Dev Services for Kubernetes started at %s. Other Quarkus applications in dev mode will find the cluster automatically." ,
134
+ started .getKubeClientConfigFor (KUBERNETES_CLIENT_API_SERVER_URL )))
140
135
.build ();
141
136
142
137
devServicesKube .produce (new KubernetesDevServiceInfoBuildItem (
@@ -167,9 +162,9 @@ private boolean devServiceDisabled(DockerStatusBuildItem dockerStatusBuildItem,
167
162
}
168
163
169
164
// Check if kubernetes-client.api-server-url is set
170
- if (ConfigUtils .isPropertyNonEmpty (KUBERNETES_CLIENT_MASTER_URL )) {
165
+ if (ConfigUtils .isPropertyNonEmpty (KUBERNETES_CLIENT_API_SERVER_URL )) {
171
166
log .debug ("Not starting Dev Services for Kubernetes as the client has been explicitly configured via "
172
- + KUBERNETES_CLIENT_MASTER_URL );
167
+ + KUBERNETES_CLIENT_API_SERVER_URL );
173
168
return true ;
174
169
}
175
170
@@ -227,34 +222,22 @@ private StartableKubernetesContainer createContainer(KubernetesDevServicesBuildT
227
222
}
228
223
229
224
/**
230
- * Deploys a set of manifests as files in the resources directory to the Kubernetes dev service.
231
- * This build step produces a {@link ServiceStartBuildItem} that ensures the Build Step always runs even if no other build
232
- * step consumes it.
225
+ * Prepares configured manifests via {@link KubernetesDevServicesBuildTimeConfig#manifests()} to be applied at runtime
233
226
*
234
- * @param kubernetesDevServiceInfoBuildItem This ensures the manifests are deployed after the Kubernetes dev service is
235
- * started.
236
227
* @param kubernetesClientBuildTimeConfig This config is used to read the extension configuration for dev services.
228
+ * @param clusterFixtures records byte-code to apply configure manifests at runtime
237
229
*/
238
- @ BuildStep
239
- @ Produce ( ServiceStartBuildItem . class )
230
+ @ BuildStep ( onlyIf = { IsDevelopment . class , IsTest . class })
231
+ @ Record ( ExecutionTime . STATIC_INIT )
240
232
public void applyManifests (
241
- KubernetesDevServiceInfoBuildItem kubernetesDevServiceInfoBuildItem ,
242
- KubernetesClientBuildConfig kubernetesClientBuildTimeConfig ) {
243
- if (kubernetesDevServiceInfoBuildItem == null ) {
244
- // Gracefully return in case the Kubernetes dev service could not be spun up.
245
- log .warn ("Cannot apply manifests because the Kubernetes dev service is not running" );
246
- return ;
247
- }
248
-
233
+ KubernetesClientBuildConfig kubernetesClientBuildTimeConfig , KubernetesClusterFixtures clusterFixtures ) {
249
234
var manifests = kubernetesClientBuildTimeConfig .devservices ().manifests ();
250
235
251
236
// Do not run the manifest deployment if no manifests are configured
252
237
if (manifests .isEmpty ())
253
238
return ;
254
239
255
- try (KubernetesClient client = new KubernetesClientBuilder ()
256
- .withConfig (Config .fromKubeconfig (kubernetesDevServiceInfoBuildItem .getKubeConfig ()))
257
- .build ()) {
240
+ try (KubernetesClient client = new KubernetesClientBuilder ().build ()) {
258
241
for (String manifestPath : manifests .get ()) {
259
242
InputStream manifestStream = getManifestStream (manifestPath );
260
243
@@ -267,49 +250,19 @@ public void applyManifests(
267
250
try {
268
251
// A single manifest file may contain multiple resources to deploy
269
252
List <HasMetadata > resources = client .load (manifestStream ).items ();
270
- List <HasMetadata > resourcesWithReadiness = new ArrayList <>();
271
-
272
- if (resources .isEmpty ()) {
273
- log .warnf ("No resources found in manifest: %s" , manifestPath );
274
- } else {
275
- resources .forEach (resource -> {
276
- client .resource (resource ).create ();
277
-
278
- if (isReadinessApplicable (resource )) {
279
- resourcesWithReadiness .add (resource );
280
- }
281
- });
282
-
283
- resourcesWithReadiness .forEach (resource -> {
284
- log .info ("Waiting for " + resource .getClass ().getSimpleName () + " "
285
- + resource .getMetadata ().getName ()
286
- + " to be ready..." );
287
- client .resource (resource ).waitUntilReady (60 , TimeUnit .SECONDS );
288
- });
289
-
290
- log .infof ("Applied manifest %s." , manifestPath );
291
- }
253
+ // records byte-code to apply the loaded resources at runtime
254
+ clusterFixtures .apply (resources );
255
+ log .infof ("==== Recorded manifest %s to be applied at runtime" , manifestPath );
292
256
} catch (Exception ex ) {
293
- log .errorf ("Failed to apply manifest %s: %s" , manifestPath , ex .getMessage ());
257
+ log .errorf ("Failed to record manifest %s: %s" , manifestPath , ex .getMessage ());
294
258
}
295
259
}
296
260
}
297
261
} catch (Exception e ) {
298
- log .error ("Failed to create Kubernetes client while trying to apply manifests. " , e );
262
+ log .error ("Failed to create Kubernetes client to load manifests" , e );
299
263
}
300
264
}
301
265
302
- private boolean isReadinessApplicable (HasMetadata item ) {
303
- return (item instanceof Deployment ||
304
- item instanceof io .fabric8 .kubernetes .api .model .extensions .Deployment ||
305
- item instanceof ReplicaSet ||
306
- item instanceof Pod ||
307
- item instanceof ReplicationController ||
308
- item instanceof Endpoints ||
309
- item instanceof Node ||
310
- item instanceof StatefulSet );
311
- }
312
-
313
266
private InputStream getManifestStream (String manifestPath ) throws IOException {
314
267
try {
315
268
URL url = new URL (manifestPath );
0 commit comments