| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  |  * Minio Cloud Storage, (C) 2016, 2017, 2018 Minio, Inc. | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-03-16 04:27:16 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | 	"crypto/x509" | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-06-01 00:21:28 +08:00
										 |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 03:48:07 +08:00
										 |  |  | 	humanize "github.com/dustin/go-humanize" | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Documentation links, these are part of message printing code.
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2017-05-24 04:57:27 +08:00
										 |  |  | 	mcQuickStartGuide     = "https://docs.minio.io/docs/minio-client-quickstart-guide" | 
					
						
							|  |  |  | 	goQuickStartGuide     = "https://docs.minio.io/docs/golang-client-quickstart-guide" | 
					
						
							|  |  |  | 	jsQuickStartGuide     = "https://docs.minio.io/docs/javascript-client-quickstart-guide" | 
					
						
							|  |  |  | 	javaQuickStartGuide   = "https://docs.minio.io/docs/java-client-quickstart-guide" | 
					
						
							|  |  |  | 	pyQuickStartGuide     = "https://docs.minio.io/docs/python-client-quickstart-guide" | 
					
						
							|  |  |  | 	dotnetQuickStartGuide = "https://docs.minio.io/docs/dotnet-client-quickstart-guide" | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // generates format string depending on the string length and padding.
 | 
					
						
							|  |  |  | func getFormatStr(strLen int, padding int) string { | 
					
						
							|  |  |  | 	formatStr := fmt.Sprintf("%ds", strLen+padding) | 
					
						
							|  |  |  | 	return "%" + formatStr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Prints the formatted startup message.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | func printStartupMessage(apiEndPoints []string) { | 
					
						
							| 
									
										
										
										
											2017-04-13 00:22:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-01 00:21:28 +08:00
										 |  |  | 	strippedAPIEndpoints := stripStandardPorts(apiEndPoints) | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | 	// If cache layer is enabled, print cache capacity.
 | 
					
						
							|  |  |  | 	cacheObjectAPI := newCacheObjectsFn() | 
					
						
							|  |  |  | 	if cacheObjectAPI != nil { | 
					
						
							|  |  |  | 		printCacheStorageInfo(cacheObjectAPI.StorageInfo(context.Background())) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-12-22 19:28:13 +08:00
										 |  |  | 	// Object layer is initialized then print StorageInfo.
 | 
					
						
							|  |  |  | 	objAPI := newObjectLayerFn() | 
					
						
							|  |  |  | 	if objAPI != nil { | 
					
						
							| 
									
										
										
										
											2018-03-16 04:27:16 +08:00
										 |  |  | 		printStorageInfo(objAPI.StorageInfo(context.Background())) | 
					
						
							| 
									
										
										
										
											2017-12-22 19:28:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 	// Prints credential, region and browser access.
 | 
					
						
							| 
									
										
										
										
											2017-06-01 00:21:28 +08:00
										 |  |  | 	printServerCommonMsg(strippedAPIEndpoints) | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Prints `mc` cli configuration message chooses
 | 
					
						
							|  |  |  | 	// first endpoint as default.
 | 
					
						
							| 
									
										
										
										
											2017-06-10 10:50:51 +08:00
										 |  |  | 	printCLIAccessMsg(strippedAPIEndpoints[0], "myminio") | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Prints documentation message.
 | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	printObjectAPIMsg() | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 	// SSL is configured reads certification chain, prints
 | 
					
						
							|  |  |  | 	// authority and expiry.
 | 
					
						
							| 
									
										
										
										
											2017-01-12 05:59:51 +08:00
										 |  |  | 	if globalIsSSL { | 
					
						
							| 
									
										
										
										
											2017-03-31 02:21:19 +08:00
										 |  |  | 		printCertificateMsg(globalPublicCerts) | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-01 00:21:28 +08:00
										 |  |  | // strip api endpoints list with standard ports such as
 | 
					
						
							|  |  |  | // port "80" and "443" before displaying on the startup
 | 
					
						
							|  |  |  | // banner.  Returns a new list of API endpoints.
 | 
					
						
							|  |  |  | func stripStandardPorts(apiEndpoints []string) (newAPIEndpoints []string) { | 
					
						
							|  |  |  | 	newAPIEndpoints = make([]string, len(apiEndpoints)) | 
					
						
							|  |  |  | 	// Check all API endpoints for standard ports and strip them.
 | 
					
						
							|  |  |  | 	for i, apiEndpoint := range apiEndpoints { | 
					
						
							|  |  |  | 		url, err := url.Parse(apiEndpoint) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			newAPIEndpoints[i] = apiEndpoint | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		host, port := mustSplitHostPort(url.Host) | 
					
						
							|  |  |  | 		// For standard HTTP(s) ports such as "80" and "443"
 | 
					
						
							|  |  |  | 		// apiEndpoints should only be host without port.
 | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		case url.Scheme == "http" && port == "80": | 
					
						
							|  |  |  | 			fallthrough | 
					
						
							|  |  |  | 		case url.Scheme == "https" && port == "443": | 
					
						
							|  |  |  | 			url.Host = host | 
					
						
							|  |  |  | 			newAPIEndpoints[i] = url.String() | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			newAPIEndpoints[i] = apiEndpoint | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return newAPIEndpoints | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | // Prints common server startup message. Prints credential, region and browser access.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | func printServerCommonMsg(apiEndpoints []string) { | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	// Get saved credentials.
 | 
					
						
							| 
									
										
										
										
											2017-11-30 05:12:47 +08:00
										 |  |  | 	cred := globalServerConfig.GetCredential() | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Get saved region.
 | 
					
						
							| 
									
										
										
										
											2017-11-30 05:12:47 +08:00
										 |  |  | 	region := globalServerConfig.GetRegion() | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 	apiEndpointStr := strings.Join(apiEndpoints, "  ") | 
					
						
							| 
									
										
										
										
											2017-06-01 00:21:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	// Colorize the message and print.
 | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 	logger.StartupMessage(colorBlue("Endpoint: ") + colorBold(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 1), apiEndpointStr))) | 
					
						
							| 
									
										
										
										
											2018-10-17 04:19:12 +08:00
										 |  |  | 	if isTerminal() { | 
					
						
							|  |  |  | 		logger.StartupMessage(colorBlue("AccessKey: ") + colorBold(fmt.Sprintf("%s ", cred.AccessKey))) | 
					
						
							|  |  |  | 		logger.StartupMessage(colorBlue("SecretKey: ") + colorBold(fmt.Sprintf("%s ", cred.SecretKey))) | 
					
						
							|  |  |  | 		if region != "" { | 
					
						
							|  |  |  | 			logger.StartupMessage(colorBlue("Region: ") + colorBold(fmt.Sprintf(getFormatStr(len(region), 3), region))) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-16 09:17:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-14 16:11:03 +08:00
										 |  |  | 	printEventNotifiers() | 
					
						
							| 
									
										
										
										
											2016-09-14 02:00:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-04 13:30:52 +08:00
										 |  |  | 	if globalIsBrowserEnabled { | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 		logger.StartupMessage(colorBlue("\nBrowser Access:")) | 
					
						
							|  |  |  | 		logger.StartupMessage(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 3), apiEndpointStr)) | 
					
						
							| 
									
										
										
										
											2018-01-04 13:30:52 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-14 02:00:40 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Prints bucket notification configurations.
 | 
					
						
							|  |  |  | func printEventNotifiers() { | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	arns := globalNotificationSys.GetARNList() | 
					
						
							|  |  |  | 	if len(arns) == 0 { | 
					
						
							| 
									
										
										
										
											2017-05-16 09:17:02 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-09-14 02:00:40 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 09:17:02 +08:00
										 |  |  | 	arnMsg := colorBlue("SQS ARNs: ") | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 	for _, arn := range arns { | 
					
						
							|  |  |  | 		arnMsg += colorBold(fmt.Sprintf(getFormatStr(len(arn), 1), arn)) | 
					
						
							| 
									
										
										
										
											2016-09-10 17:23:28 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-16 04:03:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 	logger.StartupMessage(arnMsg) | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Prints startup message for command line access. Prints link to our documentation
 | 
					
						
							|  |  |  | // and custom platform specific message.
 | 
					
						
							| 
									
										
										
										
											2017-06-10 10:50:51 +08:00
										 |  |  | func printCLIAccessMsg(endPoint string, alias string) { | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	// Get saved credentials.
 | 
					
						
							| 
									
										
										
										
											2017-11-30 05:12:47 +08:00
										 |  |  | 	cred := globalServerConfig.GetCredential() | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Configure 'mc', following block prints platform specific information for minio client.
 | 
					
						
							| 
									
										
										
										
											2018-10-17 04:19:12 +08:00
										 |  |  | 	if isTerminal() { | 
					
						
							|  |  |  | 		logger.StartupMessage(colorBlue("\nCommand-line Access: ") + mcQuickStartGuide) | 
					
						
							|  |  |  | 		if runtime.GOOS == globalWindowsOSName { | 
					
						
							|  |  |  | 			mcMessage := fmt.Sprintf("$ mc.exe config host add %s %s %s %s", alias, endPoint, cred.AccessKey, cred.SecretKey) | 
					
						
							|  |  |  | 			logger.StartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			mcMessage := fmt.Sprintf("$ mc config host add %s %s %s %s", alias, endPoint, cred.AccessKey, cred.SecretKey) | 
					
						
							|  |  |  | 			logger.StartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Prints startup message for Object API acces, prints link to our SDK documentation.
 | 
					
						
							|  |  |  | func printObjectAPIMsg() { | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 	logger.StartupMessage(colorBlue("\nObject API (Amazon S3 compatible):")) | 
					
						
							|  |  |  | 	logger.StartupMessage(colorBlue("   Go: ") + fmt.Sprintf(getFormatStr(len(goQuickStartGuide), 8), goQuickStartGuide)) | 
					
						
							|  |  |  | 	logger.StartupMessage(colorBlue("   Java: ") + fmt.Sprintf(getFormatStr(len(javaQuickStartGuide), 6), javaQuickStartGuide)) | 
					
						
							|  |  |  | 	logger.StartupMessage(colorBlue("   Python: ") + fmt.Sprintf(getFormatStr(len(pyQuickStartGuide), 4), pyQuickStartGuide)) | 
					
						
							|  |  |  | 	logger.StartupMessage(colorBlue("   JavaScript: ") + jsQuickStartGuide) | 
					
						
							|  |  |  | 	logger.StartupMessage(colorBlue("   .NET: ") + fmt.Sprintf(getFormatStr(len(dotnetQuickStartGuide), 6), dotnetQuickStartGuide)) | 
					
						
							| 
									
										
										
										
											2016-07-13 14:21:18 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-06 03:48:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Get formatted disk/storage info message.
 | 
					
						
							| 
									
										
										
										
											2016-10-10 14:03:10 +08:00
										 |  |  | func getStorageInfoMsg(storageInfo StorageInfo) string { | 
					
						
							| 
									
										
										
										
											2018-05-24 08:30:25 +08:00
										 |  |  | 	var msg string | 
					
						
							| 
									
										
										
										
											2018-08-24 14:35:37 +08:00
										 |  |  | 	if storageInfo.Backend.Type == BackendErasure { | 
					
						
							| 
									
										
										
										
											2016-10-23 01:36:50 +08:00
										 |  |  | 		diskInfo := fmt.Sprintf(" %d Online, %d Offline. ", storageInfo.Backend.OnlineDisks, storageInfo.Backend.OfflineDisks) | 
					
						
							| 
									
										
										
										
											2018-05-24 08:30:25 +08:00
										 |  |  | 		msg += colorBlue("Status:") + fmt.Sprintf(getFormatStr(len(diskInfo), 8), diskInfo) | 
					
						
							| 
									
										
										
										
											2016-10-06 03:48:07 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return msg | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Prints startup message of storage capacity and erasure information.
 | 
					
						
							| 
									
										
										
										
											2016-10-10 14:03:10 +08:00
										 |  |  | func printStorageInfo(storageInfo StorageInfo) { | 
					
						
							| 
									
										
										
										
											2018-05-24 08:30:25 +08:00
										 |  |  | 	if msg := getStorageInfoMsg(storageInfo); msg != "" { | 
					
						
							|  |  |  | 		logger.StartupMessage(msg) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-06 03:48:07 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | func printCacheStorageInfo(storageInfo CacheStorageInfo) { | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | 	msg := fmt.Sprintf("%s %s Free, %s Total", colorBlue("Cache Capacity:"), | 
					
						
							|  |  |  | 		humanize.IBytes(uint64(storageInfo.Free)), | 
					
						
							|  |  |  | 		humanize.IBytes(uint64(storageInfo.Total))) | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 	logger.StartupMessage(msg) | 
					
						
							| 
									
										
										
										
											2018-03-29 05:14:06 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | // Prints certificate expiry date warning
 | 
					
						
							|  |  |  | func getCertificateChainMsg(certs []*x509.Certificate) string { | 
					
						
							|  |  |  | 	msg := colorBlue("\nCertificate expiry info:\n") | 
					
						
							|  |  |  | 	totalCerts := len(certs) | 
					
						
							|  |  |  | 	var expiringCerts int | 
					
						
							|  |  |  | 	for i := totalCerts - 1; i >= 0; i-- { | 
					
						
							|  |  |  | 		cert := certs[i] | 
					
						
							| 
									
										
										
										
											2017-03-19 02:28:41 +08:00
										 |  |  | 		if cert.NotAfter.Before(UTCNow().Add(globalMinioCertExpireWarnDays)) { | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | 			expiringCerts++ | 
					
						
							|  |  |  | 			msg += fmt.Sprintf(colorBold("#%d %s will expire on %s\n"), expiringCerts, cert.Subject.CommonName, cert.NotAfter) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if expiringCerts > 0 { | 
					
						
							|  |  |  | 		return msg | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-15 02:15:59 +08:00
										 |  |  | // Prints the certificate expiry message.
 | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | func printCertificateMsg(certs []*x509.Certificate) { | 
					
						
							| 
									
										
										
										
											2018-04-11 00:37:14 +08:00
										 |  |  | 	logger.StartupMessage(getCertificateChainMsg(certs)) | 
					
						
							| 
									
										
										
										
											2016-10-14 19:48:08 +08:00
										 |  |  | } |