diff --git a/cmd/config-migrate.go b/cmd/config-migrate.go index 8fa6a57d8..95c4cd12e 100644 --- a/cmd/config-migrate.go +++ b/cmd/config-migrate.go @@ -58,6 +58,10 @@ func migrateConfig() error { if err := migrateV8ToV9(); err != nil { return err } + // Migrate version '9' to '10'. + if err := migrateV9ToV10(); err != nil { + return err + } return nil } @@ -124,7 +128,7 @@ func migrateV2ToV3() error { } srvConfig.Logger.File = flogger - slogger := syslogLogger{} + slogger := syslogLoggerV3{} slogger.Level = "debug" if cv2.SyslogLogger.Addr != "" { slogger.Enable = true @@ -543,3 +547,88 @@ func migrateV8ToV9() error { ) return nil } + +// Version '9' to '10' migration. Remove syslog config +// but it's otherwise the same as V9. +func migrateV9ToV10() error { + cv9, err := loadConfigV9() + if err != nil { + if os.IsNotExist(err) { + return nil + } + return fmt.Errorf("Unable to load config version ‘9’. %v", err) + } + if cv9.Version != "9" { + return nil + } + + // Copy over fields from V9 into V10 config struct + srvConfig := &serverConfigV10{} + srvConfig.Version = "10" + srvConfig.Credential = cv9.Credential + srvConfig.Region = cv9.Region + if srvConfig.Region == "" { + // Region needs to be set for AWS Signature Version 4. + srvConfig.Region = "us-east-1" + } + srvConfig.Logger.Console = cv9.Logger.Console + srvConfig.Logger.File = cv9.Logger.File + + // check and set notifiers config + if len(cv9.Notify.AMQP) == 0 { + srvConfig.Notify.AMQP = make(map[string]amqpNotify) + srvConfig.Notify.AMQP["1"] = amqpNotify{} + } else { + srvConfig.Notify.AMQP = cv9.Notify.AMQP + } + if len(cv9.Notify.NATS) == 0 { + srvConfig.Notify.NATS = make(map[string]natsNotify) + srvConfig.Notify.NATS["1"] = natsNotify{} + } else { + srvConfig.Notify.NATS = cv9.Notify.NATS + } + if len(cv9.Notify.ElasticSearch) == 0 { + srvConfig.Notify.ElasticSearch = make(map[string]elasticSearchNotify) + srvConfig.Notify.ElasticSearch["1"] = elasticSearchNotify{} + } else { + srvConfig.Notify.ElasticSearch = cv9.Notify.ElasticSearch + } + if len(cv9.Notify.Redis) == 0 { + srvConfig.Notify.Redis = make(map[string]redisNotify) + srvConfig.Notify.Redis["1"] = redisNotify{} + } else { + srvConfig.Notify.Redis = cv9.Notify.Redis + } + if len(cv9.Notify.PostgreSQL) == 0 { + srvConfig.Notify.PostgreSQL = make(map[string]postgreSQLNotify) + srvConfig.Notify.PostgreSQL["1"] = postgreSQLNotify{} + } else { + srvConfig.Notify.PostgreSQL = cv9.Notify.PostgreSQL + } + + 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 ‘"+ + cv9.Version+"’ to ‘"+srvConfig.Version+ + "’ failed. %v", err, + ) + } + + console.Println( + "Migration from version ‘" + + cv9.Version + "’ to ‘" + srvConfig.Version + + "’ completed successfully.", + ) + return nil +} diff --git a/cmd/config-migrate_test.go b/cmd/config-migrate_test.go index db980c119..1955f0720 100644 --- a/cmd/config-migrate_test.go +++ b/cmd/config-migrate_test.go @@ -19,12 +19,9 @@ package cmd import ( "io/ioutil" "os" - "strconv" "testing" ) -const lastConfigVersion = 9 - // Test if config v1 is purged func TestServerConfigMigrateV1(t *testing.T) { rootPath, err := newTestConfig("us-east-1") @@ -97,10 +94,13 @@ func TestServerConfigMigrateInexistentConfig(t *testing.T) { if err := migrateV8ToV9(); err != nil { t.Fatal("migrate v8 to v9 should succeed when no config file is found") } + if err := migrateV9ToV10(); err != nil { + t.Fatal("migrate v9 to v10 should succeed when no config file is found") + } } -// Test if a config migration from v2 to v9 is successfully done -func TestServerConfigMigrateV2toV9(t *testing.T) { +// Test if a config migration from v2 to v10 is successfully done +func TestServerConfigMigrateV2toV10(t *testing.T) { rootPath, err := newTestConfig("us-east-1") if err != nil { t.Fatalf("Init Test config failed") @@ -139,7 +139,7 @@ func TestServerConfigMigrateV2toV9(t *testing.T) { } // Check the version number in the upgraded config file - expectedVersion := strconv.Itoa(lastConfigVersion) + expectedVersion := globalMinioConfigVersion if serverConfig.Version != expectedVersion { t.Fatalf("Expect version "+expectedVersion+", found: %v", serverConfig.Version) } @@ -197,4 +197,7 @@ func TestServerConfigMigrateFaultyConfig(t *testing.T) { if err := migrateV8ToV9(); err == nil { t.Fatal("migrateConfigV8ToV9() should fail with a corrupted json") } + if err := migrateV9ToV10(); err == nil { + t.Fatal("migrateConfigV9ToV10() should fail with a corrupted json") + } } diff --git a/cmd/config-old.go b/cmd/config-old.go index 8361d22aa..53ca77229 100644 --- a/cmd/config-old.go +++ b/cmd/config-old.go @@ -89,6 +89,13 @@ type backendV3 struct { Disks []string `json:"disks,omitempty"` } +// syslogLogger v3 +type syslogLoggerV3 struct { + Enable bool `json:"enable"` + Addr string `json:"address"` + Level string `json:"level"` +} + // loggerV3 type. type loggerV3 struct { Console struct { @@ -276,6 +283,12 @@ func loadConfigV5() (*configV5, error) { return c, nil } +type loggerV6 struct { + Console consoleLogger `json:"console"` + File fileLogger `json:"file"` + Syslog syslogLoggerV3 `json:"syslog"` +} + // configV6 server configuration version '6'. type configV6 struct { Version string `json:"version"` @@ -285,7 +298,7 @@ type configV6 struct { Region string `json:"region"` // Additional error logging configuration. - Logger logger `json:"logger"` + Logger loggerV6 `json:"logger"` // Notification queue configuration. Notify notifier `json:"notify"` @@ -321,7 +334,7 @@ type serverConfigV7 struct { Region string `json:"region"` // Additional error logging configuration. - Logger logger `json:"logger"` + Logger loggerV6 `json:"logger"` // Notification queue configuration. Notify notifier `json:"notify"` @@ -361,7 +374,7 @@ type serverConfigV8 struct { Region string `json:"region"` // Additional error logging configuration. - Logger logger `json:"logger"` + Logger loggerV6 `json:"logger"` // Notification queue configuration. Notify notifier `json:"notify"` @@ -390,3 +403,46 @@ func loadConfigV8() (*serverConfigV8, error) { } return c, nil } + +// serverConfigV9 server configuration version '9'. Adds PostgreSQL +// notifier configuration. +type serverConfigV9 struct { + Version string `json:"version"` + + // S3 API configuration. + Credential credential `json:"credential"` + Region string `json:"region"` + + // Additional error logging configuration. + Logger loggerV6 `json:"logger"` + + // Notification queue configuration. + Notify notifier `json:"notify"` + + // Read Write mutex. + rwMutex *sync.RWMutex +} + +func loadConfigV9() (*serverConfigV9, error) { + configFile, err := getConfigFile() + if err != nil { + return nil, err + } + if _, err = os.Stat(configFile); err != nil { + return nil, err + } + srvCfg := &serverConfigV9{} + srvCfg.Version = "9" + srvCfg.rwMutex = &sync.RWMutex{} + qc, err := quick.New(srvCfg) + if err != nil { + return nil, err + } + if err := qc.Load(configFile); err != nil { + return nil, err + } + // Set the version properly after the unmarshalled json is loaded. + srvCfg.Version = "9" + + return srvCfg, nil +} diff --git a/cmd/config-v9.go b/cmd/config-v10.go similarity index 71% rename from cmd/config-v9.go rename to cmd/config-v10.go index f462641c9..ea43de0cb 100644 --- a/cmd/config-v9.go +++ b/cmd/config-v10.go @@ -23,9 +23,9 @@ import ( "github.com/minio/minio/pkg/quick" ) -// serverConfigV9 server configuration version '9'. Adds PostgreSQL -// notifier configuration. -type serverConfigV9 struct { +// serverConfigV10 server configuration version '10' which is like version '9' +// except it drops support of syslog config +type serverConfigV10 struct { Version string `json:"version"` // S3 API configuration. @@ -46,7 +46,7 @@ type serverConfigV9 struct { func initConfig() (bool, error) { if !isConfigFileExists() { // Initialize server config. - srvCfg := &serverConfigV9{} + srvCfg := &serverConfigV10{} srvCfg.Version = globalMinioConfigVersion srvCfg.Region = "us-east-1" srvCfg.Credential = mustGenAccessKeys() @@ -89,7 +89,7 @@ func initConfig() (bool, error) { if _, err = os.Stat(configFile); err != nil { return false, err } - srvCfg := &serverConfigV9{} + srvCfg := &serverConfigV10{} srvCfg.Version = globalMinioConfigVersion srvCfg.rwMutex = &sync.RWMutex{} qc, err := quick.New(srvCfg) @@ -108,10 +108,10 @@ func initConfig() (bool, error) { } // serverConfig server config. -var serverConfig *serverConfigV9 +var serverConfig *serverConfigV10 // GetVersion get current config version. -func (s serverConfigV9) GetVersion() string { +func (s serverConfigV10) GetVersion() string { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Version @@ -119,173 +119,159 @@ func (s serverConfigV9) GetVersion() string { /// Logger related. -func (s *serverConfigV9) SetAMQPNotifyByID(accountID string, amqpn amqpNotify) { +func (s *serverConfigV10) SetAMQPNotifyByID(accountID string, amqpn amqpNotify) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Notify.AMQP[accountID] = amqpn } -func (s serverConfigV9) GetAMQP() map[string]amqpNotify { +func (s serverConfigV10) GetAMQP() map[string]amqpNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.AMQP } // GetAMQPNotify get current AMQP logger. -func (s serverConfigV9) GetAMQPNotifyByID(accountID string) amqpNotify { +func (s serverConfigV10) GetAMQPNotifyByID(accountID string) amqpNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.AMQP[accountID] } // -func (s *serverConfigV9) SetNATSNotifyByID(accountID string, natsn natsNotify) { +func (s *serverConfigV10) SetNATSNotifyByID(accountID string, natsn natsNotify) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Notify.NATS[accountID] = natsn } -func (s serverConfigV9) GetNATS() map[string]natsNotify { +func (s serverConfigV10) GetNATS() map[string]natsNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.NATS } // GetNATSNotify get current NATS logger. -func (s serverConfigV9) GetNATSNotifyByID(accountID string) natsNotify { +func (s serverConfigV10) GetNATSNotifyByID(accountID string) natsNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.NATS[accountID] } -func (s *serverConfigV9) SetElasticSearchNotifyByID(accountID string, esNotify elasticSearchNotify) { +func (s *serverConfigV10) SetElasticSearchNotifyByID(accountID string, esNotify elasticSearchNotify) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Notify.ElasticSearch[accountID] = esNotify } -func (s serverConfigV9) GetElasticSearch() map[string]elasticSearchNotify { +func (s serverConfigV10) GetElasticSearch() map[string]elasticSearchNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.ElasticSearch } // GetElasticSearchNotify get current ElasicSearch logger. -func (s serverConfigV9) GetElasticSearchNotifyByID(accountID string) elasticSearchNotify { +func (s serverConfigV10) GetElasticSearchNotifyByID(accountID string) elasticSearchNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.ElasticSearch[accountID] } -func (s *serverConfigV9) SetRedisNotifyByID(accountID string, rNotify redisNotify) { +func (s *serverConfigV10) SetRedisNotifyByID(accountID string, rNotify redisNotify) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Notify.Redis[accountID] = rNotify } -func (s serverConfigV9) GetRedis() map[string]redisNotify { +func (s serverConfigV10) GetRedis() map[string]redisNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.Redis } // GetRedisNotify get current Redis logger. -func (s serverConfigV9) GetRedisNotifyByID(accountID string) redisNotify { +func (s serverConfigV10) GetRedisNotifyByID(accountID string) redisNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.Redis[accountID] } -func (s *serverConfigV9) SetPostgreSQLNotifyByID(accountID string, pgn postgreSQLNotify) { +func (s *serverConfigV10) SetPostgreSQLNotifyByID(accountID string, pgn postgreSQLNotify) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Notify.PostgreSQL[accountID] = pgn } -func (s serverConfigV9) GetPostgreSQL() map[string]postgreSQLNotify { +func (s serverConfigV10) GetPostgreSQL() map[string]postgreSQLNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.PostgreSQL } -func (s serverConfigV9) GetPostgreSQLNotifyByID(accountID string) postgreSQLNotify { +func (s serverConfigV10) GetPostgreSQLNotifyByID(accountID string) postgreSQLNotify { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Notify.PostgreSQL[accountID] } // SetFileLogger set new file logger. -func (s *serverConfigV9) SetFileLogger(flogger fileLogger) { +func (s *serverConfigV10) SetFileLogger(flogger fileLogger) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Logger.File = flogger } // GetFileLogger get current file logger. -func (s serverConfigV9) GetFileLogger() fileLogger { +func (s serverConfigV10) GetFileLogger() fileLogger { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Logger.File } // SetConsoleLogger set new console logger. -func (s *serverConfigV9) SetConsoleLogger(clogger consoleLogger) { +func (s *serverConfigV10) SetConsoleLogger(clogger consoleLogger) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Logger.Console = clogger } // GetConsoleLogger get current console logger. -func (s serverConfigV9) GetConsoleLogger() consoleLogger { +func (s serverConfigV10) GetConsoleLogger() consoleLogger { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Logger.Console } -// SetSyslogLogger set new syslog logger. -func (s *serverConfigV9) SetSyslogLogger(slogger syslogLogger) { - s.rwMutex.Lock() - defer s.rwMutex.Unlock() - s.Logger.Syslog = slogger -} - -// GetSyslogLogger get current syslog logger. -func (s *serverConfigV9) GetSyslogLogger() syslogLogger { - s.rwMutex.RLock() - defer s.rwMutex.RUnlock() - return s.Logger.Syslog -} - // SetRegion set new region. -func (s *serverConfigV9) SetRegion(region string) { +func (s *serverConfigV10) SetRegion(region string) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Region = region } // GetRegion get current region. -func (s serverConfigV9) GetRegion() string { +func (s serverConfigV10) GetRegion() string { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Region } // SetCredentials set new credentials. -func (s *serverConfigV9) SetCredential(creds credential) { +func (s *serverConfigV10) SetCredential(creds credential) { s.rwMutex.Lock() defer s.rwMutex.Unlock() s.Credential = creds } // GetCredentials get current credentials. -func (s serverConfigV9) GetCredential() credential { +func (s serverConfigV10) GetCredential() credential { s.rwMutex.RLock() defer s.rwMutex.RUnlock() return s.Credential } // Save config. -func (s serverConfigV9) Save() error { +func (s serverConfigV10) Save() error { s.rwMutex.RLock() defer s.rwMutex.RUnlock() diff --git a/cmd/config-v9_test.go b/cmd/config-v10_test.go similarity index 91% rename from cmd/config-v9_test.go rename to cmd/config-v10_test.go index e58c1c15f..1f3d31623 100644 --- a/cmd/config-v9_test.go +++ b/cmd/config-v10_test.go @@ -78,15 +78,6 @@ func TestServerConfig(t *testing.T) { t.Errorf("Expecting file logger config %#v found %#v", fileLogger{Enable: true}, consoleCfg) } - // Set new syslog logger. - serverConfig.SetSyslogLogger(syslogLogger{ - Enable: true, - }) - sysLogCfg := serverConfig.GetSyslogLogger() - if !reflect.DeepEqual(sysLogCfg, syslogLogger{Enable: true}) { - t.Errorf("Expecting syslog logger config %#v found %#v", syslogLogger{Enable: true}, sysLogCfg) - } - // Match version. if serverConfig.GetVersion() != globalMinioConfigVersion { t.Errorf("Expecting version %s found %s", serverConfig.GetVersion(), globalMinioConfigVersion) diff --git a/cmd/globals.go b/cmd/globals.go index 4a7d4cf57..37b1830f6 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -32,7 +32,7 @@ const ( // minio configuration related constants. const ( - globalMinioConfigVersion = "9" + globalMinioConfigVersion = "10" globalMinioConfigDir = ".minio" globalMinioCertsDir = "certs" globalMinioCertsCADir = "CAs" diff --git a/cmd/logger-syslog-hook_nix.go b/cmd/logger-syslog-hook_nix.go deleted file mode 100644 index 8a83f6a0b..000000000 --- a/cmd/logger-syslog-hook_nix.go +++ /dev/null @@ -1,90 +0,0 @@ -// +build !windows - -/* - * Minio Cloud Storage, (C) 2015, 2016 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cmd - -import ( - "fmt" - "io/ioutil" - "log/syslog" - - "github.com/Sirupsen/logrus" -) - -type syslogLogger struct { - Enable bool `json:"enable"` - Addr string `json:"address"` - Level string `json:"level"` -} - -// syslogHook to send logs via syslog. -type syslogHook struct { - writer *syslog.Writer - syslogNetwork string - syslogRaddr string -} - -// enableSyslogLogger - enable logger at raddr. -func enableSyslogLogger(raddr string) { - syslogHook, err := newSyslog("udp", raddr, syslog.LOG_ERR, "MINIO") - fatalIf(err, "Unable to initialize syslog logger.") - - sysLogger := logrus.New() - - sysLogger.Hooks.Add(syslogHook) // Add syslog hook. - sysLogger.Formatter = &logrus.JSONFormatter{} // JSON formatted log. - sysLogger.Level = logrus.ErrorLevel // Minimum log level. - sysLogger.Out = ioutil.Discard - - log.mu.Lock() - log.loggers = append(log.loggers, sysLogger) - log.mu.Unlock() -} - -// newSyslog - Creates a hook to be added to an instance of logger. -func newSyslog(network, raddr string, priority syslog.Priority, tag string) (*syslogHook, error) { - w, err := syslog.Dial(network, raddr, priority, tag) - return &syslogHook{w, network, raddr}, err -} - -// Fire - fire the log event -func (hook *syslogHook) Fire(entry *logrus.Entry) error { - line, err := entry.String() - if err != nil { - return fmt.Errorf("Unable to read entry, %v", err) - } - switch entry.Level { - case logrus.PanicLevel: - return hook.writer.Crit(line) - case logrus.FatalLevel: - return hook.writer.Crit(line) - case logrus.ErrorLevel: - return hook.writer.Err(line) - default: - return nil - } -} - -// Levels - -func (hook *syslogHook) Levels() []logrus.Level { - return []logrus.Level{ - logrus.PanicLevel, - logrus.FatalLevel, - logrus.ErrorLevel, - } -} diff --git a/cmd/logger-syslog-hook_windows.go b/cmd/logger-syslog-hook_windows.go deleted file mode 100644 index 7841b215a..000000000 --- a/cmd/logger-syslog-hook_windows.go +++ /dev/null @@ -1,30 +0,0 @@ -// +build windows - -/* - * Minio Cloud Storage, (C) 2016 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cmd - -type syslogLogger struct { - Enable bool `json:"enable"` - Addr string `json:"address"` - Level string `json:"level"` -} - -// enableSyslogLogger - unsupported on windows. -func enableSyslogLogger(raddr string) { - fatalIf(errSyslogNotSupported, "Unable to enable syslog.") -} diff --git a/cmd/logger.go b/cmd/logger.go index 90bc94484..d41a53ac5 100644 --- a/cmd/logger.go +++ b/cmd/logger.go @@ -38,11 +38,9 @@ var log = struct { // // - console [default] // - file -// - syslog type logger struct { Console consoleLogger `json:"console"` File fileLogger `json:"file"` - Syslog syslogLogger `json:"syslog"` // Add new loggers here. } diff --git a/cmd/typed-errors.go b/cmd/typed-errors.go index a2b950f50..e79ab0dd6 100644 --- a/cmd/typed-errors.go +++ b/cmd/typed-errors.go @@ -18,9 +18,6 @@ package cmd import "errors" -// errSyslogNotSupported - this message is only meaningful on windows -var errSyslogNotSupported = errors.New("Syslog logger not supported on windows") - // errInvalidArgument means that input argument is invalid. var errInvalidArgument = errors.New("Invalid arguments specified")