Files
mostlymatter/store/storetest/docker.go
Chris 917e4789c2 Use tmpfs containers for api/api4 tests, move and speed up CLI tests (#7606)
* use tmpfs containers for api/api4, move and speed up cli tests

* minor optimizations

* add missing files, fix pre-existing race condition

* add . to TestMain check

* add requested log message
2017-10-12 12:24:54 -07:00

143 строки
3.7 KiB
Go

// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package storetest
import (
"encoding/json"
"fmt"
"io"
"net"
"os/exec"
"strings"
"time"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/mattermost-server/model"
)
type Container struct {
Id string
NetworkSettings struct {
Ports map[string][]struct {
HostPort string
}
}
}
type RunningContainer struct {
Container
}
func (c *RunningContainer) Stop() error {
l4g.Info("Removing container: %v", c.Id)
return exec.Command("docker", "rm", "-f", c.Id).Run()
}
func NewMySQLContainer() (*RunningContainer, *model.SqlSettings, error) {
container, err := runContainer([]string{
"-e", "MYSQL_ROOT_PASSWORD=mostest",
"-e", "MYSQL_USER=mmuser",
"-e", "MYSQL_PASSWORD=mostest",
"-e", "MYSQL_DATABASE=mattermost_test",
"--tmpfs", "/var/lib/mysql",
"mysql:5.7",
})
if err != nil {
return nil, nil, err
}
l4g.Info("Waiting for mysql connectivity")
port := container.NetworkSettings.Ports["3306/tcp"][0].HostPort
if err := waitForPort(port); err != nil {
container.Stop()
return nil, nil, err
}
return container, databaseSettings("mysql", "mmuser:mostest@tcp(127.0.0.1:"+port+")/mattermost_test?charset=utf8mb4,utf8"), nil
}
func NewPostgreSQLContainer() (*RunningContainer, *model.SqlSettings, error) {
container, err := runContainer([]string{
"-e", "POSTGRES_USER=mmuser",
"-e", "POSTGRES_PASSWORD=mostest",
"--tmpfs", "/var/lib/postgresql/data",
"postgres:9.4",
})
if err != nil {
return nil, nil, err
}
l4g.Info("Waiting for postgres connectivity")
port := container.NetworkSettings.Ports["5432/tcp"][0].HostPort
if err := waitForPort(port); err != nil {
container.Stop()
return nil, nil, err
}
return container, databaseSettings("postgres", "postgres://mmuser:mostest@127.0.0.1:"+port+"?sslmode=disable"), nil
}
func databaseSettings(driver, dataSource string) *model.SqlSettings {
settings := &model.SqlSettings{
DriverName: &driver,
DataSource: &dataSource,
DataSourceReplicas: []string{},
DataSourceSearchReplicas: []string{},
MaxIdleConns: new(int),
MaxOpenConns: new(int),
Trace: false,
AtRestEncryptKey: model.NewRandomString(32),
QueryTimeout: new(int),
}
*settings.MaxIdleConns = 10
*settings.MaxOpenConns = 100
*settings.QueryTimeout = 10
return settings
}
func runContainer(args []string) (*RunningContainer, error) {
name := "mattermost-storetest-" + model.NewId()
dockerArgs := append([]string{"run", "-d", "-P", "--name", name}, args...)
out, err := exec.Command("docker", dockerArgs...).Output()
if err != nil {
return nil, err
}
id := strings.TrimSpace(string(out))
out, err = exec.Command("docker", "inspect", id).Output()
if err != nil {
exec.Command("docker", "rm", "-f", id).Run()
return nil, err
}
var containers []Container
if err := json.Unmarshal(out, &containers); err != nil {
exec.Command("docker", "rm", "-f", id).Run()
return nil, err
}
l4g.Info("Running container: %v", id)
return &RunningContainer{containers[0]}, nil
}
func waitForPort(port string) error {
deadline := time.Now().Add(time.Minute * 10)
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", "127.0.0.1:"+port, time.Minute)
if err != nil {
return err
}
if err = conn.SetReadDeadline(time.Now().Add(time.Millisecond * 500)); err != nil {
return err
}
_, err = conn.Read(make([]byte, 1))
conn.Close()
if err == nil {
return nil
}
if e, ok := err.(net.Error); ok && e.Timeout() {
return nil
}
if err != io.EOF {
return err
}
time.Sleep(time.Millisecond * 200)
}
return fmt.Errorf("timeout waiting for port %v", port)
}