mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-04 04:28:08 +00:00 
			
		
		
		
	Clean up container on connection failure, switch to ory/dockertest on package postgresql (#5050)
This commit is contained in:
		
				
					committed by
					
						
						Brian Kassouf
					
				
			
			
				
	
			
			
			
						parent
						
							6977aa70f1
						
					
				
				
					commit
					ece7569aca
				
			@@ -145,6 +145,12 @@ func testPostgresDB(t testing.TB) (string, func()) {
 | 
				
			|||||||
		t.Fatalf("postgresdb: could not start container: %s", err)
 | 
							t.Fatalf("postgresdb: could not start container: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cleanup := func() {
 | 
				
			||||||
 | 
							if err := pool.Purge(resource); err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("failed to cleanup local container: %s", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	addr := fmt.Sprintf("postgres://postgres:secret@localhost:%s/database?sslmode=disable", resource.GetPort("5432/tcp"))
 | 
						addr := fmt.Sprintf("postgres://postgres:secret@localhost:%s/database?sslmode=disable", resource.GetPort("5432/tcp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := pool.Retry(func() error {
 | 
						if err := pool.Retry(func() error {
 | 
				
			||||||
@@ -155,12 +161,9 @@ func testPostgresDB(t testing.TB) (string, func()) {
 | 
				
			|||||||
		defer db.Close()
 | 
							defer db.Close()
 | 
				
			||||||
		return db.Ping()
 | 
							return db.Ping()
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
		t.Fatalf("postgresdb: could not connect: %s", err)
 | 
							t.Fatalf("postgresdb: could not connect: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return addr, func() {
 | 
						return addr, cleanup
 | 
				
			||||||
		if err := pool.Purge(resource); err != nil {
 | 
					 | 
				
			||||||
			t.Fatalf("postgresdb: failed to cleanup container: %s", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,6 +77,7 @@ func preparePostgresTestContainer(t *testing.T, s logical.Storage, b logical.Bac
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
		t.Fatalf("Could not connect to PostgreSQL docker container: %s", err)
 | 
							t.Fatalf("Could not connect to PostgreSQL docker container: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,71 +9,57 @@ import (
 | 
				
			|||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/hashicorp/vault/logical"
 | 
						"github.com/hashicorp/vault/logical"
 | 
				
			||||||
	logicaltest "github.com/hashicorp/vault/logical/testing"
 | 
						logicaltest "github.com/hashicorp/vault/logical/testing"
 | 
				
			||||||
	"github.com/lib/pq"
 | 
						"github.com/lib/pq"
 | 
				
			||||||
	"github.com/mitchellh/mapstructure"
 | 
						"github.com/mitchellh/mapstructure"
 | 
				
			||||||
	dockertest "gopkg.in/ory-am/dockertest.v2"
 | 
						"github.com/ory/dockertest"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					func prepareTestContainer(t *testing.T) (cleanup func(), retURL string) {
 | 
				
			||||||
	testImagePull sync.Once
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func prepareTestContainer(t *testing.T, s logical.Storage, b logical.Backend) (cid dockertest.ContainerID, retURL string) {
 | 
					 | 
				
			||||||
	if os.Getenv("PG_URL") != "" {
 | 
						if os.Getenv("PG_URL") != "" {
 | 
				
			||||||
		return "", os.Getenv("PG_URL")
 | 
							return func() {}, os.Getenv("PG_URL")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Without this the checks for whether the container has started seem to
 | 
						pool, err := dockertest.NewPool("")
 | 
				
			||||||
	// never actually pass. There's really no reason to expose the test
 | 
						if err != nil {
 | 
				
			||||||
	// containers, so don't.
 | 
							t.Fatalf("Failed to connect to docker: %s", err)
 | 
				
			||||||
	dockertest.BindDockerToLocalhost = "yep"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	testImagePull.Do(func() {
 | 
					 | 
				
			||||||
		dockertest.Pull("postgres")
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cid, connErr := dockertest.ConnectToPostgreSQL(60, 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
 | 
						resource, err := pool.Run("postgres", "latest", []string{"POSTGRES_PASSWORD=secret", "POSTGRES_DB=database"})
 | 
				
			||||||
		return true
 | 
						if err != nil {
 | 
				
			||||||
	})
 | 
							t.Fatalf("Could not start local PostgreSQL docker container: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if connErr != nil {
 | 
						cleanup = func() {
 | 
				
			||||||
		t.Fatalf("could not connect to database: %v", connErr)
 | 
							err := pool.Purge(resource)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("Failed to cleanup local container: %s", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						retURL = fmt.Sprintf("postgres://postgres:secret@localhost:%s/database?sslmode=disable", resource.GetPort("5432/tcp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// exponential backoff-retry
 | 
				
			||||||
 | 
						if err = pool.Retry(func() error {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							var db *sql.DB
 | 
				
			||||||
 | 
							db, err = sql.Open("postgres", retURL)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer db.Close()
 | 
				
			||||||
 | 
							return db.Ping()
 | 
				
			||||||
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
 | 
							t.Fatalf("Could not connect to PostgreSQL docker container: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func cleanupTestContainer(t *testing.T, cid dockertest.ContainerID) {
 | 
					 | 
				
			||||||
	err := cid.KillRemove()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestBackend_config_connection(t *testing.T) {
 | 
					func TestBackend_config_connection(t *testing.T) {
 | 
				
			||||||
	var resp *logical.Response
 | 
						var resp *logical.Response
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
@@ -123,14 +109,12 @@ func TestBackend_basic(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cid, connURL := prepareTestContainer(t, config.StorageView, b)
 | 
						cleanup, connURL := prepareTestContainer(t)
 | 
				
			||||||
	if cid != "" {
 | 
						defer cleanup()
 | 
				
			||||||
		defer cleanupTestContainer(t, cid)
 | 
					
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	connData := map[string]interface{}{
 | 
						connData := map[string]interface{}{
 | 
				
			||||||
		"connection_url": connURL,
 | 
							"connection_url": connURL,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	logicaltest.Test(t, logicaltest.TestCase{
 | 
						logicaltest.Test(t, logicaltest.TestCase{
 | 
				
			||||||
		Backend: b,
 | 
							Backend: b,
 | 
				
			||||||
		Steps: []logicaltest.TestStep{
 | 
							Steps: []logicaltest.TestStep{
 | 
				
			||||||
@@ -149,14 +133,12 @@ func TestBackend_roleCrud(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cid, connURL := prepareTestContainer(t, config.StorageView, b)
 | 
						cleanup, connURL := prepareTestContainer(t)
 | 
				
			||||||
	if cid != "" {
 | 
						defer cleanup()
 | 
				
			||||||
		defer cleanupTestContainer(t, cid)
 | 
					
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	connData := map[string]interface{}{
 | 
						connData := map[string]interface{}{
 | 
				
			||||||
		"connection_url": connURL,
 | 
							"connection_url": connURL,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	logicaltest.Test(t, logicaltest.TestCase{
 | 
						logicaltest.Test(t, logicaltest.TestCase{
 | 
				
			||||||
		Backend: b,
 | 
							Backend: b,
 | 
				
			||||||
		Steps: []logicaltest.TestStep{
 | 
							Steps: []logicaltest.TestStep{
 | 
				
			||||||
@@ -177,14 +159,12 @@ func TestBackend_BlockStatements(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cid, connURL := prepareTestContainer(t, config.StorageView, b)
 | 
						cleanup, connURL := prepareTestContainer(t)
 | 
				
			||||||
	if cid != "" {
 | 
						defer cleanup()
 | 
				
			||||||
		defer cleanupTestContainer(t, cid)
 | 
					
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	connData := map[string]interface{}{
 | 
						connData := map[string]interface{}{
 | 
				
			||||||
		"connection_url": connURL,
 | 
							"connection_url": connURL,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	jsonBlockStatement, err := json.Marshal(testBlockStatementRoleSlice)
 | 
						jsonBlockStatement, err := json.Marshal(testBlockStatementRoleSlice)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
@@ -209,14 +189,12 @@ func TestBackend_roleReadOnly(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cid, connURL := prepareTestContainer(t, config.StorageView, b)
 | 
						cleanup, connURL := prepareTestContainer(t)
 | 
				
			||||||
	if cid != "" {
 | 
						defer cleanup()
 | 
				
			||||||
		defer cleanupTestContainer(t, cid)
 | 
					
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	connData := map[string]interface{}{
 | 
						connData := map[string]interface{}{
 | 
				
			||||||
		"connection_url": connURL,
 | 
							"connection_url": connURL,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	logicaltest.Test(t, logicaltest.TestCase{
 | 
						logicaltest.Test(t, logicaltest.TestCase{
 | 
				
			||||||
		Backend: b,
 | 
							Backend: b,
 | 
				
			||||||
		Steps: []logicaltest.TestStep{
 | 
							Steps: []logicaltest.TestStep{
 | 
				
			||||||
@@ -242,14 +220,12 @@ func TestBackend_roleReadOnly_revocationSQL(t *testing.T) {
 | 
				
			|||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cid, connURL := prepareTestContainer(t, config.StorageView, b)
 | 
						cleanup, connURL := prepareTestContainer(t)
 | 
				
			||||||
	if cid != "" {
 | 
						defer cleanup()
 | 
				
			||||||
		defer cleanupTestContainer(t, cid)
 | 
					
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	connData := map[string]interface{}{
 | 
						connData := map[string]interface{}{
 | 
				
			||||||
		"connection_url": connURL,
 | 
							"connection_url": connURL,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	logicaltest.Test(t, logicaltest.TestCase{
 | 
						logicaltest.Test(t, logicaltest.TestCase{
 | 
				
			||||||
		Backend: b,
 | 
							Backend: b,
 | 
				
			||||||
		Steps: []logicaltest.TestStep{
 | 
							Steps: []logicaltest.TestStep{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -311,6 +311,7 @@ func prepareDynamoDBTestContainer(t *testing.T) (cleanup func(), retAddress stri
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
		t.Fatalf("Could not connect to docker: %s", err)
 | 
							t.Fatalf("Could not connect to docker: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cleanup, retAddress, credentials.NewStaticCredentials("fake", "fake", "")
 | 
						return cleanup, retAddress, credentials.NewStaticCredentials("fake", "fake", "")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,6 +60,7 @@ func prepareMongoDBTestContainer(t *testing.T) (cleanup func(), retURL string) {
 | 
				
			|||||||
		session.SetSocketTimeout(1 * time.Minute)
 | 
							session.SetSocketTimeout(1 * time.Minute)
 | 
				
			||||||
		return session.Ping()
 | 
							return session.Ping()
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
		t.Fatalf("Could not connect to mongo docker container: %s", err)
 | 
							t.Fatalf("Could not connect to mongo docker container: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,7 @@ func preparePostgresTestContainer(t *testing.T) (cleanup func(), retURL string)
 | 
				
			|||||||
		defer db.Close()
 | 
							defer db.Close()
 | 
				
			||||||
		return db.Ping()
 | 
							return db.Ping()
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
 | 
							cleanup()
 | 
				
			||||||
		t.Fatalf("Could not connect to PostgreSQL docker container: %s", err)
 | 
							t.Fatalf("Could not connect to PostgreSQL docker container: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user