mirror of
https://github.com/minio/minio.git
synced 2025-01-25 13:43:17 -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 {
|
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,
|
||||||
|
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.",
|
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,
|
||||||
|
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
|
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
|
||||||
|
29
main.go
29
main.go
@ -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)
|
||||||
|
|
||||||
|
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
|
// 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…
x
Reference in New Issue
Block a user