github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/quota-set.go (about) 1 // Copyright (c) 2015-2022 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "fmt" 22 23 "github.com/dustin/go-humanize" 24 "github.com/fatih/color" 25 "github.com/minio/cli" 26 json "github.com/minio/colorjson" 27 "github.com/minio/madmin-go/v3" 28 "github.com/minio/mc/pkg/probe" 29 "github.com/minio/pkg/v2/console" 30 ) 31 32 var quotaSetFlags = []cli.Flag{ 33 cli.StringFlag{ 34 Name: "size", 35 Usage: "set a hard quota, disallowing writes after quota is reached", 36 }, 37 } 38 39 var quotaSetCmd = cli.Command{ 40 Name: "set", 41 Usage: "set bucket quota", 42 Action: mainQuotaSet, 43 OnUsageError: onUsageError, 44 Before: setGlobalsFromContext, 45 Flags: append(quotaSetFlags, globalFlags...), 46 CustomHelpTemplate: `NAME: 47 {{.HelpName}} - {{.Usage}} 48 49 USAGE: 50 {{.HelpName}} TARGET [--size QUOTA] 51 52 QUOTA 53 quota accepts human-readable case-insensitive number 54 suffixes such as "k", "m", "g" and "t" referring to the metric units KB, 55 MB, GB and TB respectively. Adding an "i" to these prefixes, uses the IEC 56 units, so that "gi" refers to "gibibyte" or "GiB". A "b" at the end is 57 also accepted. Without suffixes the unit is bytes. 58 59 FLAGS: 60 {{range .VisibleFlags}}{{.}} 61 {{end}} 62 EXAMPLES: 63 1. Set hard quota of 1gb for a bucket "mybucket" on MinIO. 64 {{.Prompt}} {{.HelpName}} myminio/mybucket --size 1GB 65 `, 66 } 67 68 // quotaMessage container for content message structure 69 type quotaMessage struct { 70 op string 71 Status string `json:"status"` 72 Bucket string `json:"bucket"` 73 Quota uint64 `json:"quota,omitempty"` 74 QuotaType string `json:"type,omitempty"` 75 } 76 77 func (q quotaMessage) String() string { 78 switch q.op { 79 case "set": 80 return console.Colorize("QuotaMessage", 81 fmt.Sprintf("Successfully set bucket quota of %s on `%s`", humanize.IBytes(q.Quota), q.Bucket)) 82 case "clear": 83 return console.Colorize("QuotaMessage", 84 fmt.Sprintf("Successfully cleared bucket quota configured on `%s`", q.Bucket)) 85 default: 86 return console.Colorize("QuotaInfo", 87 fmt.Sprintf("Bucket `%s` has %s quota of %s", q.Bucket, q.QuotaType, humanize.IBytes(q.Quota))) 88 } 89 } 90 91 func (q quotaMessage) JSON() string { 92 jsonMessageBytes, e := json.MarshalIndent(q, "", " ") 93 fatalIf(probe.NewError(e), "Unable to marshal into JSON.") 94 95 return string(jsonMessageBytes) 96 } 97 98 // checkQuotaSetSyntax - validate all the passed arguments 99 func checkQuotaSetSyntax(ctx *cli.Context) { 100 if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 { 101 showCommandHelpAndExit(ctx, 1) // last argument is exit code 102 } 103 } 104 105 // mainQuotaSet is the handler for "mc quota set" command. 106 func mainQuotaSet(ctx *cli.Context) error { 107 checkQuotaSetSyntax(ctx) 108 109 console.SetColor("QuotaMessage", color.New(color.FgGreen)) 110 console.SetColor("QuotaInfo", color.New(color.FgBlue)) 111 112 // Get the alias parameter from cli 113 args := ctx.Args() 114 aliasedURL := args.Get(0) 115 116 // Create a new MinIO Admin Client 117 client, err := newAdminClient(aliasedURL) 118 fatalIf(err, "Unable to initialize admin connection.") 119 120 _, targetURL := url2Alias(args[0]) 121 if !ctx.IsSet("size") { 122 fatalIf(errInvalidArgument().Trace(ctx.Args().Tail()...), 123 "--size flag needs to be set.") 124 } 125 qType := madmin.HardQuota 126 quotaStr := ctx.String("size") 127 quota, e := humanize.ParseBytes(quotaStr) 128 fatalIf(probe.NewError(e).Trace(quotaStr), "Unable to parse quota") 129 130 fatalIf(probe.NewError(client.SetBucketQuota(globalContext, targetURL, &madmin.BucketQuota{ 131 Quota: quota, 132 Type: qType, 133 })).Trace(args...), "Unable to set bucket quota") 134 135 printMsg(quotaMessage{ 136 op: ctx.Command.Name, 137 Bucket: targetURL, 138 Quota: quota, 139 QuotaType: string(qType), 140 Status: "success", 141 }) 142 143 return nil 144 }