github.com/pingcap/tiup@v1.15.1/components/playground/instance/pump.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package instance 15 16 import ( 17 "context" 18 "fmt" 19 "net/http" 20 "path/filepath" 21 "strings" 22 "time" 23 24 tiupexec "github.com/pingcap/tiup/pkg/exec" 25 "github.com/pingcap/tiup/pkg/utils" 26 ) 27 28 // Pump represent a pump instance. 29 type Pump struct { 30 instance 31 pds []*PDInstance 32 Process 33 } 34 35 var _ Instance = &Pump{} 36 37 // NewPump create a Pump instance. 38 func NewPump(binPath string, dir, host, configPath string, id int, pds []*PDInstance) *Pump { 39 pump := &Pump{ 40 instance: instance{ 41 BinPath: binPath, 42 ID: id, 43 Dir: dir, 44 Host: host, 45 Port: utils.MustGetFreePort(host, 8249), 46 ConfigPath: configPath, 47 }, 48 pds: pds, 49 } 50 pump.StatusPort = pump.Port 51 return pump 52 } 53 54 // NodeID return the node id of pump. 55 func (p *Pump) NodeID() string { 56 return fmt.Sprintf("pump_%d", p.ID) 57 } 58 59 // Ready return nil when pump is ready to serve. 60 func (p *Pump) Ready(ctx context.Context) error { 61 url := fmt.Sprintf("http://%s/status", utils.JoinHostPort(p.Host, p.Port)) 62 63 ready := func() bool { 64 resp, err := http.Get(url) 65 if err != nil { 66 return false 67 } 68 defer resp.Body.Close() 69 return resp.StatusCode == 200 70 } 71 72 for { 73 if ready() { 74 return nil 75 } 76 77 select { 78 case <-ctx.Done(): 79 return ctx.Err() 80 case <-time.After(time.Second): 81 // just retry 82 } 83 } 84 } 85 86 // Addr return the address of Pump. 87 func (p *Pump) Addr() string { 88 return utils.JoinHostPort(AdvertiseHost(p.Host), p.Port) 89 } 90 91 // Start implements Instance interface. 92 func (p *Pump) Start(ctx context.Context, version utils.Version) error { 93 endpoints := pdEndpoints(p.pds, true) 94 95 args := []string{ 96 fmt.Sprintf("--node-id=%s", p.NodeID()), 97 fmt.Sprintf("--addr=%s", utils.JoinHostPort(p.Host, p.Port)), 98 fmt.Sprintf("--advertise-addr=%s", utils.JoinHostPort(AdvertiseHost(p.Host), p.Port)), 99 fmt.Sprintf("--pd-urls=%s", strings.Join(endpoints, ",")), 100 fmt.Sprintf("--log-file=%s", p.LogFile()), 101 } 102 if p.ConfigPath != "" { 103 args = append(args, fmt.Sprintf("--config=%s", p.ConfigPath)) 104 } 105 106 var err error 107 if p.BinPath, err = tiupexec.PrepareBinary("pump", version, p.BinPath); err != nil { 108 return err 109 } 110 p.Process = &process{cmd: PrepareCommand(ctx, p.BinPath, args, nil, p.Dir)} 111 112 logIfErr(p.Process.SetOutputFile(p.LogFile())) 113 return p.Process.Start() 114 } 115 116 // Component return component name. 117 func (p *Pump) Component() string { 118 return "pump" 119 } 120 121 // LogFile return the log file. 122 func (p *Pump) LogFile() string { 123 return filepath.Join(p.Dir, "pump.log") 124 }