From 260d565e6ee65705ef36d95f430e006dc514a2f5 Mon Sep 17 00:00:00 2001 From: Aravind Shankar Date: Fri, 29 Jun 2018 15:32:33 +0530 Subject: [PATCH] cli: tests for metadata commands (#18) * [cli] added urlPrefix, consoleMode * [cli] fix: down=all should throw error if down migration is missing * [cli] added tests for metadata --- cli/assets/assets.go | 4 +- cli/assets/console.html | 4 +- cli/commands/console_test.go | 5 +- cli/commands/init_test.go | 10 +++- cli/commands/metadata_apply_test.go | 31 +++++++++++ cli/commands/metadata_export_test.go | 31 +++++++++++ cli/commands/metadata_reset_test.go | 31 +++++++++++ cli/commands/migrate_apply_test.go | 53 ++++++++++++++++++- cli/commands/migrate_status_test.go | 24 +++++++++ cli/commands/migrate_test.go | 79 +++++++++++++++++++++++++--- cli/migrate/migrate.go | 16 ++++-- cli/util/migrate.go | 1 + 12 files changed, 267 insertions(+), 22 deletions(-) create mode 100644 cli/commands/metadata_apply_test.go create mode 100644 cli/commands/metadata_export_test.go create mode 100644 cli/commands/metadata_reset_test.go diff --git a/cli/assets/assets.go b/cli/assets/assets.go index cbeeed24..fa84fe53 100644 --- a/cli/assets/assets.go +++ b/cli/assets/assets.go @@ -68,7 +68,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _assetsConsoleHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x55\xdf\x8b\xe3\x36\x10\x7e\xbf\xbf\x42\xa8\x94\x7b\xa9\xa5\xdc\xf5\xa0\x87\x63\x07\x4a\xa1\x14\xda\x87\x42\xbb\x7d\x5d\x66\xe5\xb1\x3d\x59\x59\x72\x35\x4a\xb2\x6e\xf0\xff\x5e\xfc\x2b\xf1\x26\x85\xb6\x07\x4b\x5e\x34\xdf\x8c\xe7\xfb\xbe\x91\x98\x64\x75\x6c\xac\xb0\xe0\xaa\x5c\xa2\x4b\x0e\x2c\x77\xef\x84\xc8\x6a\x84\x62\x38\x08\x91\x59\x72\xcf\x22\xa0\xcd\x25\x19\xef\xa4\x88\x5d\x8b\xb9\xa4\x06\x2a\xd4\xad\xab\xa4\xa8\x03\x96\xb9\xac\x63\x6c\x39\xd5\x9a\xa3\x0f\x50\xa1\xaa\xbc\xaf\x2c\x42\x4b\xac\x8c\x6f\x74\x0d\x7c\x08\x60\xa2\xd5\xc6\x3b\xf6\x16\x35\x30\x63\x64\x5d\xc2\x71\xe8\xab\xc6\x56\x7a\xe6\x64\x13\xa8\x8d\x53\x20\x4e\xe4\x0a\x7f\x52\x8f\x8f\xe8\x8e\x22\x17\xe7\x09\x15\x02\x5a\xfa\xc9\x73\x4c\xc5\xf9\xac\xe6\x73\xdf\x7f\xb3\xca\xfe\xea\x43\x4c\x85\x9c\xd2\x43\xd0\xf7\xf2\x92\x37\x96\xfe\xc0\xc0\xe4\xdd\xd8\xe0\x1a\xae\x7a\x14\x10\xe1\xfb\x96\x1e\x82\x1d\x6b\xae\xe1\x7d\xcd\xba\xd7\x6b\x68\xad\xc9\x18\x64\xfe\x19\xbb\x49\xf3\x12\xf5\xfd\x54\xd0\x6f\x27\xf7\xfa\x6a\x3f\xd3\xcb\x4d\x64\x4f\xbe\xe8\x96\xf1\xc4\xce\xe2\x74\x56\x0d\x90\xfb\xc1\xbb\x88\x2e\x5e\x46\x53\x10\xb7\x16\xba\x54\xbc\x77\xde\xe1\xfb\xed\x0c\xfb\x16\x0c\xc5\x2e\x15\x9b\x05\x89\x01\x1c\x53\x1c\x85\xcf\x59\xa1\x3e\x6e\x58\x58\x72\x08\x61\x2a\xeb\xef\x88\x14\xd7\xfe\xf4\x0f\x6c\x4f\xd6\x9b\xe7\x7b\xba\x0f\x5f\x40\x97\xe9\xd9\xe4\x14\x15\x74\x14\x54\xe4\xd2\x7a\x28\xc8\x55\x72\x7e\x1a\x53\xc2\x58\x60\xce\x65\x0b\x15\x26\x4b\x81\x18\x3f\xcf\xe5\x5c\xd7\x90\x4b\x6a\xa4\xaa\x8e\xa9\xf8\xb0\xd9\x1c\xeb\x45\xd2\x89\x8a\x58\x8f\xd8\xd7\xdb\x5b\x3f\xa5\xc5\x97\x05\x04\x4b\x95\x4b\x28\x62\xc3\xa9\x30\xe8\x22\x86\x25\x55\x7a\x17\x93\x12\x1a\xb2\x5d\x2a\x18\x1c\x27\x8c\x81\xca\x25\xbd\x3f\x70\xa4\xb2\x4b\xcc\x34\xbb\xdb\xaf\x2f\x56\x86\x7b\x6d\xc1\x2d\x6e\x6e\x1d\xcc\x3c\x4c\x7f\x61\x2a\x3e\x62\xb3\xbd\xe0\x0d\x84\x8a\x5c\x12\x7d\x9b\x8a\xe4\xdb\x75\xc6\x78\xeb\x43\x2a\xbe\xfa\xfc\x69\xf8\x5d\xf1\x15\xe7\x2f\xd3\xbc\x94\x52\xcb\x44\xf5\xa0\xe2\x32\x5f\x5d\xd0\x71\x7e\x75\xab\xe3\x72\x1d\xb3\x27\xb9\x88\x5e\xbd\x11\xb9\x5b\x7f\x70\x5d\x22\xa3\x2b\xae\x11\xe3\xed\xe6\x30\x85\xdb\xb3\x32\xd6\x1f\x8a\xd2\x42\xc0\x71\x6f\xc0\x1e\x5e\xb4\xa5\x27\xd6\xa3\x7d\x38\x21\xfb\x06\xf5\x27\xf5\x9d\xda\x68\xc3\xaf\x61\xd5\x90\x53\x86\x59\xea\xff\x41\xfb\x9f\x17\x56\x15\xa0\xad\xff\xb4\xc9\x1c\x9f\xcf\x2a\xa0\x45\x60\xfc\xed\x50\x96\xf4\xd2\xf7\x7a\xb0\x3f\xf2\x0b\x53\x43\x60\x8c\xb9\x7c\xf8\xfd\xc7\xe4\xb3\x7c\xbd\xd7\x04\x07\xf3\x26\xfc\x47\x74\x85\x0f\x6a\x7f\x2f\x60\xb7\x5e\x2a\x6f\x2f\x64\x1c\xc4\xbf\xc9\xc8\xf4\xb4\xd2\x32\x3d\xfc\x07\xed\xde\xfd\x1d\x00\x00\xff\xff\x0b\xc0\x59\x4f\x8b\x06\x00\x00") +var _assetsConsoleHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x55\xdd\x8b\xdc\x36\x10\x7f\xcf\x5f\x31\xa8\x94\xbc\xd4\xd2\x26\x0d\x34\xf8\xd6\x07\xa5\x50\x0a\x6d\x21\xd0\xa6\xaf\x61\x4e\x1e\xdb\x73\x91\x25\x57\xa3\xdd\x3d\x77\xf1\xff\x5e\xfc\xb5\xeb\xbb\x2b\xb4\x0d\x1c\xfb\xa2\xf9\xf0\xfc\x3e\x24\x66\xf7\x4d\x6a\x1d\x38\xf4\x75\xa1\xc8\x67\x07\x51\xb7\xaf\x00\xf6\x0d\x61\x39\x1e\x00\xf6\x8e\xfd\x67\x88\xe4\x0a\xc5\x36\x78\x05\xa9\xef\xa8\x50\xdc\x62\x4d\xa6\xf3\xb5\x82\x26\x52\x55\xa8\x26\xa5\x4e\x72\x63\x24\x85\x88\x35\xe9\x3a\x84\xda\x11\x76\x2c\xda\x86\xd6\x34\x28\x87\x88\x36\x39\x63\x83\x97\xe0\xc8\xa0\x08\x25\x31\x15\x1e\xc7\xb9\x7a\x1a\x65\x16\x4c\xb1\x91\xbb\x34\x07\x70\x62\x5f\x86\x93\xfe\xf4\x89\xfc\x11\x0a\x38\xcf\x59\x00\xec\xf8\xa7\x20\x29\x87\xf3\x59\x2f\xe7\x61\xf8\x66\x53\xfd\x10\x62\xca\x41\xcd\xe5\x31\x18\x06\x75\xa9\x5b\xc7\x7f\x50\x14\x0e\x7e\x1a\x70\x0d\x37\x33\x4a\x4c\xf8\x7d\xc7\x1f\xa3\x9b\x7a\xae\xe1\xf3\x9e\xed\xac\xc7\xa9\x2d\x27\x6b\x49\xe4\x67\xea\x67\xce\x6b\xb4\xe9\x38\x44\xf7\x21\x52\xc5\x0f\x39\x28\xb3\x21\x3b\x7b\xf6\x6b\x28\x29\x07\x65\x1d\xab\xb9\x32\xdc\xcc\x7e\x99\xab\x61\x7b\xb3\xde\xdd\xfe\x2e\x94\xfd\x6a\x68\xea\x1d\xcd\x67\xdd\x22\xfb\x1f\x82\x4f\xe4\xd3\xc5\xcc\x92\xa5\x73\xd8\xe7\xf0\xda\x07\x4f\xaf\x6f\x96\x74\xe8\xd0\x72\xea\x73\xd8\xad\x99\x14\xd1\x0b\xa7\x49\xea\x52\x05\xfd\x76\x27\xe0\xd8\x13\xc6\xb9\x6d\x78\x06\xa4\xa5\x09\xa7\x7f\x40\xbb\x73\xc1\x7e\x7e\x0e\xf7\xe6\x0b\xe0\xf6\x66\x11\x39\x47\x25\x1f\x81\xcb\x42\xb9\x80\x25\xfb\x5a\x2d\x8f\x69\x2e\x58\x87\x22\x85\xea\xb0\xa6\x6c\x6d\x80\xe9\xf3\x62\x71\x16\x5a\xf6\x59\x43\x5c\x37\x29\x87\x37\xbb\xdd\xb1\x59\x29\x9d\xb8\x4c\xcd\x94\xfb\xfa\xe6\xa9\x9e\xca\xd1\xc3\x9a\x44\xc7\xb5\xcf\x38\x51\x2b\x39\x58\xf2\x89\xe2\x5a\xaa\x82\x4f\x59\x85\x2d\xbb\x3e\x07\x41\x2f\x99\x50\xe4\x6a\x2d\xdf\x1f\x24\x71\xd5\x67\x76\xf6\xee\xe9\xd7\x17\x29\xe3\xbd\x76\xe8\x57\x35\x4f\x15\x2c\x38\xc2\x7f\x51\x0e\x6f\xa9\xbd\xb9\xe4\x5b\x8c\x35\xfb\x2c\x85\x2e\x87\xec\xdb\x6d\xc5\x06\x17\x62\x0e\x5f\xbd\x7f\x37\xfe\xae\xf9\x0d\xe6\x2f\xb3\x5f\x5a\xeb\xd5\x51\x33\xb2\xb8\xf8\x6b\x4a\x3e\x2e\xaf\x6e\x73\x5c\xaf\x63\xd1\xa4\x56\xd2\x9b\x37\xa2\x6e\xb7\x1f\x5c\xd7\xce\xa4\x4a\x1a\xa2\xf4\x74\xd7\xd8\xd2\xdf\x8b\xb6\x2e\x1c\xca\xca\x61\xa4\x69\xd3\xe0\x3d\x3e\x18\xc7\x77\x62\x26\xf9\x78\x22\x09\x2d\x99\x77\xfa\x3b\xbd\x33\x56\x1e\xa7\x75\xcb\x5e\x5b\x11\x65\xfe\x07\xec\x7f\x5e\x71\x75\xc4\xae\xf9\xd3\x65\x4b\x7c\x3e\xeb\x48\x8e\x50\xe8\xb7\x43\x55\xf1\xc3\x30\x98\x51\xfe\x84\x0f\xb6\xc1\x28\x94\x0a\xf5\xf1\xf7\x1f\xb3\xf7\xea\xf1\x26\x04\x89\xf6\x45\xf0\x8f\xe4\xcb\x10\xf5\xfd\x73\x02\xb7\xdb\xa5\xf2\xf2\x44\x26\x23\xfe\x8d\xc6\xde\xcc\x2b\x6d\x6f\xc6\x7f\xad\xdb\x57\x7f\x07\x00\x00\xff\xff\x47\x34\x54\x11\xbd\x06\x00\x00") func assetsConsoleHtmlBytes() ([]byte, error) { return bindataRead( @@ -83,7 +83,7 @@ func assetsConsoleHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "assets/console.html", size: 1675, mode: os.FileMode(420), modTime: time.Unix(1529907571, 0)} + info := bindataFileInfo{name: "assets/console.html", size: 1725, mode: os.FileMode(420), modTime: time.Unix(1530211716, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cli/assets/console.html b/cli/assets/console.html index aba73178..e2daf6b0 100644 --- a/cli/assets/console.html +++ b/cli/assets/console.html @@ -8,7 +8,9 @@ cliVersion: {{.cliVersion}}, dataApiUrl: {{.dataApiUrl}}, dataApiVersion: {{.dataApiVersion}}, - accessKey: {{.accessKey}} + accessKey: {{.accessKey}}, + urlPrefix: "/", + consoleMode: "cli" }; diff --git a/cli/commands/console_test.go b/cli/commands/console_test.go index 0476c768..e2de3387 100644 --- a/cli/commands/console_test.go +++ b/cli/commands/console_test.go @@ -6,13 +6,14 @@ import ( "github.com/briandowns/spinner" "github.com/hasura/graphql-engine/cli" - "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" ) func TestConsoleCmd(t *testing.T) { + logger, _ := test.NewNullLogger() opts := &consoleOptions{ EC: &cli.ExecutionContext{ - Logger: logrus.New(), + Logger: logger, Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), Config: &cli.HasuraGraphQLConfig{ Endpoint: "http://localhost:8080", diff --git a/cli/commands/init_test.go b/cli/commands/init_test.go index 16697e8e..e8d40e33 100644 --- a/cli/commands/init_test.go +++ b/cli/commands/init_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/hasura/graphql-engine/cli" + "github.com/sirupsen/logrus/hooks/test" ) func init() { @@ -16,19 +17,24 @@ func init() { } func TestInitCmd(t *testing.T) { + logger, _ := test.NewNullLogger() tt := []struct { name string opts *initOptions err error }{ {"only-init-dir", &initOptions{ - EC: &cli.ExecutionContext{}, + EC: &cli.ExecutionContext{ + Logger: logger, + }, Endpoint: "", AccessKey: "", InitDir: filepath.Join(os.TempDir(), "hasura-cli-test-"+strconv.Itoa(rand.Intn(1000))), }, nil}, {"with-endpoint-flag", &initOptions{ - EC: &cli.ExecutionContext{}, + EC: &cli.ExecutionContext{ + Logger: logger, + }, Endpoint: "https://localhost:8080", AccessKey: "", InitDir: filepath.Join(os.TempDir(), "hasura-cli-test-"+strconv.Itoa(rand.Intn(1000))), diff --git a/cli/commands/metadata_apply_test.go b/cli/commands/metadata_apply_test.go new file mode 100644 index 00000000..0e430f6a --- /dev/null +++ b/cli/commands/metadata_apply_test.go @@ -0,0 +1,31 @@ +package commands + +import ( + "testing" + "time" + + "github.com/briandowns/spinner" + "github.com/hasura/graphql-engine/cli" + "github.com/sirupsen/logrus/hooks/test" +) + +func testMetadataApply(t *testing.T, executionDir string, endpoint string) { + logger, _ := test.NewNullLogger() + opts := &metadataApplyOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + ExecutionDirectory: executionDir, + Config: &cli.HasuraGraphQLConfig{ + Endpoint: endpoint, + AccessKey: "", + }, + }, + actionType: "apply", + } + + err := opts.run() + if err != nil { + t.Fatalf("failed exporting metadata: %v", err) + } +} diff --git a/cli/commands/metadata_export_test.go b/cli/commands/metadata_export_test.go new file mode 100644 index 00000000..b89007c3 --- /dev/null +++ b/cli/commands/metadata_export_test.go @@ -0,0 +1,31 @@ +package commands + +import ( + "testing" + "time" + + "github.com/briandowns/spinner" + "github.com/hasura/graphql-engine/cli" + "github.com/sirupsen/logrus/hooks/test" +) + +func testMetadataExport(t *testing.T, executionDir string, endpoint string) { + logger, _ := test.NewNullLogger() + opts := &metadataExportOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + ExecutionDirectory: executionDir, + Config: &cli.HasuraGraphQLConfig{ + Endpoint: endpoint, + AccessKey: "", + }, + }, + actionType: "export", + } + + err := opts.run() + if err != nil { + t.Fatalf("failed exporting metadata: %v", err) + } +} diff --git a/cli/commands/metadata_reset_test.go b/cli/commands/metadata_reset_test.go new file mode 100644 index 00000000..984ce734 --- /dev/null +++ b/cli/commands/metadata_reset_test.go @@ -0,0 +1,31 @@ +package commands + +import ( + "testing" + "time" + + "github.com/briandowns/spinner" + "github.com/hasura/graphql-engine/cli" + "github.com/sirupsen/logrus/hooks/test" +) + +func testMetadataReset(t *testing.T, executionDir string, endpoint string) { + logger, _ := test.NewNullLogger() + opts := &metadataResetOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + ExecutionDirectory: executionDir, + Config: &cli.HasuraGraphQLConfig{ + Endpoint: endpoint, + AccessKey: "", + }, + }, + actionType: "reset", + } + + err := opts.run() + if err != nil { + t.Fatalf("failed exporting metadata: %v", err) + } +} diff --git a/cli/commands/migrate_apply_test.go b/cli/commands/migrate_apply_test.go index 5861d14d..2bfbd04c 100644 --- a/cli/commands/migrate_apply_test.go +++ b/cli/commands/migrate_apply_test.go @@ -1,6 +1,10 @@ package commands import ( + "math/rand" + "os" + "path/filepath" + "strconv" "testing" "time" @@ -10,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testMigrateApply(t *testing.T, endpoint string, migrationsDir string) { +func testMigrateApply(t *testing.T, endpoint string, migrationsDir string, up string, down string, version string, versionType string) { logger, hook := test.NewNullLogger() opts := &migrateApplyOptions{ EC: &cli.ExecutionContext{ @@ -22,7 +26,10 @@ func testMigrateApply(t *testing.T, endpoint string, migrationsDir string) { AccessKey: "", }, }, - upMigration: "1", + upMigration: up, + downMigration: down, + versionMigration: version, + migrationType: versionType, } err := opts.run() @@ -32,3 +39,45 @@ func testMigrateApply(t *testing.T, endpoint string, migrationsDir string) { assert.Equal(t, "migrations applied", hook.LastEntry().Message) } + +func TestMigrateApplyWithInvalidEndpoint(t *testing.T) { + logger, _ := test.NewNullLogger() + opts := &migrateApplyOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + MigrationDir: filepath.Join(os.TempDir(), "hasura-cli-test-"+strconv.Itoa(rand.Intn(1000))), + Config: &cli.HasuraGraphQLConfig{ + Endpoint: ":", + AccessKey: "", + }, + }, + } + + err := opts.run() + if err == nil { + t.Fatalf("expected err not to be nil") + } +} + +func TestMigrateApplyWithMultipleFlags(t *testing.T) { + logger, _ := test.NewNullLogger() + opts := &migrateApplyOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + MigrationDir: filepath.Join(os.TempDir(), "hasura-cli-test-"+strconv.Itoa(rand.Intn(1000))), + Config: &cli.HasuraGraphQLConfig{ + Endpoint: ":", + AccessKey: "", + }, + }, + upMigration: "1", + downMigration: "2", + } + + err := opts.run() + if err == nil { + t.Fatalf("expected err not to be nil") + } +} diff --git a/cli/commands/migrate_status_test.go b/cli/commands/migrate_status_test.go index 77c5af34..70f1a4e2 100644 --- a/cli/commands/migrate_status_test.go +++ b/cli/commands/migrate_status_test.go @@ -1,6 +1,10 @@ package commands import ( + "math/rand" + "os" + "path/filepath" + "strconv" "testing" "time" @@ -30,3 +34,23 @@ func testMigrateStatus(t *testing.T, endpoint string, migrationsDir string, expe } assert.Equal(t, expectedStatus, hook.LastEntry().Message) } + +func TestMigrateStatusWithInvalidEndpoint(t *testing.T) { + logger, _ := test.NewNullLogger() + opts := &migrateStatusOptions{ + EC: &cli.ExecutionContext{ + Logger: logger, + Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), + MigrationDir: filepath.Join(os.TempDir(), "hasura-cli-test-"+strconv.Itoa(rand.Intn(1000))), + Config: &cli.HasuraGraphQLConfig{ + Endpoint: ":", + AccessKey: "", + }, + }, + } + + err := opts.run() + if err == nil { + t.Fatalf("expected err not to be nil") + } +} diff --git a/cli/commands/migrate_test.go b/cli/commands/migrate_test.go index 670e0a72..06f0b6f0 100644 --- a/cli/commands/migrate_test.go +++ b/cli/commands/migrate_test.go @@ -8,11 +8,13 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "testing" mt "github.com/hasura/graphql-engine/cli/migrate/testing" _ "github.com/lib/pq" "github.com/parnurzeal/gorequest" + "github.com/stretchr/testify/assert" ) var postgresVersions = []mt.Version{ @@ -23,6 +25,22 @@ var ravenVersions = []mt.Version{ {Image: "hasura/graphql-engine:190d78e", Cmd: []string{"raven", "serve", "--database-url"}, ExposedPort: 8080}, } +var testMetadata = map[string][]byte{ + "metadata": []byte(`query_templates: [] +tables: +- array_relationships: [] + delete_permissions: [] + insert_permissions: [] + object_relationships: [] + select_permissions: [] + table: test + update_permissions: [] +`), + "empty-metadata": []byte(`query_templates: [] +tables: [] +`), +} + func isReadyPostgres(i mt.Instance) bool { db, err := sql.Open("postgres", fmt.Sprintf("postgres://postgres@%v:%v/postgres?sslmode=disable", i.Host(), i.Port())) if err != nil { @@ -70,26 +88,63 @@ func TestMigrateCmd(t *testing.T) { } defer os.RemoveAll(migrationsDir) + executionDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(executionDir) + // Create 1_create_table_test.up.sql which creates table test mustWriteFile(t, migrationsDir, "1_create_table_test.up.sql", `CREATE TABLE "test"("id" serial NOT NULL, PRIMARY KEY ("id") )`) - - // Apply 1_create_table_test.up.sql - testMigrateApply(t, endpoint, migrationsDir) - - // Check Migration status - testMigrateStatus(t, endpoint, migrationsDir, "VERSION SOURCE STATUS DATABASE STATUS\n1 Present Present\n") - + // Create 1_create_table_test.down.sql which creates table test + mustWriteFile(t, migrationsDir, "1_create_table_test.down.sql", `DROP TABLE "test";`) // Create 2_add_table_test.up.yaml which adds table test to metadata mustWriteFile(t, migrationsDir, "2_add_table_test.up.yaml", `- args: name: test type: add_existing_table_or_view `) + mustWriteFile(t, migrationsDir, "2_add_table_test.down.yaml", `- args: + table: test + type: untrack_table +`) + + // Apply 1_create_table_test.up.sql + testMigrateApply(t, endpoint, migrationsDir, "1", "", "", "") + + // Check Migration status + testMigrateStatus(t, endpoint, migrationsDir, "VERSION SOURCE STATUS DATABASE STATUS\n1 Present Present\n2 Present Not Present\n") + // Apply 2_add_table_test.up.yaml - testMigrateApply(t, endpoint, migrationsDir) + testMigrateApply(t, endpoint, migrationsDir, "", "", "2", "") // Check Migration status testMigrateStatus(t, endpoint, migrationsDir, "VERSION SOURCE STATUS DATABASE STATUS\n1 Present Present\n2 Present Present\n") + // Apply 2_add_table_test.down.yaml + testMigrateApply(t, endpoint, migrationsDir, "", "1", "", "") + + // Check Migration status + testMigrateStatus(t, endpoint, migrationsDir, "VERSION SOURCE STATUS DATABASE STATUS\n1 Present Present\n2 Present Not Present\n") + + // Apply 1_create_table_test.down.sql + testMigrateApply(t, endpoint, migrationsDir, "", "", "1", "down") + + // Check Migration status + testMigrateStatus(t, endpoint, migrationsDir, "VERSION SOURCE STATUS DATABASE STATUS\n1 Present Not Present\n2 Present Not Present\n") + + // Apply both 1 and 2 + testMigrateApply(t, endpoint, migrationsDir, "", "", "", "") + + testMetadataExport(t, executionDir, endpoint) + compareMetadata(t, executionDir, testMetadata["metadata"]) + + testMetadataApply(t, executionDir, endpoint) + testMetadataExport(t, executionDir, endpoint) + compareMetadata(t, executionDir, testMetadata["metadata"]) + + testMetadataReset(t, executionDir, endpoint) + testMetadataExport(t, executionDir, endpoint) + compareMetadata(t, executionDir, testMetadata["empty-metadata"]) }) }) } @@ -99,3 +154,11 @@ func mustWriteFile(t testing.TB, dir, file string, body string) { t.Fatal(err) } } + +func compareMetadata(t testing.TB, executionDir string, actualData []byte) { + data, err := ioutil.ReadFile(filepath.Join(executionDir, "metadata.yaml")) + if err != nil { + t.Fatalf("error reading metadata %s", err) + } + assert.Equal(t, actualData, data) +} diff --git a/cli/migrate/migrate.go b/cli/migrate/migrate.go index 7fc73113..bf45503f 100644 --- a/cli/migrate/migrate.go +++ b/cli/migrate/migrate.go @@ -624,7 +624,7 @@ func (m *Migrate) readUp(limit int64, ret chan<- interface{}) { // reached end, and didn't apply any migrations if limit > 0 && count == 0 { - ret <- os.ErrNotExist + ret <- ErrNoChange return } @@ -702,7 +702,7 @@ func (m *Migrate) readDown(limit int64, ret chan<- interface{}) { // can't go over limit if already at nil version if from == -1 && limit > 0 { - ret <- os.ErrNotExist + ret <- ErrNoChange return } @@ -712,6 +712,12 @@ func (m *Migrate) readDown(limit int64, ret chan<- interface{}) { return } + err = m.versionDownExists(suint64(from)) + if err != nil { + ret <- err + return + } + prev, ok := m.databaseDrv.Prev(suint64(from)) if !ok { // no limit or haven't reached limit, apply "first" migration @@ -809,10 +815,10 @@ func (m *Migrate) versionUpExists(version uint64) error { // try up migration first directions := m.sourceDrv.GetDirections(version) if !directions[source.Up] && !directions[source.MetaUp] { - return fmt.Errorf("%d migration not found", version) + return fmt.Errorf("%d up migration not found", version) } - if directions["up"] { + if directions[source.Up] { up, _, _, err := m.sourceDrv.ReadUp(version) if err == nil { defer up.Close() @@ -847,7 +853,7 @@ func (m *Migrate) versionDownExists(version uint64) error { // try up migration first directions := m.sourceDrv.GetDirections(version) if !directions[source.Down] && !directions[source.MetaDown] { - return fmt.Errorf("%d migration not found", version) + return fmt.Errorf("%d down migration not found", version) } if directions[source.Down] { diff --git a/cli/util/migrate.go b/cli/util/migrate.go index 5580ac85..4abfb235 100644 --- a/cli/util/migrate.go +++ b/cli/util/migrate.go @@ -44,6 +44,7 @@ func ExecuteMigration(cmd, dir, db string, stepOrVersion int64) error { direction = "up" } else { direction = "down" + stepOrVersion = -(stepOrVersion) } err = mig.GotoCmd(t, uint64(stepOrVersion), direction) default: