storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/server-startup-msg.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2016, 2017, 2018 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "crypto/x509" 21 "fmt" 22 "net" 23 "runtime" 24 "strings" 25 26 humanize "github.com/dustin/go-humanize" 27 28 "storj.io/minio/cmd/config" 29 "storj.io/minio/cmd/logger" 30 color "storj.io/minio/pkg/color" 31 "storj.io/minio/pkg/madmin" 32 xnet "storj.io/minio/pkg/net" 33 ) 34 35 // Documentation links, these are part of message printing code. 36 const ( 37 mcQuickStartGuide = "https://docs.min.io/docs/minio-client-quickstart-guide" 38 goQuickStartGuide = "https://docs.min.io/docs/golang-client-quickstart-guide" 39 jsQuickStartGuide = "https://docs.min.io/docs/javascript-client-quickstart-guide" 40 javaQuickStartGuide = "https://docs.min.io/docs/java-client-quickstart-guide" 41 pyQuickStartGuide = "https://docs.min.io/docs/python-client-quickstart-guide" 42 dotnetQuickStartGuide = "https://docs.min.io/docs/dotnet-client-quickstart-guide" 43 ) 44 45 // generates format string depending on the string length and padding. 46 func getFormatStr(strLen int, padding int) string { 47 formatStr := fmt.Sprintf("%ds", strLen+padding) 48 return "%" + formatStr 49 } 50 51 func mustGetStorageInfo(objAPI ObjectLayer) StorageInfo { 52 storageInfo, _ := objAPI.StorageInfo(GlobalContext) 53 return storageInfo 54 } 55 56 // Prints the formatted startup message. 57 func printStartupMessage(apiEndpoints []string, err error) { 58 if err != nil { 59 logStartupMessage(color.RedBold("Server startup failed with '%v'", err)) 60 logStartupMessage(color.RedBold("Not all features may be available on this server")) 61 logStartupMessage(color.RedBold("Please use 'mc admin' commands to further investigate this issue")) 62 } 63 64 strippedAPIEndpoints := stripStandardPorts(apiEndpoints) 65 // If cache layer is enabled, print cache capacity. 66 cachedObjAPI := newCachedObjectLayerFn() 67 if cachedObjAPI != nil { 68 printCacheStorageInfo(cachedObjAPI.StorageInfo(GlobalContext)) 69 } 70 71 // Object layer is initialized then print StorageInfo. 72 objAPI := newObjectLayerFn() 73 if objAPI != nil { 74 printStorageInfo(mustGetStorageInfo(objAPI)) 75 } 76 77 // Prints credential, region and browser access. 78 printServerCommonMsg(strippedAPIEndpoints) 79 80 // Prints `mc` cli configuration message chooses 81 // first endpoint as default. 82 printCLIAccessMsg(strippedAPIEndpoints[0], "myminio") 83 84 // Prints documentation message. 85 printObjectAPIMsg() 86 87 // SSL is configured reads certification chain, prints 88 // authority and expiry. 89 if color.IsTerminal() && !GlobalCLIContext.Anonymous { 90 if GlobalIsTLS { 91 printCertificateMsg(globalPublicCerts) 92 } 93 } 94 } 95 96 // Returns true if input is not IPv4, false if it is. 97 func isNotIPv4(host string) bool { 98 h, _, err := net.SplitHostPort(host) 99 if err != nil { 100 h = host 101 } 102 ip := net.ParseIP(h) 103 ok := ip.To4() != nil // This is always true of IP is IPv4 104 105 // Returns true if input is not IPv4. 106 return !ok 107 } 108 109 // strip api endpoints list with standard ports such as 110 // port "80" and "443" before displaying on the startup 111 // banner. Returns a new list of API endpoints. 112 func stripStandardPorts(apiEndpoints []string) (newAPIEndpoints []string) { 113 newAPIEndpoints = make([]string, len(apiEndpoints)) 114 // Check all API endpoints for standard ports and strip them. 115 for i, apiEndpoint := range apiEndpoints { 116 u, err := xnet.ParseHTTPURL(apiEndpoint) 117 if err != nil { 118 continue 119 } 120 if globalMinioHost == "" && isNotIPv4(u.Host) { 121 // Skip all non-IPv4 endpoints when we bind to all interfaces. 122 continue 123 } 124 newAPIEndpoints[i] = u.String() 125 } 126 return newAPIEndpoints 127 } 128 129 // Prints common server startup message. Prints credential, region and browser access. 130 func printServerCommonMsg(apiEndpoints []string) { 131 // Get saved credentials. 132 cred := globalActiveCred 133 134 // Get saved region. 135 region := globalServerRegion 136 137 apiEndpointStr := strings.Join(apiEndpoints, " ") 138 139 // Colorize the message and print. 140 logStartupMessage(color.Blue("Endpoint: ") + color.Bold(fmt.Sprintf("%s ", apiEndpointStr))) 141 if color.IsTerminal() && !GlobalCLIContext.Anonymous { 142 logStartupMessage(color.Blue("RootUser: ") + color.Bold(fmt.Sprintf("%s ", cred.AccessKey))) 143 logStartupMessage(color.Blue("RootPass: ") + color.Bold(fmt.Sprintf("%s ", cred.SecretKey))) 144 if region != "" { 145 logStartupMessage(color.Blue("Region: ") + color.Bold(fmt.Sprintf(getFormatStr(len(region), 2), region))) 146 } 147 } 148 printEventNotifiers() 149 150 if globalBrowserEnabled { 151 logStartupMessage(color.Blue("\nBrowser Access:")) 152 logStartupMessage(fmt.Sprintf(getFormatStr(len(apiEndpointStr), 3), apiEndpointStr)) 153 } 154 } 155 156 // Prints bucket notification configurations. 157 func printEventNotifiers() { 158 if GlobalNotificationSys == nil { 159 return 160 } 161 162 arns := GlobalNotificationSys.GetARNList(true) 163 if len(arns) == 0 { 164 return 165 } 166 167 arnMsg := color.Blue("SQS ARNs: ") 168 for _, arn := range arns { 169 arnMsg += color.Bold(fmt.Sprintf("%s ", arn)) 170 } 171 172 logStartupMessage(arnMsg) 173 } 174 175 // Prints startup message for command line access. Prints link to our documentation 176 // and custom platform specific message. 177 func printCLIAccessMsg(endPoint string, alias string) { 178 // Get saved credentials. 179 cred := globalActiveCred 180 181 // Configure 'mc', following block prints platform specific information for minio client. 182 if color.IsTerminal() && !GlobalCLIContext.Anonymous { 183 logStartupMessage(color.Blue("\nCommand-line Access: ") + mcQuickStartGuide) 184 if runtime.GOOS == globalWindowsOSName { 185 mcMessage := fmt.Sprintf("$ mc.exe alias set %s %s %s %s", alias, 186 endPoint, cred.AccessKey, cred.SecretKey) 187 logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) 188 } else { 189 mcMessage := fmt.Sprintf("$ mc alias set %s %s %s %s", alias, 190 endPoint, cred.AccessKey, cred.SecretKey) 191 logStartupMessage(fmt.Sprintf(getFormatStr(len(mcMessage), 3), mcMessage)) 192 } 193 } 194 } 195 196 // Prints startup message for Object API acces, prints link to our SDK documentation. 197 func printObjectAPIMsg() { 198 logStartupMessage(color.Blue("\nObject API (Amazon S3 compatible):")) 199 logStartupMessage(color.Blue(" Go: ") + fmt.Sprintf(getFormatStr(len(goQuickStartGuide), 8), goQuickStartGuide)) 200 logStartupMessage(color.Blue(" Java: ") + fmt.Sprintf(getFormatStr(len(javaQuickStartGuide), 6), javaQuickStartGuide)) 201 logStartupMessage(color.Blue(" Python: ") + fmt.Sprintf(getFormatStr(len(pyQuickStartGuide), 4), pyQuickStartGuide)) 202 logStartupMessage(color.Blue(" JavaScript: ") + jsQuickStartGuide) 203 logStartupMessage(color.Blue(" .NET: ") + fmt.Sprintf(getFormatStr(len(dotnetQuickStartGuide), 6), dotnetQuickStartGuide)) 204 } 205 206 // Get formatted disk/storage info message. 207 func getStorageInfoMsg(storageInfo StorageInfo) string { 208 var msg string 209 var mcMessage string 210 onlineDisks, offlineDisks := getOnlineOfflineDisksStats(storageInfo.Disks) 211 if storageInfo.Backend.Type == madmin.Erasure { 212 if offlineDisks.Sum() > 0 { 213 mcMessage = "Use `mc admin info` to look for latest server/disk info\n" 214 } 215 216 diskInfo := fmt.Sprintf(" %d Online, %d Offline. ", onlineDisks.Sum(), offlineDisks.Sum()) 217 msg += color.Blue("Status:") + fmt.Sprintf(getFormatStr(len(diskInfo), 8), diskInfo) 218 if len(mcMessage) > 0 { 219 msg = fmt.Sprintf("%s %s", mcMessage, msg) 220 } 221 } 222 return msg 223 } 224 225 // Prints startup message of storage capacity and erasure information. 226 func printStorageInfo(storageInfo StorageInfo) { 227 if msg := getStorageInfoMsg(storageInfo); msg != "" { 228 if GlobalCLIContext.Quiet { 229 logger.Info(msg) 230 } 231 logStartupMessage(msg) 232 } 233 } 234 235 func printCacheStorageInfo(storageInfo CacheStorageInfo) { 236 msg := fmt.Sprintf("%s %s Free, %s Total", color.Blue("Cache Capacity:"), 237 humanize.IBytes(storageInfo.Free), 238 humanize.IBytes(storageInfo.Total)) 239 logStartupMessage(msg) 240 } 241 242 // Prints the certificate expiry message. 243 func printCertificateMsg(certs []*x509.Certificate) { 244 for _, cert := range certs { 245 logStartupMessage(config.CertificateText(cert)) 246 } 247 }