github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+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 MaxOpenConns: new(int), 85 Trace: false, 86 AtRestEncryptKey: model.NewRandomString(32), 87 QueryTimeout: new(int), 88 } 89 *settings.MaxIdleConns = 10 90 *settings.MaxOpenConns = 100 91 *settings.QueryTimeout = 10 92 return settings 93 } 94 95 func runContainer(args []string) (*RunningContainer, error) { 96 name := "mattermost-storetest-" + model.NewId() 97 dockerArgs := append([]string{"run", "-d", "-P", "--name", name}, args...) 98 out, err := exec.Command("docker", dockerArgs...).Output() 99 if err != nil { 100 return nil, err 101 } 102 id := strings.TrimSpace(string(out)) 103 out, err = exec.Command("docker", "inspect", id).Output() 104 if err != nil { 105 exec.Command("docker", "rm", "-f", id).Run() 106 return nil, err 107 } 108 var containers []Container 109 if err := json.Unmarshal(out, &containers); err != nil { 110 exec.Command("docker", "rm", "-f", id).Run() 111 return nil, err 112 } 113 mlog.Info(fmt.Sprintf("Running container: %v", id)) 114 return &RunningContainer{containers[0]}, nil 115 } 116 117 func waitForPort(port string) error { 118 deadline := time.Now().Add(time.Minute * 10) 119 for time.Now().Before(deadline) { 120 conn, err := net.DialTimeout("tcp", "127.0.0.1:"+port, time.Minute) 121 if err != nil { 122 return err 123 } 124 if err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)); err != nil { 125 return err 126 } 127 _, err = conn.Read(make([]byte, 1)) 128 conn.Close() 129 if err == nil { 130 return nil 131 } 132 if e, ok := err.(net.Error); ok && e.Timeout() { 133 return nil 134 } 135 if err != io.EOF { 136 return err 137 } 138 time.Sleep(time.Millisecond * 200) 139 } 140 return fmt.Errorf("timeout waiting for port %v", port) 141 }