github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/retention-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  	"context"
    22  	"strings"
    23  	"time"
    24  
    25  	"github.com/fatih/color"
    26  	"github.com/minio/cli"
    27  	"github.com/minio/mc/pkg/probe"
    28  	minio "github.com/minio/minio-go/v7"
    29  	"github.com/minio/pkg/v2/console"
    30  )
    31  
    32  var retentionSetFlags = []cli.Flag{
    33  	cli.BoolFlag{
    34  		Name:  "recursive, r",
    35  		Usage: "apply retention recursively",
    36  	},
    37  	cli.BoolFlag{
    38  		Name:  "bypass",
    39  		Usage: "bypass governance",
    40  	},
    41  	cli.StringFlag{
    42  		Name:  "version-id, vid",
    43  		Usage: "apply retention to a specific object version",
    44  	},
    45  	cli.StringFlag{
    46  		Name:  "rewind",
    47  		Usage: "roll back object(s) to current version at specified time",
    48  	},
    49  	cli.BoolFlag{
    50  		Name:  "versions",
    51  		Usage: "apply retention object(s) and all its versions",
    52  	},
    53  	cli.BoolFlag{
    54  		Name:  "default",
    55  		Usage: "set bucket default retention mode",
    56  	},
    57  }
    58  
    59  var retentionSetCmd = cli.Command{
    60  	Name:         "set",
    61  	Usage:        "apply retention settings on object(s)",
    62  	Action:       mainRetentionSet,
    63  	OnUsageError: onUsageError,
    64  	Before:       setGlobalsFromContext,
    65  	Flags:        append(retentionSetFlags, globalFlags...),
    66  	CustomHelpTemplate: `NAME:
    67    {{.HelpName}} - {{.Usage}}
    68  
    69  USAGE:
    70    {{.HelpName}} [FLAGS] [governance | compliance] VALIDITY TARGET
    71  
    72  FLAGS:
    73    {{range .VisibleFlags}}{{.}}
    74    {{end}}
    75  VALIDITY:
    76    This argument must be formatted like Nd or Ny where 'd' denotes days and 'y' denotes years e.g. 10d, 3y.
    77  
    78  EXAMPLES:
    79    1. Set object retention for a specific object
    80       $ {{.HelpName}} compliance 30d myminio/mybucket/prefix/obj.csv
    81  
    82    2. Set object retention for recursively for all objects at a given prefix
    83       $ {{.HelpName}} governance 30d myminio/mybucket/prefix --recursive
    84  
    85    3. Set object retention to a specific version of a specific object
    86       $ {{.HelpName}} governance 30d myminio/mybucket/prefix/obj.csv --version-id "3Jr2x6fqlBUsVzbvPihBO3HgNpgZgAnp"
    87  
    88    4. Set object retention for recursively for all versions of all objects
    89       $ {{.HelpName}} governance 30d myminio/mybucket/prefix --recursive --versions
    90  
    91    5. Set default lock retention configuration for a bucket
    92       $ {{.HelpName}} --default governance 30d myminio/mybucket/
    93  `,
    94  }
    95  
    96  func parseSetRetentionArgs(cliCtx *cli.Context) (target, versionID string, recursive bool, timeRef time.Time, withVersions bool, mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit, bypass, bucketMode bool) {
    97  	args := cliCtx.Args()
    98  	if len(args) != 3 {
    99  		showCommandHelpAndExit(cliCtx, 1)
   100  	}
   101  
   102  	mode = minio.RetentionMode(strings.ToUpper(args[0]))
   103  	if !mode.IsValid() {
   104  		fatalIf(errInvalidArgument().Trace(args...), "invalid retention mode '%v'", mode)
   105  	}
   106  
   107  	var err *probe.Error
   108  	validity, unit, err = parseRetentionValidity(args[1])
   109  	fatalIf(err.Trace(args[1]), "invalid validity argument")
   110  
   111  	target = args[2]
   112  	if target == "" {
   113  		fatalIf(errInvalidArgument().Trace(), "invalid target url '%v'", target)
   114  	}
   115  
   116  	versionID = cliCtx.String("version-id")
   117  	timeRef = parseRewindFlag(cliCtx.String("rewind"))
   118  	withVersions = cliCtx.Bool("versions")
   119  	recursive = cliCtx.Bool("recursive")
   120  	bypass = cliCtx.Bool("bypass")
   121  	bucketMode = cliCtx.Bool("default")
   122  
   123  	if bucketMode && (versionID != "" || !timeRef.IsZero() || withVersions || recursive || bypass) {
   124  		fatalIf(errDummy(), "--default cannot be specified with any of --version-id, --rewind, --versions, --recursive, --bypass.")
   125  	}
   126  
   127  	return
   128  }
   129  
   130  // Set Retention for one object/version or many objects within a given prefix.
   131  func setRetention(ctx context.Context, target, versionID string, timeRef time.Time, withOlderVersions, isRecursive bool,
   132  	mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit, bypassGovernance bool,
   133  ) error {
   134  	return applyRetention(ctx, lockOpSet, target, versionID, timeRef, withOlderVersions, isRecursive, mode, validity, unit, bypassGovernance)
   135  }
   136  
   137  func setBucketLock(urlStr string, mode minio.RetentionMode, validity uint64, unit minio.ValidityUnit) error {
   138  	return applyBucketLock(lockOpSet, urlStr, mode, validity, unit)
   139  }
   140  
   141  // main for retention set command.
   142  func mainRetentionSet(cliCtx *cli.Context) error {
   143  	ctx, cancelSetRetention := context.WithCancel(globalContext)
   144  	defer cancelSetRetention()
   145  
   146  	console.SetColor("RetentionSuccess", color.New(color.FgGreen, color.Bold))
   147  	console.SetColor("RetentionFailure", color.New(color.FgYellow))
   148  
   149  	target, versionID, recursive, rewind, withVersions, mode, validity, unit, bypass, bucketMode := parseSetRetentionArgs(cliCtx)
   150  
   151  	fatalIfBucketLockNotSupported(ctx, target)
   152  
   153  	if bucketMode {
   154  		return setBucketLock(target, mode, validity, unit)
   155  	}
   156  
   157  	if withVersions && rewind.IsZero() {
   158  		rewind = time.Now().UTC()
   159  	}
   160  
   161  	return setRetention(ctx, target, versionID, rewind, withVersions, recursive, mode, validity, unit, bypass)
   162  }