diff --git a/cmd/admin-handlers_test.go b/cmd/admin-handlers_test.go index 5ed2f095b..133aa70e8 100644 --- a/cmd/admin-handlers_test.go +++ b/cmd/admin-handlers_test.go @@ -37,15 +37,13 @@ import ( var ( configJSON = []byte(`{ - "version": "28", + "version": "29", "credential": { "accessKey": "minio", "secretKey": "minio123" }, "region": "", - "browser": "on", "worm": "off", - "domain": "", "storageclass": { "standard": "", "rrs": "" diff --git a/cmd/common-main.go b/cmd/common-main.go index 7eadbc1c6..525a6285f 100644 --- a/cmd/common-main.go +++ b/cmd/common-main.go @@ -26,6 +26,7 @@ import ( "time" etcd "github.com/coreos/etcd/clientv3" + dns2 "github.com/miekg/dns" "github.com/minio/cli" "github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/logger" @@ -119,7 +120,7 @@ func handleCommonEnvVars() { if browser := os.Getenv("MINIO_BROWSER"); browser != "" { browserFlag, err := ParseBoolFlag(browser) if err != nil { - logger.Fatal(uiErrInvalidBrowserValue(nil).Msg("Unknown value `%s`", browser), "Unable to validate MINIO_BROWSER environment variable") + logger.Fatal(uiErrInvalidBrowserValue(nil).Msg("Unknown value `%s`", browser), "Invalid MINIO_BROWSER environment variable") } // browser Envs are set globally, this does not represent @@ -148,6 +149,11 @@ func handleCommonEnvVars() { } globalDomainName, globalIsEnvDomainName = os.LookupEnv("MINIO_DOMAIN") + if globalDomainName != "" { + if _, ok := dns2.IsDomainName(globalDomainName); !ok { + logger.Fatal(uiErrInvalidDomainValue(nil).Msg("Unknown value `%s`", globalDomainName), "Invalid MINIO_DOMAIN environment variable") + } + } minioEndpointsEnv, ok := os.LookupEnv("MINIO_PUBLIC_IPS") if ok { diff --git a/cmd/config-current.go b/cmd/config-current.go index 1dbacc9b4..d386a240a 100644 --- a/cmd/config-current.go +++ b/cmd/config-current.go @@ -23,7 +23,6 @@ import ( "reflect" "sync" - "github.com/miekg/dns" "github.com/minio/minio/cmd/crypto" "github.com/minio/minio/cmd/logger" @@ -41,9 +40,9 @@ import ( // 6. Make changes in config-current_test.go for any test change // Config version -const serverConfigVersion = "28" +const serverConfigVersion = "29" -type serverConfig = serverConfigV28 +type serverConfig = serverConfigV29 var ( // globalServerConfig server config. @@ -97,12 +96,6 @@ func (s *serverConfig) GetCredential() auth.Credentials { return s.Credential } -// SetBrowser set if browser is enabled. -func (s *serverConfig) SetBrowser(b bool) { - // Set the new value. - s.Browser = BoolFlag(b) -} - // SetWorm set if worm is enabled. func (s *serverConfig) SetWorm(b bool) { // Set the new value. @@ -126,17 +119,6 @@ func (s *serverConfig) GetStorageClass() (storageClass, storageClass) { return s.StorageClass.Standard, s.StorageClass.RRS } -// GetBrowser get current credentials. -func (s *serverConfig) GetBrowser() bool { - if globalIsEnvBrowser { - return globalIsBrowserEnabled - } - if s == nil { - return true - } - return bool(s.Browser) -} - // GetWorm get current credentials. func (s *serverConfig) GetWorm() bool { if globalIsEnvWORM { @@ -188,14 +170,7 @@ func (s *serverConfig) Validate() error { } // Region: nothing to validate - // Browser, Worm, Cache and StorageClass values are already validated during json unmarshal - - if s.Domain != "" { - if _, ok := dns.IsDomainName(s.Domain); !ok { - return errors.New("invalid domain name") - } - } - + // Worm, Cache and StorageClass values are already validated during json unmarshal for _, v := range s.Notify.AMQP { if err := v.Validate(); err != nil { return fmt.Errorf("amqp: %s", err.Error()) @@ -259,10 +234,6 @@ func (s *serverConfig) loadFromEnvs() { s.SetCredential(globalActiveCred) } - if globalIsEnvBrowser { - s.SetBrowser(globalIsBrowserEnabled) - } - if globalIsEnvWORM { s.SetWorm(globalWORMEnabled) } @@ -271,10 +242,6 @@ func (s *serverConfig) loadFromEnvs() { s.SetRegion(globalServerRegion) } - if globalIsEnvDomainName { - s.Domain = globalDomainName - } - if globalIsStorageClass { s.SetStorageClass(globalStandardStorageClass, globalRRStorageClass) } @@ -395,10 +362,6 @@ func (s *serverConfig) ConfigDiff(t *serverConfig) string { return "Credential configuration differs" case s.Region != t.Region: return "Region configuration differs" - case s.Browser != t.Browser: - return "Browser configuration differs" - case s.Domain != t.Domain: - return "Domain configuration differs" case s.StorageClass != t.StorageClass: return "StorageClass configuration differs" case !reflect.DeepEqual(s.Cache, t.Cache): @@ -442,7 +405,6 @@ func newServerConfig() *serverConfig { Version: serverConfigVersion, Credential: cred, Region: globalMinioDefaultRegion, - Browser: true, StorageClass: storageClassConfig{ Standard: storageClass{}, RRS: storageClass{}, @@ -495,18 +457,12 @@ func (s *serverConfig) loadToCachedConfigs() { if !globalIsEnvCreds { globalActiveCred = s.GetCredential() } - if !globalIsEnvBrowser { - globalIsBrowserEnabled = s.GetBrowser() - } if !globalIsEnvWORM { globalWORMEnabled = s.GetWorm() } if !globalIsEnvRegion { globalServerRegion = s.GetRegion() } - if !globalIsEnvDomainName { - globalDomainName = s.Domain - } if !globalIsStorageClass { globalStandardStorageClass, globalRRStorageClass = s.GetStorageClass() } diff --git a/cmd/config-current_test.go b/cmd/config-current_test.go index 2b456d126..047203702 100644 --- a/cmd/config-current_test.go +++ b/cmd/config-current_test.go @@ -104,7 +104,7 @@ func TestServerConfigWithEnvs(t *testing.T) { initConfig(objLayer) // Check if serverConfig has browser disabled - if globalServerConfig.GetBrowser() { + if globalIsBrowserEnabled { t.Error("Expected browser to be disabled but it is not") } @@ -130,8 +130,8 @@ func TestServerConfigWithEnvs(t *testing.T) { } // Check if serverConfig has the correct domain - if globalServerConfig.Domain != "domain.com" { - t.Errorf("Expected Domain to be `domain.com`, found " + globalServerConfig.Domain) + if globalDomainName != "domain.com" { + t.Errorf("Expected Domain to be `domain.com`, found " + globalDomainName) } } @@ -267,70 +267,66 @@ func TestConfigDiff(t *testing.T) { // 3 {&serverConfig{Region: "us-east-1"}, &serverConfig{Region: "us-west-1"}, "Region configuration differs"}, // 4 - {&serverConfig{Browser: false}, &serverConfig{Browser: true}, "Browser configuration differs"}, - // 5 - {&serverConfig{Domain: "domain1"}, &serverConfig{Domain: "domain2"}, "Domain configuration differs"}, - // 6 { &serverConfig{StorageClass: storageClassConfig{storageClass{"1", 8}, storageClass{"2", 6}}}, &serverConfig{StorageClass: storageClassConfig{storageClass{"1", 8}, storageClass{"2", 4}}}, "StorageClass configuration differs", }, - // 7 + // 5 { &serverConfig{Notify: notifier{AMQP: map[string]target.AMQPArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{AMQP: map[string]target.AMQPArgs{"1": {Enable: false}}}}, "AMQP Notification configuration differs", }, - // 8 + // 6 { &serverConfig{Notify: notifier{NATS: map[string]target.NATSArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{NATS: map[string]target.NATSArgs{"1": {Enable: false}}}}, "NATS Notification configuration differs", }, - // 9 + // 7 { &serverConfig{Notify: notifier{Elasticsearch: map[string]target.ElasticsearchArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{Elasticsearch: map[string]target.ElasticsearchArgs{"1": {Enable: false}}}}, "ElasticSearch Notification configuration differs", }, - // 10 + // 8 { &serverConfig{Notify: notifier{Redis: map[string]target.RedisArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{Redis: map[string]target.RedisArgs{"1": {Enable: false}}}}, "Redis Notification configuration differs", }, - // 11 + // 9 { &serverConfig{Notify: notifier{PostgreSQL: map[string]target.PostgreSQLArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{PostgreSQL: map[string]target.PostgreSQLArgs{"1": {Enable: false}}}}, "PostgreSQL Notification configuration differs", }, - // 12 + // 10 { &serverConfig{Notify: notifier{Kafka: map[string]target.KafkaArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{Kafka: map[string]target.KafkaArgs{"1": {Enable: false}}}}, "Kafka Notification configuration differs", }, - // 13 + // 11 { &serverConfig{Notify: notifier{Webhook: map[string]target.WebhookArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{Webhook: map[string]target.WebhookArgs{"1": {Enable: false}}}}, "Webhook Notification configuration differs", }, - // 14 + // 12 { &serverConfig{Notify: notifier{MySQL: map[string]target.MySQLArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{MySQL: map[string]target.MySQLArgs{"1": {Enable: false}}}}, "MySQL Notification configuration differs", }, - // 15 + // 13 { &serverConfig{Notify: notifier{MQTT: map[string]target.MQTTArgs{"1": {Enable: true}}}}, &serverConfig{Notify: notifier{MQTT: map[string]target.MQTTArgs{"1": {Enable: false}}}}, "MQTT Notification configuration differs", }, - // 16 + // 14 { &serverConfig{Logger: loggerConfig{ Console: loggerConsole{Enabled: true}, diff --git a/cmd/config-migrate.go b/cmd/config-migrate.go index 626bf77ec..dfb8257ff 100644 --- a/cmd/config-migrate.go +++ b/cmd/config-migrate.go @@ -2411,7 +2411,31 @@ func migrateV27ToV28() error { // Migrates '.minio.sys/config.json' v27 to v28. func migrateMinioSysConfig(objAPI ObjectLayer) error { - return migrateV27ToV28MinioSys(objAPI) + if err := migrateV27ToV28MinioSys(objAPI); err != nil { + return err + } + return migrateV28ToV29MinioSys(objAPI) +} + +func migrateV28ToV29MinioSys(objAPI ObjectLayer) error { + configFile := path.Join(minioConfigPrefix, minioConfigFile) + srvConfig, err := readServerConfig(context.Background(), objAPI) + if err == errConfigNotFound { + return nil + } else if err != nil { + return fmt.Errorf("Unable to load config file. %v", err) + } + if srvConfig.Version != "28" { + return nil + } + + srvConfig.Version = "29" + if err = saveServerConfig(context.Background(), objAPI, srvConfig); err != nil { + return fmt.Errorf("Failed to migrate config from ‘28’ to ‘29’. %v", err) + } + + logger.Info(configMigrateMSGTemplate, configFile, "28", "29") + return nil } func migrateV27ToV28MinioSys(objAPI ObjectLayer) error { diff --git a/cmd/config-migrate_test.go b/cmd/config-migrate_test.go index f984d8959..8116c4320 100644 --- a/cmd/config-migrate_test.go +++ b/cmd/config-migrate_test.go @@ -159,8 +159,8 @@ func TestServerConfigMigrateInexistentConfig(t *testing.T) { } } -// Test if a config migration from v2 to v28 is successfully done -func TestServerConfigMigrateV2toV28(t *testing.T) { +// Test if a config migration from v2 to v29 is successfully done +func TestServerConfigMigrateV2toV29(t *testing.T) { rootPath, err := ioutil.TempDir(globalTestTmpDir, "minio-") if err != nil { t.Fatal(err) @@ -203,6 +203,10 @@ func TestServerConfigMigrateV2toV28(t *testing.T) { t.Fatal("Unexpected error: ", err) } + if err := migrateMinioSysConfig(objLayer); err != nil { + t.Fatal("Unexpected error: ", err) + } + // Initialize server config and check again if everything is fine if err := loadConfig(objLayer); err != nil { t.Fatalf("Unable to initialize from updated config file %s", err) diff --git a/cmd/config-versions.go b/cmd/config-versions.go index 5edc32a7d..4c6b4163a 100644 --- a/cmd/config-versions.go +++ b/cmd/config-versions.go @@ -737,9 +737,34 @@ type serverConfigV28 struct { // S3 API configuration. Credential auth.Credentials `json:"credential"` Region string `json:"region"` - Browser BoolFlag `json:"browser"` Worm BoolFlag `json:"worm"` - Domain string `json:"domain"` + + // Storage class configuration + StorageClass storageClassConfig `json:"storageclass"` + + // Cache configuration + Cache CacheConfig `json:"cache"` + + // KMS configuration + KMS crypto.KMSConfig `json:"kms"` + + // Notification queue configuration. + Notify notifier `json:"notify"` + + // Logger configuration + Logger loggerConfig `json:"logger"` +} + +// serverConfigV29 is just like version '28', browser and domain are deprecated. +type serverConfigV29 struct { + quick.Config `json:"-"` // ignore interfaces + + Version string `json:"version"` + + // S3 API configuration. + Credential auth.Credentials `json:"credential"` + Region string `json:"region"` + Worm BoolFlag `json:"worm"` // Storage class configuration StorageClass storageClassConfig `json:"storageclass"` diff --git a/cmd/ui-errors.go b/cmd/ui-errors.go index d6d22f878..5bdd8490a 100644 --- a/cmd/ui-errors.go +++ b/cmd/ui-errors.go @@ -29,6 +29,12 @@ var ( "Browser can only accept `on` and `off` values. To disable web browser access, set this value to `off`", ) + uiErrInvalidDomainValue = newUIErrFn( + "Invalid domain value", + "Please check the passed value", + "Domain can only accept DNS compatible values.", + ) + uiErrInvalidErasureSetSize = newUIErrFn( "Invalid erasure set size", "Please check the passed value", diff --git a/docs/config/README.md b/docs/config/README.md index 052bd895b..de2634dd2 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -71,18 +71,6 @@ export MINIO_REGION="my_region" minio server /data ``` -#### Browser -|Field|Type|Description| -|:---|:---|:---| -|``browser``| _string_ | Enable or disable access to web UI. By default it is set to `on`. You may override this field with ``MINIO_BROWSER`` environment variable.| - -Example: - -```sh -export MINIO_BROWSER=off -minio server /data -``` - #### Worm |Field|Type|Description| |:---|:---|:---| @@ -95,20 +83,6 @@ export MINIO_WORM=on minio server /data ``` -### Domain -|Field|Type|Description| -|:---|:---|:---| -|``domain``| _string_ | Enable virtual-host-style requests i.e http://bucket.mydomain.com/object| - -By default, Minio supports path-style requests which look like http://mydomain.com/bucket/object. MINIO_DOMAIN environmental variable (or `domain` in config.json) can be used to enable virtual-host-style requests. If the request `Host` header matches with `(.+).mydomain.com` then the mattched pattern `$1` is used as bucket and the path is used as object. More information on path-style and virtual-host-style [here](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAPI.html) - -Example: - -```sh -export MINIO_DOMAIN=mydomain.com -minio server /data -``` - ### Storage Class |Field|Type|Description| |:---|:---|:---| @@ -140,5 +114,25 @@ By default, parity for objects with standard storage class is set to `N/2`, and |``notify.mysql``| |[Configure to publish Minio events via MySql target.](https://docs.minio.io/docs/minio-bucket-notification-guide#MySQL)| |``notify.mqtt``| |[Configure to publish Minio events via MQTT target.](https://docs.minio.io/docs/minio-bucket-notification-guide#MQTT)| +## Environment only settings + +#### Browser +Enable or disable access to web UI. By default it is set to `on`. You may override this field with ``MINIO_BROWSER`` environment variable. + +Example: +```sh +export MINIO_BROWSER=off +minio server /data +``` + +### Domain +By default, Minio supports path-style requests which look like http://mydomain.com/bucket/object. MINIO_DOMAIN environmental variable is used to enable virtual-host-style requests. If the request `Host` header matches with `(.+).mydomain.com` then the mattched pattern `$1` is used as bucket and the path is used as object. More information on path-style and virtual-host-style [here](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAPI.html) + +Example: +```sh +export MINIO_DOMAIN=mydomain.com +minio server /data +``` + ## Explore Further * [Minio Quickstart Guide](https://docs.minio.io/docs/minio-quickstart-guide) diff --git a/docs/config/config.sample.json b/docs/config/config.sample.json index 94d96a763..1f0242c5b 100644 --- a/docs/config/config.sample.json +++ b/docs/config/config.sample.json @@ -1,13 +1,11 @@ { - "version": "28", + "version": "29", "credential": { "accessKey": "USWUXHGYZQYFYFFIT3RE", "secretKey": "MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03" }, "region": "us-east-1", - "browser": "on", "worm": "off", - "domain": "", "storageclass": { "standard": "", "rrs": "" @@ -136,4 +134,3 @@ } } } -