vitess.io/vitess@v0.16.2/go/test/endtoend/docker/vttestserver.go (about) 1 /* 2 Copyright 2021 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package docker 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "os" 23 "os/exec" 24 "path" 25 "strconv" 26 "strings" 27 "time" 28 29 "vitess.io/vitess/go/vt/log" 30 ) 31 32 const ( 33 vttestserverMysql57image = "vttestserver-e2etest/mysql57" 34 vttestserverMysql80image = "vttestserver-e2etest/mysql80" 35 ) 36 37 type vttestserver struct { 38 dockerImage string 39 keyspaces []string 40 numShards []int 41 mysqlMaxConnecetions int 42 port int 43 } 44 45 func newVttestserver(dockerImage string, keyspaces []string, numShards []int, mysqlMaxConnections, port int) *vttestserver { 46 return &vttestserver{ 47 dockerImage: dockerImage, 48 keyspaces: keyspaces, 49 numShards: numShards, 50 mysqlMaxConnecetions: mysqlMaxConnections, 51 port: port, 52 } 53 } 54 55 func (v *vttestserver) teardown() { 56 cmd := exec.Command("docker", "rm", "--force", "vttestserver-end2end-test") 57 err := cmd.Run() 58 if err != nil { 59 log.Errorf("docker teardown failed :- %s", err.Error()) 60 } 61 } 62 63 // startDockerImage starts the docker image for the vttestserver 64 func (v *vttestserver) startDockerImage() error { 65 cmd := exec.Command("docker", "run") 66 cmd.Args = append(cmd.Args, "--name=vttestserver-end2end-test") 67 cmd.Args = append(cmd.Args, "-p", fmt.Sprintf("%d:33577", v.port)) 68 cmd.Args = append(cmd.Args, "-e", "PORT=33574") 69 cmd.Args = append(cmd.Args, "-e", fmt.Sprintf("KEYSPACES=%s", strings.Join(v.keyspaces, ","))) 70 cmd.Args = append(cmd.Args, "-e", fmt.Sprintf("NUM_SHARDS=%s", strings.Join(convertToStringSlice(v.numShards), ","))) 71 cmd.Args = append(cmd.Args, "-e", "MYSQL_BIND_HOST=0.0.0.0") 72 cmd.Args = append(cmd.Args, "-e", fmt.Sprintf("MYSQL_MAX_CONNECTIONS=%d", v.mysqlMaxConnecetions)) 73 cmd.Args = append(cmd.Args, "--health-cmd", "mysqladmin ping -h127.0.0.1 -P33577") 74 cmd.Args = append(cmd.Args, "--health-interval=5s") 75 cmd.Args = append(cmd.Args, "--health-timeout=2s") 76 cmd.Args = append(cmd.Args, "--health-retries=5") 77 cmd.Args = append(cmd.Args, v.dockerImage) 78 79 err := cmd.Start() 80 if err != nil { 81 return err 82 } 83 return nil 84 } 85 86 // dockerStatus is a struct used to unmarshal json output from `docker inspect` 87 type dockerStatus struct { 88 State struct { 89 Health struct { 90 Status string 91 } 92 } 93 } 94 95 // waitUntilDockerHealthy waits until the docker image is healthy. It takes in as argument the amount of seconds to wait before timeout 96 func (v *vttestserver) waitUntilDockerHealthy(timeoutDelay int) error { 97 timeOut := time.After(time.Duration(timeoutDelay) * time.Second) 98 99 for { 100 select { 101 case <-timeOut: 102 // return error due to timeout 103 return fmt.Errorf("timed out waiting for docker image to start") 104 case <-time.After(time.Second): 105 cmd := exec.Command("docker", "inspect", "vttestserver-end2end-test") 106 out, err := cmd.Output() 107 if err != nil { 108 return err 109 } 110 var x []dockerStatus 111 err = json.Unmarshal(out, &x) 112 if err != nil { 113 return err 114 } 115 if len(x) > 0 { 116 status := x[0].State.Health.Status 117 if status == "healthy" { 118 return nil 119 } 120 } 121 } 122 } 123 } 124 125 // convertToStringSlice converts an integer slice to string slice 126 func convertToStringSlice(intSlice []int) []string { 127 var stringSlice []string 128 for _, val := range intSlice { 129 str := strconv.Itoa(val) 130 stringSlice = append(stringSlice, str) 131 } 132 return stringSlice 133 } 134 135 // makeVttestserverDockerImages creates the vttestserver docker images for both MySQL57 and MySQL80 136 func makeVttestserverDockerImages() error { 137 mainVitessPath := path.Join(os.Getenv("PWD"), "../../../..") 138 dockerFilePath := path.Join(mainVitessPath, "docker/vttestserver/Dockerfile.mysql57") 139 cmd57 := exec.Command("docker", "build", "-f", dockerFilePath, "-t", vttestserverMysql57image, ".") 140 cmd57.Dir = mainVitessPath 141 err := cmd57.Start() 142 if err != nil { 143 return err 144 } 145 146 dockerFilePath = path.Join(mainVitessPath, "docker/vttestserver/Dockerfile.mysql80") 147 cmd80 := exec.Command("docker", "build", "-f", dockerFilePath, "-t", vttestserverMysql80image, ".") 148 cmd80.Dir = mainVitessPath 149 err = cmd80.Start() 150 if err != nil { 151 return err 152 } 153 154 err = cmd57.Wait() 155 if err != nil { 156 return err 157 } 158 159 err = cmd80.Wait() 160 if err != nil { 161 return err 162 } 163 164 return nil 165 }