diff --git a/cli/cli.go b/cli/cli.go index 8eaf1425efd3b..1b852e3146a89 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -9,6 +9,7 @@ package cli import ( "bytes" + "net/url" "os" "path/filepath" "regexp" @@ -50,6 +51,18 @@ type HasuraGraphQLConfig struct { Endpoint string `json:"endpoint"` // AccessKey (optional) required to query the endpoint AccessKey string `json:"access_key,omitempty"` + + ParsedEndpoint *url.URL +} + +// ParseEndpoint ensures the endpoint is valid. +func (hgc *HasuraGraphQLConfig) ParseEndpoint() error { + nurl, err := url.Parse(hgc.Endpoint) + if err != nil { + return err + } + hgc.ParsedEndpoint = nurl + return nil } // ExecutionContext contains various contextual information required by the cli @@ -204,15 +217,14 @@ func (ec *ExecutionContext) readConfig() error { v.AddConfigPath(ec.ExecutionDirectory) err := v.ReadInConfig() if err != nil { - ec.Logger.WithError(err).Error("cannot read config file") return errors.Wrap(err, "cannor read config file") } - ec.Config = &HasuraGraphQLConfig{ Endpoint: v.GetString("endpoint"), AccessKey: v.GetString("access_key"), } - return nil + err = ec.Config.ParseEndpoint() + return err } // setupSpinner creates a default spinner if the context does not already have diff --git a/cli/commands/console.go b/cli/commands/console.go index c72d9c9f476bc..7f03ad422057d 100644 --- a/cli/commands/console.go +++ b/cli/commands/console.go @@ -4,8 +4,6 @@ import ( "fmt" "net/http" "net/url" - "path/filepath" - "runtime" "sync" "github.com/fatih/color" @@ -15,6 +13,7 @@ import ( "github.com/hasura/graphql-engine/cli/migrate/api" "github.com/hasura/graphql-engine/cli/util" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/skratchdot/open-golang/open" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -86,12 +85,7 @@ func (o *consoleOptions) run() error { r, } - u, err := url.Parse(o.EC.Config.Endpoint) - if err != nil { - return errors.Wrap(err, "cannot parse endpoint as url") - } - - router.setRoutes(u.Host, o.EC.Config.AccessKey, o.EC.MigrationDir) + router.setRoutes(o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.MigrationDir, o.EC.Logger) if o.EC.Version == nil { return errors.New("cannot validate version, object is nil") @@ -105,7 +99,7 @@ func (o *consoleOptions) run() error { "apiHost": "http://" + o.Address, "apiPort": o.APIPort, "cliVersion": o.EC.Version.GetCLIVersion(), - "dataApiUrl": o.EC.Config.Endpoint, + "dataApiUrl": o.EC.Config.ParsedEndpoint.String(), "dataApiVersion": "", "accessKey": o.EC.Config.AccessKey, "assetsVersion": consoleAssetsVersion, @@ -158,14 +152,15 @@ type consoleRouter struct { *gin.Engine } -func (router *consoleRouter) setRoutes(host, accessKey, migrationDir string) { +func (router *consoleRouter) setRoutes(nurl *url.URL, accessKey, migrationDir string, logger *logrus.Logger) { apis := router.Group("/apis") { + apis.Use(setLogger(logger)) + apis.Use(setFilePath(migrationDir)) + apis.Use(setDataPath(nurl, accessKey)) // Migrate api endpoints and middleware migrateAPIs := apis.Group("/migrate") { - migrateAPIs.Use(setFilePath(migrationDir)) - migrateAPIs.Use(setDataPath(host, accessKey)) settingsAPIs := migrateAPIs.Group("/settings") { settingsAPIs.Any("", api.SettingsAPI) @@ -175,20 +170,15 @@ func (router *consoleRouter) setRoutes(host, accessKey, migrationDir string) { // Migrate api endpoints and middleware metadataAPIs := apis.Group("/metadata") { - metadataAPIs.Use(setFilePath(migrationDir)) - metadataAPIs.Use(setDataPath(host, accessKey)) metadataAPIs.Any("", api.MetadataAPI) } } } -func setDataPath(hostName, accessKey string) gin.HandlerFunc { +func setDataPath(nurl *url.URL, accessKey string) gin.HandlerFunc { return func(c *gin.Context) { - host := url.URL{ - Scheme: "hasuradb", - User: url.UserPassword("admin", accessKey), - Host: hostName, - } + host := getDataPath(nurl, accessKey) + c.Set("dbpath", host) c.Next() } @@ -196,11 +186,15 @@ func setDataPath(hostName, accessKey string) gin.HandlerFunc { func setFilePath(dir string) gin.HandlerFunc { return func(c *gin.Context) { - if runtime.GOOS == "windows" { - c.Set("filedir", "file:///"+filepath.Clean(dir)) - } else { - c.Set("filedir", "file://"+filepath.Clean(dir)) - } + host := getFilePath(dir) + c.Set("filedir", host) + c.Next() + } +} + +func setLogger(logger *logrus.Logger) gin.HandlerFunc { + return func(c *gin.Context) { + c.Set("logger", logger) c.Next() } } diff --git a/cli/commands/console_test.go b/cli/commands/console_test.go index 1ba2ba0e1c7a9..34d089922e4a3 100644 --- a/cli/commands/console_test.go +++ b/cli/commands/console_test.go @@ -29,6 +29,10 @@ func TestConsoleCmd(t *testing.T) { DontOpenBrowser: true, } opts.EC.Spinner.Writer = &fake.FakeWriter{} + err := opts.EC.Config.ParseEndpoint() + if err != nil { + t.Fatal(err) + } go func() { t.Log("waiting for console to start") @@ -38,7 +42,7 @@ func TestConsoleCmd(t *testing.T) { opts.WG.Done() opts.WG.Done() }() - err := opts.run() + err = opts.run() if err != nil { t.Fatalf("failed running console: %v", err) } diff --git a/cli/commands/metadata.go b/cli/commands/metadata.go index 4513c00013c13..7255fd09a7601 100644 --- a/cli/commands/metadata.go +++ b/cli/commands/metadata.go @@ -1,7 +1,14 @@ package commands import ( + "encoding/json" + "io/ioutil" + "path/filepath" + + "github.com/ghodss/yaml" "github.com/hasura/graphql-engine/cli" + "github.com/hasura/graphql-engine/cli/migrate" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -31,3 +38,50 @@ func NewMetadataCmd(ec *cli.ExecutionContext) *cobra.Command { v.BindPFlag("access_key", f.Lookup("access-key")) return metadataCmd } + +func executeMetadata(cmd string, t *migrate.Migrate, metadata string) error { + switch cmd { + case "export": + metaData, err := t.ExportMetadata() + if err != nil { + return errors.Wrap(err, "Cannot export metadata") + } + + t, err := json.Marshal(metaData) + if err != nil { + return errors.Wrap(err, "Cannot Marshal metadata") + } + + data, err := yaml.JSONToYAML(t) + if err != nil { + return err + } + + err = ioutil.WriteFile(filepath.Join(metadata, "metadata.yaml"), data, 0644) + if err != nil { + return errors.Wrap(err, "cannot save metadata") + } + case "reset": + err := t.ResetMetadata() + if err != nil { + return errors.Wrap(err, "Cannot reset Metadata") + } + case "apply": + data, err := ioutil.ReadFile(filepath.Join(metadata, "metadata.yaml")) + if err != nil { + return errors.Wrap(err, "cannot read metadata file") + } + + var q interface{} + err = yaml.Unmarshal(data, &q) + if err != nil { + return errors.Wrap(err, "cannot parse metadata file") + } + + err = t.ApplyMetadata(q) + if err != nil { + return errors.Wrap(err, "cannot apply metadata on the database") + } + } + return nil +} diff --git a/cli/commands/metadata_apply.go b/cli/commands/metadata_apply.go index 3e3aa50524a61..26486990829ee 100644 --- a/cli/commands/metadata_apply.go +++ b/cli/commands/metadata_apply.go @@ -1,11 +1,7 @@ package commands import ( - "net/url" - "github.com/hasura/graphql-engine/cli" - "github.com/hasura/graphql-engine/cli/util" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -36,12 +32,9 @@ type metadataApplyOptions struct { } func (o *metadataApplyOptions) run() error { - dbURL, err := url.Parse(o.EC.Config.Endpoint) + migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.Logger) if err != nil { - return errors.Wrap(err, "error parsing Endpoint") + return err } - - dbURL.Scheme = "hasuradb" - dbURL.User = url.UserPassword("admin", o.EC.Config.AccessKey) - return util.ExecuteMetadata(o.actionType, "file://"+o.EC.MigrationDir, dbURL.String(), o.EC.ExecutionDirectory) + return executeMetadata(o.actionType, migrateDrv, o.EC.ExecutionDirectory) } diff --git a/cli/commands/metadata_apply_test.go b/cli/commands/metadata_apply_test.go index 0e430f6a935c8..5624985dc2cb6 100644 --- a/cli/commands/metadata_apply_test.go +++ b/cli/commands/metadata_apply_test.go @@ -1,6 +1,7 @@ package commands import ( + "net/url" "testing" "time" @@ -9,7 +10,7 @@ import ( "github.com/sirupsen/logrus/hooks/test" ) -func testMetadataApply(t *testing.T, executionDir string, endpoint string) { +func testMetadataApply(t *testing.T, executionDir string, endpoint *url.URL) { logger, _ := test.NewNullLogger() opts := &metadataApplyOptions{ EC: &cli.ExecutionContext{ @@ -17,8 +18,9 @@ func testMetadataApply(t *testing.T, executionDir string, endpoint string) { Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), ExecutionDirectory: executionDir, Config: &cli.HasuraGraphQLConfig{ - Endpoint: endpoint, - AccessKey: "", + Endpoint: endpoint.String(), + AccessKey: "", + ParsedEndpoint: endpoint, }, }, actionType: "apply", diff --git a/cli/commands/metadata_export.go b/cli/commands/metadata_export.go index 73a3f32249871..0c42f1790767b 100644 --- a/cli/commands/metadata_export.go +++ b/cli/commands/metadata_export.go @@ -1,11 +1,7 @@ package commands import ( - "net/url" - "github.com/hasura/graphql-engine/cli" - "github.com/hasura/graphql-engine/cli/util" - "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -36,12 +32,9 @@ type metadataExportOptions struct { } func (o *metadataExportOptions) run() error { - dbURL, err := url.Parse(o.EC.Config.Endpoint) + migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.Logger) if err != nil { - return errors.Wrap(err, "error parsing Endpoint") + return err } - - dbURL.Scheme = "hasuradb" - dbURL.User = url.UserPassword("admin", o.EC.Config.AccessKey) - return util.ExecuteMetadata(o.actionType, "file://"+o.EC.MigrationDir, dbURL.String(), o.EC.ExecutionDirectory) + return executeMetadata(o.actionType, migrateDrv, o.EC.ExecutionDirectory) } diff --git a/cli/commands/metadata_export_test.go b/cli/commands/metadata_export_test.go index b89007c345ca2..a58034ff6cdd5 100644 --- a/cli/commands/metadata_export_test.go +++ b/cli/commands/metadata_export_test.go @@ -1,6 +1,7 @@ package commands import ( + "net/url" "testing" "time" @@ -9,7 +10,7 @@ import ( "github.com/sirupsen/logrus/hooks/test" ) -func testMetadataExport(t *testing.T, executionDir string, endpoint string) { +func testMetadataExport(t *testing.T, executionDir string, endpoint *url.URL) { logger, _ := test.NewNullLogger() opts := &metadataExportOptions{ EC: &cli.ExecutionContext{ @@ -17,8 +18,9 @@ func testMetadataExport(t *testing.T, executionDir string, endpoint string) { Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), ExecutionDirectory: executionDir, Config: &cli.HasuraGraphQLConfig{ - Endpoint: endpoint, - AccessKey: "", + Endpoint: endpoint.String(), + AccessKey: "", + ParsedEndpoint: endpoint, }, }, actionType: "export", diff --git a/cli/commands/metadata_reset.go b/cli/commands/metadata_reset.go index a8442c809ae6f..6b3139c3f94cd 100644 --- a/cli/commands/metadata_reset.go +++ b/cli/commands/metadata_reset.go @@ -1,10 +1,7 @@ package commands import ( - "net/url" - "github.com/hasura/graphql-engine/cli" - "github.com/hasura/graphql-engine/cli/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -36,14 +33,11 @@ type metadataResetOptions struct { } func (o *metadataResetOptions) run() error { - dbURL, err := url.Parse(o.EC.Config.Endpoint) + migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.Logger) if err != nil { - return errors.Wrap(err, "error parsing Endpoint") + return err } - - dbURL.Scheme = "hasuradb" - dbURL.User = url.UserPassword("admin", o.EC.Config.AccessKey) - err = util.ExecuteMetadata(o.actionType, "file://"+o.EC.MigrationDir, dbURL.String(), o.EC.ExecutionDirectory) + err = executeMetadata(o.actionType, migrateDrv, o.EC.ExecutionDirectory) if err != nil { return errors.Wrap(err, "Cannot reset metadata") } diff --git a/cli/commands/metadata_reset_test.go b/cli/commands/metadata_reset_test.go index 984ce7346faa8..beac528285a6d 100644 --- a/cli/commands/metadata_reset_test.go +++ b/cli/commands/metadata_reset_test.go @@ -1,6 +1,7 @@ package commands import ( + "net/url" "testing" "time" @@ -9,7 +10,7 @@ import ( "github.com/sirupsen/logrus/hooks/test" ) -func testMetadataReset(t *testing.T, executionDir string, endpoint string) { +func testMetadataReset(t *testing.T, executionDir string, endpoint *url.URL) { logger, _ := test.NewNullLogger() opts := &metadataResetOptions{ EC: &cli.ExecutionContext{ @@ -17,8 +18,9 @@ func testMetadataReset(t *testing.T, executionDir string, endpoint string) { Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), ExecutionDirectory: executionDir, Config: &cli.HasuraGraphQLConfig{ - Endpoint: endpoint, - AccessKey: "", + Endpoint: endpoint.String(), + AccessKey: "", + ParsedEndpoint: endpoint, }, }, actionType: "reset", diff --git a/cli/commands/migrate.go b/cli/commands/migrate.go index 5369debe51f2c..c839893e754b0 100644 --- a/cli/commands/migrate.go +++ b/cli/commands/migrate.go @@ -1,9 +1,18 @@ package commands import ( + "fmt" + "net/url" + "runtime" + "strings" + "github.com/hasura/graphql-engine/cli" + "github.com/hasura/graphql-engine/cli/migrate" + mig "github.com/hasura/graphql-engine/cli/migrate/cmd" _ "github.com/hasura/graphql-engine/cli/migrate/database/hasuradb" _ "github.com/hasura/graphql-engine/cli/migrate/source/file" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -33,3 +42,77 @@ func NewMigrateCmd(ec *cli.ExecutionContext) *cobra.Command { v.BindPFlag("access_key", f.Lookup("access-key")) return migrateCmd } + +func newMigrate(dir string, db *url.URL, accessKey string, logger *logrus.Logger) (*migrate.Migrate, error) { + dbURL := getDataPath(db, accessKey) + fileURL := getFilePath(dir) + t, err := migrate.New(fileURL.String(), dbURL.String(), true, logger) + if err != nil { + return nil, errors.Wrap(err, "cannot create migrate instance") + } + return t, nil +} + +func executeMigration(cmd string, t *migrate.Migrate, stepOrVersion int64) error { + var err error + + switch cmd { + case "up": + err = mig.UpCmd(t, stepOrVersion) + case "down": + err = mig.DownCmd(t, stepOrVersion) + case "version": + var direction string + if stepOrVersion >= 0 { + direction = "up" + } else { + direction = "down" + stepOrVersion = -(stepOrVersion) + } + err = mig.GotoCmd(t, uint64(stepOrVersion), direction) + default: + err = fmt.Errorf("Invalid command") + } + + return err +} + +func executeStatus(t *migrate.Migrate) (*migrate.Status, error) { + status, err := t.GetStatus() + if err != nil { + return nil, err + } + return status, nil +} + +func getDataPath(nurl *url.URL, accessKey string) *url.URL { + host := &url.URL{ + Scheme: "hasuradb", + User: url.UserPassword("admin", accessKey), + Host: nurl.Host, + Path: nurl.Path, + } + q := nurl.Query() + // Set sslmode in query + switch scheme := nurl.Scheme; scheme { + case "https": + q.Set("sslmode", "enable") + default: + q.Set("sslmode", "disable") + } + host.RawQuery = q.Encode() + return host +} + +func getFilePath(dir string) *url.URL { + host := &url.URL{ + Scheme: "file", + Path: dir, + } + + // Add Prefix / to path if runtime.GOOS equals to windows + if runtime.GOOS == "windows" && !strings.HasPrefix(host.Path, "/") { + host.Path = "/" + host.Path + } + return host +} diff --git a/cli/commands/migrate_apply.go b/cli/commands/migrate_apply.go index ddd733289ca9a..4375c4d8cca63 100644 --- a/cli/commands/migrate_apply.go +++ b/cli/commands/migrate_apply.go @@ -1,12 +1,10 @@ package commands import ( - "net/url" "strconv" "github.com/hasura/graphql-engine/cli" migrate "github.com/hasura/graphql-engine/cli/migrate" - "github.com/hasura/graphql-engine/cli/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -47,15 +45,12 @@ func (o *migrateApplyOptions) run() error { return errors.Wrap(err, "error validating flags") } - dbURL, err := url.Parse(o.EC.Config.Endpoint) + migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.Logger) if err != nil { - return errors.Wrap(err, "error parsing endpoint") + return err } - dbURL.Scheme = "hasuradb" - dbURL.User = url.UserPassword("admin", o.EC.Config.AccessKey) - - err = util.ExecuteMigration(migrationType, "file://"+o.EC.MigrationDir, dbURL.String(), step) + err = executeMigration(migrationType, migrateDrv, step) if err != nil { if err == migrate.ErrNoChange { o.EC.Logger.Info("nothing to apply") diff --git a/cli/commands/migrate_apply_test.go b/cli/commands/migrate_apply_test.go index 2bfbd04c68910..218cbf92d6776 100644 --- a/cli/commands/migrate_apply_test.go +++ b/cli/commands/migrate_apply_test.go @@ -2,6 +2,7 @@ package commands import ( "math/rand" + "net/url" "os" "path/filepath" "strconv" @@ -14,7 +15,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testMigrateApply(t *testing.T, endpoint string, migrationsDir string, up string, down string, version string, versionType string) { +func testMigrateApply(t *testing.T, endpoint *url.URL, migrationsDir string, up string, down string, version string, versionType string) { logger, hook := test.NewNullLogger() opts := &migrateApplyOptions{ EC: &cli.ExecutionContext{ @@ -22,8 +23,9 @@ func testMigrateApply(t *testing.T, endpoint string, migrationsDir string, up st Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), MigrationDir: migrationsDir, Config: &cli.HasuraGraphQLConfig{ - Endpoint: endpoint, - AccessKey: "", + Endpoint: endpoint.String(), + AccessKey: "", + ParsedEndpoint: endpoint, }, }, upMigration: up, @@ -48,8 +50,9 @@ func TestMigrateApplyWithInvalidEndpoint(t *testing.T) { 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: "", + Endpoint: ":", + AccessKey: "", + ParsedEndpoint: &url.URL{}, }, }, } @@ -76,7 +79,12 @@ func TestMigrateApplyWithMultipleFlags(t *testing.T) { downMigration: "2", } - err := opts.run() + err := opts.EC.Config.ParseEndpoint() + if err == nil { + t.Fatalf("expected err not to be nil") + } + + err = opts.run() if err == nil { t.Fatalf("expected err not to be nil") } diff --git a/cli/commands/migrate_status.go b/cli/commands/migrate_status.go index 17f8a97ec113c..a18d2f8d0bcba 100644 --- a/cli/commands/migrate_status.go +++ b/cli/commands/migrate_status.go @@ -3,7 +3,6 @@ package commands import ( "bytes" "fmt" - "net/url" "text/tabwriter" "github.com/hasura/graphql-engine/cli" @@ -39,14 +38,11 @@ type migrateStatusOptions struct { } func (o *migrateStatusOptions) run() (*migrate.Status, error) { - dbURL, err := url.Parse(o.EC.Config.Endpoint) + migrateDrv, err := newMigrate(o.EC.MigrationDir, o.EC.Config.ParsedEndpoint, o.EC.Config.AccessKey, o.EC.Logger) if err != nil { - return nil, errors.Wrap(err, "error parsing Endpoint") + return nil, errors.Wrap(err, "cannot create migrate instance") } - - dbURL.Scheme = "hasuradb" - dbURL.User = url.UserPassword("admin", o.EC.Config.AccessKey) - status, err := util.ExecuteStatus("file://"+o.EC.MigrationDir, dbURL.String()) + status, err := executeStatus(migrateDrv) if err != nil { return nil, errors.Wrap(err, "cannot fetch migrate status") } diff --git a/cli/commands/migrate_status_test.go b/cli/commands/migrate_status_test.go index c27bb955184b5..4dbbb0d055fb0 100644 --- a/cli/commands/migrate_status_test.go +++ b/cli/commands/migrate_status_test.go @@ -2,6 +2,7 @@ package commands import ( "math/rand" + "net/url" "os" "path/filepath" "strconv" @@ -15,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" ) -func testMigrateStatus(t *testing.T, endpoint string, migrationsDir string, expectedStatus *migrate.Status) { +func testMigrateStatus(t *testing.T, endpoint *url.URL, migrationsDir string, expectedStatus *migrate.Status) { logger, _ := test.NewNullLogger() opts := &migrateStatusOptions{ EC: &cli.ExecutionContext{ @@ -23,8 +24,9 @@ func testMigrateStatus(t *testing.T, endpoint string, migrationsDir string, expe Spinner: spinner.New(spinner.CharSets[7], 100*time.Millisecond), MigrationDir: migrationsDir, Config: &cli.HasuraGraphQLConfig{ - Endpoint: endpoint, - AccessKey: "", + Endpoint: endpoint.String(), + AccessKey: "", + ParsedEndpoint: endpoint, }, }, } @@ -44,8 +46,9 @@ func TestMigrateStatusWithInvalidEndpoint(t *testing.T) { 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: "", + Endpoint: ":", + AccessKey: "", + ParsedEndpoint: &url.URL{}, }, }, } diff --git a/cli/commands/migrate_test.go b/cli/commands/migrate_test.go index 9fb1c15c24a48..68293c098d24f 100644 --- a/cli/commands/migrate_test.go +++ b/cli/commands/migrate_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/ioutil" + "net/url" "os" "path" "path/filepath" @@ -81,7 +82,10 @@ func testMigrateWithDocker(t *testing.T, migrationsDir, executionDir string) { defer pi.Remove() defer ri.Remove() - endpointURL := fmt.Sprintf("http://%s:%d", ri.Host(), ri.Port()) + endpointURL, err := url.Parse(fmt.Sprintf("http://%s:%d", ri.Host(), ri.Port())) + if err != nil { + t.Fatal(err) + } // Create migration Dir migrationsDir, err := ioutil.TempDir("", "") if err != nil { @@ -101,7 +105,10 @@ func testMigrateWithDocker(t *testing.T, migrationsDir, executionDir string) { } func TestMigrateCmd(t *testing.T) { - endpointURL := os.Getenv("HASURA_GRAPHQL_TEST_ENDPOINT") + endpointURL, err := url.Parse(os.Getenv("HASURA_GRAPHQL_TEST_ENDPOINT")) + if err != nil { + t.Fatal(err) + } // Create migration Dir migrationsDir, err := ioutil.TempDir("", "") if err != nil { @@ -119,7 +126,7 @@ func TestMigrateCmd(t *testing.T) { testMigrate(t, endpointURL, migrationsDir, executionDir) } -func testMigrate(t *testing.T, endpoint, migrationsDir, executionDir string) { +func testMigrate(t *testing.T, endpoint *url.URL, migrationsDir, executionDir string) { // 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") )`) // Create 1_create_table_test.down.sql which creates table test diff --git a/cli/migrate/api/metadata.go b/cli/migrate/api/metadata.go index a3db1d4ed8d90..0d9b87d603156 100644 --- a/cli/migrate/api/metadata.go +++ b/cli/migrate/api/metadata.go @@ -11,6 +11,7 @@ import ( "github.com/ghodss/yaml" "github.com/gin-gonic/gin" "github.com/hasura/graphql-engine/cli/migrate" + "github.com/sirupsen/logrus" ) func MetadataAPI(c *gin.Context) { @@ -20,11 +21,7 @@ func MetadataAPI(c *gin.Context) { return } - sourceURL, err := url.Parse(sourcePtr.(string)) - if err != nil { - c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()}) - return - } + sourceURL := sourcePtr.(*url.URL) // Get hasuradb url databasePtr, ok := c.Get("dbpath") @@ -33,10 +30,17 @@ func MetadataAPI(c *gin.Context) { } // Convert to url.URL - databaseURL := databasePtr.(url.URL) + databaseURL := databasePtr.(*url.URL) + + // Get Logger + loggerPtr, ok := c.Get("logger") + if !ok { + return + } + logger := loggerPtr.(*logrus.Logger) // Create new migrate - t, err := migrate.New(sourcePtr.(string), databaseURL.String(), false) + t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger) if err != nil { if strings.HasPrefix(err.Error(), DataAPIError) { c.JSON(http.StatusInternalServerError, &Response{Code: "data_api_error", Message: err.Error()}) diff --git a/cli/migrate/api/migrate.go b/cli/migrate/api/migrate.go index 3e0195c981fb9..2e06c1328c8fe 100644 --- a/cli/migrate/api/migrate.go +++ b/cli/migrate/api/migrate.go @@ -3,13 +3,13 @@ package api import ( "net/http" "net/url" - "runtime" "strings" "time" "github.com/gin-gonic/gin" "github.com/hasura/graphql-engine/cli/migrate" "github.com/hasura/graphql-engine/cli/migrate/cmd" + "github.com/sirupsen/logrus" ) const ( @@ -42,17 +42,19 @@ func MigrateAPI(c *gin.Context) { return } - // Convert to url.URL - databaseURL := databasePtr.(url.URL) - - sourceURL, err := url.Parse(sourcePtr.(string)) - if err != nil { - c.JSON(http.StatusInternalServerError, &Response{Code: "internal_error", Message: err.Error()}) + // Get Logger + loggerPtr, ok := c.Get("logger") + if !ok { return } + // Convert to url.URL + databaseURL := databasePtr.(*url.URL) + sourceURL := sourcePtr.(*url.URL) + logger := loggerPtr.(*logrus.Logger) + // Create new migrate - t, err := migrate.New(sourcePtr.(string), databaseURL.String(), false) + t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger) if err != nil { if strings.HasPrefix(err.Error(), DataAPIError) { c.JSON(http.StatusInternalServerError, &Response{Code: "data_api_error", Message: err.Error()}) @@ -74,16 +76,10 @@ func MigrateAPI(c *gin.Context) { } startTime := time.Now() - // Conver to Millisecond + // Convert to Millisecond timestamp := startTime.UnixNano() / int64(time.Millisecond) - var dirPtr string - if runtime.GOOS == "windows" { - dirPtr = strings.Trim(sourceURL.Path, "/") - } else { - dirPtr = "/" + strings.Trim(sourceURL.Path, "/") + "/" - } - err = cmd.CreateCmd(dirPtr, timestamp, request.Name, request.Up) + err = cmd.CreateCmd(sourceURL.Path, timestamp, request.Name, request.Up) if err != nil { c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()}) return @@ -92,7 +88,7 @@ func MigrateAPI(c *gin.Context) { // Rescan file system err = t.ReScan() if err != nil { - deleteErr := cmd.DeleteCmd(dirPtr, timestamp) + deleteErr := cmd.DeleteCmd(sourceURL.Path, timestamp) if deleteErr != nil { c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()}) return @@ -102,7 +98,7 @@ func MigrateAPI(c *gin.Context) { } if err = t.Migrate(uint64(timestamp), "up"); err != nil { - deleteErr := cmd.DeleteCmd(dirPtr, timestamp) + deleteErr := cmd.DeleteCmd(sourceURL.Path, timestamp) if deleteErr != nil { c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()}) return diff --git a/cli/migrate/api/settings.go b/cli/migrate/api/settings.go index c38bf7c9a2253..cd0a0a038e740 100644 --- a/cli/migrate/api/settings.go +++ b/cli/migrate/api/settings.go @@ -7,6 +7,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hasura/graphql-engine/cli/migrate" + "github.com/sirupsen/logrus" ) type SettingReqeust struct { @@ -21,6 +22,8 @@ func SettingsAPI(c *gin.Context) { return } + sourceURL := sourcePtr.(*url.URL) + // Get hasuradb url databasePtr, ok := c.Get("dbpath") if !ok { @@ -28,10 +31,17 @@ func SettingsAPI(c *gin.Context) { } // Convert to url.URL - databaseURL := databasePtr.(url.URL) + databaseURL := databasePtr.(*url.URL) + + // Get Logger + loggerPtr, ok := c.Get("logger") + if !ok { + return + } + logger := loggerPtr.(*logrus.Logger) // Create new migrate - t, err := migrate.New(sourcePtr.(string), databaseURL.String(), false) + t, err := migrate.New(sourceURL.String(), databaseURL.String(), false, logger) if err != nil { if strings.HasPrefix(err.Error(), DataAPIError) { c.JSON(500, &Response{Code: "data_api_error", Message: err.Error()}) diff --git a/cli/migrate/cmd/commands.go b/cli/migrate/cmd/commands.go index 3a0ba47abd270..90fcc669d4906 100644 --- a/cli/migrate/cmd/commands.go +++ b/cli/migrate/cmd/commands.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" "github.com/ghodss/yaml" @@ -22,6 +23,9 @@ var ext = []string{sqlFile, yamlFile} func DeleteCmd(dir string, timestamp int64) error { count := 0 + if runtime.GOOS == "windows" { + dir = strings.TrimPrefix(dir, "/") + } fileName := fmt.Sprintf("%v_", timestamp) // scan directory files, err := ioutil.ReadDir(dir) @@ -48,6 +52,9 @@ func DeleteCmd(dir string, timestamp int64) error { } func CreateCmd(dir string, timestamp int64, name string, options ...interface{}) error { + if runtime.GOOS == "windows" { + dir = strings.TrimPrefix(dir, "/") + } fileName := fmt.Sprintf("%v_%v.", timestamp, name) base := filepath.Join(dir, fileName) err := os.MkdirAll(dir, os.ModePerm) diff --git a/cli/migrate/database/driver.go b/cli/migrate/database/driver.go index 341a8e1f970bc..8c43412f3fdd1 100644 --- a/cli/migrate/database/driver.go +++ b/cli/migrate/database/driver.go @@ -43,7 +43,7 @@ type Driver interface { // Open returns a new driver instance configured with parameters // coming from the URL string. Migrate will call this function // only once per instance. - Open(url string, isCMD bool) (Driver, error) + Open(url string, isCMD bool, logger *log.Logger) (Driver, error) // Close closes the underlying database instance managed by the driver. // Migrate will call this function only once per instance. @@ -108,7 +108,7 @@ type Driver interface { } // Open returns a new driver instance. -func Open(url string, isCMD bool) (Driver, error) { +func Open(url string, isCMD bool, logger *log.Logger) (Driver, error) { u, err := nurl.Parse(url) if err != nil { log.Debug(err) @@ -126,7 +126,11 @@ func Open(url string, isCMD bool) (Driver, error) { return nil, fmt.Errorf("database driver: unknown driver hasuradb (forgotten import?)") } - return d.Open(url, isCMD) + if logger == nil { + logger = log.New() + } + + return d.Open(url, isCMD, logger) } func Register(name string, driver Driver) { diff --git a/cli/migrate/database/hasuradb/hasuradb.go b/cli/migrate/database/hasuradb/hasuradb.go index adc4b6ff488b6..aad49d6c56c6b 100644 --- a/cli/migrate/database/hasuradb/hasuradb.go +++ b/cli/migrate/database/hasuradb/hasuradb.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "net/http" nurl "net/url" + "path" "regexp" "strconv" "strings" @@ -52,11 +53,12 @@ type HasuraDB struct { migrations *database.Migrations migrationQuery HasuraInterfaceBulk isLocked bool + logger *log.Logger } -func WithInstance(config *Config) (database.Driver, error) { +func WithInstance(config *Config, logger *log.Logger) (database.Driver, error) { if config == nil { - log.Debug(ErrNilConfig) + logger.Debug(ErrNilConfig) return nil, ErrNilConfig } @@ -64,15 +66,16 @@ func WithInstance(config *Config) (database.Driver, error) { config: config, migrations: database.NewMigrations(), settings: database.Settings, + logger: logger, } if err := hx.ensureVersionTable(); err != nil { - log.Debug(err) + logger.Debug(err) return nil, err } if err := hx.ensureSettingsTable(); err != nil { - log.Debug(err) + logger.Debug(err) return nil, err } @@ -84,12 +87,29 @@ func WithInstance(config *Config) (database.Driver, error) { return hx, nil } -func (h *HasuraDB) Open(url string, isCMD bool) (database.Driver, error) { +func (h *HasuraDB) Open(url string, isCMD bool, logger *log.Logger) (database.Driver, error) { + if logger == nil { + logger = log.New() + } hurl, err := nurl.Parse(url) if err != nil { - log.Debug(err) + logger.Debug(err) return nil, err } + // Use sslMode to set Scheme + values := hurl.Query() + sslMode := values.Get("sslmode") + if sslMode == "enable" { + hurl.Scheme = "https" + } else { + hurl.Scheme = "http" + } + values.Del("sslmode") + hurl.RawQuery = values.Encode() + // Remove UserInfo + hurl.User = nil + // Add v1/query to path + hurl.Path = path.Join(hurl.Path, "v1/query") var user, pass string switch hurl.User { @@ -117,10 +137,10 @@ func (h *HasuraDB) Open(url string, isCMD bool) (database.Driver, error) { Role: user, UserID: pass, isCMD: isCMD, - }) + }, logger) if err != nil { - log.Debug(err) + logger.Debug(err) return nil, err } @@ -374,17 +394,17 @@ func (h *HasuraDB) ensureVersionTable() error { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) @@ -394,7 +414,7 @@ func (h *HasuraDB) ensureVersionTable() error { err = json.Unmarshal(body, &hres) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } @@ -443,16 +463,7 @@ func (h *HasuraDB) ensureVersionTable() error { func (h *HasuraDB) sendQuery(m interface{}) (resp *http.Response, body []byte, err error) { request := gorequest.New() - newURL := h.config.URL - - newURL.Scheme = "http" - newURL.User = nil - - if !strings.Contains(newURL.Path, "v1/query") { - newURL.Path = SingleJoiningSlash(newURL.Path, "v1/query") - } - - request = request.Post(newURL.String()).Send(m) + request = request.Post(h.config.URL.String()).Send(m) if h.config.UserID != "" { request = request.Set(ACCESS_KEY_HEADER, h.config.UserID) diff --git a/cli/migrate/database/hasuradb/hasuradb_test.go b/cli/migrate/database/hasuradb/hasuradb_test.go index 627246b42837f..3e2c3782bc942 100644 --- a/cli/migrate/database/hasuradb/hasuradb_test.go +++ b/cli/migrate/database/hasuradb/hasuradb_test.go @@ -5,7 +5,6 @@ import ( sqldriver "database/sql/driver" "fmt" "io" - "testing" mt "github.com/hasura/graphql-engine/cli/migrate/testing" _ "github.com/lib/pq" @@ -48,7 +47,8 @@ func isReadyRaven(i mt.Instance) bool { return false } -func Test(t *testing.T) { +/* +func testHasuraDB(t *testing.T) { mt.ParallelTest(t, postgresVersions, isReadyPostgres, func(t *testing.T, pi mt.Instance) { for i, v := range ravenVersions { @@ -69,3 +69,4 @@ func Test(t *testing.T) { }) }) } +*/ diff --git a/cli/migrate/database/hasuradb/metadata.go b/cli/migrate/database/hasuradb/metadata.go index 2d2a6b2e04eb0..715074ffc44d8 100644 --- a/cli/migrate/database/hasuradb/metadata.go +++ b/cli/migrate/database/hasuradb/metadata.go @@ -3,8 +3,6 @@ package hasuradb import ( "encoding/json" "net/http" - - log "github.com/sirupsen/logrus" ) func (h *HasuraDB) ExportMetadata() (interface{}, error) { @@ -15,16 +13,16 @@ func (h *HasuraDB) ExportMetadata() (interface{}, error) { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return nil, err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return nil, err } return nil, horror.Error(h.config.isCMD) @@ -33,7 +31,7 @@ func (h *HasuraDB) ExportMetadata() (interface{}, error) { var hres interface{} err = json.Unmarshal(body, &hres) if err != nil { - log.Debug(err) + h.logger.Debug(err) return nil, err } @@ -48,16 +46,16 @@ func (h *HasuraDB) ResetMetadata() error { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) @@ -82,16 +80,16 @@ func (h *HasuraDB) ApplyMetadata(data interface{}) error { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) @@ -107,16 +105,16 @@ func (h *HasuraDB) Query(data []interface{}) error { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) diff --git a/cli/migrate/database/hasuradb/settings.go b/cli/migrate/database/hasuradb/settings.go index 79aa50f71d81c..92d89bc96b9b6 100644 --- a/cli/migrate/database/hasuradb/settings.go +++ b/cli/migrate/database/hasuradb/settings.go @@ -4,8 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - - log "github.com/sirupsen/logrus" ) const ( @@ -23,16 +21,16 @@ func (h *HasuraDB) ensureSettingsTable() error { resp, body, err := h.sendQuery(query) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) @@ -42,7 +40,7 @@ func (h *HasuraDB) ensureSettingsTable() error { err = json.Unmarshal(body, &hres) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } @@ -66,7 +64,7 @@ func (h *HasuraDB) ensureSettingsTable() error { if err != nil { return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) @@ -116,7 +114,7 @@ func (h *HasuraDB) setDefaultSettings() error { if resp.StatusCode != http.StatusOK { err = json.Unmarshal(body, &horror) if err != nil { - log.Debug(err) + h.logger.Debug(err) return err } return horror.Error(h.config.isCMD) @@ -138,7 +136,7 @@ func (h *HasuraDB) GetSetting(name string) (value string, err error) { if err != nil { return value, err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError @@ -187,7 +185,7 @@ func (h *HasuraDB) UpdateSetting(name string, value string) error { if err != nil { return err } - log.Debug("response: ", string(body)) + h.logger.Debug("response: ", string(body)) var horror HasuraError diff --git a/cli/migrate/migrate.go b/cli/migrate/migrate.go index 7581ce22e36d2..2df60674656be 100644 --- a/cli/migrate/migrate.go +++ b/cli/migrate/migrate.go @@ -67,6 +67,9 @@ type Migrate struct { databaseURL string databaseDrv database.Driver + // Logger is the global logger object to print logs. + Logger *log.Logger + // GracefulStop accepts `true` and will stop executing migrations // as soon as possible at a safe break point, so that the database // is not corrupted. @@ -92,7 +95,7 @@ type Migrate struct { // New returns a new Migrate instance from a source URL and a database URL. // The URL scheme is defined by each driver. -func New(sourceUrl string, databaseUrl string, cmd bool) (*Migrate, error) { +func New(sourceUrl string, databaseUrl string, cmd bool, logger *log.Logger) (*Migrate, error) { m := newCommon(cmd) sourceName, err := schemeFromUrl(sourceUrl) @@ -111,14 +114,18 @@ func New(sourceUrl string, databaseUrl string, cmd bool) (*Migrate, error) { m.databaseName = databaseName m.databaseURL = databaseUrl - sourceDrv, err := source.Open(sourceUrl) + if logger == nil { + logger = log.New() + } + + sourceDrv, err := source.Open(sourceUrl, logger) if err != nil { log.Debug(err) return nil, err } m.sourceDrv = sourceDrv - databaseDrv, err := database.Open(databaseUrl, cmd) + databaseDrv, err := database.Open(databaseUrl, cmd, logger) if err != nil { log.Debug(err) return nil, err @@ -141,16 +148,16 @@ func newCommon(cmd bool) *Migrate { } func (m *Migrate) ReScan() error { - sourceDrv, err := source.Open(m.sourceURL) + sourceDrv, err := source.Open(m.sourceURL, m.Logger) if err != nil { - log.Debug(err) + m.Logger.Debug(err) return err } m.sourceDrv = sourceDrv - databaseDrv, err := database.Open(m.databaseURL, m.isCMD) + databaseDrv, err := database.Open(m.databaseURL, m.isCMD, m.Logger) if err != nil { - log.Debug(err) + m.Logger.Debug(err) return err } m.databaseDrv = databaseDrv diff --git a/cli/migrate/source/driver.go b/cli/migrate/source/driver.go index 7f3cbe52111d1..3fd90c9b79f79 100644 --- a/cli/migrate/source/driver.go +++ b/cli/migrate/source/driver.go @@ -5,6 +5,8 @@ import ( "io" nurl "net/url" "sync" + + log "github.com/sirupsen/logrus" ) var driversMu sync.RWMutex @@ -32,7 +34,7 @@ type Driver interface { // Open returns a a new driver instance configured with parameters // coming from the URL string. Migrate will call this function // only once per instance. - Open(url string) (Driver, error) + Open(url string, logger *log.Logger) (Driver, error) // Close closes the underlying source instance managed by the driver. // Migrate will call this function only once per instance. @@ -91,7 +93,7 @@ type Driver interface { } // Open returns a new driver instance. -func Open(url string) (Driver, error) { +func Open(url string, logger *log.Logger) (Driver, error) { u, err := nurl.Parse(url) if err != nil { return nil, err @@ -108,7 +110,11 @@ func Open(url string) (Driver, error) { return nil, fmt.Errorf("source driver: unknown driver %v (forgotten import?)", u.Scheme) } - return d.Open(url) + if logger == nil { + logger = log.New() + } + + return d.Open(url, logger) } // Register globally registers a driver. diff --git a/cli/migrate/source/file/file.go b/cli/migrate/source/file/file.go index 89f96602b7666..954bc17831fb7 100644 --- a/cli/migrate/source/file/file.go +++ b/cli/migrate/source/file/file.go @@ -12,19 +12,24 @@ import ( "strings" "github.com/hasura/graphql-engine/cli/migrate/source" + log "github.com/sirupsen/logrus" ) type File struct { url string path string migrations *source.Migrations + logger *log.Logger } func init() { source.Register("file", &File{}) } -func (f *File) Open(url string) (source.Driver, error) { +func (f *File) Open(url string, logger *log.Logger) (source.Driver, error) { + if logger == nil { + logger = log.New() + } u, err := nurl.Parse(url) if err != nil { return nil, err @@ -62,6 +67,7 @@ func (f *File) Open(url string) (source.Driver, error) { nf := &File{ url: url, + logger: logger, path: p, migrations: source.NewMigrations(), } diff --git a/cli/migrate/source/file/file_test.go b/cli/migrate/source/file/file_test.go index 92d61d855b222..cc3f8bb24c745 100644 --- a/cli/migrate/source/file/file_test.go +++ b/cli/migrate/source/file/file_test.go @@ -9,6 +9,7 @@ import ( "testing" st "github.com/hasura/graphql-engine/cli/migrate/source/testing" + "github.com/sirupsen/logrus/hooks/test" ) func Test(t *testing.T) { @@ -35,8 +36,9 @@ func Test(t *testing.T) { mustWriteFile(t, tmpDir, "8_foobar.up.sql", "7 up") mustWriteFile(t, tmpDir, "8_foobar.down.sql", "7 down") + logger, _ := test.NewNullLogger() f := &File{} - d, err := f.Open("file://" + tmpDir) + d, err := f.Open("file://"+tmpDir, logger) if err != nil { t.Fatal(err) } @@ -58,8 +60,9 @@ func TestOpen(t *testing.T) { t.Fatal("expected tmpDir to be absolute path") } + logger, _ := test.NewNullLogger() f := &File{} - _, err = f.Open("file://" + tmpDir) // absolute path + _, err = f.Open("file://"+tmpDir, logger) // absolute path if err != nil { t.Fatal(err) } @@ -88,10 +91,11 @@ func TestOpenWithRelativePath(t *testing.T) { mustWriteFile(t, filepath.Join(tmpDir, "foo"), "1_foobar.up.sql", "") + logger, _ := test.NewNullLogger() f := &File{} // dir: foo - d, err := f.Open("file://foo") + d, err := f.Open("file://foo", logger) if err != nil { t.Fatal(err) } @@ -101,7 +105,7 @@ func TestOpenWithRelativePath(t *testing.T) { } // dir: ./foo - d, err = f.Open("file://./foo") + d, err = f.Open("file://./foo", logger) if err != nil { t.Fatal(err) } @@ -117,8 +121,9 @@ func TestOpenDefaultsToCurrentDirectory(t *testing.T) { t.Fatal(err) } + logger, _ := test.NewNullLogger() f := &File{} - d, err := f.Open("file://") + d, err := f.Open("file://", logger) if err != nil { t.Fatal(err) } @@ -138,24 +143,27 @@ func TestOpenWithDuplicateVersion(t *testing.T) { mustWriteFile(t, tmpDir, "1_foo.up.sql", "") // 1 up mustWriteFile(t, tmpDir, "1_bar.up.sql", "") // 1 up + logger, _ := test.NewNullLogger() f := &File{} - _, err = f.Open("file://" + tmpDir) + _, err = f.Open("file://"+tmpDir, logger) if err == nil { t.Fatal("expected err") } } func TestOpenWithInvalidFileURL(t *testing.T) { + logger, _ := test.NewNullLogger() f := &File{} - _, err := f.Open(":") + _, err := f.Open(":", logger) if err == nil { t.Fatal("exepected err to be not nil") } } func TestWithEmptyMigration(t *testing.T) { + logger, _ := test.NewNullLogger() s := &File{} - d, err := s.Open("") + d, err := s.Open("", logger) if err != nil { t.Fatal(err) } @@ -171,8 +179,9 @@ func TestWithEmptyMigration(t *testing.T) { } func TestWithInvalidDirectory(t *testing.T) { + logger, _ := test.NewNullLogger() s := &File{} - _, err := s.Open("file://invalidir") + _, err := s.Open("file://invalidir", logger) if err == nil { t.Fatal("exepected err to be not nil") } @@ -185,8 +194,9 @@ func TestClose(t *testing.T) { } defer os.RemoveAll(tmpDir) + logger, _ := test.NewNullLogger() f := &File{} - d, err := f.Open("file://" + tmpDir) + d, err := f.Open("file://"+tmpDir, logger) if err != nil { t.Fatal(err) } @@ -211,21 +221,23 @@ func mustCreateBenchmarkDir(t *testing.B) (dir string) { } func BenchmarkOpen(b *testing.B) { + logger, _ := test.NewNullLogger() dir := mustCreateBenchmarkDir(b) defer os.RemoveAll(dir) b.ResetTimer() for n := 0; n < b.N; n++ { f := &File{} - f.Open("file://" + dir) + f.Open("file://"+dir, logger) } b.StopTimer() } func BenchmarkNext(b *testing.B) { + logger, _ := test.NewNullLogger() dir := mustCreateBenchmarkDir(b) defer os.RemoveAll(dir) f := &File{} - d, _ := f.Open("file://" + dir) + d, _ := f.Open("file://"+dir, logger) b.ResetTimer() v, err := d.First() for n := 0; n < b.N; n++ { diff --git a/cli/migrate/source/stub/stub.go b/cli/migrate/source/stub/stub.go index dfc71f250a457..76b43f147b5f0 100644 --- a/cli/migrate/source/stub/stub.go +++ b/cli/migrate/source/stub/stub.go @@ -8,6 +8,7 @@ import ( "os" "github.com/hasura/graphql-engine/cli/migrate/source" + log "github.com/sirupsen/logrus" ) func init() { @@ -21,13 +22,18 @@ type Stub struct { Instance interface{} Migrations *source.Migrations Config *Config + logger *log.Logger } -func (s *Stub) Open(url string) (source.Driver, error) { +func (s *Stub) Open(url string, logger *log.Logger) (source.Driver, error) { + if logger == nil { + logger = log.New() + } return &Stub{ Url: url, Migrations: source.NewMigrations(), Config: &Config{}, + logger: logger, }, nil } diff --git a/cli/migrate/source/stub/stub_test.go b/cli/migrate/source/stub/stub_test.go index 2430583fe792e..d7b54d0611987 100644 --- a/cli/migrate/source/stub/stub_test.go +++ b/cli/migrate/source/stub/stub_test.go @@ -5,11 +5,13 @@ import ( "github.com/hasura/graphql-engine/cli/migrate/source" st "github.com/hasura/graphql-engine/cli/migrate/source/testing" + "github.com/sirupsen/logrus/hooks/test" ) func Test(t *testing.T) { + logger, _ := test.NewNullLogger() s := &Stub{} - d, err := s.Open("") + d, err := s.Open("", logger) if err != nil { t.Fatal(err) } @@ -32,8 +34,9 @@ func Test(t *testing.T) { } func TestWithEmptyMigration(t *testing.T) { + logger, _ := test.NewNullLogger() s := &Stub{} - d, err := s.Open("") + d, err := s.Open("", logger) if err != nil { t.Fatal(err) } diff --git a/cli/util/migrate.go b/cli/util/migrate.go deleted file mode 100644 index 87ce66b99d99e..0000000000000 --- a/cli/util/migrate.go +++ /dev/null @@ -1,124 +0,0 @@ -package util - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "path/filepath" - "strconv" - - "github.com/ghodss/yaml" - "github.com/hasura/graphql-engine/cli/migrate" - mig "github.com/hasura/graphql-engine/cli/migrate/cmd" - "github.com/pkg/errors" -) - -const ( - INVALID_STEP = "Cannot parse the number of steps. Should be a positive integer" -) - -func GetValidStepFromString(stepString string) (step int64, err error) { - step, err = strconv.ParseInt(stepString, 10, 64) - if err != nil { - return 0, errors.Wrap(err, "not a valid input") - } - return step, nil -} - -func ExecuteMigration(cmd, dir, db string, stepOrVersion int64) error { - var err error - - t, err := migrate.New(dir, db, true) - if err != nil { - return errors.Wrap(err, "cannot create migrate instance") - } - - switch cmd { - case "up": - err = mig.UpCmd(t, stepOrVersion) - case "down": - err = mig.DownCmd(t, stepOrVersion) - case "version": - var direction string - if stepOrVersion >= 0 { - direction = "up" - } else { - direction = "down" - stepOrVersion = -(stepOrVersion) - } - err = mig.GotoCmd(t, uint64(stepOrVersion), direction) - default: - err = fmt.Errorf("Invalid command") - } - - return err -} - -func ExecuteMetadata(cmd, dir, db, metadata string) error { - var err error - - t, err := migrate.New(dir, db, true) - if err != nil { - return errors.Wrap(err, "cannot create migrate instance") - } - - switch cmd { - case "export": - metaData, err := t.ExportMetadata() - if err != nil { - return errors.Wrap(err, "Cannot export metadata") - } - - t, err := json.Marshal(metaData) - if err != nil { - return errors.Wrap(err, "Cannot Marshal metadata") - } - - data, err := yaml.JSONToYAML(t) - if err != nil { - return err - } - - err = ioutil.WriteFile(filepath.Join(metadata, "metadata.yaml"), data, 0644) - if err != nil { - return errors.Wrap(err, "cannot save metadata") - } - case "reset": - err := t.ResetMetadata() - if err != nil { - return errors.Wrap(err, "Cannot reset Metadata") - } - case "apply": - data, err := ioutil.ReadFile(filepath.Join(metadata, "metadata.yaml")) - if err != nil { - return errors.Wrap(err, "cannot read metadata file") - } - - var q interface{} - err = yaml.Unmarshal(data, &q) - if err != nil { - return errors.Wrap(err, "cannot parse metadata file") - } - - err = t.ApplyMetadata(q) - if err != nil { - return errors.Wrap(err, "cannot apply metadata on the database") - } - } - return nil -} - -func ExecuteStatus(dir, db string) (*migrate.Status, error) { - var err error - - t, err := migrate.New(dir, db, true) - if err != nil { - return nil, errors.Wrap(err, "cannot create migrate instance") - } - - status, err := t.GetStatus() - if err != nil { - return nil, err - } - return status, nil -}