config: Add browser parameter (#3807)

browser new parameter receives "on" or "off" parameter which is similar
to MINIO_BROWSER
This commit is contained in:
Anis Elleuch 2017-02-27 23:59:53 +01:00 committed by Harshavardhana
parent c9619673fb
commit 9b3c014bab
9 changed files with 290 additions and 38 deletions

View File

@ -74,6 +74,10 @@ func migrateConfig() error {
if err := migrateV12ToV13(); err != nil {
return err
}
// Migration version '13' to '14'.
if err := migrateV13ToV14(); err != nil {
return err
}
return nil
}
@ -937,3 +941,105 @@ func migrateV12ToV13() error {
)
return nil
}
// Version '13' to '14' migration. Add support for custom webhook endpoint.
func migrateV13ToV14() error {
cv13, err := loadConfigV13()
if err != nil {
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("Unable to load config version 13. %v", err)
}
if cv13.Version != "13" {
return nil
}
// Copy over fields from V13 into V14 config struct
srvConfig := &serverConfigV14{
Logger: &logger{},
Notify: &notifier{},
}
srvConfig.Version = "14"
srvConfig.Credential = cv13.Credential
srvConfig.Region = cv13.Region
if srvConfig.Region == "" {
// Region needs to be set for AWS Signature Version 4.
srvConfig.Region = globalMinioDefaultRegion
}
srvConfig.Logger.Console = cv13.Logger.Console
srvConfig.Logger.File = cv13.Logger.File
// check and set notifiers config
if len(cv13.Notify.AMQP) == 0 {
srvConfig.Notify.AMQP = make(map[string]amqpNotify)
srvConfig.Notify.AMQP["1"] = amqpNotify{}
} else {
srvConfig.Notify.AMQP = cv13.Notify.AMQP
}
if len(cv13.Notify.ElasticSearch) == 0 {
srvConfig.Notify.ElasticSearch = make(map[string]elasticSearchNotify)
srvConfig.Notify.ElasticSearch["1"] = elasticSearchNotify{}
} else {
srvConfig.Notify.ElasticSearch = cv13.Notify.ElasticSearch
}
if len(cv13.Notify.Redis) == 0 {
srvConfig.Notify.Redis = make(map[string]redisNotify)
srvConfig.Notify.Redis["1"] = redisNotify{}
} else {
srvConfig.Notify.Redis = cv13.Notify.Redis
}
if len(cv13.Notify.PostgreSQL) == 0 {
srvConfig.Notify.PostgreSQL = make(map[string]postgreSQLNotify)
srvConfig.Notify.PostgreSQL["1"] = postgreSQLNotify{}
} else {
srvConfig.Notify.PostgreSQL = cv13.Notify.PostgreSQL
}
if len(cv13.Notify.Kafka) == 0 {
srvConfig.Notify.Kafka = make(map[string]kafkaNotify)
srvConfig.Notify.Kafka["1"] = kafkaNotify{}
} else {
srvConfig.Notify.Kafka = cv13.Notify.Kafka
}
if len(cv13.Notify.NATS) == 0 {
srvConfig.Notify.NATS = make(map[string]natsNotify)
srvConfig.Notify.NATS["1"] = natsNotify{}
} else {
srvConfig.Notify.NATS = cv13.Notify.NATS
}
if len(cv13.Notify.Webhook) == 0 {
srvConfig.Notify.Webhook = make(map[string]webhookNotify)
srvConfig.Notify.Webhook["1"] = webhookNotify{}
} else {
srvConfig.Notify.Webhook = cv13.Notify.Webhook
}
// Set the new browser parameter to true by default
srvConfig.Browser = "on"
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 "+
cv13.Version+" to "+srvConfig.Version+
" failed. %v", err,
)
}
console.Println(
"Migration from version " +
cv13.Version + " to " + srvConfig.Version +
" completed successfully.",
)
return nil
}

View File

