github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/mb-main.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  	"context"
    22  
    23  	"github.com/fatih/color"
    24  	"github.com/minio/cli"
    25  	json "github.com/minio/colorjson"
    26  	"github.com/minio/mc/pkg/probe"
    27  	"github.com/minio/pkg/v2/console"
    28  )
    29  
    30  var mbFlags = []cli.Flag{
    31  	cli.StringFlag{
    32  		Name:  "region",
    33  		Value: "us-east-1",
    34  		Usage: "specify bucket region; defaults to 'us-east-1'",
    35  	},
    36  	cli.BoolFlag{
    37  		Name:  "ignore-existing, p",
    38  		Usage: "ignore if bucket/directory already exists",
    39  	},
    40  	cli.BoolFlag{
    41  		Name:  "with-lock, l",
    42  		Usage: "enable object lock",
    43  	},
    44  	cli.BoolFlag{
    45  		Name:  "with-versioning",
    46  		Usage: "enable versioned bucket",
    47  	},
    48  }
    49  
    50  // make a bucket.
    51  var mbCmd = cli.Command{
    52  	Name:         "mb",
    53  	Usage:        "make a bucket",
    54  	Action:       mainMakeBucket,
    55  	Before:       setGlobalsFromContext,
    56  	OnUsageError: onUsageError,
    57  	Flags:        append(mbFlags, globalFlags...),
    58  	CustomHelpTemplate: `NAME:
    59    {{.HelpName}} - {{.Usage}}
    60  
    61  USAGE:
    62    {{.HelpName}} [FLAGS] TARGET [TARGET...]
    63  {{if .VisibleFlags}}
    64  FLAGS:
    65    {{range .VisibleFlags}}{{.}}
    66    {{end}}{{end}}
    67  EXAMPLES:
    68    1. Create a bucket on Amazon S3 cloud storage.
    69       {{.Prompt}} {{.HelpName}} s3/mynewbucket
    70  
    71    2. Create a new bucket on Google Cloud Storage.
    72       {{.Prompt}} {{.HelpName}} gcs/miniocloud
    73  
    74    3. Create a new bucket on Amazon S3 cloud storage in region 'us-west-2'.
    75       {{.Prompt}} {{.HelpName}} --region=us-west-2 s3/myregionbucket
    76  
    77    4. Create a new directory including its missing parents (equivalent to 'mkdir -p').
    78       {{.Prompt}} {{.HelpName}} /tmp/this/new/dir1
    79  
    80    5. Create multiple directories including its missing parents (behavior similar to 'mkdir -p').
    81       {{.Prompt}} {{.HelpName}} /mnt/sdb/mydisk /mnt/sdc/mydisk /mnt/sdd/mydisk
    82  
    83    6. Ignore if bucket/directory already exists.
    84       {{.Prompt}} {{.HelpName}} --ignore-existing myminio/mynewbucket
    85  
    86    7. Create a new bucket on Amazon S3 cloud storage in region 'us-west-2' with object lock enabled.
    87       {{.Prompt}} {{.HelpName}} --with-lock --region=us-west-2 s3/myregionbucket
    88  
    89    8. Create a new bucket on MinIO with versioning enabled.
    90       {{.Prompt}} {{.HelpName}} --with-versioning myminio/myversionedbucket
    91  `,
    92  }
    93  
    94  // makeBucketMessage is container for make bucket success and failure messages.
    95  type makeBucketMessage struct {
    96  	Status string `json:"status"`
    97  	Bucket string `json:"bucket"`
    98  	Region string `json:"region"`
    99  }
   100  
   101  // String colorized make bucket message.
   102  func (s makeBucketMessage) String() string {
   103  	return console.Colorize("MakeBucket", "Bucket created successfully `"+s.Bucket+"`.")
   104  }
   105  
   106  // JSON jsonified make bucket message.
   107  func (s makeBucketMessage) JSON() string {
   108  	makeBucketJSONBytes, e := json.MarshalIndent(s, "", " ")
   109  	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
   110  
   111  	return string(makeBucketJSONBytes)
   112  }
   113  
   114  // Validate command line arguments.
   115  func checkMakeBucketSyntax(cliCtx *cli.Context) {
   116  	if !cliCtx.Args().Present() {
   117  		showCommandHelpAndExit(cliCtx, 1) // last argument is exit code
   118  	}
   119  }
   120  
   121  // mainMakeBucket is entry point for mb command.
   122  func mainMakeBucket(cliCtx *cli.Context) error {
   123  	// check 'mb' cli arguments.
   124  	checkMakeBucketSyntax(cliCtx)
   125  
   126  	// Additional command speific theme customization.
   127  	console.SetColor("MakeBucket", color.New(color.FgGreen, color.Bold))
   128  
   129  	// Save region.
   130  	region := cliCtx.String("region")
   131  	ignoreExisting := cliCtx.Bool("p")
   132  	withLock := cliCtx.Bool("l")
   133  
   134  	var cErr error
   135  	for _, targetURL := range cliCtx.Args() {
   136  		// Instantiate client for URL.
   137  		clnt, err := newClient(targetURL)
   138  		if err != nil {
   139  			errorIf(err.Trace(targetURL), "Invalid target `"+targetURL+"`.")
   140  			cErr = exitStatus(globalErrorExitStatus)
   141  			continue
   142  		}
   143  
   144  		ctx, cancelMakeBucket := context.WithCancel(globalContext)
   145  		defer cancelMakeBucket()
   146  
   147  		// Make bucket.
   148  		if err = clnt.MakeBucket(ctx, region, ignoreExisting, withLock); err != nil {
   149  			switch err.ToGoError().(type) {
   150  			case BucketNameEmpty:
   151  				errorIf(err.Trace(targetURL), "Unable to make bucket, please use `mc mb %s`.", urlJoinPath(targetURL, "your-bucket-name"))
   152  			default:
   153  				errorIf(err.Trace(targetURL), "Unable to make bucket `"+targetURL+"`.")
   154  			}
   155  			cErr = exitStatus(globalErrorExitStatus)
   156  			continue
   157  		}
   158  
   159  		if cliCtx.Bool("with-versioning") {
   160  			fatalIf(clnt.SetVersion(ctx, "enable", []string{}, false), "Unable to enable versioning")
   161  		}
   162  
   163  		// Successfully created a bucket.
   164  		printMsg(makeBucketMessage{Status: "success", Bucket: targetURL})
   165  	}
   166  	return cErr
   167  }