vitess.io/vitess@v0.16.2/go/test/endtoend/vault/vault_server.go (about) 1 /* 2 Copyright 2020 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 vault 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "net/http" 24 "os" 25 "os/exec" 26 "path" 27 "strings" 28 "syscall" 29 "time" 30 31 "vitess.io/vitess/go/vt/log" 32 ) 33 34 const ( 35 vaultExecutableName = "vault" 36 vaultDownloadSource = "https://vitess-operator.storage.googleapis.com/install/vault" 37 vaultDownloadSize = 132738840 38 vaultDirName = "vault" 39 vaultConfigFileName = "vault.hcl" 40 vaultCertFileName = "vault-cert.pem" 41 vaultCAFileName = "ca.pem" 42 vaultKeyFileName = "vault-key.pem" 43 vaultSetupScript = "vault-setup.sh" 44 ) 45 46 // Server : Basic parameters for the running the Vault server 47 type Server struct { 48 address string 49 port1 int 50 port2 int 51 execPath string 52 logDir string 53 54 proc *exec.Cmd 55 exit chan error 56 } 57 58 // Start the Vault server in dev mode 59 func (vs *Server) start() error { 60 // Download and unpack vault binary 61 vs.execPath = path.Join(os.Getenv("EXTRA_BIN"), vaultExecutableName) 62 fileStat, err := os.Stat(vs.execPath) 63 if err != nil || fileStat.Size() != vaultDownloadSize { 64 log.Warningf("Downloading Vault binary to: %v", vs.execPath) 65 err := downloadExecFile(vs.execPath, vaultDownloadSource) 66 if err != nil { 67 log.Error(err) 68 return err 69 } 70 } else { 71 log.Warningf("Vault binary already present at %v , not re-downloading", vs.execPath) 72 } 73 74 // Create Vault log directory 75 vs.logDir = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("%s_%d", vaultDirName, vs.port1)) 76 if _, err := os.Stat(vs.logDir); os.IsNotExist(err) { 77 err := os.Mkdir(vs.logDir, 0700) 78 if err != nil { 79 log.Error(err) 80 return err 81 } 82 } 83 84 hclFile := path.Join(os.Getenv("PWD"), vaultConfigFileName) 85 hcl, _ := os.ReadFile(hclFile) 86 // Replace variable parts in Vault config file 87 hcl = bytes.Replace(hcl, []byte("$server"), []byte(vs.address), 1) 88 hcl = bytes.Replace(hcl, []byte("$port"), []byte(fmt.Sprintf("%d", vs.port1)), 1) 89 hcl = bytes.Replace(hcl, []byte("$cert"), []byte(path.Join(os.Getenv("PWD"), vaultCertFileName)), 1) 90 hcl = bytes.Replace(hcl, []byte("$key"), []byte(path.Join(os.Getenv("PWD"), vaultKeyFileName)), 1) 91 newHclFile := path.Join(vs.logDir, vaultConfigFileName) 92 err = os.WriteFile(newHclFile, hcl, 0700) 93 if err != nil { 94 log.Error(err) 95 return err 96 } 97 98 vs.proc = exec.Command( 99 vs.execPath, 100 "server", 101 fmt.Sprintf("-config=%s", newHclFile), 102 ) 103 104 logFile, err := os.Create(path.Join(vs.logDir, "log.txt")) 105 if err != nil { 106 log.Error(err) 107 return err 108 } 109 vs.proc.Stderr = logFile 110 vs.proc.Stdout = logFile 111 112 vs.proc.Env = append(vs.proc.Env, os.Environ()...) 113 114 log.Infof("Running Vault server with command: %v", strings.Join(vs.proc.Args, " ")) 115 116 err = vs.proc.Start() 117 if err != nil { 118 return err 119 } 120 vs.exit = make(chan error) 121 go func() { 122 if vs.proc != nil { 123 vs.exit <- vs.proc.Wait() 124 } 125 }() 126 return nil 127 } 128 129 func (vs *Server) stop() error { 130 if vs.proc == nil || vs.exit == nil { 131 return nil 132 } 133 // Attempt graceful shutdown with SIGTERM first 134 vs.proc.Process.Signal(syscall.SIGTERM) 135 136 select { 137 case err := <-vs.exit: 138 vs.proc = nil 139 return err 140 141 case <-time.After(10 * time.Second): 142 vs.proc.Process.Kill() 143 vs.proc = nil 144 return <-vs.exit 145 } 146 } 147 148 // Download file from url to path; making it executable 149 func downloadExecFile(path string, url string) error { 150 resp, err := http.Get(url) 151 if err != nil { 152 return err 153 } 154 defer resp.Body.Close() 155 156 err = os.WriteFile(path, []byte(""), 0700) 157 if err != nil { 158 return err 159 } 160 out, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.ModeAppend) 161 if err != nil { 162 return err 163 } 164 defer out.Close() 165 166 _, err = io.Copy(out, resp.Body) 167 return err 168 }