From bef33728f85c1532653a4ad46c5d9556eb9935ef Mon Sep 17 00:00:00 2001 From: Wish Date: Tue, 20 Aug 2024 11:34:46 +0800 Subject: [PATCH] Allow specifying port offset Signed-off-by: Wish --- components/playground/grafana.go | 8 +--- components/playground/instance/drainer.go | 4 +- components/playground/instance/instance.go | 5 ++- components/playground/instance/pd.go | 6 +-- components/playground/instance/pump.go | 4 +- components/playground/instance/ticdc.go | 4 +- components/playground/instance/tidb.go | 6 +-- components/playground/instance/tiflash.go | 14 +++---- components/playground/instance/tikv.go | 6 +-- components/playground/instance/tikv_cdc.go | 4 +- components/playground/instance/tiproxy.go | 6 +-- components/playground/main.go | 19 +++++---- components/playground/monitor.go | 8 ++-- components/playground/ngmonitoring.go | 8 +--- components/playground/playground.go | 45 +++++++++++----------- pkg/proxy/proxy.go | 6 +-- pkg/proxy/tcp_proxy.go | 6 +-- pkg/utils/freeport.go | 10 ++--- pkg/utils/freeport_test.go | 4 +- 19 files changed, 78 insertions(+), 95 deletions(-) diff --git a/components/playground/grafana.go b/components/playground/grafana.go index bccae98c76..1a5573f3f7 100644 --- a/components/playground/grafana.go +++ b/components/playground/grafana.go @@ -151,12 +151,8 @@ var clusterName = "Test-Cluster" // dir should contains files untar the grafana. // return not error iff the Cmd is started successfully. -func (g *grafana) start(ctx context.Context, dir string, p8sURL string) (err error) { - g.port, err = utils.GetFreePort(g.host, g.port) - if err != nil { - return err - } - +func (g *grafana) start(ctx context.Context, dir string, portOffset int, p8sURL string) (err error) { + g.port = utils.MustGetFreePort(g.host, g.port, portOffset) fname := filepath.Join(dir, "conf", "provisioning", "dashboards", "dashboard.yml") err = writeDashboardConfig(fname, clusterName, filepath.Join(dir, "dashboards")) if err != nil { diff --git a/components/playground/instance/drainer.go b/components/playground/instance/drainer.go index f72aa4523f..30bf937871 100644 --- a/components/playground/instance/drainer.go +++ b/components/playground/instance/drainer.go @@ -32,14 +32,14 @@ type Drainer struct { var _ Instance = &Drainer{} // NewDrainer create a Drainer instance. -func NewDrainer(binPath string, dir, host, configPath string, id int, pds []*PDInstance) *Drainer { +func NewDrainer(binPath string, dir, host, configPath string, portOffset int, id int, pds []*PDInstance) *Drainer { d := &Drainer{ instance: instance{ BinPath: binPath, ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, 8250), + Port: utils.MustGetFreePort(host, 8250, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/instance/instance.go b/components/playground/instance/instance.go index 9766fd67f2..1a97e4c6d2 100644 --- a/components/playground/instance/instance.go +++ b/components/playground/instance/instance.go @@ -24,6 +24,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tiup/pkg/cluster/spec" tiupexec "github.com/pingcap/tiup/pkg/exec" + "github.com/pingcap/tiup/pkg/tui/colorstr" "github.com/pingcap/tiup/pkg/utils" ) @@ -98,9 +99,9 @@ func (inst *instance) PrepareBinary(componentName string, version utils.Version) } // distinguish whether the instance is started by specific binary path. if inst.BinPath == "" { - fmt.Printf("Start %s instance:%s\n", componentName, version) + colorstr.Printf("[dark_gray]Start %s instance: %s[reset]\n", componentName, version) } else { - fmt.Printf("Start %s instance:%s\n", componentName, instanceBinPath) + colorstr.Printf("[dark_gray]Start %s instance: %s[reset]\n", componentName, instanceBinPath) } inst.Version = version inst.BinPath = instanceBinPath diff --git a/components/playground/instance/pd.go b/components/playground/instance/pd.go index 67b2e53ed2..8c699b990c 100644 --- a/components/playground/instance/pd.go +++ b/components/playground/instance/pd.go @@ -50,7 +50,7 @@ type PDInstance struct { } // NewPDInstance return a PDInstance -func NewPDInstance(role PDRole, binPath, dir, host, configPath string, id int, pds []*PDInstance, port int, isCSEMode bool) *PDInstance { +func NewPDInstance(role PDRole, binPath, dir, host, configPath string, portOffset int, id int, pds []*PDInstance, port int, isCSEMode bool) *PDInstance { if port <= 0 { port = 2379 } @@ -60,8 +60,8 @@ func NewPDInstance(role PDRole, binPath, dir, host, configPath string, id int, p ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, 2380), - StatusPort: utils.MustGetFreePort(host, port), + Port: utils.MustGetFreePort(host, 2380, portOffset), + StatusPort: utils.MustGetFreePort(host, port, portOffset), ConfigPath: configPath, }, Role: role, diff --git a/components/playground/instance/pump.go b/components/playground/instance/pump.go index e4ca34b9cd..a5880fb7b4 100644 --- a/components/playground/instance/pump.go +++ b/components/playground/instance/pump.go @@ -34,14 +34,14 @@ type Pump struct { var _ Instance = &Pump{} // NewPump create a Pump instance. -func NewPump(binPath string, dir, host, configPath string, id int, pds []*PDInstance) *Pump { +func NewPump(binPath string, dir, host, configPath string, portOffset int, id int, pds []*PDInstance) *Pump { pump := &Pump{ instance: instance{ BinPath: binPath, ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, 8249), + Port: utils.MustGetFreePort(host, 8249, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/instance/ticdc.go b/components/playground/instance/ticdc.go index b233e8622f..62288f3525 100644 --- a/components/playground/instance/ticdc.go +++ b/components/playground/instance/ticdc.go @@ -33,7 +33,7 @@ type TiCDC struct { var _ Instance = &TiCDC{} // NewTiCDC create a TiCDC instance. -func NewTiCDC(binPath string, dir, host, configPath string, id int, port int, pds []*PDInstance) *TiCDC { +func NewTiCDC(binPath string, dir, host, configPath string, portOffset int, id int, port int, pds []*PDInstance) *TiCDC { if port <= 0 { port = 8300 } @@ -43,7 +43,7 @@ func NewTiCDC(binPath string, dir, host, configPath string, id int, port int, pd ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, port), + Port: utils.MustGetFreePort(host, port, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/instance/tidb.go b/components/playground/instance/tidb.go index 20b89e92a2..b5496ffca1 100644 --- a/components/playground/instance/tidb.go +++ b/components/playground/instance/tidb.go @@ -34,7 +34,7 @@ type TiDBInstance struct { } // NewTiDBInstance return a TiDBInstance -func NewTiDBInstance(binPath string, dir, host, configPath string, id, port int, pds []*PDInstance, tiproxyCertDir string, enableBinlog bool, isCSEMode bool) *TiDBInstance { +func NewTiDBInstance(binPath string, dir, host, configPath string, portOffset int, id, port int, pds []*PDInstance, tiproxyCertDir string, enableBinlog bool, isCSEMode bool) *TiDBInstance { if port <= 0 { port = 4000 } @@ -44,8 +44,8 @@ func NewTiDBInstance(binPath string, dir, host, configPath string, id, port int, ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, port), - StatusPort: utils.MustGetFreePort("0.0.0.0", 10080), + Port: utils.MustGetFreePort(host, port, portOffset), + StatusPort: utils.MustGetFreePort("0.0.0.0", 10080, portOffset), ConfigPath: configPath, }, tiproxyCertDir: tiproxyCertDir, diff --git a/components/playground/instance/tiflash.go b/components/playground/instance/tiflash.go index 995c7df3b1..6a35d8a3d9 100644 --- a/components/playground/instance/tiflash.go +++ b/components/playground/instance/tiflash.go @@ -53,14 +53,14 @@ type TiFlashInstance struct { } // NewTiFlashInstance return a TiFlashInstance -func NewTiFlashInstance(role TiFlashRole, cseOptions CSEOptions, binPath, dir, host, configPath string, id int, pds []*PDInstance, dbs []*TiDBInstance, version string) *TiFlashInstance { +func NewTiFlashInstance(role TiFlashRole, cseOptions CSEOptions, binPath, dir, host, configPath string, portOffset int, id int, pds []*PDInstance, dbs []*TiDBInstance, version string) *TiFlashInstance { if role != TiFlashRoleNormal && role != TiFlashRoleDisaggWrite && role != TiFlashRoleDisaggCompute { panic(fmt.Sprintf("Unknown TiFlash role %s", role)) } httpPort := 8123 if !tidbver.TiFlashNotNeedHTTPPortConfig(version) { - httpPort = utils.MustGetFreePort(host, httpPort) + httpPort = utils.MustGetFreePort(host, httpPort, portOffset) } return &TiFlashInstance{ instance: instance{ @@ -69,15 +69,15 @@ func NewTiFlashInstance(role TiFlashRole, cseOptions CSEOptions, binPath, dir, h Dir: dir, Host: host, Port: httpPort, - StatusPort: utils.MustGetFreePort(host, 8234), + StatusPort: utils.MustGetFreePort(host, 8234, portOffset), ConfigPath: configPath, }, Role: role, cseOpts: cseOptions, - TCPPort: utils.MustGetFreePort(host, 9100), // 9000 for default object store port - ServicePort: utils.MustGetFreePort(host, 3930), - ProxyPort: utils.MustGetFreePort(host, 20170), - ProxyStatusPort: utils.MustGetFreePort(host, 20292), + TCPPort: utils.MustGetFreePort(host, 9100, portOffset), // 9000 for default object store port + ServicePort: utils.MustGetFreePort(host, 3930, portOffset), + ProxyPort: utils.MustGetFreePort(host, 20170, portOffset), + ProxyStatusPort: utils.MustGetFreePort(host, 20292, portOffset), pds: pds, dbs: dbs, } diff --git a/components/playground/instance/tikv.go b/components/playground/instance/tikv.go index f70ec1bd96..8c97acd018 100644 --- a/components/playground/instance/tikv.go +++ b/components/playground/instance/tikv.go @@ -36,7 +36,7 @@ type TiKVInstance struct { } // NewTiKVInstance return a TiKVInstance -func NewTiKVInstance(binPath string, dir, host, configPath string, id int, port int, pds []*PDInstance, tsos []*PDInstance, isCSEMode bool, cseOptions CSEOptions, isPDMSMode bool) *TiKVInstance { +func NewTiKVInstance(binPath string, dir, host, configPath string, portOffset int, id int, port int, pds []*PDInstance, tsos []*PDInstance, isCSEMode bool, cseOptions CSEOptions, isPDMSMode bool) *TiKVInstance { if port <= 0 { port = 20160 } @@ -46,8 +46,8 @@ func NewTiKVInstance(binPath string, dir, host, configPath string, id int, port ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, port), - StatusPort: utils.MustGetFreePort(host, 20180), + Port: utils.MustGetFreePort(host, port, portOffset), + StatusPort: utils.MustGetFreePort(host, 20180, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/instance/tikv_cdc.go b/components/playground/instance/tikv_cdc.go index cbacb23b2e..8fd717dc32 100644 --- a/components/playground/instance/tikv_cdc.go +++ b/components/playground/instance/tikv_cdc.go @@ -32,14 +32,14 @@ type TiKVCDC struct { var _ Instance = &TiKVCDC{} // NewTiKVCDC create a TiKVCDC instance. -func NewTiKVCDC(binPath string, dir, host, configPath string, id int, pds []*PDInstance) *TiKVCDC { +func NewTiKVCDC(binPath string, dir, host, configPath string, portOffset int, id int, pds []*PDInstance) *TiKVCDC { tikvCdc := &TiKVCDC{ instance: instance{ BinPath: binPath, ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, 8600), + Port: utils.MustGetFreePort(host, 8600, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/instance/tiproxy.go b/components/playground/instance/tiproxy.go index c0ed180c90..db43d9284c 100644 --- a/components/playground/instance/tiproxy.go +++ b/components/playground/instance/tiproxy.go @@ -68,7 +68,7 @@ func GenTiProxySessionCerts(dir string) error { } // NewTiProxy create a TiProxy instance. -func NewTiProxy(binPath string, dir, host, configPath string, id int, port int, pds []*PDInstance) *TiProxy { +func NewTiProxy(binPath string, dir, host, configPath string, portOffset int, id int, port int, pds []*PDInstance) *TiProxy { if port <= 0 { port = 6000 } @@ -78,8 +78,8 @@ func NewTiProxy(binPath string, dir, host, configPath string, id int, port int, ID: id, Dir: dir, Host: host, - Port: utils.MustGetFreePort(host, port), - StatusPort: utils.MustGetFreePort(host, 3080), + Port: utils.MustGetFreePort(host, port, portOffset), + StatusPort: utils.MustGetFreePort(host, 3080, portOffset), ConfigPath: configPath, }, pds: pds, diff --git a/components/playground/main.go b/components/playground/main.go index 47531897a6..ad0429e258 100644 --- a/components/playground/main.go +++ b/components/playground/main.go @@ -75,6 +75,7 @@ type BootOptions struct { Monitor bool `yaml:"monitor"` CSEOpts instance.CSEOptions `yaml:"cse"` // Only available when mode == tidb-cse GrafanaPort int `yaml:"grafana_port"` + PortOffset int `yaml:"port_offset"` } var ( @@ -175,11 +176,8 @@ Examples: return err } - port, err := utils.GetFreePort("0.0.0.0", 9527) - if err != nil { - return err - } - err = dumpPort(filepath.Join(dataDir, "port"), port) + port := utils.MustGetFreePort("0.0.0.0", 9527, options.PortOffset) + err := dumpPort(filepath.Join(dataDir, "port"), port) p := NewPlayground(dataDir, port) if err != nil { return err @@ -207,7 +205,7 @@ Examples: sig := (<-sc).(syscall.Signal) atomic.StoreInt32(&p.curSig, int32(sig)) - fmt.Println("Playground receive signal: ", sig) + colorstr.Printf("\n[red][bold]Playground receive signal: %s[reset]\n", sig) // if bootCluster is not done we just cancel context to make it // clean up and return ASAP and exit directly after timeout. @@ -283,6 +281,7 @@ Note: Version constraint [bold]%s[reset] is resolved to [green][bold]%s[reset]. rootCmd.Flags().BoolVar(&options.Monitor, "monitor", true, "Start prometheus and grafana component") _ = rootCmd.Flags().MarkDeprecated("monitor", "Please use --without-monitor to control whether to disable monitor.") rootCmd.Flags().IntVar(&options.GrafanaPort, "grafana.port", 3000, "grafana port. If not provided, grafana will use 3000 as its port.") + rootCmd.Flags().IntVar(&options.PortOffset, "port-offset", 0, "If specified, all components will use default_port+port_offset as the port. This argument is useful when you want to start multiple playgrounds on the same host. Recommend to set to 10000, 20000, etc.") // NOTE: Do not set default values if they may be changed in different modes. @@ -347,10 +346,10 @@ Note: Version constraint [bold]%s[reset] is resolved to [green][bold]%s[reset]. rootCmd.Flags().StringVar(&options.TiKVCDC.Version, "kvcdc.version", "", "TiKV-CDC instance version") - rootCmd.Flags().StringVar(&options.CSEOpts.S3Endpoint, "cse.s3_endpoint", "http://127.0.0.1:9000", "Object store URL for the disaggregated TiFlash, available when --mode=tidb-cse") - rootCmd.Flags().StringVar(&options.CSEOpts.Bucket, "cse.bucket", "tiflash", "Object store bucket for the disaggregated TiFlash, available when --mode=tidb-cse") - rootCmd.Flags().StringVar(&options.CSEOpts.AccessKey, "cse.access_key", "minioadmin", "Object store access key, available when --mode=tidb-cse") - rootCmd.Flags().StringVar(&options.CSEOpts.SecretKey, "cse.secret_key", "minioadmin", "Object store secret key, available when --mode=tidb-cse") + rootCmd.Flags().StringVar(&options.CSEOpts.S3Endpoint, "cse.s3_endpoint", "http://127.0.0.1:9000", "Object store URL for --mode=tidb-cse") + rootCmd.Flags().StringVar(&options.CSEOpts.Bucket, "cse.bucket", "tiflash", "Object store bucket for --mode=tidb-cse") + rootCmd.Flags().StringVar(&options.CSEOpts.AccessKey, "cse.access_key", "minioadmin", "Object store access key for --mode=tidb-cse") + rootCmd.Flags().StringVar(&options.CSEOpts.SecretKey, "cse.secret_key", "minioadmin", "Object store secret key for --mode=tidb-cse") rootCmd.AddCommand(newDisplay()) rootCmd.AddCommand(newScaleOut()) diff --git a/components/playground/monitor.go b/components/playground/monitor.go index 3d17a7edae..94c52a09af 100644 --- a/components/playground/monitor.go +++ b/components/playground/monitor.go @@ -78,15 +78,12 @@ func (m *monitor) wait() error { } // the cmd is not started after return -func newMonitor(ctx context.Context, version string, host, dir string) (*monitor, error) { +func newMonitor(ctx context.Context, version string, host, dir string, portOffset int) (*monitor, error) { if err := utils.MkdirAll(dir, 0755); err != nil { return nil, errors.AddStack(err) } - port, err := utils.GetFreePort(host, 9090) - if err != nil { - return nil, err - } + port := utils.MustGetFreePort(host, 9090, portOffset) addr := utils.JoinHostPort(host, port) tmpl := ` @@ -132,6 +129,7 @@ scrape_configs: } var binPath string + var err error if binPath, err = tiupexec.PrepareBinary("prometheus", utils.Version(version), binPath); err != nil { return nil, err } diff --git a/components/playground/ngmonitoring.go b/components/playground/ngmonitoring.go index beb7a58552..851435b53a 100644 --- a/components/playground/ngmonitoring.go +++ b/components/playground/ngmonitoring.go @@ -45,16 +45,12 @@ func (m *ngMonitoring) wait() error { } // the cmd is not started after return -func newNGMonitoring(ctx context.Context, version string, host, dir string, pds []*instance.PDInstance) (*ngMonitoring, error) { +func newNGMonitoring(ctx context.Context, version string, host, dir string, portOffset int, pds []*instance.PDInstance) (*ngMonitoring, error) { if err := utils.MkdirAll(dir, 0755); err != nil { return nil, errors.AddStack(err) } - port, err := utils.GetFreePort(host, 12020) - if err != nil { - return nil, err - } - + port := utils.MustGetFreePort(host, 12020, portOffset) m := new(ngMonitoring) var endpoints []string for _, pd := range pds { diff --git a/components/playground/playground.go b/components/playground/playground.go index 9fa18b1cf4..17c08ef3c9 100644 --- a/components/playground/playground.go +++ b/components/playground/playground.go @@ -41,6 +41,7 @@ import ( "github.com/pingcap/tiup/pkg/environment" logprinter "github.com/pingcap/tiup/pkg/logger/printer" "github.com/pingcap/tiup/pkg/tidbver" + "github.com/pingcap/tiup/pkg/tui/colorstr" "github.com/pingcap/tiup/pkg/tui/progress" "github.com/pingcap/tiup/pkg/utils" "golang.org/x/mod/semver" @@ -722,7 +723,7 @@ func (p *Playground) addInstance(componentID string, pdRole instance.PDRole, tif switch componentID { case spec.ComponentPD: - inst := instance.NewPDInstance(pdRole, cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") + inst := instance.NewPDInstance(pdRole, cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") ins = inst if pdRole == instance.PDRoleNormal || pdRole == instance.PDRoleAPI { if p.booted { @@ -740,46 +741,46 @@ func (p *Playground) addInstance(componentID string, pdRole instance.PDRole, tif p.schedulings = append(p.schedulings, inst) } case spec.ComponentTSO: - inst := instance.NewPDInstance(instance.PDRoleTSO, cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") + inst := instance.NewPDInstance(instance.PDRoleTSO, cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") ins = inst p.tsos = append(p.tsos, inst) case spec.ComponentScheduling: - inst := instance.NewPDInstance(instance.PDRoleScheduling, cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") + inst := instance.NewPDInstance(instance.PDRoleScheduling, cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds, cfg.Port, p.bootOptions.Mode == "tidb-cse") ins = inst p.schedulings = append(p.schedulings, inst) case spec.ComponentTiDB: - inst := instance.NewTiDBInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id, cfg.Port, p.pds, dataDir, p.enableBinlog(), p.bootOptions.Mode == "tidb-cse") + inst := instance.NewTiDBInstance(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, cfg.Port, p.pds, dataDir, p.enableBinlog(), p.bootOptions.Mode == "tidb-cse") ins = inst p.tidbs = append(p.tidbs, inst) case spec.ComponentTiKV: - inst := instance.NewTiKVInstance(cfg.BinPath, dir, host, cfg.ConfigPath, id, cfg.Port, p.pds, p.tsos, p.bootOptions.Mode == "tidb-cse", p.bootOptions.CSEOpts, p.bootOptions.PDMode == "ms") + inst := instance.NewTiKVInstance(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, cfg.Port, p.pds, p.tsos, p.bootOptions.Mode == "tidb-cse", p.bootOptions.CSEOpts, p.bootOptions.PDMode == "ms") ins = inst p.tikvs = append(p.tikvs, inst) case spec.ComponentTiFlash: - inst := instance.NewTiFlashInstance(tiflashRole, p.bootOptions.CSEOpts, cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds, p.tidbs, cfg.Version) + inst := instance.NewTiFlashInstance(tiflashRole, p.bootOptions.CSEOpts, cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds, p.tidbs, cfg.Version) ins = inst p.tiflashs = append(p.tiflashs, inst) case spec.ComponentTiProxy: if err := instance.GenTiProxySessionCerts(dataDir); err != nil { return nil, err } - inst := instance.NewTiProxy(cfg.BinPath, dir, host, cfg.ConfigPath, id, cfg.Port, p.pds) + inst := instance.NewTiProxy(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, cfg.Port, p.pds) ins = inst p.tiproxys = append(p.tiproxys, inst) case spec.ComponentCDC: - inst := instance.NewTiCDC(cfg.BinPath, dir, host, cfg.ConfigPath, id, cfg.Port, p.pds) + inst := instance.NewTiCDC(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, cfg.Port, p.pds) ins = inst p.ticdcs = append(p.ticdcs, inst) case spec.ComponentTiKVCDC: - inst := instance.NewTiKVCDC(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds) + inst := instance.NewTiKVCDC(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds) ins = inst p.tikvCdcs = append(p.tikvCdcs, inst) case spec.ComponentPump: - inst := instance.NewPump(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds) + inst := instance.NewPump(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds) ins = inst p.pumps = append(p.pumps, inst) case spec.ComponentDrainer: - inst := instance.NewDrainer(cfg.BinPath, dir, host, cfg.ConfigPath, id, p.pds) + inst := instance.NewDrainer(cfg.BinPath, dir, host, cfg.ConfigPath, options.PortOffset, id, p.pds) ins = inst p.drainers = append(p.drainers, inst) default: @@ -797,13 +798,13 @@ func (p *Playground) waitAllDBUp() ([]string, []string) { var tidbMu, tiproxyMu sync.Mutex var bars *progress.MultiBar if len(p.tiproxys) > 0 { - bars = progress.NewMultiBar(color.YellowString("Waiting for tidb and tiproxy instances ready")) + bars = progress.NewMultiBar(colorstr.Sprintf("[dark_gray]Waiting for tidb and tiproxy instances ready")) } else { - bars = progress.NewMultiBar(color.YellowString("Waiting for tidb instances ready")) + bars = progress.NewMultiBar(colorstr.Sprintf("[dark_gray]Waiting for tidb instances ready")) } for _, db := range p.tidbs { wg.Add(1) - prefix := color.YellowString(db.Addr()) + prefix := db.Addr() bar := bars.AddBar(prefix) go func(dbInst *instance.TiDBInstance) { defer wg.Done() @@ -868,10 +869,10 @@ func (p *Playground) waitAllTiFlashUp() { ) var wg sync.WaitGroup - bars := progress.NewMultiBar(color.YellowString("Waiting for tiflash instances ready")) + bars := progress.NewMultiBar(colorstr.Sprintf("[dark_gray]Waiting for tiflash instances ready")) for _, flash := range p.tiflashs { wg.Add(1) - prefix := color.YellowString(flash.Addr()) + prefix := flash.Addr() bar := bars.AddBar(prefix) go func(flashInst *instance.TiFlashInstance) { defer wg.Done() @@ -1014,7 +1015,7 @@ func (p *Playground) bootCluster(ctx context.Context, env *environment.Environme // Try to create bucket. err := s3Client.MakeBucket(ctxCheck, options.CSEOpts.Bucket, minio.MakeBucketOptions{}) if err != nil { - return fmt.Errorf("CSE mode preflight check failed: Bucket %s doesn't exist", options.CSEOpts.Bucket) + return fmt.Errorf("CSE mode preflight check failed: Bucket %s doesn't exist and fail to create automatically (your bucket name may be invalid?)", options.CSEOpts.Bucket) } } @@ -1228,9 +1229,9 @@ func (p *Playground) wait() error { func (p *Playground) terminate(sig syscall.Signal) { kill := func(name string, pid int, wait func() error) { if sig == syscall.SIGKILL { - fmt.Printf("Force %s(%d) to quit...\n", name, pid) + colorstr.Printf("[dark_gray]Force %s(%d) to quit...\n", name, pid) } else if atomic.LoadInt32(&p.curSig) == int32(sig) { // In case of double ctr+c - fmt.Printf("Wait %s(%d) to quit...\n", name, pid) + colorstr.Printf("[dark_gray]Wait %s(%d) to quit...\n", name, pid) } _ = syscall.Kill(pid, sig) @@ -1346,7 +1347,7 @@ func (p *Playground) bootMonitor(ctx context.Context, env *environment.Environme dataDir := p.dataDir promDir := filepath.Join(dataDir, "prometheus") - monitor, err := newMonitor(ctx, options.Version, options.Host, promDir) + monitor, err := newMonitor(ctx, options.Version, options.Host, promDir, options.PortOffset) if err != nil { return nil, nil, err } @@ -1390,7 +1391,7 @@ func (p *Playground) bootNGMonitoring(ctx context.Context, env *environment.Envi dataDir := p.dataDir promDir := filepath.Join(dataDir, "prometheus") - ngm, err := newNGMonitoring(ctx, options.Version, options.Host, promDir, p.pds) + ngm, err := newNGMonitoring(ctx, options.Version, options.Host, promDir, options.PortOffset, p.pds) if err != nil { return nil, err } @@ -1469,7 +1470,7 @@ func (p *Playground) bootGrafana(ctx context.Context, env *environment.Environme grafana := newGrafana(options.Version, options.Host, options.GrafanaPort) // fmt.Println("Start Grafana instance...") - err = grafana.start(ctx, grafanaDir, "http://"+utils.JoinHostPort(monitorInfo.IP, monitorInfo.Port)) + err = grafana.start(ctx, grafanaDir, options.PortOffset, "http://"+utils.JoinHostPort(monitorInfo.IP, monitorInfo.Port)) if err != nil { return nil, err } diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index e83df39df6..63b1dd6384 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -49,11 +49,7 @@ func MaybeStartProxy( return err } - httpPort, err := utils.GetFreePort("127.0.0.1", 12345) - if err != nil { - return err - } - + httpPort := utils.MustGetFreePort("127.0.0.1", 12345, 0) addr := fmt.Sprintf("127.0.0.1:%d", httpPort) // TODO: Using environment variables to share data may not be a good idea diff --git a/pkg/proxy/tcp_proxy.go b/pkg/proxy/tcp_proxy.go index d758c06506..6250e9fd7f 100644 --- a/pkg/proxy/tcp_proxy.go +++ b/pkg/proxy/tcp_proxy.go @@ -66,11 +66,7 @@ func NewTCPProxy( p.config.Password = password } - port, err := utils.GetFreePort("127.0.0.1", 22345) - if err != nil { - logger.Errorf("get free port error: %v", err) - return nil - } + port = utils.MustGetFreePort("127.0.0.1", 22345, 0) p.endpoint = fmt.Sprintf("127.0.0.1:%d", port) listener, err := net.Listen("tcp", p.endpoint) diff --git a/pkg/utils/freeport.go b/pkg/utils/freeport.go index 24b6f30e19..b5d6bbd685 100644 --- a/pkg/utils/freeport.go +++ b/pkg/utils/freeport.go @@ -22,9 +22,8 @@ import ( // To avoid the same port be generated twice in a short time var portCache sync.Map -// GetFreePort asks the kernel for a free open port that is ready to use. -func GetFreePort(host string, priority int) (int, error) { - if port, err := getPort(host, priority); err == nil { +func getFreePort(host string, defaultPort int) (int, error) { + if port, err := getPort(host, defaultPort); err == nil { return port, nil } else if port, err := getPort(host, 0); err == nil { return port, nil @@ -34,8 +33,9 @@ func GetFreePort(host string, priority int) (int, error) { } // MustGetFreePort asks the kernel for a free open port that is ready to use, if fail, panic -func MustGetFreePort(host string, priority int) int { - if port, err := GetFreePort(host, priority); err == nil { +func MustGetFreePort(host string, defaultPort int, portOffset int) int { + bestPort := defaultPort + portOffset + if port, err := getFreePort(host, bestPort); err == nil { return port } panic("can't get a free port") diff --git a/pkg/utils/freeport_test.go b/pkg/utils/freeport_test.go index c32b1d3cfa..23ab8a1f64 100644 --- a/pkg/utils/freeport_test.go +++ b/pkg/utils/freeport_test.go @@ -10,11 +10,11 @@ type TestFreePortSuite struct{} func (s *TestFreePortSuite) TestGetFreePort(c *C) { expected := 22334 - port, err := GetFreePort("127.0.0.1", expected) + port, err := getFreePort("127.0.0.1", expected) c.Assert(err, IsNil) c.Assert(port, Equals, expected, Commentf("expect port %s", expected)) - port, err = GetFreePort("127.0.0.1", expected) + port, err = getFreePort("127.0.0.1", expected) c.Assert(err, IsNil) c.Assert(port == expected, IsFalse, Commentf("should not return same port twice")) }