From 964645d45e5d12765daba8004827dca517bceeea Mon Sep 17 00:00:00 2001 From: Calvin Leung Huang Date: Mon, 23 Apr 2018 13:03:02 -0400 Subject: [PATCH] Explicitly use 5.7 and below to test mysql backends (#4429) --- builtin/logical/mysql/backend_test.go | 116 +++++++++++--------------- plugins/database/mysql/mysql_test.go | 61 +++----------- 2 files changed, 62 insertions(+), 115 deletions(-) diff --git a/builtin/logical/mysql/backend_test.go b/builtin/logical/mysql/backend_test.go index 8c127267c4..23f0462709 100644 --- a/builtin/logical/mysql/backend_test.go +++ b/builtin/logical/mysql/backend_test.go @@ -2,72 +2,58 @@ package mysql import ( "context" + "database/sql" "fmt" "log" "os" "reflect" - "sync" "testing" - "time" "github.com/hashicorp/vault/logical" logicaltest "github.com/hashicorp/vault/logical/testing" "github.com/mitchellh/mapstructure" - dockertest "gopkg.in/ory-am/dockertest.v2" + dockertest "gopkg.in/ory-am/dockertest.v3" ) -var ( - testImagePull sync.Once -) - -func prepareTestContainer(t *testing.T, s logical.Storage, b logical.Backend) (cid dockertest.ContainerID, retURL string) { - if os.Getenv("MYSQL_DSN") != "" { - return "", os.Getenv("MYSQL_DSN") +func prepareTestContainer(t *testing.T) (func(), string) { + if os.Getenv("MYSQL_URL") != "" { + return func() {}, os.Getenv("MYSQL_URL") } - // Without this the checks for whether the container has started seem to - // never actually pass. There's really no reason to expose the test - // containers, so don't. - dockertest.BindDockerToLocalhost = "yep" - - testImagePull.Do(func() { - dockertest.Pull("mysql") - }) - - cid, connErr := dockertest.ConnectToMySQL(120, 500*time.Millisecond, func(connURL string) bool { - // This will cause a validation to run - resp, err := b.HandleRequest(context.Background(), &logical.Request{ - Storage: s, - Operation: logical.UpdateOperation, - Path: "config/connection", - Data: map[string]interface{}{ - "connection_url": connURL, - }, - }) - if err != nil || (resp != nil && resp.IsError()) { - // It's likely not up and running yet, so return false and try again - return false - } - if resp == nil { - t.Fatal("expected warning") - } - - retURL = connURL - return true - }) - - if connErr != nil { - t.Fatalf("could not connect to database: %v", connErr) - } - - return -} - -func cleanupTestContainer(t *testing.T, cid dockertest.ContainerID) { - err := cid.KillRemove() + pool, err := dockertest.NewPool("") if err != nil { - t.Fatal(err) + t.Fatalf("Failed to connect to docker: %s", err) } + + resource, err := pool.Run("mysql", "5.7", []string{"MYSQL_ROOT_PASSWORD=secret"}) + if err != nil { + t.Fatalf("Could not start local MySQL docker container: %s", err) + } + + cleanup := func() { + err := pool.Purge(resource) + if err != nil { + t.Fatalf("Failed to cleanup local container: %s", err) + } + } + + retURL := fmt.Sprintf("root:secret@(localhost:%s)/mysql?parseTime=true", resource.GetPort("3306/tcp")) + + // exponential backoff-retry + if err = pool.Retry(func() error { + var err error + var db *sql.DB + db, err = sql.Open("mysql", retURL) + if err != nil { + return err + } + return db.Ping() + }); err != nil { + cleanup() + t.Fatalf("Could not connect to MySQL docker container: %s", err) + } + + return cleanup, retURL } func TestBackend_config_connection(t *testing.T) { @@ -119,10 +105,9 @@ func TestBackend_basic(t *testing.T) { t.Fatal(err) } - cid, connURL := prepareTestContainer(t, config.StorageView, b) - if cid != "" { - defer cleanupTestContainer(t, cid) - } + cleanup, connURL := prepareTestContainer(t) + defer cleanup() + connData := map[string]interface{}{ "connection_url": connURL, } @@ -146,10 +131,9 @@ func TestBackend_basicHostRevoke(t *testing.T) { t.Fatal(err) } - cid, connURL := prepareTestContainer(t, config.StorageView, b) - if cid != "" { - defer cleanupTestContainer(t, cid) - } + cleanup, connURL := prepareTestContainer(t) + defer cleanup() + connData := map[string]interface{}{ "connection_url": connURL, } @@ -173,10 +157,9 @@ func TestBackend_roleCrud(t *testing.T) { t.Fatal(err) } - cid, connURL := prepareTestContainer(t, config.StorageView, b) - if cid != "" { - defer cleanupTestContainer(t, cid) - } + cleanup, connURL := prepareTestContainer(t) + defer cleanup() + connData := map[string]interface{}{ "connection_url": connURL, } @@ -205,10 +188,9 @@ func TestBackend_leaseWriteRead(t *testing.T) { t.Fatal(err) } - cid, connURL := prepareTestContainer(t, config.StorageView, b) - if cid != "" { - defer cleanupTestContainer(t, cid) - } + cleanup, connURL := prepareTestContainer(t) + defer cleanup() + connData := map[string]interface{}{ "connection_url": connURL, } diff --git a/plugins/database/mysql/mysql_test.go b/plugins/database/mysql/mysql_test.go index ff746bb680..6a1ee9330c 100644 --- a/plugins/database/mysql/mysql_test.go +++ b/plugins/database/mysql/mysql_test.go @@ -15,7 +15,7 @@ import ( dockertest "gopkg.in/ory-am/dockertest.v3" ) -func prepareMySQLTestContainer(t *testing.T) (cleanup func(), retURL string) { +func prepareMySQLTestContainer(t *testing.T, legacy bool) (cleanup func(), retURL string) { if os.Getenv("MYSQL_URL") != "" { return func() {}, os.Getenv("MYSQL_URL") } @@ -25,48 +25,12 @@ func prepareMySQLTestContainer(t *testing.T) (cleanup func(), retURL string) { t.Fatalf("Failed to connect to docker: %s", err) } - resource, err := pool.Run("mysql", "latest", []string{"MYSQL_ROOT_PASSWORD=secret"}) - if err != nil { - t.Fatalf("Could not start local MySQL docker container: %s", err) - } - - cleanup = func() { - err := pool.Purge(resource) - if err != nil { - t.Fatalf("Failed to cleanup local container: %s", err) - } - } - - retURL = fmt.Sprintf("root:secret@(localhost:%s)/mysql?parseTime=true", resource.GetPort("3306/tcp")) - - // exponential backoff-retry - if err = pool.Retry(func() error { - var err error - var db *sql.DB - db, err = sql.Open("mysql", retURL) - if err != nil { - return err - } - return db.Ping() - }); err != nil { - t.Fatalf("Could not connect to MySQL docker container: %s", err) - } - - return -} - -func prepareMySQLLegacyTestContainer(t *testing.T) (cleanup func(), retURL string) { - if os.Getenv("MYSQL_URL") != "" { - return func() {}, os.Getenv("MYSQL_URL") - } - - pool, err := dockertest.NewPool("") - if err != nil { - t.Fatalf("Failed to connect to docker: %s", err) - } - - // Mysql 5.6 is the last MySQL version to limit usernames to 16 characters. - resource, err := pool.Run("mysql", "5.6", []string{"MYSQL_ROOT_PASSWORD=secret"}) + imageVersion := "5.7" + if legacy { + imageVersion = "5.6" + } + + resource, err := pool.Run("mysql", imageVersion, []string{"MYSQL_ROOT_PASSWORD=secret"}) if err != nil { t.Fatalf("Could not start local MySQL docker container: %s", err) } @@ -90,6 +54,7 @@ func prepareMySQLLegacyTestContainer(t *testing.T) (cleanup func(), retURL strin } return db.Ping() }); err != nil { + cleanup() t.Fatalf("Could not connect to MySQL docker container: %s", err) } @@ -97,7 +62,7 @@ func prepareMySQLLegacyTestContainer(t *testing.T) (cleanup func(), retURL strin } func TestMySQL_Initialize(t *testing.T) { - cleanup, connURL := prepareMySQLTestContainer(t) + cleanup, connURL := prepareMySQLTestContainer(t, false) defer cleanup() connectionDetails := map[string]interface{}{ @@ -132,7 +97,7 @@ func TestMySQL_Initialize(t *testing.T) { } func TestMySQL_CreateUser(t *testing.T) { - cleanup, connURL := prepareMySQLTestContainer(t) + cleanup, connURL := prepareMySQLTestContainer(t, false) defer cleanup() connectionDetails := map[string]interface{}{ @@ -194,7 +159,7 @@ func TestMySQL_CreateUser(t *testing.T) { } func TestMySQL_CreateUser_Legacy(t *testing.T) { - cleanup, connURL := prepareMySQLLegacyTestContainer(t) + cleanup, connURL := prepareMySQLTestContainer(t, true) defer cleanup() connectionDetails := map[string]interface{}{ @@ -243,7 +208,7 @@ func TestMySQL_CreateUser_Legacy(t *testing.T) { } func TestMySQL_RotateRootCredentials(t *testing.T) { - cleanup, connURL := prepareMySQLTestContainer(t) + cleanup, connURL := prepareMySQLTestContainer(t, false) defer cleanup() connURL = strings.Replace(connURL, "root:secret", `{{username}}:{{password}}`, -1) @@ -279,7 +244,7 @@ func TestMySQL_RotateRootCredentials(t *testing.T) { } func TestMySQL_RevokeUser(t *testing.T) { - cleanup, connURL := prepareMySQLTestContainer(t) + cleanup, connURL := prepareMySQLTestContainer(t, false) defer cleanup() connectionDetails := map[string]interface{}{