github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+incompatible/store/storetest/docker.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package storetest 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io" 10 "net" 11 "os/exec" 12 "strings" 13 "time" 14 15 l4g "github.com/alecthomas/log4go" 16 17 "github.com/mattermost/mattermost-server/model" 18 ) 19 20 type Container struct { 21 Id string 22 NetworkSettings struct { 23 Ports map[string][]struct { 24 HostPort string 25 } 26 } 27 } 28 29 type RunningContainer struct { 30 Container 31 } 32 33 func (c *RunningContainer) Stop() error { 34 l4g.Info("Removing container: %v", c.Id) 35 return exec.Command("docker", "rm", "-f", c.Id).Run() 36 } 37 38 func NewMySQLContainer() (*RunningContainer, *model.SqlSettings, error) { 39 container, err := runContainer([]string{ 40 "-e", "MYSQL_ROOT_PASSWORD=mostest", 41 "-e", "MYSQL_USER=mmuser", 42 "-e", "MYSQL_PASSWORD=mostest", 43 "-e", "MYSQL_DATABASE=mattermost_test", 44 "--tmpfs", "/var/lib/mysql", 45 "mysql:5.7", 46 }) 47 if err != nil { 48 return nil, nil, err 49 } 50 l4g.Info("Waiting for mysql connectivity") 51 port := container.NetworkSettings.Ports["3306/tcp"][0].HostPort 52 if err := waitForPort(port); err != nil { 53 container.Stop() 54 return nil, nil, err 55 } 56 return container, databaseSettings("mysql", "mmuser:mostest@tcp(127.0.0.1:"+port+")/mattermost_test?charset=utf8mb4,utf8"), nil 57 } 58 59 func NewPostgreSQLContainer() (*RunningContainer, *model.SqlSettings, error) { 60 container, err := runContainer([]string{ 61 "-e", "POSTGRES_USER=mmuser", 62 "-e", "POSTGRES_PASSWORD=mostest", 63 "--tmpfs", "/var/lib/postgresql/data", 64 "postgres:9.4", 65 }) 66 if err != nil { 67 return nil, nil, err 68 } 69 l4g.Info("Waiting for postgres connectivity") 70 port := container.NetworkSettings.Ports["5432/tcp"][0].HostPort 71 if err := waitForPort(port); err != nil { 72 container.Stop() 73 return nil, nil, err 74 } 75 return container, databaseSettings("postgres", "postgres://mmuser:mostest@127.0.0.1:"+port+"?sslmode=disable"), nil 76 } 77 78 func databaseSettings(driver, dataSource string) *model.SqlSettings { 79 settings := &model.SqlSettings{ 80 DriverName: &driver, 81 DataSource: &dataSource, 82 DataSourceReplicas: []string{}, 83 DataSourceSearchReplicas: []string{}, 84 MaxIdleConns: new(int), 85 MaxOpenConns: new(int), 86 Trace: false, 87 AtRestEncryptKey: model.NewRandomString(32), 88 QueryTimeout: new(int), 89 } 90 *settings.MaxIdleConns = 10 91 *settings.MaxOpenConns = 100 92 *settings.QueryTimeout = 10 93 return settings 94 } 95 96 func runContainer(args []string) (*RunningContainer, error) { 97 name := "mattermost-storetest-" + model.NewId() 98 dockerArgs := append([]string{"run", "-d", "-P", "--name", name}, args...) 99 out, err := exec.Command("docker", dockerArgs...).Output() 100 if err != nil { 101 return nil, err 102 } 103 id := strings.TrimSpace(string(out)) 104 out, err = exec.Command("docker", "inspect", id).Output() 105 if err != nil { 106 exec.Command("docker", "rm", "-f", id).Run() 107 return nil, err 108 } 109 var containers []Container 110 if err := json.Unmarshal(out, &containers); err != nil { 111 exec.Command("docker", "rm", "-f", id).Run() 112 return nil, err 113 } 114 l4g.Info("Running container: %v", id) 115 return &RunningContainer{containers[0]}, nil 116 } 117 118 func waitForPort(port string) error { 119 deadline := time.Now().Add(time.Minute * 10) 120 for time.Now().Before(deadline) { 121 conn, err := net.DialTimeout("tcp", "127.0.0.1:"+port, time.Minute) 122 if err != nil { 123 return err 124 } 125 if err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)); err != nil { 126 return err 127 } 128 _, err = conn.Read(make([]byte, 1)) 129 conn.Close() 130 if err == nil { 131 return nil 132 } 133 if e, ok := err.(net.Error); ok && e.Timeout() { 134 return nil 135 } 136 if err != io.EOF { 137 return err 138 } 139 time.Sleep(time.Millisecond * 200) 140 } 141 return fmt.Errorf("timeout waiting for port %v", port) 142 }