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