From a060b158c8d0c346dbce8158f064f54be60eb40a Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 7 Oct 2015 17:39:18 -0700 Subject: [PATCH] Add quick.CheckVersion() to verify config version quickly before unmarshalling the full struct This is needed during migration where we would need to verify the underlying version number in a quick way. --- pkg/quick/quick.go | 108 +++++++++++++++++++++++++++------------- pkg/quick/quick_test.go | 23 +++++++++ 2 files changed, 97 insertions(+), 34 deletions(-) diff --git a/pkg/quick/quick.go b/pkg/quick/quick.go index 3aa6c6b24..37d3ca2fc 100644 --- a/pkg/quick/quick.go +++ b/pkg/quick/quick.go @@ -82,6 +82,80 @@ func New(data interface{}) (Config, *probe.Error) { return d, nil } +// CheckVersion - loads json and compares the version number provided returns back true or false - any failure +// is returned as error. +func CheckVersion(filename string, version string) (bool, *probe.Error) { + _, err := os.Stat(filename) + if err != nil { + return false, probe.NewError(err) + } + + fileData, err := ioutil.ReadFile(filename) + if err != nil { + return false, probe.NewError(err) + } + + if runtime.GOOS == "windows" { + fileData = []byte(strings.Replace(string(fileData), "\r\n", "\n", -1)) + } + data := struct { + Version string + }{ + Version: "", + } + err = json.Unmarshal(fileData, &data) + if err != nil { + switch err := err.(type) { + case *json.SyntaxError: + return false, probe.NewError(FormatJSONSyntaxError(bytes.NewReader(fileData), err)) + default: + return false, probe.NewError(err) + } + } + config, perr := New(data) + if perr != nil { + return false, perr.Trace() + } + if config.Version() != version { + return false, nil + } + return true, nil +} + +// Load - loads json config from filename for the a given struct data +func Load(filename string, data interface{}) (Config, *probe.Error) { + _, err := os.Stat(filename) + if err != nil { + return nil, probe.NewError(err) + } + + fileData, err := ioutil.ReadFile(filename) + if err != nil { + return nil, probe.NewError(err) + } + + if runtime.GOOS == "windows" { + fileData = []byte(strings.Replace(string(fileData), "\r\n", "\n", -1)) + } + + err = json.Unmarshal(fileData, &data) + if err != nil { + switch err := err.(type) { + case *json.SyntaxError: + return nil, probe.NewError(FormatJSONSyntaxError(bytes.NewReader(fileData), err)) + default: + return nil, probe.NewError(err) + } + } + + config, perr := New(data) + if perr != nil { + return nil, perr.Trace() + } + + return config, nil +} + // Version returns the current config file format version func (d config) Version() string { st := structs.New(d.data) @@ -127,40 +201,6 @@ func (d config) Save(filename string) *probe.Error { return nil } -// Load - loads json config -func Load(filename string, data interface{}) (Config, *probe.Error) { - _, err := os.Stat(filename) - if err != nil { - return nil, probe.NewError(err) - } - - fileData, err := ioutil.ReadFile(filename) - if err != nil { - return nil, probe.NewError(err) - } - - if runtime.GOOS == "windows" { - fileData = []byte(strings.Replace(string(fileData), "\r\n", "\n", -1)) - } - - err = json.Unmarshal(fileData, &data) - if err != nil { - switch err := err.(type) { - case *json.SyntaxError: - return nil, probe.NewError(FormatJSONSyntaxError(bytes.NewReader(fileData), err)) - default: - return nil, probe.NewError(err) - } - } - - config, perr := New(data) - if perr != nil { - return nil, perr.Trace() - } - - return config, nil -} - // Load - loads JSON config from file and merge with currently set values func (d *config) Load(filename string) *probe.Error { d.lock.Lock() diff --git a/pkg/quick/quick_test.go b/pkg/quick/quick_test.go index 4a7c30cba..c61646c33 100644 --- a/pkg/quick/quick_test.go +++ b/pkg/quick/quick_test.go @@ -57,6 +57,29 @@ func (s *MySuite) TestCheckData(c *C) { c.Assert(err, IsNil) } +func (s *MySuite) TestVersion(c *C) { + defer os.RemoveAll("test.json") + type myStruct struct { + Version string + User string + Password string + Folders []string + } + saveMe := myStruct{"1", "guest", "nopassword", []string{"Work", "Documents", "Music"}} + config, err := quick.New(&saveMe) + c.Assert(err, IsNil) + c.Assert(config, Not(IsNil)) + config.Save("test.json") + + valid, err := quick.CheckVersion("test.json", "1") + c.Assert(err, IsNil) + c.Assert(valid, Equals, true) + + valid, err = quick.CheckVersion("test.json", "2") + c.Assert(err, IsNil) + c.Assert(valid, Equals, false) +} + func (s *MySuite) TestSaveLoad(c *C) { defer os.RemoveAll("test.json") type myStruct struct {