@@ -45,6 +45,17 @@ const (
45
45
ingressChartRepo = "https://kubernetes.github.io/ingress-nginx"
46
46
ingressChartName = "ingress-nginx/ingress-nginx"
47
47
ingressControllerName = "ingress-nginx-controller"
48
+ ingressNodePort = 30791
49
+
50
+ // Chaos Mesh constants
51
+ chaosMeshNamespace = "chaos-mesh"
52
+ chaosMeshReleaseName = "chaos-mesh"
53
+ chaosMeshChartRepo = "https://charts.chaos-mesh.org"
54
+ chaosMeshChartName = "chaos-mesh/chaos-mesh"
55
+ chaosMeshChartVersion = "2.7.2"
56
+ chaosMeshControllerName = "chaos-controller-manager"
57
+ chaosMeshDashboardName = "chaos-dashboard"
58
+ chaosMeshDashboardHost = "chaos-mesh.localhost"
48
59
)
49
60
50
61
//go:embed yaml/tmpnet-rbac.yaml
@@ -57,6 +68,7 @@ func StartKindCluster(
57
68
configPath string ,
58
69
startMetricsCollector bool ,
59
70
startLogsCollector bool ,
71
+ installChaosMesh bool ,
60
72
) error {
61
73
configContext := KindKubeconfigContext
62
74
@@ -116,6 +128,12 @@ func StartKindCluster(
116
128
return fmt .Errorf ("failed to create defaults ConfigMap: %w" , err )
117
129
}
118
130
131
+ if installChaosMesh {
132
+ if err := deployChaosMesh (ctx , log , configPath , configContext ); err != nil {
133
+ return fmt .Errorf ("failed to deploy chaos mesh: %w" , err )
134
+ }
135
+ }
136
+
119
137
return nil
120
138
}
121
139
@@ -342,7 +360,7 @@ func deployIngressController(ctx context.Context, log logging.Logger, configPath
342
360
"--wait" ,
343
361
"--set" , "controller.service.type=NodePort" ,
344
362
// This port value must match the port configured in scripts/kind-with-registry.sh
345
- "--set" , "controller.service.nodePorts.http=30791" ,
363
+ "--set" , fmt . Sprintf ( "controller.service.nodePorts.http=%d" , ingressNodePort ) ,
346
364
"--set" , "controller.admissionWebhooks.enabled=false" ,
347
365
"--set" , "controller.config.proxy-read-timeout=600" ,
348
366
"--set" , "controller.config.proxy-send-timeout=600" ,
@@ -355,7 +373,7 @@ func deployIngressController(ctx context.Context, log logging.Logger, configPath
355
373
return fmt .Errorf ("failed to install nginx-ingress: %w" , err )
356
374
}
357
375
358
- return waitForIngressController (ctx , log , configPath , configContext )
376
+ return waitForDeployment (ctx , log , configPath , configContext , ingressNamespace , ingressControllerName , "nginx ingress controller" )
359
377
}
360
378
361
379
// isIngressControllerRunning checks if the nginx ingress controller is already running.
@@ -371,42 +389,6 @@ func isIngressControllerRunning(ctx context.Context, log logging.Logger, configP
371
389
return isRunning , nil
372
390
}
373
391
374
- // waitForIngressController waits for the nginx ingress controller to be ready.
375
- func waitForIngressController (ctx context.Context , log logging.Logger , configPath string , configContext string ) error {
376
- clientset , err := GetClientset (log , configPath , configContext )
377
- if err != nil {
378
- return fmt .Errorf ("failed to get clientset: %w" , err )
379
- }
380
-
381
- return wait .PollUntilContextCancel (ctx , statusCheckInterval , true /* immediate */ , func (ctx context.Context ) (bool , error ) {
382
- deployment , err := clientset .AppsV1 ().Deployments (ingressNamespace ).Get (ctx , ingressControllerName , metav1.GetOptions {})
383
- if err != nil {
384
- log .Debug ("failed to get nginx ingress controller deployment" ,
385
- zap .String ("namespace" , ingressNamespace ),
386
- zap .String ("deployment" , ingressControllerName ),
387
- zap .Error (err ),
388
- )
389
- return false , nil
390
- }
391
- if deployment .Status .ReadyReplicas == 0 {
392
- log .Debug ("waiting for nginx ingress controller to become ready" ,
393
- zap .String ("namespace" , ingressNamespace ),
394
- zap .String ("deployment" , ingressControllerName ),
395
- zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
396
- zap .Int32 ("replicas" , deployment .Status .Replicas ),
397
- )
398
- return false , nil
399
- }
400
-
401
- log .Info ("nginx ingress controller is ready" ,
402
- zap .String ("namespace" , ingressNamespace ),
403
- zap .String ("deployment" , ingressControllerName ),
404
- zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
405
- )
406
- return true , nil
407
- })
408
- }
409
-
410
392
// runHelmCommand runs a Helm command with the given arguments.
411
393
func runHelmCommand (ctx context.Context , args ... string ) error {
412
394
cmd := exec .CommandContext (ctx , "helm" , args ... )
@@ -448,7 +430,7 @@ func createDefaultsConfigMap(ctx context.Context, log logging.Logger, configPath
448
430
Namespace : namespace ,
449
431
},
450
432
Data : map [string ]string {
451
- ingressHostKey : "localhost:30791" ,
433
+ ingressHostKey : fmt . Sprintf ( "localhost:%d" , ingressNodePort ) ,
452
434
},
453
435
}
454
436
@@ -459,3 +441,124 @@ func createDefaultsConfigMap(ctx context.Context, log logging.Logger, configPath
459
441
460
442
return nil
461
443
}
444
+
445
+ // deployChaosMesh deploys Chaos Mesh using Helm.
446
+ func deployChaosMesh (ctx context.Context , log logging.Logger , configPath string , configContext string ) error {
447
+ log .Info ("checking if chaos mesh is already running" )
448
+
449
+ isRunning , err := isChaosMeshRunning (ctx , log , configPath , configContext )
450
+ if err != nil {
451
+ return fmt .Errorf ("failed to check chaos mesh status: %w" , err )
452
+ }
453
+ if isRunning {
454
+ log .Info ("chaos mesh already running" )
455
+ return nil
456
+ }
457
+
458
+ log .Info ("deploying chaos mesh using Helm" )
459
+
460
+ // Add the helm repo for chaos-mesh
461
+ if err := runHelmCommand (ctx , "repo" , "add" , "chaos-mesh" , chaosMeshChartRepo ); err != nil {
462
+ return fmt .Errorf ("failed to add chaos mesh helm repo: %w" , err )
463
+ }
464
+ if err := runHelmCommand (ctx , "repo" , "update" ); err != nil {
465
+ return fmt .Errorf ("failed to update helm repos: %w" , err )
466
+ }
467
+
468
+ // Install Chaos Mesh with all required settings including ingress
469
+ args := []string {
470
+ "install" ,
471
+ chaosMeshReleaseName ,
472
+ chaosMeshChartName ,
473
+ "--namespace" , chaosMeshNamespace ,
474
+ "--create-namespace" ,
475
+ "--version" , chaosMeshChartVersion ,
476
+ "--wait" ,
477
+ "--set" , "chaosDaemon.runtime=containerd" ,
478
+ "--set" , "chaosDaemon.socketPath=/run/containerd/containerd.sock" ,
479
+ "--set" , "dashboard.persistentVolume.enabled=true" ,
480
+ "--set" , "dashboard.persistentVolume.storageClass=standard" ,
481
+ "--set" , "dashboard.securityMode=false" ,
482
+ "--set" , "controllerManager.leaderElection.enabled=false" ,
483
+ "--set" , "dashboard.ingress.enabled=true" ,
484
+ "--set" , "dashboard.ingress.ingressClassName=nginx" ,
485
+ "--set" , "dashboard.ingress.hosts[0].name=" + chaosMeshDashboardHost ,
486
+ }
487
+
488
+ if err := runHelmCommand (ctx , args ... ); err != nil {
489
+ return fmt .Errorf ("failed to install chaos mesh: %w" , err )
490
+ }
491
+
492
+ // Wait for Chaos Mesh to be ready
493
+ if err := waitForChaosMesh (ctx , log , configPath , configContext ); err != nil {
494
+ return fmt .Errorf ("chaos mesh deployment failed: %w" , err )
495
+ }
496
+
497
+ // Log access information
498
+ log .Info ("Chaos Mesh installed successfully" ,
499
+ zap .String ("dashboardURL" , fmt .Sprintf ("http://%s:%d" , chaosMeshDashboardHost , ingressNodePort )),
500
+ )
501
+ log .Warn ("Chaos Mesh dashboard security is disabled - use only for local development" )
502
+
503
+ return nil
504
+ }
505
+
506
+ // isChaosMeshRunning checks if Chaos Mesh is already running.
507
+ func isChaosMeshRunning (ctx context.Context , log logging.Logger , configPath string , configContext string ) (bool , error ) {
508
+ clientset , err := GetClientset (log , configPath , configContext )
509
+ if err != nil {
510
+ return false , err
511
+ }
512
+
513
+ // Check if controller manager deployment exists
514
+ _ , err = clientset .AppsV1 ().Deployments (chaosMeshNamespace ).Get (ctx , chaosMeshControllerName , metav1.GetOptions {})
515
+ return ! apierrors .IsNotFound (err ), nil
516
+ }
517
+
518
+ // waitForChaosMesh waits for Chaos Mesh components to be ready.
519
+ func waitForChaosMesh (ctx context.Context , log logging.Logger , configPath string , configContext string ) error {
520
+ // Wait for controller manager
521
+ if err := waitForDeployment (ctx , log , configPath , configContext , chaosMeshNamespace , chaosMeshControllerName , "chaos mesh controller manager" ); err != nil {
522
+ return fmt .Errorf ("controller manager not ready: %w" , err )
523
+ }
524
+
525
+ // Wait for dashboard
526
+ return waitForDeployment (ctx , log , configPath , configContext , chaosMeshNamespace , chaosMeshDashboardName , "chaos mesh dashboard" )
527
+ }
528
+
529
+ // waitForDeployment waits for a deployment to have at least one ready replica.
530
+ func waitForDeployment (ctx context.Context , log logging.Logger , configPath string , configContext string , namespace string , deploymentName string , displayName string ) error {
531
+ clientset , err := GetClientset (log , configPath , configContext )
532
+ if err != nil {
533
+ return fmt .Errorf ("failed to get clientset: %w" , err )
534
+ }
535
+
536
+ log .Info ("waiting for " + displayName + " to be ready" )
537
+ return wait .PollUntilContextCancel (ctx , statusCheckInterval , true /* immediate */ , func (ctx context.Context ) (bool , error ) {
538
+ deployment , err := clientset .AppsV1 ().Deployments (namespace ).Get (ctx , deploymentName , metav1.GetOptions {})
539
+ if err != nil {
540
+ log .Debug ("failed to get " + displayName + " deployment" ,
541
+ zap .String ("namespace" , namespace ),
542
+ zap .String ("deployment" , deploymentName ),
543
+ zap .Error (err ),
544
+ )
545
+ return false , nil
546
+ }
547
+ if deployment .Status .ReadyReplicas == 0 {
548
+ log .Debug ("waiting for " + displayName + " to become ready" ,
549
+ zap .String ("namespace" , namespace ),
550
+ zap .String ("deployment" , deploymentName ),
551
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
552
+ zap .Int32 ("replicas" , deployment .Status .Replicas ),
553
+ )
554
+ return false , nil
555
+ }
556
+
557
+ log .Info (displayName + " is ready" ,
558
+ zap .String ("namespace" , namespace ),
559
+ zap .String ("deployment" , deploymentName ),
560
+ zap .Int32 ("readyReplicas" , deployment .Status .ReadyReplicas ),
561
+ )
562
+ return true , nil
563
+ })
564
+ }
0 commit comments