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" ) func NewMigrateCmd(ec *cli.ExecutionContext) *cobra.Command { migrateCmd := &cobra.Command{ Use: "migrate", Short: "Manage migrations on the database", SilenceUsage: true, } migrateCmd.AddCommand( newMigrateApplyCmd(ec), newMigrateStatusCmd(ec), newMigrateCreateCmd(ec), ) 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", 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") } if accessKey != "" { q.Add("headers", "X-Hasura-Access-Key:"+accessKey) } 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 }