Add logger command - also migrate from old config to newer config

master
Harshavardhana 9 years ago
parent e8892a9f3c
commit 56003fded7
  1. 24
      api-signature.go
  2. 127
      auth-config.go
  3. 78
      config-logger-main.go
  4. 53
      config-main.go
  5. 64
      config-version-main.go
  6. 6
      flags.go
  7. 54
      logger-file-hook.go
  8. 8
      logger-syslog-hook.go
  9. 29
      main.go
  10. 2
      routers.go
  11. 218
      server-config.go
  12. 51
      server-main.go
  13. 12
      server_fs_test.go

@ -105,17 +105,17 @@ func initSignatureV4(req *http.Request) (*fs.Signature, *probe.Error) {
if err != nil { if err != nil {
return nil, err.Trace() return nil, err.Trace()
} }
authConfig, err := loadAuthConfig() config, err := loadConfigV2()
if err != nil { if err != nil {
return nil, err.Trace() return nil, err.Trace()
} }
authFields := strings.Split(strings.TrimSpace(authHeaderValue), ",") authFields := strings.Split(strings.TrimSpace(authHeaderValue), ",")
signedHeaders := strings.Split(strings.Split(strings.TrimSpace(authFields[1]), "=")[1], ";") signedHeaders := strings.Split(strings.Split(strings.TrimSpace(authFields[1]), "=")[1], ";")
signature := strings.Split(strings.TrimSpace(authFields[2]), "=")[1] signature := strings.Split(strings.TrimSpace(authFields[2]), "=")[1]
if authConfig.AccessKeyID == accessKeyID { if config.Credentials.AccessKeyID == accessKeyID {
signature := &fs.Signature{ signature := &fs.Signature{
AccessKeyID: authConfig.AccessKeyID, AccessKeyID: config.Credentials.AccessKeyID,
SecretAccessKey: authConfig.SecretAccessKey, SecretAccessKey: config.Credentials.SecretAccessKey,
Signature: signature, Signature: signature,
SignedHeaders: signedHeaders, SignedHeaders: signedHeaders,
Request: req, Request: req,
@ -210,14 +210,14 @@ func initPostPresignedPolicyV4(formValues map[string]string) (*fs.Signature, *pr
if !isValidAccessKey(accessKeyID) { if !isValidAccessKey(accessKeyID) {
return nil, probe.NewError(errAccessKeyIDInvalid) return nil, probe.NewError(errAccessKeyIDInvalid)
} }
authConfig, perr := loadAuthConfig() config, perr := loadConfigV2()
if perr != nil { if perr != nil {
return nil, perr.Trace() return nil, perr.Trace()
} }
if authConfig.AccessKeyID == accessKeyID { if config.Credentials.AccessKeyID == accessKeyID {
signature := &fs.Signature{ signature := &fs.Signature{
AccessKeyID: authConfig.AccessKeyID, AccessKeyID: config.Credentials.AccessKeyID,
SecretAccessKey: authConfig.SecretAccessKey, SecretAccessKey: config.Credentials.SecretAccessKey,
Signature: formValues["X-Amz-Signature"], Signature: formValues["X-Amz-Signature"],
PresignedPolicy: formValues["Policy"], PresignedPolicy: formValues["Policy"],
} }
@ -236,16 +236,16 @@ func initPresignedSignatureV4(req *http.Request) (*fs.Signature, *probe.Error) {
if !isValidAccessKey(accessKeyID) { if !isValidAccessKey(accessKeyID) {
return nil, probe.NewError(errAccessKeyIDInvalid) return nil, probe.NewError(errAccessKeyIDInvalid)
} }
authConfig, err := loadAuthConfig() config, err := loadConfigV2()
if err != nil { if err != nil {
return nil, err.Trace() return nil, err.Trace()
} }
signedHeaders := strings.Split(strings.TrimSpace(req.URL.Query().Get("X-Amz-SignedHeaders")), ";") signedHeaders := strings.Split(strings.TrimSpace(req.URL.Query().Get("X-Amz-SignedHeaders")), ";")
signature := strings.TrimSpace(req.URL.Query().Get("X-Amz-Signature")) signature := strings.TrimSpace(req.URL.Query().Get("X-Amz-Signature"))
if authConfig.AccessKeyID == accessKeyID { if config.Credentials.AccessKeyID == accessKeyID {
signature := &fs.Signature{ signature := &fs.Signature{
AccessKeyID: authConfig.AccessKeyID, AccessKeyID: config.Credentials.AccessKeyID,
SecretAccessKey: authConfig.SecretAccessKey, SecretAccessKey: config.Credentials.SecretAccessKey,
Signature: signature, Signature: signature,
SignedHeaders: signedHeaders, SignedHeaders: signedHeaders,
Presigned: true, Presigned: true,

@ -1,127 +0,0 @@
/*
* Minio Cloud Storage, (C) 2015 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 main
import (
"os"
"os/user"
"path/filepath"
"github.com/minio/minio-xl/pkg/probe"
"github.com/minio/minio-xl/pkg/quick"
)
// AuthConfig auth keys
type AuthConfig struct {
Version string `json:"version"`
AccessKeyID string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
}
// getAuthConfigPath get users config path
func getAuthConfigPath() (string, *probe.Error) {
if customConfigPath != "" {
return customConfigPath, nil
}
u, err := user.Current()
if err != nil {
return "", probe.NewError(err)
}
authConfigPath := filepath.Join(u.HomeDir, ".minio")
return authConfigPath, nil
}
// createAuthConfigPath create users config path
func createAuthConfigPath() *probe.Error {
authConfigPath, err := getAuthConfigPath()
if err != nil {
return err.Trace()
}
if err := os.MkdirAll(authConfigPath, 0700); err != nil {
return probe.NewError(err)
}
return nil
}
// isAuthConfigFileExists is auth config file exists?
func isAuthConfigFileExists() bool {
if _, err := os.Stat(mustGetAuthConfigFile()); err != nil {
if os.IsNotExist(err) {
return false
}
panic(err)
}
return true
}
// mustGetAuthConfigFile always get users config file, if not panic
func mustGetAuthConfigFile() string {
authConfigFile, err := getAuthConfigFile()
if err != nil {
panic(err)
}
return authConfigFile
}
// getAuthConfigFile get users config file
func getAuthConfigFile() (string, *probe.Error) {
authConfigPath, err := getAuthConfigPath()
if err != nil {
return "", err.Trace()
}
return filepath.Join(authConfigPath, "fsUsers.json"), nil
}
// customConfigPath for custom config path only for testing purposes
var customConfigPath string
// saveAuthConfig save auth config
func saveAuthConfig(a *AuthConfig) *probe.Error {
authConfigFile, err := getAuthConfigFile()
if err != nil {
return err.Trace()
}
qc, err := quick.New(a)
if err != nil {
return err.Trace()
}
if err := qc.Save(authConfigFile); err != nil {
return err.Trace()
}
return nil
}
// loadAuthConfig load auth config
func loadAuthConfig() (*AuthConfig, *probe.Error) {
authConfigFile, err := getAuthConfigFile()
if err != nil {
return nil, err.Trace()
}
if _, err := os.Stat(authConfigFile); err != nil {
return nil, probe.NewError(err)
}
a := &AuthConfig{}
a.Version = "1"
qc, err := quick.New(a)
if err != nil {
return nil, err.Trace()
}
if err := qc.Load(authConfigFile); err != nil {
return nil, err.Trace()
}
return qc.Data().(*AuthConfig), nil
}

@ -0,0 +1,78 @@
/*
* Minio Cloud Storage, (C) 2015 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 main
import "github.com/minio/cli"
// Configure logger
var configLoggerCmd = cli.Command{
Name: "logger",
Usage: "Configure logger.",
Action: mainConfigLogger,
CustomHelpTemplate: `NAME:
minio config {{.Name}} - {{.Usage}}
USAGE:
minio config {{.Name}}
`,
}
func mainConfigLogger(ctx *cli.Context) {
if !ctx.Args().Present() || ctx.Args().First() == "help" {
cli.ShowCommandHelpAndExit(ctx, "logger", 1) // last argument is exit code
}
if ctx.Args().Get(0) == "mongo" {
enableLog2Mongo(ctx.Args().Tail())
}
if ctx.Args().Get(0) == "syslog" {
enableLog2Syslog(ctx.Args().Tail())
}
if ctx.Args().Get(0) == "file" {
enableLog2File(ctx.Args().Tail())
}
}
func enableLog2Mongo(args cli.Args) {
config, err := loadConfigV2()
fatalIf(err.Trace(), "Unable to load config", nil)
config.MongoLogger.Addr = args.Get(0)
config.MongoLogger.DB = args.Get(1)
config.MongoLogger.Collection = args.Get(2)
err = saveConfig(config)
fatalIf(err.Trace(), "Unable to save config.", nil)
}
func enableLog2Syslog(args cli.Args) {
config, err := loadConfigV2()
fatalIf(err.Trace(), "Unable to load config.", nil)
config.SyslogLogger.Addr = args.Get(0)
config.SyslogLogger.Network = args.Get(1)
err = saveConfig(config)
fatalIf(err.Trace(), "Unable to save config.", nil)
}
func enableLog2File(args cli.Args) {
config, err := loadConfigV2()
fatalIf(err.Trace(), "Unable to load config.", nil)
config.FileLogger.Filename = args.Get(0)
err = saveConfig(config)
fatalIf(err.Trace(), "Unable to save config.", nil)
}

@ -0,0 +1,53 @@
/*
* Minio Cloud Storage, (C) 2015 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 main
import "github.com/minio/cli"
// Configure minio server
//
// ----
// NOTE: that the configure command only writes values to the config file.
// It does not use any configuration values from the environment variables.
// ----
//
var configCmd = cli.Command{
Name: "config",
Usage: "Collection of config management commands.",
Action: mainConfig,
Subcommands: []cli.Command{
configLoggerCmd,
configVersionCmd,
},
CustomHelpTemplate: `NAME:
{{.Name}} - {{.Usage}}
USAGE:
{{.Name}} {{if .Flags}}[global flags] {{end}}command{{if .Flags}} [command flags]{{end}} [arguments...]
COMMANDS:
{{range .Commands}}{{ .Name }}{{ "\t" }}{{.Usage}}
{{end}}
`,
}
// mainConfig is the handle for "minio config" command. provides sub-commands which write configuration data in json format to config file.
func mainConfig(ctx *cli.Context) {
if !ctx.Args().Present() || ctx.Args().First() == "help" {
cli.ShowAppHelp(ctx)
}
}

@ -0,0 +1,64 @@
/*
* Minio Cloud Storage, (C) 2015 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 main
import (
"encoding/json"
"github.com/minio/cli"
"github.com/minio/minio-xl/pkg/probe"
)
// Print config version.
var configVersionCmd = cli.Command{
Name: "version",
Usage: "Print config version.",
Action: mainConfigVersion,
CustomHelpTemplate: `NAME:
minio config {{.Name}} - {{.Usage}}
USAGE:
minio config {{.Name}}
`,
}
func mainConfigVersion(ctx *cli.Context) {
if ctx.Args().First() == "help" {
cli.ShowCommandHelpAndExit(ctx, "version", 1) // last argument is exit code
}
config, err := loadConfigV2()
fatalIf(err.Trace(), "Unable to load config", nil)
// convert interface{} back to its original struct
newConf := config
type Version struct {
Value string `json:"value"`
}
if globalJSONFlag {
tB, e := json.Marshal(
struct {
Version Version `json:"version"`
}{Version: Version{newConf.Version}},
)
fatalIf(probe.NewError(e), "Unable to construct version string.", nil)
Println(string(tB))
return
}
Println(newConf.Version)
}

@ -28,6 +28,12 @@ var (
Usage: "ADDRESS:PORT for cloud storage access.", Usage: "ADDRESS:PORT for cloud storage access.",
} }
loggerFlag = cli.StringFlag{
Name: "logger",
Value: "none",
Usage: "Choose type of logging. Available options are [‘file’, ‘mongo’, ‘syslog’]",
}
accessLogFlag = cli.BoolFlag{ accessLogFlag = cli.BoolFlag{
Name: "enable-accesslog", Name: "enable-accesslog",
Hide: true, Hide: true,

@ -0,0 +1,54 @@
package main
import (
"fmt"
"os"
"github.com/Sirupsen/logrus"
"github.com/minio/minio-xl/pkg/probe"
)
type localFile struct {
*os.File
}
func log2File(filename string) *probe.Error {
fileHook, e := newFile(filename)
if e != nil {
return probe.NewError(e)
}
log.Hooks.Add(fileHook) // Add a local file hook.
log.Formatter = &logrus.JSONFormatter{} // JSON formatted log.
log.Level = logrus.InfoLevel // Minimum log level.
return nil
}
func newFile(filename string) (*localFile, error) {
file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
return &localFile{file}, nil
}
func (l *localFile) Fire(entry *logrus.Entry) error {
line, err := entry.String()
if err != nil {
return fmt.Errorf("Unable to read entry, %v", err)
}
l.File.Write([]byte(line + "\n"))
l.File.Sync()
return nil
}
// Levels -
func (l *localFile) Levels() []logrus.Level {
return []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
logrus.WarnLevel,
logrus.InfoLevel,
logrus.DebugLevel,
}
}

@ -33,8 +33,8 @@ type syslogHook struct {
syslogRaddr string syslogRaddr string
} }
func log2Syslog(network, raddr string, priority syslog.Priority, tag string) *probe.Error { func log2Syslog(network, raddr string) *probe.Error {
syslogHook, e := newSyslog(network, raddr, priority, tag) syslogHook, e := newSyslog(network, raddr, syslog.LOG_ERR, "MINIO")
if e != nil { if e != nil {
return probe.NewError(e) return probe.NewError(e)
} }
@ -44,9 +44,7 @@ func log2Syslog(network, raddr string, priority syslog.Priority, tag string) *pr
return nil return nil
} }
// newSyslog - Creates a hook to be added to an instance of logger. This is called with // newSyslog - Creates a hook to be added to an instance of logger.
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
// `if err == nil { log.Hooks.Add(hook) }`
func newSyslog(network, raddr string, priority syslog.Priority, tag string) (*syslogHook, error) { func newSyslog(network, raddr string, priority syslog.Priority, tag string) (*syslogHook, error) {
w, err := syslog.Dial(network, raddr, priority, tag) w, err := syslog.Dial(network, raddr, priority, tag)
return &syslogHook{w, network, raddr}, err return &syslogHook{w, network, raddr}, err

@ -22,33 +22,11 @@ import (
"os/user" "os/user"
"runtime" "runtime"
"strconv" "strconv"
"time"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/minio/cli" "github.com/minio/cli"
) )
// serverConfig - http server config
type serverConfig struct {
/// HTTP server options
Address string // Address:Port listening
AccessLog bool // Enable access log handler
Anonymous bool // No signature turn off
/// FS options
Path string // Path to export for cloud storage
MinFreeDisk int64 // Minimum free disk space for filesystem
Expiry time.Duration // Set auto expiry for filesystem
// TLS service
TLS bool // TLS on when certs are specified
CertFile string // Domain certificate
KeyFile string // Domain key
/// Advanced HTTP server options
RateLimit int // Ratelimited server of incoming connections
}
func init() { func init() {
// Check for the environment early on and gracefuly report. // Check for the environment early on and gracefuly report.
_, err := user.Current() _, err := user.Current()
@ -64,6 +42,11 @@ func init() {
checkGolangRuntimeVersion() checkGolangRuntimeVersion()
} }
func migrate() {
// Migrate config file
migrateConfig()
}
// Tries to get os/arch/platform specific information // Tries to get os/arch/platform specific information
// Returns a map of current os/arch/platform/memstats // Returns a map of current os/arch/platform/memstats
func getSystemData() map[string]string { func getSystemData() map[string]string {
@ -101,6 +84,7 @@ func findClosestCommands(command string) []string {
func registerApp() *cli.App { func registerApp() *cli.App {
// register all commands // register all commands
registerCommand(serverCmd) registerCommand(serverCmd)
registerCommand(configCmd)
registerCommand(versionCmd) registerCommand(versionCmd)
registerCommand(updateCmd) registerCommand(updateCmd)
@ -166,6 +150,7 @@ func main() {
app := registerApp() app := registerApp()
app.Before = func(c *cli.Context) error { app.Before = func(c *cli.Context) error {
globalJSONFlag = c.GlobalBool("json") globalJSONFlag = c.GlobalBool("json")
migrate()
return nil return nil
} }
app.ExtraInfo = func() map[string]string { app.ExtraInfo = func() map[string]string {

@ -54,7 +54,7 @@ func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI) {
} }
// getNewCloudStorageAPI instantiate a new CloudStorageAPI // getNewCloudStorageAPI instantiate a new CloudStorageAPI
func getNewCloudStorageAPI(conf serverConfig) CloudStorageAPI { func getNewCloudStorageAPI(conf cloudServerConfig) CloudStorageAPI {
fs, err := fs.New() fs, err := fs.New()
fatalIf(err.Trace(), "Instantiating filesystem failed.", nil) fatalIf(err.Trace(), "Instantiating filesystem failed.", nil)

@ -0,0 +1,218 @@
/*
* Minio Cloud Storage, (C) 2015 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 main
import (
"errors"
"os"
"os/user"
"path/filepath"
"github.com/minio/minio-xl/pkg/probe"
"github.com/minio/minio-xl/pkg/quick"
)
// configV1
type configV1 struct {
Version string `json:"version"`
AccessKeyID string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
}
// configV2
type configV2 struct {
Version string `json:"version"`
Credentials struct {
AccessKeyID string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
} `json:"credentials"`
MongoLogger struct {
Addr string `json:"addr"`
DB string `json:"db"`
Collection string `json:"collection"`
} `json:"mongoLogger"`
SyslogLogger struct {
Network string `json:"network"`
Addr string `json:"addr"`
} `json:"syslogLogger"`
FileLogger struct {
Filename string `json:"filename"`
} `json:"fileLogger"`
}
// getConfigPath get users config path
func getConfigPath() (string, *probe.Error) {
if customConfigPath != "" {
return customConfigPath, nil
}
u, err := user.Current()
if err != nil {
return "", probe.NewError(err)
}
configPath := filepath.Join(u.HomeDir, ".minio")
return configPath, nil
}
// createConfigPath create users config path
func createConfigPath() *probe.Error {
configPath, err := getConfigPath()
if err != nil {
return err.Trace()
}
if err := os.MkdirAll(configPath, 0700); err != nil {
return probe.NewError(err)
}
return nil
}
// isAuthConfigFileExists is auth config file exists?
func isConfigFileExists() bool {
if _, err := os.Stat(mustGetConfigFile()); err != nil {
if os.IsNotExist(err) {
return false
}
panic(err)
}
return true
}
// mustGetConfigFile always get users config file, if not panic
func mustGetConfigFile() string {
configFile, err := getConfigFile()
if err != nil {
panic(err)
}
return configFile
}
// getConfigFile get users config file
func getConfigFile() (string, *probe.Error) {
configPath, err := getConfigPath()
if err != nil {
return "", err.Trace()
}
return filepath.Join(configPath, "config.json"), nil
}
// configPath for custom config path only for testing purposes
var customConfigPath string
// saveConfig save config
func saveConfig(a *configV2) *probe.Error {
configFile, err := getConfigFile()
if err != nil {
return err.Trace()
}
qc, err := quick.New(a)
if err != nil {
return err.Trace()
}
if err := qc.Save(configFile); err != nil {
return err.Trace()
}
return nil
}
// loadConfigV2 load config
func loadConfigV2() (*configV2, *probe.Error) {
configFile, err := getConfigFile()
if err != nil {
return nil, err.Trace()
}
if _, err := os.Stat(configFile); err != nil {
return nil, probe.NewError(err)
}
a := &configV2{}
a.Version = "2"
qc, err := quick.New(a)
if err != nil {
return nil, err.Trace()
}
if err := qc.Load(configFile); err != nil {
return nil, err.Trace()
}
return qc.Data().(*configV2), nil
}
// loadConfigV1 load config
func loadConfigV1() (*configV1, *probe.Error) {
configPath, err := getConfigPath()
if err != nil {
return nil, err.Trace()
}
configFile := filepath.Join(configPath, "fsUsers.json")
if _, err := os.Stat(configFile); err != nil {
return nil, probe.NewError(err)
}
a := &configV1{}
a.Version = "1"
qc, err := quick.New(a)
if err != nil {
return nil, err.Trace()
}
if err := qc.Load(configFile); err != nil {
return nil, err.Trace()
}
return qc.Data().(*configV1), nil
}
func newConfigV2() *configV2 {
config := &configV2{}
config.Version = "2"
config.Credentials.AccessKeyID = ""
config.Credentials.SecretAccessKey = ""
config.MongoLogger.Addr = ""
config.MongoLogger.DB = ""
config.MongoLogger.Collection = ""
config.SyslogLogger.Network = ""
config.SyslogLogger.Addr = ""
config.FileLogger.Filename = ""
return config
}
func migrateConfig() {
migrateV1ToV2()
}
func migrateV1ToV2() {
cv1, err := loadConfigV1()
if err != nil {
if os.IsNotExist(err.ToGoError()) {
return
}
}
fatalIf(err.Trace(), "Unable to load config version ‘1’.", nil)
if cv1.Version != "1" {
fatalIf(probe.NewError(errors.New("")), "Invalid version loaded ‘"+cv1.Version+"’.", nil)
}
cv2 := newConfigV2()
cv2.Credentials.AccessKeyID = cv1.AccessKeyID
cv2.Credentials.SecretAccessKey = cv1.SecretAccessKey
err = saveConfig(cv2)
fatalIf(err.Trace(), "Unable to save config version ‘2’.", nil)
Println("Migration from version ‘1’ to ‘2’ completed successfully.")
/// Purge old fsUsers.json file
configPath, err := getConfigPath()
fatalIf(err.Trace(), "Unable to retrieve config path.", nil)
configFile := filepath.Join(configPath, "fsUsers.json")
os.RemoveAll(configFile)
}

@ -63,8 +63,29 @@ EXAMPLES:
`, `,
} }
// cloudServerConfig - http server config
type cloudServerConfig struct {
/// HTTP server options
Address string // Address:Port listening
AccessLog bool // Enable access log handler
Anonymous bool // No signature turn off
/// FS options
Path string // Path to export for cloud storage
MinFreeDisk int64 // Minimum free disk space for filesystem
Expiry time.Duration // Set auto expiry for filesystem
// TLS service
TLS bool // TLS on when certs are specified
CertFile string // Domain certificate
KeyFile string // Domain key
/// Advanced HTTP server options
RateLimit int // Ratelimited server of incoming connections
}
// configureAPIServer configure a new server instance // configureAPIServer configure a new server instance
func configureAPIServer(conf serverConfig) (*http.Server, *probe.Error) { func configureAPIServer(conf cloudServerConfig) (*http.Server, *probe.Error) {
// Minio server config // Minio server config
apiServer := &http.Server{ apiServer := &http.Server{
Addr: conf.Address, Addr: conf.Address,
@ -118,7 +139,7 @@ func configureAPIServer(conf serverConfig) (*http.Server, *probe.Error) {
} }
// startServer starts an s3 compatible cloud storage server // startServer starts an s3 compatible cloud storage server
func startServer(conf serverConfig) *probe.Error { func startServer(conf cloudServerConfig) *probe.Error {
apiServer, err := configureAPIServer(conf) apiServer, err := configureAPIServer(conf)
if err != nil { if err != nil {
return err.Trace() return err.Trace()
@ -148,19 +169,19 @@ func parsePercentToInt(s string, bitSize int) (int64, *probe.Error) {
return p, nil return p, nil
} }
func getAuth() (*AuthConfig, *probe.Error) { func getAuth() (*configV2, *probe.Error) {
if err := createAuthConfigPath(); err != nil { if err := createConfigPath(); err != nil {
return nil, err.Trace() return nil, err.Trace()
} }
config, err := loadAuthConfig() config, err := loadConfigV2()
if err != nil { if err != nil {
if os.IsNotExist(err.ToGoError()) { if os.IsNotExist(err.ToGoError()) {
// Initialize new config, since config file doesn't exist yet // Initialize new config, since config file doesn't exist yet
config := &AuthConfig{} config := &configV2{}
config.Version = "1" config.Version = "2"
config.AccessKeyID = string(mustGenerateAccessKeyID()) config.Credentials.AccessKeyID = string(mustGenerateAccessKeyID())
config.SecretAccessKey = string(mustGenerateSecretAccessKey()) config.Credentials.SecretAccessKey = string(mustGenerateSecretAccessKey())
if err := saveAuthConfig(config); err != nil { if err := saveConfig(config); err != nil {
return nil, err.Trace() return nil, err.Trace()
} }
return config, nil return config, nil
@ -171,13 +192,13 @@ func getAuth() (*AuthConfig, *probe.Error) {
} }
type accessKeys struct { type accessKeys struct {
*AuthConfig *configV2
} }
func (a accessKeys) String() string { func (a accessKeys) String() string {
magenta := color.New(color.FgMagenta, color.Bold).SprintFunc() magenta := color.New(color.FgMagenta, color.Bold).SprintFunc()
white := color.New(color.FgWhite, color.Bold).SprintfFunc() white := color.New(color.FgWhite, color.Bold).SprintfFunc()
return fmt.Sprint(magenta("AccessKey: ") + white(a.AccessKeyID) + " " + magenta("SecretKey: ") + white(a.SecretAccessKey)) return fmt.Sprint(magenta("AccessKey: ") + white(a.Credentials.AccessKeyID) + " " + magenta("SecretKey: ") + white(a.Credentials.SecretAccessKey))
} }
// JSON - json formatted output // JSON - json formatted output
@ -205,13 +226,13 @@ func fetchAuth() *probe.Error {
Println("\nTo configure Minio Client.") Println("\nTo configure Minio Client.")
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
Println("\n\tDownload https://dl.minio.io:9000/updates/2015/Oct/" + runtime.GOOS + "-" + runtime.GOARCH + "/mc.exe") Println("\n\tDownload https://dl.minio.io:9000/updates/2015/Oct/" + runtime.GOOS + "-" + runtime.GOARCH + "/mc.exe")
Println("\t$ mc.exe config host add localhost:9000 " + conf.AccessKeyID + " " + conf.SecretAccessKey) Println("\t$ mc.exe config host add localhost:9000 " + conf.Credentials.AccessKeyID + " " + conf.Credentials.SecretAccessKey)
Println("\t$ mc.exe mb localhost/photobucket") Println("\t$ mc.exe mb localhost/photobucket")
Println("\t$ mc.exe cp C:\\Photos... localhost/photobucket") Println("\t$ mc.exe cp C:\\Photos... localhost/photobucket")
} else { } else {
Println("\n\t$ wget https://dl.minio.io:9000/updates/2015/Oct/" + runtime.GOOS + "-" + runtime.GOARCH + "/mc") Println("\n\t$ wget https://dl.minio.io:9000/updates/2015/Oct/" + runtime.GOOS + "-" + runtime.GOARCH + "/mc")
Println("\t$ chmod 755 mc") Println("\t$ chmod 755 mc")
Println("\t$ ./mc config host add localhost:9000 " + conf.AccessKeyID + " " + conf.SecretAccessKey) Println("\t$ ./mc config host add localhost:9000 " + conf.Credentials.AccessKeyID + " " + conf.Credentials.SecretAccessKey)
Println("\t$ ./mc mb localhost/photobucket") Println("\t$ ./mc mb localhost/photobucket")
Println("\t$ ./mc cp ~/Photos... localhost/photobucket") Println("\t$ ./mc cp ~/Photos... localhost/photobucket")
} }
@ -287,7 +308,7 @@ func serverMain(c *cli.Context) {
fatalIf(probe.NewError(err), "Unable to validate the path", nil) fatalIf(probe.NewError(err), "Unable to validate the path", nil)
} }
tls := (certFile != "" && keyFile != "") tls := (certFile != "" && keyFile != "")
apiServerConfig := serverConfig{ apiServerConfig := cloudServerConfig{
Address: c.GlobalString("address"), Address: c.GlobalString("address"),
AccessLog: c.GlobalBool("enable-accesslog"), AccessLog: c.GlobalBool("enable-accesslog"),
Anonymous: c.GlobalBool("anonymous"), Anonymous: c.GlobalBool("anonymous"),

@ -70,24 +70,24 @@ func (s *MyAPIFSCacheSuite) SetUpSuite(c *C) {
secretAccessKey, perr := generateSecretAccessKey() secretAccessKey, perr := generateSecretAccessKey()
c.Assert(perr, IsNil) c.Assert(perr, IsNil)
authConf := &AuthConfig{} conf := newConfigV2()
authConf.AccessKeyID = string(accessKeyID) conf.Credentials.AccessKeyID = string(accessKeyID)
authConf.SecretAccessKey = string(secretAccessKey) conf.Credentials.SecretAccessKey = string(secretAccessKey)
s.accessKeyID = string(accessKeyID) s.accessKeyID = string(accessKeyID)
s.secretAccessKey = string(secretAccessKey) s.secretAccessKey = string(secretAccessKey)
// do this only once here // do this only once here
customConfigPath = root customConfigPath = root
perr = saveAuthConfig(authConf) perr = saveConfig(conf)
c.Assert(perr, IsNil) c.Assert(perr, IsNil)
server := serverConfig{ cloudServer := cloudServerConfig{
Path: fsroot, Path: fsroot,
MinFreeDisk: 0, MinFreeDisk: 0,
Anonymous: false, Anonymous: false,
} }
cloudStorageAPI := getNewCloudStorageAPI(server) cloudStorageAPI := getNewCloudStorageAPI(cloudServer)
httpHandler := getCloudStorageAPIHandler(cloudStorageAPI) httpHandler := getCloudStorageAPIHandler(cloudStorageAPI)
testAPIFSCacheServer = httptest.NewServer(httpHandler) testAPIFSCacheServer = httptest.NewServer(httpHandler)
} }

Loading…
Cancel
Save