332 lines
10 KiB
Go
332 lines
10 KiB
Go
package database_test
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"git.cryptic.systems/volker.raschek/flucky/pkg/testutils/database"
|
|
"git.cryptic.systems/volker.raschek/flucky/pkg/testutils/dockerutils"
|
|
uuid "github.com/satori/go.uuid"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
func requireCountNetworks(ctx context.Context, dockerClient *dockerutils.Client, dbOptions *database.PostgresOptions, equal int, t *testing.T) {
|
|
require := require.New(t)
|
|
containers, err := dockerClient.ContainerListByLabels(ctx, true, dbOptions.ContainerLabels)
|
|
require.NoError(err)
|
|
require.Equal(equal, len(containers[0].NetworkSettings.Networks))
|
|
}
|
|
|
|
func requireContainerHasNetworksAndAliasses(ctx context.Context, dockerClient *dockerutils.Client, dbOptions *database.PostgresOptions, t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
containers, err := dockerClient.ContainerListByNames(ctx, true, dbOptions.ContainerName)
|
|
require.NoError(err)
|
|
require.Contains(containers[0].Names, fmt.Sprintf("/%v", dbOptions.ContainerName))
|
|
|
|
for networkName, _ := range dbOptions.ContainerNetworks {
|
|
networks, err := dockerClient.NetworkListByNames(ctx, networkName)
|
|
require.NoError(err)
|
|
require.Equal(networkName, networks[0].Name)
|
|
require.Equal(dbOptions.ContainerName, networks[0].Containers[containers[0].ID].Name)
|
|
}
|
|
}
|
|
|
|
func requireTestCleanup(ctx context.Context, dockerClient *dockerutils.Client, cleanupLabels map[string]string, t *testing.T) {
|
|
require := require.New(t)
|
|
containers, err := dockerClient.ContainerListByLabels(ctx, true, cleanupLabels)
|
|
require.NoError(err)
|
|
require.NotNil(containers)
|
|
require.Len(containers, 0)
|
|
|
|
networks, err := dockerClient.NetworkListByLabels(ctx, cleanupLabels)
|
|
require.NoError(err)
|
|
require.NotNil(networks)
|
|
require.Len(networks, 0)
|
|
}
|
|
|
|
func TestPostgresDatabase(t *testing.T) {
|
|
require := require.New(t)
|
|
dbOptions, cleanup := database.NewPostgresDatabase(t)
|
|
t.Cleanup(func() { cleanup() })
|
|
|
|
require.NotEqual(0, dbOptions.HostPort)
|
|
|
|
dockerClient, err := dockerutils.New()
|
|
require.NoError(err)
|
|
|
|
dbContainers, err := dockerClient.ContainerListByLabels(context.Background(), true, dbOptions.ContainerLabels)
|
|
require.NoError(err)
|
|
require.NotNil(dbContainers)
|
|
require.Len(dbContainers, 1)
|
|
|
|
dbo, err := sql.Open(dbOptions.Driver, dbOptions.DSN)
|
|
require.NoError(err)
|
|
require.NoError(dbo.Ping())
|
|
|
|
query := "SELECT 1"
|
|
row := dbo.QueryRow(query)
|
|
|
|
var i int
|
|
err = row.Scan(&i)
|
|
require.NoError(err)
|
|
require.Equal(1, i)
|
|
}
|
|
|
|
func TestPostgresNetwork(t *testing.T) {
|
|
var (
|
|
ctx = context.Background()
|
|
require = require.New(t)
|
|
|
|
cleanupLabels = map[string]string{
|
|
uuid.NewV4().String(): uuid.NewV4().String(),
|
|
}
|
|
)
|
|
|
|
dockerClient, err := dockerutils.New()
|
|
require.NoError(err)
|
|
t.Cleanup(func() {
|
|
dockerClient.ContainerRemoveByLabels(ctx, cleanupLabels)
|
|
dockerClient.NetworkRemoveByLabels(ctx, cleanupLabels)
|
|
dockerClient.Close()
|
|
})
|
|
|
|
// TestDefaultNetwork
|
|
dbOptionsPointer, cleanup := database.NewPostgresDatabase(t)
|
|
t.Cleanup(cleanup)
|
|
|
|
require.NotNil(dbOptionsPointer.ContainerNetworks)
|
|
require.Len(dbOptionsPointer.ContainerNetworks, 0)
|
|
requireContainerHasNetworksAndAliasses(ctx, dockerClient, dbOptionsPointer, t)
|
|
|
|
// TestRandomNetwork
|
|
dbOptions := database.NewPostgresOptions()
|
|
dbOptions.HostPort = "0"
|
|
dbOptions.ContainerName = "Volker"
|
|
dbOptions.ContainerLabels = cleanupLabels
|
|
dbOptions.ContainerNetworks[uuid.NewV4().String()] = []string{
|
|
uuid.NewV4().String(),
|
|
uuid.NewV4().String(),
|
|
}
|
|
_, cleanup = database.StartPostgres(t, dbOptions)
|
|
t.Cleanup(cleanup)
|
|
|
|
requireCountNetworks(ctx, dockerClient, dbOptions, 1, t)
|
|
requireContainerHasNetworksAndAliasses(ctx, dockerClient, dbOptions, t)
|
|
|
|
// TestRandomMultipleNetworks
|
|
containerNetworkNameA := uuid.NewV4().String()
|
|
containerNetworkNameB := uuid.NewV4().String()
|
|
containerNetworks := map[string][]string{
|
|
containerNetworkNameA: {
|
|
uuid.NewV4().String(),
|
|
uuid.NewV4().String(),
|
|
},
|
|
containerNetworkNameB: {
|
|
uuid.NewV4().String(),
|
|
uuid.NewV4().String(),
|
|
},
|
|
}
|
|
|
|
containerNetworkLabels := map[string]map[string]string{
|
|
containerNetworkNameA: cleanupLabels,
|
|
containerNetworkNameB: cleanupLabels,
|
|
}
|
|
|
|
dbOptions = database.NewPostgresOptions()
|
|
dbOptions.HostPort = "0"
|
|
dbOptions.ContainerName = "Raschek"
|
|
dbOptions.ContainerNetworks = containerNetworks
|
|
dbOptions.ContainerNetworkLabels = containerNetworkLabels
|
|
dbOptions.ContainerLabels = cleanupLabels
|
|
|
|
_, cleanup = database.StartPostgres(t, dbOptions)
|
|
t.Cleanup(cleanup)
|
|
|
|
requireCountNetworks(ctx, dockerClient, dbOptions, 2, t)
|
|
requireContainerHasNetworksAndAliasses(ctx, dockerClient, dbOptions, t)
|
|
|
|
// TestCleanup
|
|
// Test if a network with an additional endpoint will not be removed
|
|
containerNetwork := uuid.NewV4().String()
|
|
containerNetworkA := map[string][]string{
|
|
containerNetwork: {
|
|
uuid.NewV4().String(),
|
|
uuid.NewV4().String(),
|
|
},
|
|
}
|
|
containerNetworkB := map[string][]string{
|
|
containerNetwork: {
|
|
uuid.NewV4().String(),
|
|
uuid.NewV4().String(),
|
|
},
|
|
}
|
|
containerNetworkLabels = map[string]map[string]string{
|
|
containerNetwork: cleanupLabels,
|
|
}
|
|
|
|
dbOptions = database.NewPostgresOptions()
|
|
dbOptions.HostPort = "0"
|
|
dbOptions.ContainerName = "is"
|
|
dbOptions.ContainerLabels = cleanupLabels
|
|
dbOptions.ContainerNetworks = containerNetworkA
|
|
dbOptions.ContainerNetworkLabels = containerNetworkLabels
|
|
_, cleanup = database.StartPostgres(t, dbOptions)
|
|
|
|
dbOptions = database.NewPostgresOptions()
|
|
dbOptions.HostPort = "0"
|
|
dbOptions.ContainerName = "the_best"
|
|
dbOptions.ContainerLabels = cleanupLabels
|
|
dbOptions.ContainerNetworks = containerNetworkB
|
|
dbOptions.ContainerNetworkLabels = containerNetworkLabels
|
|
_, cleanupSecond := database.StartPostgres(t, dbOptions)
|
|
|
|
cleanup()
|
|
|
|
networkResources, err := dockerClient.NetworkListByNames(ctx, containerNetwork)
|
|
require.NoError(err)
|
|
require.Len(networkResources[0].Containers, 1)
|
|
|
|
cleanupSecond()
|
|
requireTestCleanup(ctx, dockerClient, cleanupLabels, t)
|
|
}
|
|
|
|
func TestPostgresOptionsValidate(t *testing.T) {
|
|
|
|
require := require.New(t)
|
|
|
|
// ContainerImage is empty
|
|
dbOptions := database.PostgresOptions{}
|
|
err := dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Attribute ContainerImage is empty")
|
|
|
|
// ContainerPort is empty
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Attribute ContainerPort is empty")
|
|
|
|
// Driver is empty
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Attribute Driver is empty")
|
|
|
|
// HostPort is empty
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "sdfsdfsdf",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Attribute HostPort is empty")
|
|
|
|
// ContainerEnv: POSTGRES_PASSWORD
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "sdfsdfsdf",
|
|
HostPort: "asdasd",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Required env POSTGRES_PASSWORD not defined")
|
|
|
|
// ContainerEnv: POSTGRES_USER
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerEnv: map[string]string{
|
|
"POSTGRES_PASSWORD": "HelloWorld",
|
|
},
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "sdfsdfsdf",
|
|
HostPort: "asdasd",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Required env POSTGRES_USER not defined")
|
|
|
|
// ContainerEnv: POSTGRES_USER
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerEnv: map[string]string{
|
|
"POSTGRES_PASSWORD": "postgres",
|
|
"POSTGRES_USER": "postgres",
|
|
},
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "sdfsdfsdf",
|
|
HostPort: "asdasd",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Required env POSTGRES_DB not defined")
|
|
|
|
// Driver not supported
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerEnv: map[string]string{
|
|
"POSTGRES_PASSWORD": "postgres",
|
|
"POSTGRES_USER": "postgres",
|
|
"POSTGRES_DB": "postgres",
|
|
},
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "sdfsdfsdf",
|
|
HostPort: "asdasd",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.True(errors.Is(err, database.ErrInvalidAttr))
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: Driver sdfsdfsdf not supported")
|
|
|
|
// HostPort: Failed to parse
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerEnv: map[string]string{
|
|
"POSTGRES_PASSWORD": "postgres",
|
|
"POSTGRES_USER": "postgres",
|
|
"POSTGRES_DB": "postgres",
|
|
},
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "postgres",
|
|
HostPort: "asdasd",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.EqualError(err, "Failed to parse hostport asdasd: strconv.ParseInt: parsing \"asdasd\": invalid syntax")
|
|
|
|
// HostPort: Well-Known port
|
|
dbOptions = database.PostgresOptions{
|
|
ContainerEnv: map[string]string{
|
|
"POSTGRES_PASSWORD": "postgres",
|
|
"POSTGRES_USER": "postgres",
|
|
"POSTGRES_DB": "postgres",
|
|
},
|
|
ContainerImage: "docker.io/library/postgres:13-alpine",
|
|
ContainerPort: "5432",
|
|
Driver: "postgres",
|
|
HostPort: "443",
|
|
}
|
|
err = dbOptions.Validate()
|
|
require.Error(err)
|
|
require.EqualError(err, "Invalid DatabaseOption attribute: ContainerPort 443: Protect well-known ports between 1-1023")
|
|
}
|