2021-02-17 07:20:19 +03:00
|
|
|
package testutil
|
|
|
|
|
|
|
|
import (
|
2021-03-08 14:59:35 +03:00
|
|
|
"context"
|
2021-02-17 07:20:19 +03:00
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2021-03-08 14:59:35 +03:00
|
|
|
"strings"
|
2021-02-17 07:20:19 +03:00
|
|
|
"testing"
|
2021-03-08 14:59:35 +03:00
|
|
|
"time"
|
2021-02-17 07:20:19 +03:00
|
|
|
|
2021-03-08 14:59:35 +03:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
|
|
|
"github.com/gofrs/uuid"
|
|
|
|
|
|
|
|
"github.com/Pallinder/go-randomdata"
|
|
|
|
|
|
|
|
_ "github.com/denisenkom/go-mssqldb"
|
2021-02-17 07:20:19 +03:00
|
|
|
"github.com/hasura/graphql-engine/cli/internal/httpc"
|
|
|
|
_ "github.com/lib/pq"
|
|
|
|
"github.com/ory/dockertest/v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
func StartHasura(t *testing.T, version string) (port string, teardown func()) {
|
2021-03-08 14:59:35 +03:00
|
|
|
checkIfSkippable(t)
|
2021-02-17 07:20:19 +03:00
|
|
|
if len(version) == 0 {
|
|
|
|
t.Fatal("no hasura version provided, probably use testutil.HasuraVersion")
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
pool, err := dockertest.NewPool("")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not connect to docker: %s", err)
|
|
|
|
}
|
2021-03-08 14:59:35 +03:00
|
|
|
uniqueName := getUniqueName(t)
|
|
|
|
pgopts := &dockertest.RunOptions{
|
|
|
|
Name: fmt.Sprintf("%s-%s", uniqueName, "pg"),
|
|
|
|
Repository: "postgres",
|
|
|
|
Tag: "11",
|
|
|
|
Env: []string{
|
|
|
|
"POSTGRES_PASSWORD=postgrespassword",
|
|
|
|
"POSTGRES_DB=postgres",
|
|
|
|
},
|
|
|
|
ExposedPorts: []string{"5432/tcp"},
|
|
|
|
}
|
|
|
|
pg, err := pool.RunWithOptions(pgopts)
|
2021-02-17 07:20:19 +03:00
|
|
|
if err != nil {
|
2021-03-08 14:59:35 +03:00
|
|
|
t.Fatalf("Could not start resource: %s", err)
|
|
|
|
}
|
|
|
|
var db *sql.DB
|
|
|
|
if err = pool.Retry(func() error {
|
|
|
|
var err error
|
|
|
|
db, err = sql.Open("postgres", fmt.Sprintf("postgres://postgres:postgrespassword@%s:%s/%s?sslmode=disable", DockerSwitchIP, pg.GetPort("5432/tcp"), "postgres"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return db.Ping()
|
|
|
|
}); err != nil {
|
2021-02-17 07:20:19 +03:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2021-03-08 14:59:35 +03:00
|
|
|
|
|
|
|
hasuraopts := &dockertest.RunOptions{
|
|
|
|
Name: fmt.Sprintf("%s-%s", uniqueName, "hasura"),
|
|
|
|
Repository: "hasura/graphql-engine",
|
|
|
|
Tag: version,
|
|
|
|
Env: []string{
|
|
|
|
fmt.Sprintf("HASURA_GRAPHQL_DATABASE_URL=postgres://postgres:postgrespassword@%s:%s/postgres", DockerSwitchIP, pg.GetPort("5432/tcp")),
|
|
|
|
`HASURA_GRAPHQL_ENABLE_CONSOLE=true`,
|
|
|
|
"HASURA_GRAPHQL_DEV_MODE=true",
|
|
|
|
"HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup, http-log, webhook-log, websocket-log, query-log",
|
|
|
|
},
|
|
|
|
ExposedPorts: []string{"8080/tcp"},
|
|
|
|
}
|
|
|
|
hasura, err := pool.RunWithOptions(hasuraopts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not start resource: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = pool.Retry(func() error {
|
|
|
|
var err error
|
|
|
|
resp, err := http.Get(fmt.Sprintf("http://localhost:%s/healthz", hasura.GetPort("8080/tcp")))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
return errors.New("not ready")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatalf("Could not connect to docker: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
teardown = func() {
|
|
|
|
if err = pool.Purge(hasura); err != nil {
|
|
|
|
t.Fatalf("Could not purge resource: %s", err)
|
|
|
|
}
|
|
|
|
if err = pool.Purge(pg); err != nil {
|
|
|
|
t.Fatalf("Could not purge resource: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hasura.GetPort("8080/tcp"), teardown
|
|
|
|
}
|
|
|
|
|
|
|
|
func StartHasuraWithMetadataDatabase(t *testing.T, version string) (port string, teardown func()) {
|
|
|
|
checkIfSkippable(t)
|
|
|
|
if len(version) == 0 {
|
|
|
|
t.Fatal("no hasura version provided, probably use testutil.HasuraVersion")
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
pool, err := dockertest.NewPool("")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not connect to docker: %s", err)
|
|
|
|
}
|
|
|
|
uniqueName := getUniqueName(t)
|
2021-02-17 07:20:19 +03:00
|
|
|
pgopts := &dockertest.RunOptions{
|
2021-03-08 14:59:35 +03:00
|
|
|
Name: fmt.Sprintf("%s-%s", uniqueName, "pg"),
|
2021-02-17 07:20:19 +03:00
|
|
|
Repository: "postgres",
|
|
|
|
Tag: "11",
|
|
|
|
Env: []string{
|
|
|
|
"POSTGRES_PASSWORD=postgrespassword",
|
|
|
|
"POSTGRES_DB=postgres",
|
|
|
|
},
|
|
|
|
ExposedPorts: []string{"5432/tcp"},
|
|
|
|
}
|
|
|
|
pg, err := pool.RunWithOptions(pgopts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not start resource: %s", err)
|
|
|
|
}
|
|
|
|
var db *sql.DB
|
|
|
|
if err = pool.Retry(func() error {
|
|
|
|
var err error
|
|
|
|
db, err = sql.Open("postgres", fmt.Sprintf("postgres://postgres:postgrespassword@%s:%s/%s?sslmode=disable", DockerSwitchIP, pg.GetPort("5432/tcp"), "postgres"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return db.Ping()
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
hasuraopts := &dockertest.RunOptions{
|
2021-03-08 14:59:35 +03:00
|
|
|
Name: fmt.Sprintf("%s-%s", uniqueName, "hasura"),
|
2021-02-17 07:20:19 +03:00
|
|
|
Repository: "hasura/graphql-engine",
|
|
|
|
Tag: version,
|
|
|
|
Env: []string{
|
2021-03-08 14:59:35 +03:00
|
|
|
fmt.Sprintf("HASURA_GRAPHQL_METADATA_DATABASE_URL=postgres://postgres:postgrespassword@%s:%s/postgres", DockerSwitchIP, pg.GetPort("5432/tcp")),
|
2021-02-17 07:20:19 +03:00
|
|
|
`HASURA_GRAPHQL_ENABLE_CONSOLE=true`,
|
|
|
|
"HASURA_GRAPHQL_DEV_MODE=true",
|
|
|
|
"HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup, http-log, webhook-log, websocket-log, query-log",
|
|
|
|
},
|
|
|
|
ExposedPorts: []string{"8080/tcp"},
|
|
|
|
}
|
|
|
|
hasura, err := pool.RunWithOptions(hasuraopts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not start resource: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = pool.Retry(func() error {
|
|
|
|
var err error
|
|
|
|
resp, err := http.Get(fmt.Sprintf("http://localhost:%s/healthz", hasura.GetPort("8080/tcp")))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
return errors.New("not ready")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatalf("Could not connect to docker: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
teardown = func() {
|
|
|
|
if err = pool.Purge(hasura); err != nil {
|
|
|
|
t.Fatalf("Could not purge resource: %s", err)
|
|
|
|
}
|
|
|
|
if err = pool.Purge(pg); err != nil {
|
|
|
|
t.Fatalf("Could not purge resource: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hasura.GetPort("8080/tcp"), teardown
|
|
|
|
}
|
|
|
|
|
2021-03-08 14:59:35 +03:00
|
|
|
// starts a hasura instance with a metadata database and a msssql source
|
|
|
|
// returns the mssql port, source name and teardown function
|
|
|
|
func StartHasuraWithMSSQLSource(t *testing.T, version string) (string, string, func()) {
|
|
|
|
hasuraPort, hasuraTeardown := StartHasuraWithMetadataDatabase(t, version)
|
|
|
|
sourcename := randomdata.SillyName()
|
|
|
|
mssqlPort, mssqlTeardown := startMSSQLContainer(t)
|
|
|
|
|
|
|
|
teardown := func() {
|
|
|
|
hasuraTeardown()
|
|
|
|
mssqlTeardown()
|
|
|
|
}
|
|
|
|
connectionString := fmt.Sprintf("DRIVER={ODBC Driver 17 for SQL Server};SERVER=%s,%s;DATABASE=master;Uid=SA;Pwd=%s;Encrypt=no", DockerSwitchIP, mssqlPort, MSSQLPassword)
|
|
|
|
addSourceToHasura(t, fmt.Sprintf("%s:%s", BaseURL, hasuraPort), connectionString, sourcename)
|
|
|
|
return hasuraPort, sourcename, teardown
|
|
|
|
}
|
|
|
|
|
|
|
|
// startsMSSQLContainer and creates a database and returns the port number
|
|
|
|
func startMSSQLContainer(t *testing.T) (string, func()) {
|
|
|
|
pool, err := dockertest.NewPool("")
|
|
|
|
pool.MaxWait = time.Minute
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not connect to docker: %s", err)
|
|
|
|
}
|
|
|
|
opts := &dockertest.RunOptions{
|
|
|
|
Name: fmt.Sprintf("%s-%s", randomdata.SillyName(), "mssql"),
|
|
|
|
Repository: "mcr.microsoft.com/mssql/server",
|
|
|
|
Tag: "2019-latest",
|
|
|
|
Env: []string{
|
|
|
|
"ACCEPT_EULA=Y",
|
|
|
|
fmt.Sprintf("SA_PASSWORD=%s", MSSQLPassword),
|
|
|
|
},
|
|
|
|
ExposedPorts: []string{"1433/tcp"},
|
|
|
|
}
|
|
|
|
mssql, err := pool.RunWithOptions(opts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Could not start resource: %s", err)
|
|
|
|
}
|
|
|
|
if err = pool.Retry(func() error {
|
|
|
|
connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;",
|
|
|
|
DockerSwitchIP, "SA", MSSQLPassword, mssql.GetPort("1433/tcp"), "master")
|
|
|
|
db, err := sql.Open("sqlserver", connString)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
err = db.PingContext(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
teardown := func() {
|
|
|
|
if err = pool.Purge(mssql); err != nil {
|
|
|
|
t.Fatalf("Could not purge resource: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return mssql.GetPort("1433/tcp"), teardown
|
|
|
|
}
|
|
|
|
|
|
|
|
func addSourceToHasura(t *testing.T, hasuraEndpoint, connectionString, sourceName string) {
|
|
|
|
url := fmt.Sprintf("%s/v1/metadata", hasuraEndpoint)
|
|
|
|
body := fmt.Sprintf(`
|
|
|
|
{
|
|
|
|
"type": "mssql_add_source",
|
|
|
|
"args": {
|
|
|
|
"name": "%s",
|
|
|
|
"configuration": {
|
|
|
|
"connection_info": {
|
|
|
|
"connection_string": "%s"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`, sourceName, connectionString)
|
|
|
|
fmt.Println(connectionString)
|
|
|
|
fmt.Println(hasuraEndpoint)
|
|
|
|
r, err := http.Post(url, "application/json", strings.NewReader(body))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if r.StatusCode != http.StatusOK {
|
|
|
|
body, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
t.Fatalf("cannot add mssql source to hasura: %s", string(body))
|
|
|
|
}
|
|
|
|
}
|
2021-02-17 07:20:19 +03:00
|
|
|
func NewHttpcClient(t *testing.T, port string, headers map[string]string) *httpc.Client {
|
|
|
|
c, err := httpc.New(nil, fmt.Sprintf("%s:%s/", BaseURL, port), headers)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
2021-03-08 14:59:35 +03:00
|
|
|
|
|
|
|
func getUniqueName(t *testing.T) string {
|
|
|
|
u, err := uuid.NewV4()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
return u.String() + "-" + randomdata.SillyName()
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkIfSkippable(t *testing.T) {
|
2021-04-01 15:58:24 +03:00
|
|
|
if SkipDockerTests {
|
2021-03-08 14:59:35 +03:00
|
|
|
t.Skip()
|
|
|
|
}
|
|
|
|
}
|