-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add migration test using concrete database
- Loading branch information
Showing
3 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Migrations test | ||
|
||
This package allow to test the migration of an existing database regarding current code. | ||
|
||
The test can be run using the following command : | ||
```shell | ||
go test . \ | ||
-databases.source <database source dsn> | ||
``` | ||
|
||
The test will start a new postgres server, copy the database inside, then apply migrations. | ||
|
||
Additionally, you can add the flag : | ||
```shell | ||
go test . \ | ||
-databases.source <database source dsn> \ | ||
-databases.destination <database destination dsn> | ||
``` | ||
|
||
In this case, the destination database will be used and no local postgres server will be started. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package migrations | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"github.com/formancehq/go-libs/bun/bunconnect" | ||
"github.com/formancehq/go-libs/logging" | ||
"github.com/formancehq/go-libs/testing/docker" | ||
"github.com/formancehq/go-libs/testing/platform/pgtesting" | ||
"github.com/formancehq/ledger/internal/storage/driver" | ||
"github.com/ory/dockertest/v3" | ||
dockerlib "github.com/ory/dockertest/v3/docker" | ||
"github.com/stretchr/testify/require" | ||
"github.com/xo/dburl" | ||
"os" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
var ( | ||
sourceDatabase string | ||
destinationDatabase string | ||
) | ||
|
||
func TestMain(m *testing.M) { | ||
flag.StringVar(&sourceDatabase, "databases.source", "", "Source database") | ||
flag.StringVar(&destinationDatabase, "databases.destination", "", "Destination database") | ||
flag.Parse() | ||
|
||
os.Exit(m.Run()) | ||
} | ||
|
||
func TestMigrations(t *testing.T) { | ||
if sourceDatabase == "" { | ||
t.Skip() | ||
} | ||
// debug | ||
//sourceDatabase = "postgresql://formance:[email protected]:5432/qkjnwtkxwaof-oknl-ledger?sslmode=disable" | ||
|
||
ctx := logging.TestingContext() | ||
dockerPool := docker.NewPool(t, logging.Testing()) | ||
|
||
if destinationDatabase == "" { | ||
pgServer := pgtesting.CreatePostgresServer(t, dockerPool) | ||
destinationDatabase = pgServer.GetDSN() | ||
} | ||
|
||
copyDatabase(t, dockerPool, sourceDatabase, destinationDatabase) | ||
|
||
db, err := bunconnect.OpenSQLDB(ctx, bunconnect.ConnectionOptions{ | ||
DatabaseSourceName: destinationDatabase, | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Migrate database | ||
driver := driver.New(db) | ||
require.NoError(t, driver.Initialize(ctx)) | ||
require.NoError(t, driver.UpgradeAllLedgers(ctx)) | ||
} | ||
|
||
func copyDatabase(t *testing.T, dockerPool *docker.Pool, source, destination string) { | ||
resource := dockerPool.Run(docker.Configuration{ | ||
RunOptions: &dockertest.RunOptions{ | ||
Repository: "postgres", | ||
Tag: "15-alpine", | ||
Entrypoint: []string{"sleep", "infinity"}, | ||
}, | ||
HostConfigOptions: []func(config *dockerlib.HostConfig){ | ||
func(config *dockerlib.HostConfig) { | ||
config.NetworkMode = "host" | ||
}, | ||
}, | ||
}) | ||
|
||
execArgs := []string{"sh", "-c", fmt.Sprintf(` | ||
%s | %s | ||
`, | ||
preparePGDumpCommand(t, source), | ||
preparePSQLCommand(t, destination), | ||
)} | ||
|
||
fmt.Printf("Exec command: %s\n", execArgs) | ||
|
||
_, err := resource.Exec(execArgs, dockertest.ExecOptions{ | ||
StdOut: os.Stdout, | ||
StdErr: os.Stdout, | ||
}) | ||
|
||
require.NoError(t, err) | ||
} | ||
|
||
func preparePGDumpCommand(t *testing.T, dsn string) string { | ||
parsedSource, err := dburl.Parse(dsn) | ||
require.NoError(t, err) | ||
|
||
args := make([]string, 0) | ||
|
||
password, ok := parsedSource.User.Password() | ||
if ok { | ||
args = append(args, "PGPASSWORD="+password) | ||
} | ||
|
||
args = append(args, | ||
"pg_dump", | ||
"--no-owner", // skip roles | ||
"-x", // Skip privileges | ||
"-h", parsedSource.Hostname(), | ||
"-p", parsedSource.Port(), | ||
) | ||
|
||
if username := parsedSource.User.Username(); username != "" { | ||
args = append(args, "-U", username) | ||
} | ||
|
||
return strings.Join(append(args, parsedSource.Path[1:]), " ") | ||
} | ||
|
||
func preparePSQLCommand(t *testing.T, dsn string) string { | ||
parsedSource, err := dburl.Parse(dsn) | ||
require.NoError(t, err) | ||
|
||
args := make([]string, 0) | ||
|
||
password, ok := parsedSource.User.Password() | ||
if ok { | ||
args = append(args, "PGPASSWORD="+password) | ||
} | ||
|
||
args = append(args, | ||
"psql", | ||
"-h", parsedSource.Hostname(), | ||
"-p", parsedSource.Port(), | ||
parsedSource.Path[1:], | ||
) | ||
|
||
if username := parsedSource.User.Username(); username != "" { | ||
args = append(args, "-U", username) | ||
} | ||
|
||
return strings.Join(args, " ") | ||
} |