@ -50,7 +50,7 @@ func TestServerConfigMigrateV1(t *testing.T) {
}
// Initialize server config and check again if everything is fine
if err := loadConfig(credential{}); err != nil {
if err := loadConfig(envParams{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
}
@ -106,10 +106,13 @@ func TestServerConfigMigrateInexistentConfig(t *testing.T) {
if err := migrateV12ToV13(); err != nil {
t.Fatal("migrate v12 to v13 should succeed when no config file is found")
}
if err := migrateV13ToV14(); err != nil {
t.Fatal("migrate v13 to v14 should succeed when no config file is found")
}
}
// Test if a config migration from v2 to v12 is successfully done
func TestServerConfigMigrateV2toV12(t *testing.T) {
func TestServerConfigMigrateV2toV14(t *testing.T) {
rootPath, err := newTestConfig(globalMinioDefaultRegion)
if err != nil {
t.Fatalf("Init Test config failed")
@ -143,7 +146,7 @@ func TestServerConfigMigrateV2toV12(t *testing.T) {
}
// Initialize server config and check again if everything is fine
if err := loadConfig(credential{}); err != nil {
if err := loadConfig(envParams{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
@ -213,4 +216,7 @@ func TestServerConfigMigrateFaultyConfig(t *testing.T) {
if err := migrateV12ToV13(); err == nil {
t.Fatal("migrateConfigV12ToV13() should fail with a corrupted json")
}
if err := migrateV13ToV14(); err == nil {
t.Fatal("migrateConfigV13ToV14() should fail with a corrupted json")
}
}

View File

@ -522,3 +522,31 @@ func loadConfigV12() (*serverConfigV12, error) {
}
return config.(*serverConfigV12), err
}
// serverConfigV13 server configuration version '13' which is like
// version '12' except it adds support for webhook notification.
type serverConfigV13 struct {
Version string `json:"version"`
// S3 API configuration.
Credential credential `json:"credential"`
Region string `json:"region"`
// Additional error logging configuration.
Logger *logger `json:"logger"`
// Notification queue configuration.
Notify *notifier `json:"notify"`
}
func loadConfigV13() (*serverConfigV13, error) {
configFile, err := getConfigFile()
if err != nil {
return nil, err
}
config, err := loadOldConfig(configFile, &serverConfigV13{Version: "13"})
if config == nil {
return nil, err
}
return config.(*serverConfigV13), err
}

View File

@ -18,6 +18,7 @@ package cmd
import (
"os"
"strings"
"sync"
"github.com/minio/minio/pkg/quick"
@ -26,14 +27,15 @@ import (
// Read Write mutex for safe access to ServerConfig.
var serverConfigMu sync.RWMutex
// serverConfigV13 server configuration version '13' which is like
// version '12' except it adds support for webhook notification.
type serverConfigV13 struct {
// serverConfigV14 server configuration version '14' which is like
// version '13' except it adds support of browser param.
type serverConfigV14 struct {
Version string `json:"version"`
// S3 API configuration.
Credential credential `json:"credential"`
Region string `json:"region"`
Browser string `json:"browser"`
// Additional error logging configuration.
Logger *logger `json:"logger"`
@ -42,12 +44,11 @@ type serverConfigV13 struct {
Notify *notifier `json:"notify"`
}
// newConfig - initialize a new server config, saves creds from env
// if globalIsEnvCreds is set otherwise generates a new set of keys
// and those are saved.
func newConfig(envCreds credential) error {
// newConfig - initialize a new server config, saves env parameters if
// found, otherwise use default parameters
func newConfig(envParams envParams) error {
// Initialize server config.
srvCfg := &serverConfigV13{
srvCfg := &serverConfigV14{
Logger: &logger{},
Notify: &notifier{},
}
@ -56,11 +57,17 @@ func newConfig(envCreds credential) error {
// If env is set for a fresh start, save them to config file.
if globalIsEnvCreds {
srvCfg.SetCredential(envCreds)
srvCfg.SetCredential(envParams.creds)
} else {
srvCfg.SetCredential(newCredential())
}
if globalIsEnvBrowser {
srvCfg.SetBrowser(envParams.browser)
} else {
srvCfg.SetBrowser("on")
}
// Enable console logger by default on a fresh run.
srvCfg.Logger.Console = consoleLogger{
Enable: true,
@ -99,10 +106,9 @@ func newConfig(envCreds credential) error {
return serverConfig.Save()
}
// loadConfig - loads a new config from disk, overrides creds from env
// if globalIsEnvCreds is set otherwise serves the creds from loaded
// from the disk.
func loadConfig(envCreds credential) error {
// loadConfig - loads a new config from disk, overrides params from env
// if found and valid
func loadConfig(envParams envParams) error {
configFile, err := getConfigFile()
if err != nil {
return err
@ -111,7 +117,7 @@ func loadConfig(envCreds credential) error {
if _, err = os.Stat(configFile); err != nil {
return err
}
srvCfg := &serverConfigV13{}
srvCfg := &serverConfigV14{}
srvCfg.Version = globalMinioConfigVersion
qc, err := quick.New(srvCfg)
if err != nil {
@ -124,11 +130,19 @@ func loadConfig(envCreds credential) error {
// If env is set override the credentials from config file.
if globalIsEnvCreds {
srvCfg.SetCredential(envCreds)
srvCfg.SetCredential(envParams.creds)
} else {
srvCfg.SetCredential(srvCfg.Credential)
}
if globalIsEnvBrowser {
srvCfg.SetBrowser(envParams.browser)
}
if strings.ToLower(srvCfg.GetBrowser()) == "off" {
globalIsBrowserEnabled = false
}
// hold the mutex lock before a new config is assigned.
serverConfigMu.Lock()
// Save the loaded config globally.
@ -141,10 +155,10 @@ func loadConfig(envCreds credential) error {
}
// serverConfig server config.
var serverConfig *serverConfigV13
var serverConfig *serverConfigV14
// GetVersion get current config version.
func (s serverConfigV13) GetVersion() string {
func (s serverConfigV14) GetVersion() string {
serverConfigMu.RLock()
defer serverConfigMu.RUnlock()
@ -152,7 +166,7 @@ func (s serverConfigV13) GetVersion() string {
}
// SetRegion set new region.
func (s *serverConfigV13) SetRegion(region string) {
func (s *serverConfigV14) SetRegion(region string) {
serverConfigMu.Lock()
defer serverConfigMu.Unlock()
@ -160,7 +174,7 @@ func (s *serverConfigV13) SetRegion(region string) {
}
// GetRegion get current region.
func (s serverConfigV13) GetRegion() string {
func (s serverConfigV14) GetRegion() string {
serverConfigMu.RLock()
defer serverConfigMu.RUnlock()
@ -168,7 +182,7 @@ func (s serverConfigV13) GetRegion() string {
}
// SetCredentials set new credentials.
func (s *serverConfigV13) SetCredential(creds credential) {
func (s *serverConfigV14) SetCredential(creds credential) {
serverConfigMu.Lock()
defer serverConfigMu.Unlock()
@ -177,15 +191,32 @@ func (s *serverConfigV13) SetCredential(creds credential) {
}
// GetCredentials get current credentials.
func (s serverConfigV13) GetCredential() credential {
func (s serverConfigV14) GetCredential() credential {
serverConfigMu.RLock()
defer serverConfigMu.RUnlock()
return s.Credential
}
// SetBrowser set if browser is enabled.
func (s *serverConfigV14) SetBrowser(v string) {
serverConfigMu.Lock()
defer serverConfigMu.Unlock()
// Set browser param
s.Browser = v
}
// GetCredentials get current credentials.
func (s serverConfigV14) GetBrowser() string {
serverConfigMu.RLock()
defer serverConfigMu.RUnlock()
return s.Browser
}
// Save config.
func (s serverConfigV13) Save() error {
func (s serverConfigV14) Save() error {
serverConfigMu.RLock()
defer serverConfigMu.RUnlock()

View File

@ -17,6 +17,7 @@
package cmd
import (
"os"
"reflect"
"testing"
)
@ -114,7 +115,55 @@ func TestServerConfig(t *testing.T) {
setGlobalConfigPath(rootPath)
// Initialize server config.
if err := loadConfig(credential{}); err != nil {
if err := loadConfig(envParams{}); err != nil {
t.Fatalf("Unable to initialize from updated config file %s", err)
}
}
func TestServerConfigWithEnvs(t *testing.T) {
os.Setenv("MINIO_BROWSER", "off")
defer os.Unsetenv("MINIO_BROWSER")
os.Setenv("MINIO_ACCESS_KEY", "minio")
defer os.Unsetenv("MINIO_ACCESS_KEY")
os.Setenv("MINIO_SECRET_KEY", "minio123")
defer os.Unsetenv("MINIO_SECRET_KEY")
defer func() {
globalIsEnvBrowser = false
globalIsEnvCreds = false
}()
// Get test root.
rootPath, err := getTestRoot()
if err != nil {
t.Error(err)
}
// Do this only once here.
setGlobalConfigPath(rootPath)
// Init config
initConfig()
// remove the root directory after the test ends.
defer removeAll(rootPath)
// Check if serverConfig has
if serverConfig.GetBrowser() != "off" {
t.Errorf("Expecting browser `off` found %s", serverConfig.GetBrowser())
}
// Check if serverConfig has
cred := serverConfig.GetCredential()
if cred.AccessKey != "minio" {
t.Errorf("Expecting access key to be `minio` found %s", cred.AccessKey)
}
if cred.SecretKey != "minio123" {
t.Errorf("Expecting access key to be `minio123` found %s", cred.SecretKey)
}
}

View File

@ -19,9 +19,7 @@ package cmd
import (
"crypto/x509"
"net/url"
"os"
"runtime"
"strings"
"time"
humanize "github.com/dustin/go-humanize"
@ -74,9 +72,12 @@ var (
// Indicates if the running minio server is an erasure-code backend.
globalIsXL = false
// This flag is set to 'true' by default, it is set to `false`
// when MINIO_BROWSER env is set to 'off'.
globalIsBrowserEnabled = !strings.EqualFold(os.Getenv("MINIO_BROWSER"), "off")
// This flag is set to 'true' by default
globalIsBrowserEnabled = true
// This flag is set to 'true' when MINIO_BROWSER env is set.
globalIsEnvBrowser = false
// Set to true if credentials were passed from env, default is false.
globalIsEnvCreds = false
// Maximum cache size. Defaults to disabled.
// Caching is enabled only for RAM size > 8GiB.
@ -113,9 +114,6 @@ var (
// Minio server user agent string.
globalServerUserAgent = "Minio/" + ReleaseTag + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
// Set to true if credentials were passed from env, default is false.
globalIsEnvCreds = false
// url.URL endpoints of disks that belong to the object storage.
globalEndpoints = []*url.URL{}

View File

@ -159,14 +159,24 @@ func checkUpdate() {
}
}
// envParams holds all env parameters
type envParams struct {
creds credential
browser string
}
// Initializes a new config if it doesn't exist, else migrates any old config
// to newer config and finally loads the config to memory.
func initConfig() {
envCreds := mustGetCredentialFromEnv()
envs := envParams{
creds: mustGetCredentialFromEnv(),
browser: mustGetBrowserFromEnv(),
}
// Config file does not exist, we create it fresh and return upon success.
if !isConfigFileExists() {
if err := newConfig(envCreds); err != nil {
if err := newConfig(envs); err != nil {
console.Fatalf("Unable to initialize minio config for the first time. Err: %s.\n", err)
}
console.Println("Created minio configuration file successfully at " + mustGetConfigPath())
@ -177,7 +187,7 @@ func initConfig() {
migrate()
// Once we have migrated all the old config, now load them.
if err := loadConfig(envCreds); err != nil {
if err := loadConfig(envs); err != nil {
console.Fatalf("Unable to initialize minio config. Err: %s.\n", err)
}
}

View File

@ -533,7 +533,7 @@ func newTestConfig(bucketLocation string) (rootPath string, err error) {
setGlobalConfigPath(rootPath)
// Initialize server config.
if err = newConfig(credential{}); err != nil {
if err = newConfig(envParams{}); err != nil {
return "", err
}

View File

@ -23,11 +23,13 @@ import (
"io"
"net/http"
"net/url"
"os"
"strings"
"encoding/json"
humanize "github.com/dustin/go-humanize"
"github.com/minio/mc/pkg/console"
"github.com/pkg/profile"
)
@ -238,3 +240,25 @@ func dumpRequest(r *http.Request) string {
}
return string(jsonBytes)
}
// Variant of getBrowserFromEnv but upon error fails right here.
func mustGetBrowserFromEnv() string {
browser, err := getBrowserFromEnv()
if err != nil {
console.Fatalf("Unable to load MINIO_BROWSER value from environment. Err: %s.\n", err)
}
return browser
}
//
func getBrowserFromEnv() (string, error) {
b := os.Getenv("MINIO_BROWSER")
if strings.TrimSpace(b) == "" {
return "", nil
}
if !strings.EqualFold(b, "off") && !strings.EqualFold(b, "on") {
return "", errInvalidArgument
}
globalIsEnvBrowser = true
return strings.ToLower(b), nil
}