graphql-engine/cli/migrate/cmd/commands.go

260 lines
4.9 KiB
Go

package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"github.com/ghodss/yaml"
"github.com/hasura/graphql-engine/cli/migrate"
"github.com/pkg/errors"
)
/*
const (
sqlFile = ".sql"
yamlFile = ".yaml"
)
var ext = []string{sqlFile, yamlFile}
*/
type CreateOptions struct {
Version string
Directory string
Name string
MetaUp []byte
MetaDown []byte
SQLUp []byte
SQLDown []byte
}
func New(version int64, name, directory string) *CreateOptions {
v := strconv.FormatInt(version, 10)
if runtime.GOOS == "windows" {
directory = strings.TrimPrefix(directory, "/")
}
return &CreateOptions{
Version: v,
Directory: directory,
Name: name,
}
}
func (c *CreateOptions) SetMetaUp(data interface{}) error {
t, err := json.Marshal(data)
if err != nil {
return err
}
yamlData, err := yaml.JSONToYAML(t)
if err != nil {
return err
}
c.MetaUp = yamlData
return nil
}
func (c *CreateOptions) SetMetaUpFromFile(filePath string) error {
data, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
var metadata []interface{}
var q interface{}
err = yaml.Unmarshal(data, &q)
if err != nil {
return err
}
metadata = append(
metadata,
map[string]interface{}{
"type": "replace_metadata",
"args": q,
},
)
return c.SetMetaUp(metadata)
}
func (c *CreateOptions) SetMetaDown(data interface{}) error {
t, err := json.Marshal(data)
if err != nil {
return err
}
yamlData, err := yaml.JSONToYAML(t)
if err != nil {
return err
}
c.MetaDown = yamlData
return nil
}
func (c *CreateOptions) SetSQLUp(data string) error {
c.SQLUp = []byte(data)
return nil
}
func (c *CreateOptions) SetSQLUpFromFile(filePath string) error {
data, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
c.SQLUp = data
return nil
}
func (c *CreateOptions) SetSQLDown(data string) error {
c.SQLDown = []byte(data)
return nil
}
func (c *CreateOptions) Create() error {
path := filepath.Join(c.Directory, fmt.Sprintf("%s_%s", c.Version, c.Name))
err := os.MkdirAll(path, os.ModePerm)
if err != nil {
return err
}
// Check if data has been set in one of the files
if c.MetaUp == nil && c.MetaDown == nil && c.SQLUp == nil && c.SQLDown == nil {
return errors.New("none of the files has been set with data")
}
if c.MetaUp != nil {
// Create MetaUp
err = createFile(filepath.Join(path, "up.yaml"), c.MetaUp)
if err != nil {
return err
}
}
if c.MetaDown != nil {
// Create MetaDown
err = createFile(filepath.Join(path, "down.yaml"), c.MetaDown)
if err != nil {
return err
}
}
if c.SQLUp != nil {
// Create SQLUp
err = createFile(filepath.Join(path, "up.sql"), c.SQLUp)
if err != nil {
return err
}
}
if c.SQLDown != nil {
// Create SQLDown
err = createFile(filepath.Join(path, "down.sql"), c.SQLDown)
if err != nil {
return err
}
}
return nil
}
func (c *CreateOptions) Delete() error {
files, err := ioutil.ReadDir(c.Directory)
if err != nil {
return err
}
for _, fi := range files {
if strings.HasPrefix(fi.Name(), fmt.Sprintf("%s_", c.Version)) {
if fi.IsDir() {
path := filepath.Join(c.Directory, fi.Name())
return deleteFile(path)
}
path := filepath.Join(c.Directory, fi.Name())
err := deleteFile(path)
if err != nil {
return err
}
}
}
return nil
}
func createFile(fname string, data []byte) error {
file, err := os.Create(fname)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return err
}
return nil
}
func deleteFile(fname string) error {
return os.RemoveAll(fname)
}
func GotoCmd(m *migrate.Migrate, v uint64, direction string) error {
return m.Migrate(v, direction)
}
func UpCmd(m *migrate.Migrate, limit int64) error {
if limit >= 0 {
return m.Steps(limit)
} else {
return m.Up()
}
}
func DownCmd(m *migrate.Migrate, limit int64) error {
if limit >= 0 {
return m.Steps(-limit)
} else {
return m.Down()
}
}
func SquashCmd(m *migrate.Migrate, from uint64, version int64, name, directory string) (versions []int64, err error) {
versions, upMeta, upSql, downMeta, downSql, err := m.Squash(from)
if err != nil {
return
}
createOptions := New(version, name, directory)
if len(upMeta) != 0 {
byteUp, err := yaml.Marshal(upMeta)
if err != nil {
return versions, errors.Wrap(err, "cannot unmarshall up query")
}
createOptions.MetaUp = byteUp
}
if len(downMeta) != 0 {
byteDown, err := yaml.Marshal(downMeta)
if err != nil {
return versions, errors.Wrap(err, "cannot unmarshall down query")
}
createOptions.MetaDown = byteDown
}
createOptions.SQLUp = upSql
createOptions.SQLDown = downSql
err = createOptions.Create()
if err != nil {
return versions, errors.Wrap(err, "cannot create migration")
}
return
}
func GotoVersionCmd(m *migrate.Migrate, gotoVersion int64) error {
return m.GotoVersion(gotoVersion)
}