func (s *MySuite) TestDeepDiff(c *C) { 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)) mismatch := myStruct{"1", "Guest", "nopassword", []string{"Work", "documents", "Music"}} newConfig, err := quick.New(&mismatch) c.Assert(err, IsNil) c.Assert(newConfig, Not(IsNil)) fields, err := config.DeepDiff(newConfig) c.Assert(err, IsNil) c.Assert(len(fields), Equals, 2) // Uncomment for debugging // for i, field := range fields { // fmt.Printf("DeepDiff[%d]: %s=%v\n", i, field.Name(), field.Value()) // } }
// removeAlias - remove alias func removeAlias(alias string) { if alias == "" { fatalIf(errDummy().Trace(), "Alias or URL cannot be empty.") } conf := newConfigV2() config, err := quick.New(conf) fatalIf(err.Trace(conf.Version), "Failed to initialize ‘quick’ configuration data structure.") err = config.Load(mustGetMcConfigPath()) fatalIf(err.Trace(), "Unable to load config path") if isAliasReserved(alias) { fatalIf(errDummy().Trace(), fmt.Sprintf("Cannot use a reserved name ‘%s’ as an alias. Following are reserved names: [help, private, readonly, public, authenticated].", alias)) } if !isValidAliasName(alias) { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias name ‘%s’ is invalid, valid examples are: mybucket, Area51, Grand-Nagus", alias)) } // convert interface{} back to its original struct newConf := config.Data().(*configV2) if _, ok := newConf.Aliases[alias]; !ok { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias ‘%s’ does not exist.", alias)) } delete(newConf.Aliases, alias) newConfig, err := quick.New(newConf) fatalIf(err.Trace(conf.Version), "Failed to initialize ‘quick’ configuration data structure.") err = writeConfig(newConfig) fatalIf(err.Trace(alias), "Unable to save alias ‘"+alias+"’.") console.Println(AliasMessage{ op: "remove", Alias: alias, }) }
func (s *MySuite) TestSaveLoad(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)) err = config.Save("test.json") c.Assert(err, IsNil) loadMe := myStruct{Version: "1"} newConfig, err := quick.New(&loadMe) c.Assert(err, IsNil) c.Assert(newConfig, Not(IsNil)) err = newConfig.Load("test.json") c.Assert(err, IsNil) c.Assert(config.Data(), DeepEquals, newConfig.Data()) c.Assert(config.Data(), DeepEquals, &loadMe) mismatch := myStruct{"1.1", "guest", "nopassword", []string{"Work", "Documents", "Music"}} c.Assert(newConfig.Data(), Not(DeepEquals), &mismatch) }
// removeAlias - remove alias func removeAlias(alias string) { if strings.TrimSpace(alias) == "" { fatalIf(errDummy().Trace(), "Alias or URL cannot be empty.") } config, err := newConfig() fatalIf(err.Trace(), "Failed to initialize ‘quick’ configuration data structure.") configPath := mustGetMcConfigPath() err = config.Load(configPath) fatalIf(err.Trace(configPath), "Unable to load config path") if !isValidAliasName(alias) { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias name ‘%s’ is invalid, valid examples are: mybucket, Area51, Grand-Nagus", alias)) } // convert interface{} back to its original struct newConf := config.Data().(*configV5) if _, ok := newConf.Aliases[alias]; !ok { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias ‘%s’ does not exist.", alias)) } delete(newConf.Aliases, alias) newConfig, err := quick.New(newConf) fatalIf(err.Trace(globalMCConfigVersion), "Failed to initialize ‘quick’ configuration data structure.") err = writeConfig(newConfig) fatalIf(err.Trace(alias), "Unable to save alias ‘"+alias+"’.") Prints("%s\n", AliasMessage{ op: "remove", Alias: alias, }) }
// Migrate config version ‘4’ to ‘5’. Rename hostConfigV4.Signature -> hostConfigV5.API. func migrateConfigV4ToV5() { if !isMcConfigExists() { return } mcCfgV4, e := quick.Load(mustGetMcConfigPath(), newConfigV4()) fatalIf(probe.NewError(e), "Unable to load mc config V4.") // update to newer version if mcCfgV4.Version() != "4" { return } cfgV5 := newConfigV5() for k, v := range mcCfgV4.Data().(*configV4).Aliases { cfgV5.Aliases[k] = v } for host, hostCfgV4 := range mcCfgV4.Data().(*configV4).Hosts { cfgV5.Hosts[host] = hostConfigV5{ AccessKeyID: hostCfgV4.AccessKeyID, SecretAccessKey: hostCfgV4.SecretAccessKey, API: "v4", // Rename from .Signature to .API } } mcNewCfgV5, e := quick.New(cfgV5) fatalIf(probe.NewError(e), "Unable to initialize quick config for config version ‘5’.") e = mcNewCfgV5.Save(mustGetMcConfigPath()) fatalIf(probe.NewError(e), "Unable to save config version ‘5’.") console.Infof("Successfully migrated %s from version ‘4’ to version ‘5’.\n", mustGetMcConfigPath()) }
// Migrate from config ‘1.0.1’ to ‘2’. Drop semantic versioning and move to integer versioning. No other changes. func migrateConfigV101ToV2() { if !isMcConfigExists() { return } mcCfgV101, e := quick.Load(mustGetMcConfigPath(), newConfigV101()) fatalIf(probe.NewError(e), "Unable to load config version ‘1.0.1’.") // update to newer version if mcCfgV101.Version() != "1.0.1" { return } cfgV2 := newConfigV2() // Copy aliases. for k, v := range mcCfgV101.Data().(*configV101).Aliases { cfgV2.Aliases[k] = v } // Copy hosts. for k, hostCfgV101 := range mcCfgV101.Data().(*configV101).Hosts { cfgV2.Hosts[k] = hostConfigV2{ AccessKeyID: hostCfgV101.AccessKeyID, SecretAccessKey: hostCfgV101.SecretAccessKey, } } mcCfgV2, e := quick.New(cfgV2) fatalIf(probe.NewError(e), "Unable to initialize quick config for config version ‘2’.") e = mcCfgV2.Save(mustGetMcConfigPath()) fatalIf(probe.NewError(e), "Unable to save config version ‘2’.") console.Infof("Successfully migrated %s from version ‘1.0.1’ to version ‘2’.\n", mustGetMcConfigPath()) }
func loadSessionV6Header(sid string) (*sessionV6Header, *probe.Error) { if !isSessionDirExists() { return nil, errInvalidArgument().Trace() } sessionFile, err := getSessionFile(sid) if err != nil { return nil, err.Trace(sid) } if _, e := os.Stat(sessionFile); e != nil { return nil, probe.NewError(e) } sV6Header := &sessionV6Header{} sV6Header.Version = "6" qs, e := quick.New(sV6Header) if e != nil { return nil, probe.NewError(e).Trace(sid, sV6Header.Version) } e = qs.Load(sessionFile) if e != nil { return nil, probe.NewError(e).Trace(sid, sV6Header.Version) } sV6Header = qs.Data().(*sessionV6Header) return sV6Header, nil }
func removeHost(hostGlob string) { if strings.TrimSpace(hostGlob) == "" { fatalIf(errDummy().Trace(), "Alias or URL cannot be empty.") } if strings.TrimSpace(hostGlob) == "dl.minio.io:9000" { fatalIf(errDummy().Trace(), "‘"+hostGlob+"’ is reserved hostname and cannot be removed.") } config, err := newConfig() fatalIf(err.Trace(globalMCConfigVersion), "Failed to initialize ‘quick’ configuration data structure.") configPath := mustGetMcConfigPath() err = config.Load(configPath) fatalIf(err.Trace(configPath), "Unable to load config path") // convert interface{} back to its original struct newConf := config.Data().(*configV5) if _, ok := newConf.Hosts[hostGlob]; !ok { fatalIf(errDummy().Trace(), fmt.Sprintf("Host glob ‘%s’ does not exist.", hostGlob)) } delete(newConf.Hosts, hostGlob) newConfig, err := quick.New(newConf) fatalIf(err.Trace(globalMCConfigVersion), "Failed to initialize ‘quick’ configuration data structure.") err = writeConfig(newConfig) fatalIf(err.Trace(hostGlob), "Unable to save host glob ‘"+hostGlob+"’.") Prints("%s\n", HostMessage{ op: "remove", Host: hostGlob, }) }
// Load shareDB entries from disk. Any entries held in memory are reset. func (s *shareDBV1) Load(filename string) *probe.Error { s.mutex.Lock() defer s.mutex.Unlock() // Check if the db file exist. if _, e := os.Stat(filename); e != nil { return probe.NewError(e) } // Initialize and load using quick package. qs, e := quick.New(newShareDBV1()) if e != nil { return probe.NewError(e).Trace(filename) } e = qs.Load(filename) if e != nil { return probe.NewError(e).Trace(filename) } // Copy map over. for k, v := range qs.Data().(*shareDBV1).Shares { s.Shares[k] = v } // Filter out expired entries and save changes back to disk. s.deleteAllExpired() s.save(filename) return nil }
// addAlias - add new aliases func addAlias(alias, url string) { if alias == "" || url == "" { fatalIf(errDummy().Trace(), "Alias or URL cannot be empty.") } config, err := newConfig() fatalIf(err.Trace(globalMCConfigVersion), "Failed to initialize ‘quick’ configuration data structure.") err = config.Load(mustGetMcConfigPath()) fatalIf(err.Trace(), "Unable to load config path") url = strings.TrimSuffix(url, "/") if !strings.HasPrefix(url, "http") { fatalIf(errDummy().Trace(), fmt.Sprintf("Invalid alias URL ‘%s’. Valid examples are: http://s3.amazonaws.com, https://yourbucket.example.com.", url)) } if !isValidAliasName(alias) { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias name ‘%s’ is invalid, valid examples are: mybucket, Area51, Grand-Nagus", alias)) } // convert interface{} back to its original struct newConf := config.Data().(*configV5) if oldURL, ok := newConf.Aliases[alias]; ok { fatalIf(errDummy().Trace(), fmt.Sprintf("Alias ‘%s’ already exists for ‘%s’.", alias, oldURL)) } newConf.Aliases[alias] = url newConfig, err := quick.New(newConf) fatalIf(err.Trace(globalMCConfigVersion), "Failed to initialize ‘quick’ configuration data structure.") err = writeConfig(newConfig) fatalIf(err.Trace(alias, url), "Unable to save alias ‘"+alias+"’.") Prints("%s\n", AliasMessage{ op: "add", Alias: alias, URL: url, }) }
// getMcConfig - reads configuration file and returns config func getMcConfig() (*configV2, *probe.Error) { if !isMcConfigExists() { return nil, errInvalidArgument().Trace() } configFile, err := getMcConfigPath() if err != nil { return nil, err.Trace() } // Cached in private global variable. if v := cache.Get(); v != nil { // Use previously cached config. return v.(quick.Config).Data().(*configV2), nil } conf := newConfigV2() qconf, err := quick.New(conf) if err != nil { return nil, err.Trace() } err = qconf.Load(configFile) if err != nil { return nil, err.Trace() } cache.Put(qconf) return qconf.Data().(*configV2), nil }
// Version '3' to '4' migrates config, removes previous fields related // to backend types and server address. This change further simplifies // the config for future additions. func migrateV3ToV4() { cv3, err := loadConfigV3() if err != nil && os.IsNotExist(err) { return } fatalIf(err, "Unable to load config version ‘3’.") if cv3.Version != "3" { return } // Save only the new fields, ignore the rest. srvConfig := &configV4{} srvConfig.Version = "4" srvConfig.Credential = cv3.Credential srvConfig.Region = cv3.Region if srvConfig.Region == "" { // Region needs to be set for AWS Signature Version 4. srvConfig.Region = "us-east-1" } srvConfig.Logger.Console = cv3.Logger.Console srvConfig.Logger.File = cv3.Logger.File srvConfig.Logger.Syslog = cv3.Logger.Syslog qc, err := quick.New(srvConfig) fatalIf(err, "Unable to initialize the quick config.") configFile, err := getConfigFile() fatalIf(err, "Unable to get config file.") err = qc.Save(configFile) fatalIf(err, "Failed to migrate config from ‘"+cv3.Version+"’ to ‘"+srvConfig.Version+"’ failed.") console.Println("Migration from version ‘" + cv3.Version + "’ to ‘" + srvConfig.Version + "’ completed successfully.") }
// loadSession - reads session file if exists and re-initiates internal variables func loadSessionV1(sid string) (*sessionV1, *probe.Error) { if !isSessionDirExists() { return nil, probe.NewError(errors.New("Session folder does not exist.")) } sessionFile, err := getSessionFileV1(sid) if err != nil { return nil, err.Trace(sid) } s := new(sessionV1) s.Version = "1.0.0" // map of command and files copied s.URLs = nil s.Lock = new(sync.Mutex) s.Files = make(map[string]bool) qs, err := quick.New(s) if err != nil { return nil, err.Trace(s.Version) } err = qs.Load(sessionFile) if err != nil { return nil, err.Trace(sessionFile, s.Version) } return qs.Data().(*sessionV1), nil }
// IsModified - returns if in memory session header has changed from // its on disk value. func (s *sessionV8) isModified(sessionFile string) (bool, *probe.Error) { qs, e := quick.New(s.Header) if e != nil { return false, probe.NewError(e).Trace(s.SessionID) } var currentHeader = &sessionV8Header{} currentQS, e := quick.Load(sessionFile, currentHeader) if e != nil { // If session does not exist for the first, return modified to // be true. if os.IsNotExist(e) { return true, nil } // For all other errors return. return false, probe.NewError(e).Trace(s.SessionID) } changedFields, e := qs.DeepDiff(currentQS) if e != nil { return false, probe.NewError(e).Trace(s.SessionID) } // Returns true if there are changed entries. return len(changedFields) > 0, nil }
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)) err = config.Save("test.json") c.Assert(err, IsNil) 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) _, err = quick.CheckVersion("test1.json", "1") c.Assert(err, Not(IsNil)) file, err := os.Create("test.json") c.Assert(err, IsNil) c.Assert(file.Close(), IsNil) _, err = quick.CheckVersion("test.json", "1") c.Assert(err, Not(IsNil)) }
// save - wrapper for quick.Save and saves only if sessionHeader is // modified. func (s *sessionV8) save() *probe.Error { sessionFile, err := getSessionFile(s.SessionID) if err != nil { return err.Trace(s.SessionID) } // Verify if sessionFile is modified. modified, err := s.isModified(sessionFile) if err != nil { return err.Trace(s.SessionID) } // Header is modified, we save it. if modified { qs, e := quick.New(s.Header) if e != nil { return probe.NewError(e).Trace(s.SessionID) } // Save an return. e = qs.Save(sessionFile) if e != nil { return probe.NewError(e).Trace(sessionFile) } } return nil }
// Version '6' to '7' migrates config, removes previous fields related // to backend types and server address. This change further simplifies // the config for future additions. func migrateV6ToV7() error { cv6, err := loadConfigV6() if err != nil { if os.IsNotExist(err) { return nil } return fmt.Errorf("Unable to load config version ‘6’. %v", err) } if cv6.Version != "6" { return nil } // Save only the new fields, ignore the rest. srvConfig := &serverConfigV7{} srvConfig.Version = "7" srvConfig.Credential = cv6.Credential srvConfig.Region = cv6.Region if srvConfig.Region == "" { // Region needs to be set for AWS Signature Version 4. srvConfig.Region = "us-east-1" } srvConfig.Logger.Console = cv6.Logger.Console srvConfig.Logger.File = cv6.Logger.File srvConfig.Logger.Syslog = cv6.Logger.Syslog srvConfig.Notify.AMQP = make(map[string]amqpNotify) srvConfig.Notify.ElasticSearch = make(map[string]elasticSearchNotify) srvConfig.Notify.Redis = make(map[string]redisNotify) if len(cv6.Notify.AMQP) == 0 { srvConfig.Notify.AMQP["1"] = amqpNotify{} } else { srvConfig.Notify.AMQP = cv6.Notify.AMQP } if len(cv6.Notify.ElasticSearch) == 0 { srvConfig.Notify.ElasticSearch["1"] = elasticSearchNotify{} } else { srvConfig.Notify.ElasticSearch = cv6.Notify.ElasticSearch } if len(cv6.Notify.Redis) == 0 { srvConfig.Notify.Redis["1"] = redisNotify{} } else { srvConfig.Notify.Redis = cv6.Notify.Redis } qc, err := quick.New(srvConfig) if err != nil { return fmt.Errorf("Unable to initialize the quick config. %v", err) } configFile, err := getConfigFile() if err != nil { return fmt.Errorf("Unable to get config file. %v", err) } err = qc.Save(configFile) if err != nil { return fmt.Errorf("Failed to migrate config from ‘"+cv6.Version+"’ to ‘"+srvConfig.Version+"’ failed. %v", err) } console.Println("Migration from version ‘" + cv6.Version + "’ to ‘" + srvConfig.Version + "’ completed successfully.") return nil }
// Save this session. func (s *sessionV8) Save() *probe.Error { s.mutex.Lock() defer s.mutex.Unlock() if s.DataFP.dirty { if err := s.DataFP.Sync(); err != nil { return probe.NewError(err) } s.DataFP.dirty = false } qs, e := quick.New(s.Header) if e != nil { return probe.NewError(e).Trace(s.SessionID) } sessionFile, err := getSessionFile(s.SessionID) if err != nil { return err.Trace(s.SessionID) } e = qs.Save(sessionFile) if e != nil { return probe.NewError(e).Trace(sessionFile) } return nil }
// initConfig - initialize server config. config version (called only once). func initConfig() error { if !isConfigFileExists() { // Initialize server config. srvCfg := &serverConfigV7{} srvCfg.Version = globalMinioConfigVersion srvCfg.Region = "us-east-1" srvCfg.Credential = mustGenAccessKeys() // Enable console logger by default on a fresh run. srvCfg.Logger.Console = consoleLogger{ Enable: true, Level: "fatal", } // Make sure to initialize notification configs. srvCfg.Notify.AMQP = make(map[string]amqpNotify) srvCfg.Notify.AMQP["1"] = amqpNotify{} srvCfg.Notify.ElasticSearch = make(map[string]elasticSearchNotify) srvCfg.Notify.ElasticSearch["1"] = elasticSearchNotify{} srvCfg.Notify.Redis = make(map[string]redisNotify) srvCfg.Notify.Redis["1"] = redisNotify{} srvCfg.rwMutex = &sync.RWMutex{} // Create config path. err := createConfigPath() if err != nil { return err } // Save the new config globally. serverConfig = srvCfg // Save config into file. return serverConfig.Save() } configFile, err := getConfigFile() if err != nil { return err } if _, err = os.Stat(configFile); err != nil { return err } srvCfg := &serverConfigV7{} srvCfg.Version = globalMinioConfigVersion srvCfg.rwMutex = &sync.RWMutex{} qc, err := quick.New(srvCfg) if err != nil { return err } if err := qc.Load(configFile); err != nil { return err } // Save the loaded config globally. serverConfig = srvCfg // Set the version properly after the unmarshalled json is loaded. serverConfig.Version = globalMinioConfigVersion return nil }
// newConfig - get new config interface func newConfig() (config quick.Config, err *probe.Error) { conf := newConfigV2() config, err = quick.New(conf) if err != nil { return nil, err.Trace() } return config, nil }
// saveBucketsMetadata - save metadata of all buckets func saveBucketsMetadata(buckets Buckets) *probe.Error { qc, err := quick.New(buckets) if err != nil { return err.Trace() } if err := qc.Save(bucketsMetadataPath); err != nil { return err.Trace() } return nil }
// saveMultipartsSession - save multiparts func saveMultipartsSession(multiparts Multiparts) *probe.Error { qc, err := quick.New(multiparts) if err != nil { return err.Trace() } if err := qc.Save(multipartsMetadataPath); err != nil { return err.Trace() } return nil }
func (s *CmdTestSuite) TestNewConfigV2(c *C) { root, err := ioutil.TempDir(os.TempDir(), "mc-") c.Assert(err, IsNil) defer os.RemoveAll(root) conf, perr := newConfig() c.Assert(perr, IsNil) configFile := filepath.Join(root, "config.json") perr = conf.Save(configFile) c.Assert(perr, IsNil) confNew := newConfigV2() config, perr := quick.New(confNew) c.Assert(perr, IsNil) perr = config.Load(configFile) c.Assert(perr, IsNil) data := config.Data().(*configV2) type aliases struct { name string url string } wantAliases := []aliases{ { "s3", "https://s3.amazonaws.com", }, { "play", "https://play.minio.io:9000", }, { "localhost", "http://localhost:9000", }, } for _, alias := range wantAliases { url, ok := data.Aliases[alias.name] c.Assert(ok, Equals, true) c.Assert(url, Equals, alias.url) } wantHosts := []string{ "localhost:*", "127.0.0.1:*", "play.minio.io:9000", "dl.minio.io:9000", "s3*.amazonaws.com", } for _, host := range wantHosts { _, ok := data.Hosts[host] c.Assert(ok, Equals, true) } }
// Migrate from config version 1.0 to 1.0.1. Populate example entries and save it back. func migrateConfigV1ToV101() { if !isMcConfigExists() { return } mcCfgV1, e := quick.Load(mustGetMcConfigPath(), newConfigV1()) fatalIf(probe.NewError(e), "Unable to load config version ‘1’.") // If loaded config version does not match 1.0.0, we do nothing. if mcCfgV1.Version() != "1.0.0" { return } // 1.0.1 is compatible to 1.0.0. We are just adding new entries. cfgV101 := newConfigV101() // Copy aliases. for k, v := range mcCfgV1.Data().(*configV1).Aliases { cfgV101.Aliases[k] = v } // Copy hosts. for k, hostCfgV1 := range mcCfgV1.Data().(*configV1).Hosts { cfgV101.Hosts[k] = hostConfigV101{ AccessKeyID: hostCfgV1.AccessKeyID, SecretAccessKey: hostCfgV1.SecretAccessKey, } } // Example localhost entry. if _, ok := cfgV101.Hosts["localhost:*"]; !ok { cfgV101.Hosts["localhost:*"] = hostConfigV101{} } // Example loopback IP entry. if _, ok := cfgV101.Hosts["127.0.0.1:*"]; !ok { cfgV101.Hosts["127.0.0.1:*"] = hostConfigV101{} } // Example AWS entry. // Look for glob string (not glob match). We used to support glob based key matching earlier. if _, ok := cfgV101.Hosts["*.s3*.amazonaws.com"]; !ok { cfgV101.Hosts["*.s3*.amazonaws.com"] = hostConfigV101{ AccessKeyID: "YOUR-ACCESS-KEY-ID-HERE", SecretAccessKey: "YOUR-SECRET-ACCESS-KEY-HERE", } } // Save the new config back to the disk. mcCfgV101, e := quick.New(cfgV101) fatalIf(probe.NewError(e), "Unable to initialize quick config for config version ‘1.0.1’.") e = mcCfgV101.Save(mustGetMcConfigPath()) fatalIf(probe.NewError(e), "Unable to save config version ‘1.0.1’.") console.Infof("Successfully migrated %s from version ‘1.0.0’ to version ‘1.0.1’.\n", mustGetMcConfigPath()) }
func saveSharedURLsV2(s *sharedURLsV2) *probe.Error { qs, err := quick.New(s) if err != nil { return err.Trace() } sharedURLsDataFile, err := getSharedURLsDataFile() if err != nil { return err.Trace() } return qs.Save(sharedURLsDataFile).Trace(sharedURLsDataFile) }
// Persist share uploads to disk. func (s shareDBV1) save(filename string) *probe.Error { // Initialize a new quick file. qs, e := quick.New(s) if e != nil { return probe.NewError(e).Trace(filename) } if e := qs.Save(filename); e != nil { return probe.NewError(e).Trace(filename) } return nil }
// initConfig - initialize server config. config version (called only once). func initConfig() error { if !isConfigFileExists() { srvCfg := &serverConfigV4{} srvCfg.Version = globalMinioConfigVersion srvCfg.Region = "us-east-1" srvCfg.Credential = mustGenAccessKeys() // Enable console logger by default on a fresh run. srvCfg.Logger.Console = consoleLogger{ Enable: true, Level: "fatal", } srvCfg.rwMutex = &sync.RWMutex{} // Create config path. err := createConfigPath() if err != nil { return err } // Create certs path. err = createCertsPath() if err != nil { return err } // Save the new config globally. serverConfig = srvCfg // Save config into file. return serverConfig.Save() } configFile, err := getConfigFile() if err != nil { return err } if _, err = os.Stat(configFile); err != nil { return err } srvCfg := &serverConfigV4{} srvCfg.Version = globalMinioConfigVersion srvCfg.rwMutex = &sync.RWMutex{} qc, err := quick.New(srvCfg) if err != nil { return err } if err := qc.Load(configFile); err != nil { return err } // Save the loaded config globally. serverConfig = srvCfg // Set the version properly after the unmarshalled json is loaded. serverConfig.Version = globalMinioConfigVersion return nil }
// Version '2' to '3' config migration adds new fields and re-orders // previous fields. Simplifies config for future additions. func migrateV2ToV3() { cv2, err := loadConfigV2() if err != nil && os.IsNotExist(err) { return } fatalIf(err, "Unable to load config version ‘2’.") if cv2.Version != "2" { return } srvConfig := &configV3{} srvConfig.Version = "3" srvConfig.Addr = ":9000" srvConfig.Credential = credential{ AccessKeyID: cv2.Credentials.AccessKeyID, SecretAccessKey: cv2.Credentials.SecretAccessKey, } srvConfig.Region = cv2.Credentials.Region if srvConfig.Region == "" { // Region needs to be set for AWS Signature V4. srvConfig.Region = "us-east-1" } srvConfig.Logger.Console = consoleLogger{ Enable: true, Level: "fatal", } flogger := fileLogger{} flogger.Level = "error" if cv2.FileLogger.Filename != "" { flogger.Enable = true flogger.Filename = cv2.FileLogger.Filename } srvConfig.Logger.File = flogger slogger := syslogLogger{} slogger.Level = "debug" if cv2.SyslogLogger.Addr != "" { slogger.Enable = true slogger.Addr = cv2.SyslogLogger.Addr } srvConfig.Logger.Syslog = slogger qc, err := quick.New(srvConfig) fatalIf(err, "Unable to initialize config.") configFile, err := getConfigFile() fatalIf(err, "Unable to get config file.") // Migrate the config. err = qc.Save(configFile) fatalIf(err, "Failed to migrate config from ‘"+cv2.Version+"’ to ‘"+srvConfig.Version+"’ failed.") console.Println("Migration from version ‘" + cv2.Version + "’ to ‘" + srvConfig.Version + "’ completed successfully.") }
// If the host key does not have http(s), fix it. func fixConfigV6ForHosts() { if !isMcConfigExists() { return } brokenMcCfgV6, e := quick.Load(mustGetMcConfigPath(), newConfigV6()) fatalIf(probe.NewError(e), "Unable to load config.") if brokenMcCfgV6.Version() != "6" { return } newCfgV6 := newConfigV6() isMutated := false // Copy aliases. for k, v := range brokenMcCfgV6.Data().(*configV6).Aliases { newCfgV6.Aliases[k] = v } url := &clientURL{} // Copy hosts. for host, hostCfgV6 := range brokenMcCfgV6.Data().(*configV6).Hosts { // Already fixed - Copy and move on. if strings.HasPrefix(host, "https") || strings.HasPrefix(host, "http") { newCfgV6.Hosts[host] = hostCfgV6 continue } // If host entry does not contain "http(s)", introduce a new entry and delete the old one. if host == "s3.amazonaws.com" || host == "storage.googleapis.com" || host == "localhost:9000" || host == "127.0.0.1:9000" || host == "play.minio.io:9000" || host == "dl.minio.io:9000" { console.Infoln("Found broken host entries, replacing " + host + " with https://" + host + ".") url.Host = host url.Scheme = "https" url.SchemeSeparator = "://" newCfgV6.Hosts[url.String()] = hostCfgV6 isMutated = true continue } } if isMutated { // Save the new config back to the disk. mcCfgV6, e := quick.New(newCfgV6) fatalIf(probe.NewError(e), "Unable to initialize quick config for config version ‘v6’.") e = mcCfgV6.Save(mustGetMcConfigPath()) fatalIf(probe.NewError(e), "Unable to save config version ‘v6’.") } }
func (s *MySuite) TestLoadFile(c *C) { type myStruct struct { Version string User string Password string Folders []string } saveMe := myStruct{} _, err := quick.Load("test.json", &saveMe) c.Assert(err, Not(IsNil)) file, err := os.Create("test.json") c.Assert(err, IsNil) c.Assert(file.Close(), IsNil) _, err = quick.Load("test.json", &saveMe) c.Assert(err, Not(IsNil)) config, err := quick.New(&saveMe) c.Assert(err, IsNil) err = config.Load("test-non-exist.json") c.Assert(err, Not(IsNil)) err = config.Load("test.json") c.Assert(err, Not(IsNil)) saveMe = myStruct{"1", "guest", "nopassword", []string{"Work", "Documents", "Music"}} config, err = quick.New(&saveMe) c.Assert(err, IsNil) c.Assert(config, Not(IsNil)) err = config.Save("test.json") c.Assert(err, IsNil) saveMe1 := myStruct{} _, err = quick.Load("test.json", &saveMe1) c.Assert(err, IsNil) c.Assert(saveMe1, DeepEquals, saveMe) saveMe2 := myStruct{} err = json.Unmarshal([]byte(config.String()), &saveMe2) c.Assert(err, IsNil) c.Assert(saveMe2, DeepEquals, saveMe1) }