@@ -18,6 +18,7 @@ import (
1818 "time"
1919
2020 "github.com/docker/docker/api/types/container"
21+ "github.com/docker/go-connections/nat"
2122 "github.com/go-sql-driver/mysql"
2223 "github.com/testcontainers/testcontainers-go"
2324 "github.com/testcontainers/testcontainers-go/network"
@@ -357,6 +358,8 @@ type TiDBTestCluster struct {
357358 Endpoint string
358359 Username string
359360 Password string
361+ // PlaygroundContainer is used when TiUP Playground is used instead of separate containers
362+ PlaygroundContainer testcontainers.Container
360363}
361364
362365// startTiDBCluster starts a TiDB cluster (PD, TiKV, TiDB) for testing
@@ -423,8 +426,8 @@ func startTiDBCluster(ctx context.Context, t *testing.T, version string) *TiDBTe
423426 hostConfig .Ulimits = []* container.Ulimit {
424427 {
425428 Name : "nofile" ,
426- Soft : tikvFdLimit ,
427- Hard : tikvFdLimit ,
429+ Soft : int64 ( tikvFdLimit ) ,
430+ Hard : int64 ( tikvFdLimit ) ,
428431 },
429432 }
430433 },
@@ -487,9 +490,89 @@ func startTiDBCluster(ctx context.Context, t *testing.T, version string) *TiDBTe
487490 }
488491}
489492
493+ // startSharedTiDBClusterWithTiUP starts a TiDB cluster using TiUP Playground inside a single container
494+ // This is faster and simpler than managing separate PD, TiKV, and TiDB containers
495+ func startSharedTiDBClusterWithTiUP (version string ) (* TiDBTestCluster , error ) {
496+ ctx := context .Background ()
497+
498+ // Build TiUP Playground image from Dockerfile
499+ // This builds a container with TiUP installed that can run playground
500+ req := testcontainers.ContainerRequest {
501+ FromDockerfile : testcontainers.FromDockerfile {
502+ Context : "." ,
503+ Dockerfile : "Dockerfile.tiup-playground" ,
504+ PrintBuildLog : true , // Helpful for debugging
505+ },
506+ ExposedPorts : []string {"4000/tcp" },
507+ // TiUP Playground needs to run processes, so we need privileged mode
508+ HostConfigModifier : func (hostConfig * container.HostConfig ) {
509+ hostConfig .Privileged = true
510+ // Set ulimit for file descriptors (TiKV inside playground needs this)
511+ hostConfig .Ulimits = []* container.Ulimit {
512+ {
513+ Name : "nofile" ,
514+ Soft : 250000 ,
515+ Hard : 250000 ,
516+ },
517+ }
518+ },
519+ Cmd : []string {
520+ "/root/.tiup/bin/tiup" , "playground" , version ,
521+ "--db" , "1" ,
522+ "--kv" , "1" ,
523+ "--pd" , "1" ,
524+ "--tiflash" , "0" ,
525+ "--without-monitor" ,
526+ "--host" , "0.0.0.0" ,
527+ "--db.port" , "4000" ,
528+ },
529+ WaitingFor : wait .ForAll (
530+ wait .ForListeningPort ("4000/tcp" ),
531+ wait .ForSQL (nat .Port ("4000/tcp" ), "mysql" , func (host string , port nat.Port ) string {
532+ return fmt .Sprintf ("root@tcp(%s:%s)/" , host , port .Port ())
533+ }),
534+ ).WithStartupTimeout (240 * time .Second ), // Longer timeout for first-time TiUP component downloads
535+ }
536+
537+ playgroundContainer , err := testcontainers .GenericContainer (ctx , testcontainers.GenericContainerRequest {
538+ ContainerRequest : req ,
539+ Started : true ,
540+ })
541+ if err != nil {
542+ return nil , fmt .Errorf ("failed to start TiUP Playground container: %v" , err )
543+ }
544+
545+ // Get endpoint
546+ host , err := playgroundContainer .Host (ctx )
547+ if err != nil {
548+ return nil , fmt .Errorf ("failed to get playground container host: %v" , err )
549+ }
550+
551+ port , err := playgroundContainer .MappedPort (ctx , "4000" )
552+ if err != nil {
553+ return nil , fmt .Errorf ("failed to get playground container port: %v" , err )
554+ }
555+
556+ endpoint := fmt .Sprintf ("%s:%s" , host , port .Port ())
557+
558+ return & TiDBTestCluster {
559+ PlaygroundContainer : playgroundContainer ,
560+ Endpoint : endpoint ,
561+ Username : "root" ,
562+ Password : "" ,
563+ }, nil
564+ }
565+
490566// startSharedTiDBCluster starts a shared TiDB cluster without requiring a testing.T
491567// Used by TestMain for initial setup
568+ // Now uses TiUP Playground for better performance and reliability
492569func startSharedTiDBCluster (version string ) (* TiDBTestCluster , error ) {
570+ // Use TiUP Playground approach - much faster and simpler
571+ return startSharedTiDBClusterWithTiUP (version )
572+ }
573+
574+ // Legacy multi-container approach (kept for reference, but not used)
575+ func startSharedTiDBClusterLegacy (version string ) (* TiDBTestCluster , error ) {
493576 ctx := context .Background ()
494577
495578 // Create a Docker network for TiDB cluster components
@@ -553,8 +636,8 @@ func startSharedTiDBCluster(version string) (*TiDBTestCluster, error) {
553636 hostConfig .Ulimits = []* container.Ulimit {
554637 {
555638 Name : "nofile" ,
556- Soft : tikvFdLimit ,
557- Hard : tikvFdLimit ,
639+ Soft : int64 ( tikvFdLimit ) ,
640+ Hard : int64 ( tikvFdLimit ) ,
558641 },
559642 }
560643 },
@@ -624,17 +707,34 @@ func cleanupSharedTiDBCluster() {
624707
625708 if sharedTiDBCluster != nil {
626709 ctx := context .Background ()
627- if err := sharedTiDBCluster .TiDBContainer .Terminate (ctx ); err != nil {
628- fmt .Printf ("Warning: Failed to terminate TiDB container: %v\n " , err )
629- }
630- if err := sharedTiDBCluster .TiKVContainer .Terminate (ctx ); err != nil {
631- fmt .Printf ("Warning: Failed to terminate TiKV container: %v\n " , err )
632- }
633- if err := sharedTiDBCluster .PDContainer .Terminate (ctx ); err != nil {
634- fmt .Printf ("Warning: Failed to terminate PD container: %v\n " , err )
635- }
636- if err := sharedTiDBCluster .Network .Remove (ctx ); err != nil {
637- fmt .Printf ("Warning: Failed to remove TiDB network: %v\n " , err )
710+
711+ // If using TiUP Playground (single container)
712+ if sharedTiDBCluster .PlaygroundContainer != nil {
713+ if err := sharedTiDBCluster .PlaygroundContainer .Terminate (ctx ); err != nil {
714+ fmt .Printf ("Warning: Failed to terminate TiUP Playground container: %v\n " , err )
715+ }
716+ } else {
717+ // Legacy multi-container approach
718+ if sharedTiDBCluster .TiDBContainer != nil {
719+ if err := sharedTiDBCluster .TiDBContainer .Terminate (ctx ); err != nil {
720+ fmt .Printf ("Warning: Failed to terminate TiDB container: %v\n " , err )
721+ }
722+ }
723+ if sharedTiDBCluster .TiKVContainer != nil {
724+ if err := sharedTiDBCluster .TiKVContainer .Terminate (ctx ); err != nil {
725+ fmt .Printf ("Warning: Failed to terminate TiKV container: %v\n " , err )
726+ }
727+ }
728+ if sharedTiDBCluster .PDContainer != nil {
729+ if err := sharedTiDBCluster .PDContainer .Terminate (ctx ); err != nil {
730+ fmt .Printf ("Warning: Failed to terminate PD container: %v\n " , err )
731+ }
732+ }
733+ if sharedTiDBCluster .Network != nil {
734+ if err := sharedTiDBCluster .Network .Remove (ctx ); err != nil {
735+ fmt .Printf ("Warning: Failed to remove TiDB network: %v\n " , err )
736+ }
737+ }
638738 }
639739 sharedTiDBCluster = nil
640740 }
0 commit comments