github.com/devcamcar/cli@v0.0.0-20181107134215-706a05759d18/commands/migrate.go (about) 1 package commands 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "github.com/fnproject/cli/common" 11 "github.com/fnproject/cli/config" 12 yamltojson "github.com/ghodss/yaml" 13 "github.com/mitchellh/mapstructure" 14 "github.com/urfave/cli" 15 yaml "gopkg.in/yaml.v2" 16 ) 17 18 const ( 19 MigrateSuccessMessage = "Successfully migrated func.yaml and created a back up func.yaml.bak" 20 MigrateFailureMessage = "you have an up to date func.yaml file and do not need to migrate" 21 ) 22 23 type migrateFnCmd struct { 24 newFF *common.FuncFileV20180708 25 } 26 27 func MigrateCommand() cli.Command { 28 m := &migrateFnCmd{newFF: &common.FuncFileV20180708{}} 29 30 return cli.Command{ 31 Name: "migrate", 32 Usage: "\tMigrate a local func.yaml file to the latest version", 33 Category: "DEVELOPMENT COMMANDS", 34 Aliases: []string{"m"}, 35 Description: "This command will detect the version of a func.yaml file and update it to match the latest version supported by the Fn CLI.\n\tAny old or unsupported attributes will be removed, and any new ones may be added.\n\tThe current func.yaml will be renamed to func.yaml.bak and a new func.yaml created.", 36 Action: m.migrate, 37 } 38 } 39 40 func (m *migrateFnCmd) migrate(c *cli.Context) error { 41 var err error 42 oldFF, err := common.ReadInFuncFile() 43 if err != nil { 44 return err 45 } 46 47 version := common.GetFuncYamlVersion(oldFF) 48 if version == common.LatestYamlVersion { 49 return errors.New(MigrateFailureMessage) 50 } 51 52 err = backUpYamlFile(oldFF) 53 if err != nil { 54 return err 55 } 56 57 b, err := m.creatFuncFileBytes(oldFF) 58 if err != nil { 59 return err 60 } 61 62 err = vaidateFuncFileSchema(b) 63 if err != nil { 64 return err 65 } 66 67 err = writeYamlFile(b, "func.yaml") 68 if err != nil { 69 return err 70 } 71 72 fmt.Println(MigrateSuccessMessage) 73 return nil 74 } 75 76 func backUpYamlFile(ff map[string]interface{}) error { 77 b, err := yaml.Marshal(ff) 78 if err != nil { 79 return err 80 } 81 82 return writeYamlFile(b, "func.yaml.bak") 83 } 84 85 func (m *migrateFnCmd) decodeFuncFile(oldFF map[string]interface{}) ([]byte, error) { 86 _ = mapstructure.Decode(oldFF, &m.newFF) 87 return yaml.Marshal(oldFF) 88 } 89 90 func (m *migrateFnCmd) creatFuncFileBytes(oldFF map[string]interface{}) ([]byte, error) { 91 b, err := m.decodeFuncFile(oldFF) 92 if err != nil { 93 return nil, err 94 } 95 96 err = vaidateFuncFileSchema(b) 97 if err != nil { 98 return nil, err 99 } 100 101 m.newFF.Schema_version = 20180708 102 trig := make([]common.Trigger, 1) 103 104 var trigName, trigSource string 105 106 if oldFF["name"] != nil { 107 trigName = oldFF["name"].(string) 108 trigSource = "/" + oldFF["name"].(string) 109 } 110 111 trigType := "http" 112 113 trig[0] = common.Trigger{ 114 trigName, 115 trigType, 116 trigSource, 117 } 118 m.newFF.Triggers = trig 119 120 return yaml.Marshal(m.newFF) 121 } 122 123 func vaidateFuncFileSchema(b []byte) error { 124 jsonB, err := yamltojson.YAMLToJSON(b) 125 if err != nil { 126 return err 127 } 128 129 err = ioutil.WriteFile("temp.json", jsonB, config.ReadWritePerms) 130 if err != nil { 131 return err 132 } 133 defer os.Remove("temp.json") 134 135 err = common.ValidateFileAgainstSchema("temp.json", common.V20180708Schema) 136 if err != nil { 137 return err 138 } 139 140 return nil 141 } 142 143 func writeYamlFile(b []byte, filename string) error { 144 wd := common.GetWd() 145 fpath := filepath.Join(wd, filename) 146 147 return ioutil.WriteFile(fpath, b, config.ReadWritePerms) 148 }