go.etcd.io/etcd@v3.3.27+incompatible/tests/e2e/etcd_process.go (about) 1 // Copyright 2017 The etcd Authors 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package e2e 16 17 import ( 18 "fmt" 19 "net/url" 20 "os" 21 22 "github.com/coreos/etcd/pkg/expect" 23 "github.com/coreos/etcd/pkg/fileutil" 24 ) 25 26 var ( 27 etcdServerReadyLines = []string{"enabled capabilities for version", "published"} 28 binPath string 29 ctlBinPath string 30 ) 31 32 // etcdProcess is a process that serves etcd requests. 33 type etcdProcess interface { 34 EndpointsV2() []string 35 EndpointsV3() []string 36 EndpointsMetrics() []string 37 38 Start() error 39 Restart() error 40 Stop() error 41 Close() error 42 WithStopSignal(sig os.Signal) os.Signal 43 Config() *etcdServerProcessConfig 44 } 45 46 type etcdServerProcess struct { 47 cfg *etcdServerProcessConfig 48 proc *expect.ExpectProcess 49 donec chan struct{} // closed when Interact() terminates 50 } 51 52 type etcdServerProcessConfig struct { 53 execPath string 54 args []string 55 tlsArgs []string 56 57 dataDirPath string 58 keepDataDir bool 59 60 name string 61 62 purl url.URL 63 64 acurl string 65 murl string 66 67 initialToken string 68 initialCluster string 69 } 70 71 func newEtcdServerProcess(cfg *etcdServerProcessConfig) (*etcdServerProcess, error) { 72 if !fileutil.Exist(cfg.execPath) { 73 return nil, fmt.Errorf("could not find etcd binary") 74 } 75 if !cfg.keepDataDir { 76 if err := os.RemoveAll(cfg.dataDirPath); err != nil { 77 return nil, err 78 } 79 } 80 return &etcdServerProcess{cfg: cfg, donec: make(chan struct{})}, nil 81 } 82 83 func (ep *etcdServerProcess) EndpointsV2() []string { return []string{ep.cfg.acurl} } 84 func (ep *etcdServerProcess) EndpointsV3() []string { return ep.EndpointsV2() } 85 func (ep *etcdServerProcess) EndpointsMetrics() []string { return []string{ep.cfg.murl} } 86 87 func (ep *etcdServerProcess) Start() error { 88 if ep.proc != nil { 89 panic("already started") 90 } 91 proc, err := spawnCmd(append([]string{ep.cfg.execPath}, ep.cfg.args...)) 92 if err != nil { 93 return err 94 } 95 ep.proc = proc 96 return ep.waitReady() 97 } 98 99 func (ep *etcdServerProcess) Restart() error { 100 if err := ep.Stop(); err != nil { 101 return err 102 } 103 ep.donec = make(chan struct{}) 104 return ep.Start() 105 } 106 107 func (ep *etcdServerProcess) Stop() (err error) { 108 if ep == nil || ep.proc == nil { 109 return nil 110 } 111 err = ep.proc.Stop() 112 if err != nil { 113 return err 114 } 115 ep.proc = nil 116 <-ep.donec 117 ep.donec = make(chan struct{}) 118 if ep.cfg.purl.Scheme == "unix" || ep.cfg.purl.Scheme == "unixs" { 119 err = os.Remove(ep.cfg.purl.Host + ep.cfg.purl.Path) 120 if err != nil { 121 return err 122 } 123 } 124 return nil 125 } 126 127 func (ep *etcdServerProcess) Close() error { 128 if err := ep.Stop(); err != nil { 129 return err 130 } 131 return os.RemoveAll(ep.cfg.dataDirPath) 132 } 133 134 func (ep *etcdServerProcess) WithStopSignal(sig os.Signal) os.Signal { 135 ret := ep.proc.StopSignal 136 ep.proc.StopSignal = sig 137 return ret 138 } 139 140 func (ep *etcdServerProcess) waitReady() error { 141 defer close(ep.donec) 142 return waitReadyExpectProc(ep.proc, etcdServerReadyLines) 143 } 144 145 func (ep *etcdServerProcess) Config() *etcdServerProcessConfig { return ep.cfg }