2016-08-19 01:23:42 +02:00
/ *
* Minio Cloud Storage , ( C ) 2015 , 2016 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 cmd
import (
2016-09-21 18:44:57 +02:00
"errors"
2016-08-19 01:23:42 +02:00
"fmt"
"os"
"sort"
2016-08-19 17:09:05 +02:00
"strings"
2016-10-13 03:09:08 +02:00
"time"
2016-08-19 01:23:42 +02:00
"github.com/minio/cli"
"github.com/minio/mc/pkg/console"
)
var (
// global flags for minio.
2016-09-02 00:12:49 +02:00
globalFlags = [ ] cli . Flag {
2016-08-19 01:23:42 +02:00
cli . BoolFlag {
Name : "help, h" ,
Usage : "Show help." ,
} ,
2016-09-02 00:12:49 +02:00
cli . StringFlag {
Name : "config-dir, C" ,
Value : mustGetConfigPath ( ) ,
Usage : "Path to configuration folder." ,
} ,
cli . BoolFlag {
Name : "quiet" ,
Usage : "Suppress chatty output." ,
} ,
2016-08-19 01:23:42 +02:00
}
)
// Help template for minio.
var minioHelpTemplate = ` NAME :
{ { . Name } } - { { . Usage } }
DESCRIPTION :
{ { . Description } }
USAGE :
minio { { if . Flags } } [ flags ] { { end } } command { { if . Flags } } { { end } } [ arguments ... ]
COMMANDS :
{ { range . Commands } } { { join . Names ", " } } { { "\t" } } { { . Usage } }
{ { end } } { { if . Flags } }
FLAGS :
{ { range . Flags } } { { . } }
{ { end } } { { end } }
VERSION :
` + Version +
` {{ "\n" }} `
// init - check the environment before main starts
func init ( ) {
// Check if minio was compiled using a supported version of Golang.
checkGoVersion ( )
// Set global trace flag.
globalTrace = os . Getenv ( "MINIO_TRACE" ) == "1"
}
func migrate ( ) {
// Migrate config file
2016-09-21 18:44:57 +02:00
err := migrateConfig ( )
fatalIf ( err , "Config migration failed." )
2016-08-19 01:23:42 +02:00
// Migrate other configs here.
}
func enableLoggers ( ) {
// Enable all loggers here.
enableConsoleLogger ( )
enableFileLogger ( )
// Add your logger here.
}
func findClosestCommands ( command string ) [ ] string {
var closestCommands [ ] string
for _ , value := range commandsTree . PrefixMatch ( command ) {
closestCommands = append ( closestCommands , value . ( string ) )
}
sort . Strings ( closestCommands )
// Suggest other close commands - allow missed, wrongly added and
// even transposed characters
for _ , value := range commandsTree . walk ( commandsTree . root ) {
if sort . SearchStrings ( closestCommands , value . ( string ) ) < len ( closestCommands ) {
continue
}
// 2 is arbitrary and represents the max
// allowed number of typed errors
if DamerauLevenshteinDistance ( command , value . ( string ) ) < 2 {
closestCommands = append ( closestCommands , value . ( string ) )
}
}
return closestCommands
}
func registerApp ( ) * cli . App {
// Register all commands.
registerCommand ( serverCmd )
registerCommand ( versionCmd )
registerCommand ( updateCmd )
registerCommand ( controlCmd )
// Set up app.
app := cli . NewApp ( )
app . Name = "Minio"
app . Author = "Minio.io"
app . Usage = "Cloud Storage Server."
app . Description = ` Minio is an Amazon S3 compatible object storage server. Use it to store photos, videos, VMs, containers, log files, or any blob of data as objects. `
2016-09-02 00:12:49 +02:00
app . Flags = globalFlags
2016-08-19 01:23:42 +02:00
app . Commands = commands
app . CustomAppHelpTemplate = minioHelpTemplate
app . CommandNotFound = func ( ctx * cli . Context , command string ) {
msg := fmt . Sprintf ( "‘ %s’ is not a minio sub-command. See ‘ minio --help’ ." , command )
closestCommands := findClosestCommands ( command )
if len ( closestCommands ) > 0 {
msg += fmt . Sprintf ( "\n\nDid you mean one of these?\n" )
for _ , cmd := range closestCommands {
msg += fmt . Sprintf ( " ‘ %s’ \n" , cmd )
}
}
console . Fatalln ( msg )
}
return app
}
2016-09-02 05:13:11 +02:00
// Verify main command syntax.
2016-08-19 01:23:42 +02:00
func checkMainSyntax ( c * cli . Context ) {
configPath , err := getConfigPath ( )
if err != nil {
console . Fatalf ( "Unable to obtain user's home directory. \nError: %s\n" , err )
}
if configPath == "" {
console . Fatalln ( "Config folder cannot be empty, please specify --config-dir <foldername>." )
}
}
2016-09-02 05:13:11 +02:00
// Main main for minio server.
2016-08-19 01:23:42 +02:00
func Main ( ) {
app := registerApp ( )
app . Before = func ( c * cli . Context ) error {
2016-09-21 18:44:57 +02:00
configDir := c . GlobalString ( "config-dir" )
if configDir == "" {
fatalIf ( errors . New ( "Config directory is empty" ) , "Unable to get config file." )
}
2016-08-19 01:23:42 +02:00
// Sets new config folder.
2016-09-21 18:44:57 +02:00
setGlobalConfigPath ( configDir )
2016-08-19 01:23:42 +02:00
// Valid input arguments to main.
checkMainSyntax ( c )
// Migrate any old version of config / state files to newer format.
migrate ( )
// Initialize config.
2016-10-27 03:44:22 +02:00
configCreated , err := initConfig ( )
2016-08-19 01:23:42 +02:00
fatalIf ( err , "Unable to initialize minio config." )
2016-10-27 03:44:22 +02:00
if configCreated {
console . Println ( "Created minio configuration file at " + mustGetConfigPath ( ) )
}
2016-08-19 01:23:42 +02:00
2016-10-18 08:14:41 +02:00
// Fetch access keys from environment variables and update the config.
accessKey := os . Getenv ( "MINIO_ACCESS_KEY" )
secretKey := os . Getenv ( "MINIO_SECRET_KEY" )
if accessKey != "" && secretKey != "" {
// Set new credentials.
serverConfig . SetCredential ( credential {
AccessKeyID : accessKey ,
SecretAccessKey : secretKey ,
} )
}
2016-10-21 01:07:24 +02:00
if ! isValidAccessKey . MatchString ( serverConfig . GetCredential ( ) . AccessKeyID ) {
fatalIf ( errInvalidArgument , "Invalid access key. Accept only a string starting with a alphabetic and containing from 5 to 20 characters." )
}
if ! isValidSecretKey . MatchString ( serverConfig . GetCredential ( ) . SecretAccessKey ) {
fatalIf ( errInvalidArgument , "Invalid secret key. Accept only a string containing from 8 to 40 characters." )
}
2016-10-18 08:14:41 +02:00
2016-08-19 01:23:42 +02:00
// Enable all loggers by now.
enableLoggers ( )
2016-08-25 18:39:01 +02:00
// Init the error tracing module.
initError ( )
2016-08-19 01:23:42 +02:00
// Set global quiet flag.
globalQuiet = c . Bool ( "quiet" ) || c . GlobalBool ( "quiet" )
// Do not print update messages, if quiet flag is set.
if ! globalQuiet {
2016-10-13 03:09:08 +02:00
if strings . HasPrefix ( ReleaseTag , "RELEASE." ) && c . Args ( ) . Get ( 0 ) != "update" {
updateMsg , _ , err := getReleaseUpdate ( minioUpdateStableURL , 1 * time . Second )
2016-08-19 17:09:05 +02:00
if err != nil {
2016-10-13 03:09:08 +02:00
// Ignore any errors during getReleaseUpdate(), possibly
// because of network errors.
2016-08-19 17:09:05 +02:00
return nil
}
2016-10-13 18:17:08 +02:00
if updateMsg . Update {
console . Println ( updateMsg )
}
2016-08-19 01:23:42 +02:00
}
}
return nil
}
2016-09-02 05:13:11 +02:00
// Start profiler if env is set.
if profiler := os . Getenv ( "MINIO_PROFILER" ) ; profiler != "" {
globalProfiler = startProfiler ( profiler )
2016-08-19 01:23:42 +02:00
}
// Run the app - exit on error.
app . RunAndExitOnError ( )
}