mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
Add logger command - also migrate from old config to newer config
This commit is contained in:
parent
e8892a9f3c
commit
56003fded7
@ -105,17 +105,17 @@ func initSignatureV4(req *http.Request) (*fs.Signature, *probe.Error) {
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
authConfig, err := loadAuthConfig()
|
||||
config, err := loadConfigV2()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
authFields := strings.Split(strings.TrimSpace(authHeaderValue), ",")
|
||||
signedHeaders := strings.Split(strings.Split(strings.TrimSpace(authFields[1]), "=")[1], ";")
|
||||
signature := strings.Split(strings.TrimSpace(authFields[2]), "=")[1]
|
||||
if authConfig.AccessKeyID == accessKeyID {
|
||||
if config.Credentials.AccessKeyID == accessKeyID {
|
||||
signature := &fs.Signature{
|
||||
AccessKeyID: authConfig.AccessKeyID,
|
||||
SecretAccessKey: authConfig.SecretAccessKey,
|
||||
AccessKeyID: config.Credentials.AccessKeyID,
|
||||
SecretAccessKey: config.Credentials.SecretAccessKey,
|
||||
Signature: signature,
|
||||
SignedHeaders: signedHeaders,
|
||||
Request: req,
|
||||
@ -210,14 +210,14 @@ func initPostPresignedPolicyV4(formValues map[string]string) (*fs.Signature, *pr
|
||||
if !isValidAccessKey(accessKeyID) {
|
||||
return nil, probe.NewError(errAccessKeyIDInvalid)
|
||||
}
|
||||
authConfig, perr := loadAuthConfig()
|
||||
config, perr := loadConfigV2()
|
||||
if perr != nil {
|
||||
return nil, perr.Trace()
|
||||
}
|
||||
if authConfig.AccessKeyID == accessKeyID {
|
||||
if config.Credentials.AccessKeyID == accessKeyID {
|
||||
signature := &fs.Signature{
|
||||
AccessKeyID: authConfig.AccessKeyID,
|
||||
SecretAccessKey: authConfig.SecretAccessKey,
|
||||
AccessKeyID: config.Credentials.AccessKeyID,
|
||||
SecretAccessKey: config.Credentials.SecretAccessKey,
|
||||
Signature: formValues["X-Amz-Signature"],
|
||||
PresignedPolicy: formValues["Policy"],
|
||||
}
|
||||
@ -236,16 +236,16 @@ func initPresignedSignatureV4(req *http.Request) (*fs.Signature, *probe.Error) {
|
||||
if !isValidAccessKey(accessKeyID) {
|
||||
return nil, probe.NewError(errAccessKeyIDInvalid)
|
||||
}
|
||||
authConfig, err := loadAuthConfig()
|
||||
config, err := loadConfigV2()
|
||||
if err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
signedHeaders := strings.Split(strings.TrimSpace(req.URL.Query().Get("X-Amz-SignedHeaders")), ";")
|
||||
signature := strings.TrimSpace(req.URL.Query().Get("X-Amz-Signature"))
|
||||
if authConfig.AccessKeyID == accessKeyID {
|
||||
if config.Credentials.AccessKeyID == accessKeyID {
|
||||
signature := &fs.Signature{
|
||||
AccessKeyID: authConfig.AccessKeyID,
|
||||
SecretAccessKey: authConfig.SecretAccessKey,
|
||||
AccessKeyID: config.Credentials.AccessKeyID,
|
||||
SecretAccessKey: config.Credentials.SecretAccessKey,
|
||||
Signature: signature,
|
||||
SignedHeaders: signedHeaders,
|
||||
Presigned: true,
|
||||
|
127
auth-config.go
127
auth-config.go
@ -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
|
||||
}
|
78
config-logger-main.go
Normal file
78
config-logger-main.go
Normal file
@ -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)
|
||||
}
|
53
config-main.go
Normal file
53
config-main.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
64
config-version-main.go
Normal file
64
config-version-main.go
Normal file
@ -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)
|
||||
}
|
6
flags.go
6
flags.go
@ -28,6 +28,12 @@ var (
|
||||
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{
|
||||
Name: "enable-accesslog",
|
||||
Hide: true,
|
||||
|
54
logger-file-hook.go
Normal file
54
logger-file-hook.go
Normal file
@ -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
|
||||
}
|
||||
|
||||
func log2Syslog(network, raddr string, priority syslog.Priority, tag string) *probe.Error {
|
||||
syslogHook, e := newSyslog(network, raddr, priority, tag)
|
||||
func log2Syslog(network, raddr string) *probe.Error {
|
||||
syslogHook, e := newSyslog(network, raddr, syslog.LOG_ERR, "MINIO")
|
||||
if e != nil {
|
||||
return probe.NewError(e)
|
||||
}
|
||||
@ -44,9 +44,7 @@ func log2Syslog(network, raddr string, priority syslog.Priority, tag string) *pr
|
||||
return nil
|
||||
}
|
||||
|
||||
// newSyslog - Creates a hook to be added to an instance of logger. This is called with
|
||||
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
|
||||
// `if err == nil { log.Hooks.Add(hook) }`
|
||||
// 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
|
||||
|
29
main.go
29
main.go
@ -22,33 +22,11 @@ import (
|
||||
"os/user"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"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() {
|
||||
// Check for the environment early on and gracefuly report.
|
||||
_, err := user.Current()
|
||||
@ -64,6 +42,11 @@ func init() {
|
||||
checkGolangRuntimeVersion()
|
||||
}
|
||||
|
||||
func migrate() {
|
||||
// Migrate config file
|
||||
migrateConfig()
|
||||
}
|
||||
|
||||
// Tries to get os/arch/platform specific information
|
||||
// Returns a map of current os/arch/platform/memstats
|
||||
func getSystemData() map[string]string {
|
||||
@ -101,6 +84,7 @@ func findClosestCommands(command string) []string {
|
||||
func registerApp() *cli.App {
|
||||
// register all commands
|
||||
registerCommand(serverCmd)
|
||||
registerCommand(configCmd)
|
||||
registerCommand(versionCmd)
|
||||
registerCommand(updateCmd)
|
||||
|
||||
@ -166,6 +150,7 @@ func main() {
|
||||
app := registerApp()
|
||||
app.Before = func(c *cli.Context) error {
|
||||
globalJSONFlag = c.GlobalBool("json")
|
||||
migrate()
|
||||
return nil
|
||||
}
|
||||
app.ExtraInfo = func() map[string]string {
|
||||
|
@ -54,7 +54,7 @@ func registerCloudStorageAPI(mux *router.Router, a CloudStorageAPI) {
|
||||
}
|
||||
|
||||
// getNewCloudStorageAPI instantiate a new CloudStorageAPI
|
||||
func getNewCloudStorageAPI(conf serverConfig) CloudStorageAPI {
|
||||
func getNewCloudStorageAPI(conf cloudServerConfig) CloudStorageAPI {
|
||||
fs, err := fs.New()
|
||||
fatalIf(err.Trace(), "Instantiating filesystem failed.", nil)
|
||||
|
||||
|
218
server-config.go
Normal file
218
server-config.go
Normal file
@ -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
|
||||
func configureAPIServer(conf serverConfig) (*http.Server, *probe.Error) {
|
||||
func configureAPIServer(conf cloudServerConfig) (*http.Server, *probe.Error) {
|
||||
// Minio server config
|
||||
apiServer := &http.Server{
|
||||
Addr: conf.Address,
|
||||
@ -118,7 +139,7 @@ func configureAPIServer(conf serverConfig) (*http.Server, *probe.Error) {
|
||||
}
|
||||
|
||||
// startServer starts an s3 compatible cloud storage server
|
||||
func startServer(conf serverConfig) *probe.Error {
|
||||
func startServer(conf cloudServerConfig) *probe.Error {
|
||||
apiServer, err := configureAPIServer(conf)
|
||||
if err != nil {
|
||||
return err.Trace()
|
||||
@ -148,19 +169,19 @@ func parsePercentToInt(s string, bitSize int) (int64, *probe.Error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func getAuth() (*AuthConfig, *probe.Error) {
|
||||
if err := createAuthConfigPath(); err != nil {
|
||||
func getAuth() (*configV2, *probe.Error) {
|
||||
if err := createConfigPath(); err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
config, err := loadAuthConfig()
|
||||
config, err := loadConfigV2()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err.ToGoError()) {
|
||||
// Initialize new config, since config file doesn't exist yet
|
||||
config := &AuthConfig{}
|
||||
config.Version = "1"
|
||||
config.AccessKeyID = string(mustGenerateAccessKeyID())
|
||||
config.SecretAccessKey = string(mustGenerateSecretAccessKey())
|
||||
if err := saveAuthConfig(config); err != nil {
|
||||
config := &configV2{}
|
||||
config.Version = "2"
|
||||
config.Credentials.AccessKeyID = string(mustGenerateAccessKeyID())
|
||||
config.Credentials.SecretAccessKey = string(mustGenerateSecretAccessKey())
|
||||
if err := saveConfig(config); err != nil {
|
||||
return nil, err.Trace()
|
||||
}
|
||||
return config, nil
|
||||
@ -171,13 +192,13 @@ func getAuth() (*AuthConfig, *probe.Error) {
|
||||
}
|
||||
|
||||
type accessKeys struct {
|
||||
*AuthConfig
|
||||
*configV2
|
||||
}
|
||||
|
||||
func (a accessKeys) String() string {
|
||||
magenta := color.New(color.FgMagenta, color.Bold).SprintFunc()
|
||||
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
|
||||
@ -205,13 +226,13 @@ func fetchAuth() *probe.Error {
|
||||
Println("\nTo configure Minio Client.")
|
||||
if runtime.GOOS == "windows" {
|
||||
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 cp C:\\Photos... localhost/photobucket")
|
||||
} else {
|
||||
Println("\n\t$ wget https://dl.minio.io:9000/updates/2015/Oct/" + runtime.GOOS + "-" + runtime.GOARCH + "/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 cp ~/Photos... localhost/photobucket")
|
||||
}
|
||||
@ -287,7 +308,7 @@ func serverMain(c *cli.Context) {
|
||||
fatalIf(probe.NewError(err), "Unable to validate the path", nil)
|
||||
}
|
||||
tls := (certFile != "" && keyFile != "")
|
||||
apiServerConfig := serverConfig{
|
||||
apiServerConfig := cloudServerConfig{
|
||||
Address: c.GlobalString("address"),
|
||||
AccessLog: c.GlobalBool("enable-accesslog"),
|
||||
Anonymous: c.GlobalBool("anonymous"),
|
||||
|
@ -70,24 +70,24 @@ func (s *MyAPIFSCacheSuite) SetUpSuite(c *C) {
|
||||
secretAccessKey, perr := generateSecretAccessKey()
|
||||
c.Assert(perr, IsNil)
|
||||
|
||||
authConf := &AuthConfig{}
|
||||
authConf.AccessKeyID = string(accessKeyID)
|
||||
authConf.SecretAccessKey = string(secretAccessKey)
|
||||
conf := newConfigV2()
|
||||
conf.Credentials.AccessKeyID = string(accessKeyID)
|
||||
conf.Credentials.SecretAccessKey = string(secretAccessKey)
|
||||
s.accessKeyID = string(accessKeyID)
|
||||
s.secretAccessKey = string(secretAccessKey)
|
||||
|
||||
// do this only once here
|
||||
customConfigPath = root
|
||||
|
||||
perr = saveAuthConfig(authConf)
|
||||
perr = saveConfig(conf)
|
||||
c.Assert(perr, IsNil)
|
||||
|
||||
server := serverConfig{
|
||||
cloudServer := cloudServerConfig{
|
||||
Path: fsroot,
|
||||
MinFreeDisk: 0,
|
||||
Anonymous: false,
|
||||
}
|
||||
cloudStorageAPI := getNewCloudStorageAPI(server)
|
||||
cloudStorageAPI := getNewCloudStorageAPI(cloudServer)
|
||||
httpHandler := getCloudStorageAPIHandler(cloudStorageAPI)
|
||||
testAPIFSCacheServer = httptest.NewServer(httpHandler)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user