github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/ilm-rule-list.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  	"errors"
    23  	"os"
    24  	"time"
    25  
    26  	"github.com/jedib0t/go-pretty/v6/table"
    27  	"github.com/jedib0t/go-pretty/v6/text"
    28  	"github.com/minio/cli"
    29  	json "github.com/minio/colorjson"
    30  	"github.com/minio/mc/cmd/ilm"
    31  	"github.com/minio/mc/pkg/probe"
    32  	"github.com/minio/minio-go/v7/pkg/lifecycle"
    33  )
    34  
    35  var ilmListFlags = []cli.Flag{
    36  	cli.BoolFlag{
    37  		Name:  "expiry",
    38  		Usage: "display only expiration fields",
    39  	},
    40  	cli.BoolFlag{
    41  		Name:  "transition",
    42  		Usage: "display only transition fields",
    43  	},
    44  }
    45  
    46  var ilmLsCmd = cli.Command{
    47  	Name:         "list",
    48  	ShortName:    "ls",
    49  	Usage:        "lists lifecycle configuration rules set on a bucket",
    50  	Action:       mainILMList,
    51  	OnUsageError: onUsageError,
    52  	Before:       setGlobalsFromContext,
    53  	Flags:        append(ilmListFlags, globalFlags...),
    54  	CustomHelpTemplate: `NAME:
    55    {{.HelpName}} - {{.Usage}}
    56  
    57  USAGE:
    58    {{.HelpName}} [FLAGS] TARGET
    59  
    60  FLAGS:
    61    {{range .VisibleFlags}}{{.}}
    62    {{end}}
    63  DESCRIPTION:
    64    List lifecycle configuration rules set on a bucket.
    65  
    66  EXAMPLES:
    67    1. List the lifecycle management rules (all fields) for mybucket on alias 'myminio'.
    68       {{.Prompt}} {{.HelpName}} myminio/mybucket
    69  
    70    2. List the lifecycle management rules (expration date/days fields) for mybucket on alias 'myminio'.
    71       {{.Prompt}} {{.HelpName}} --expiry myminio/mybucket
    72  
    73    3. List the lifecycle management rules (transition date/days, storage class fields) for mybucket on alias 'myminio'.
    74       {{.Prompt}} {{.HelpName}} --transition myminio/mybucket
    75  
    76    4. List the lifecycle management rules in JSON format for mybucket on alias 'myminio'.
    77       {{.Prompt}} {{.HelpName}} --json myminio/mybucket
    78  `,
    79  }
    80  
    81  type ilmListMessage struct {
    82  	Status    string                   `json:"status"`
    83  	Target    string                   `json:"target"`
    84  	Context   *cli.Context             `json:"-"`
    85  	Config    *lifecycle.Configuration `json:"config"`
    86  	UpdatedAt time.Time                `json:"updatedAt,omitempty"`
    87  }
    88  
    89  func (i ilmListMessage) String() string {
    90  	// We don't use this method to display ilm-ls output. This is here to
    91  	// implement the interface required by printMsg
    92  	return ""
    93  }
    94  
    95  func (i ilmListMessage) JSON() string {
    96  	msgBytes, e := json.MarshalIndent(i, "", " ")
    97  	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
    98  	return string(msgBytes)
    99  }
   100  
   101  // validateILMListFlagSet - validates ilm list flags
   102  func validateILMListFlagSet(ctx *cli.Context) bool {
   103  	expiryOnly := ctx.Bool("expiry")
   104  	transitionOnly := ctx.Bool("transition")
   105  	// Only one of expiry or transition rules can be filtered
   106  	if expiryOnly && transitionOnly {
   107  		return false
   108  	}
   109  	return true
   110  }
   111  
   112  // checkILMListSyntax - validate arguments passed by a user
   113  func checkILMListSyntax(ctx *cli.Context) {
   114  	if len(ctx.Args()) != 1 {
   115  		showCommandHelpAndExit(ctx, globalErrorExitStatus)
   116  	}
   117  
   118  	if !validateILMListFlagSet(ctx) {
   119  		fatalIf(errInvalidArgument(), "only one display field flag is allowed per ls command. Refer mc "+ctx.Command.FullName()+" --help.")
   120  	}
   121  }
   122  
   123  func mainILMList(cliCtx *cli.Context) error {
   124  	ctx, cancelILMList := context.WithCancel(globalContext)
   125  	defer cancelILMList()
   126  
   127  	checkILMListSyntax(cliCtx)
   128  	setILMDisplayColorScheme()
   129  
   130  	args := cliCtx.Args()
   131  	urlStr := args.Get(0)
   132  
   133  	// Note: validateILMListFlagsSet ensures we deal with only valid
   134  	// combinations here.
   135  	var filter ilm.LsFilter
   136  	if v := cliCtx.Bool("expiry"); v {
   137  		filter = ilm.ExpiryOnly
   138  	}
   139  	if v := cliCtx.Bool("transition"); v {
   140  		filter = ilm.TransitionOnly
   141  	}
   142  	client, err := newClient(urlStr)
   143  	fatalIf(err.Trace(urlStr), "Unable to initialize client for "+urlStr)
   144  
   145  	ilmCfg, updatedAt, err := client.GetLifecycle(ctx)
   146  	fatalIf(err.Trace(args...), "Unable to get lifecycle")
   147  
   148  	if len(ilmCfg.Rules) == 0 {
   149  		fatalIf(probe.NewError(errors.New("lifecycle configuration not set")).Trace(urlStr),
   150  			"Unable to ls lifecycle configuration")
   151  	}
   152  
   153  	// applies listing filter on ILM rules
   154  	ilmCfg.Rules = filter.Apply(ilmCfg.Rules)
   155  
   156  	if globalJSON {
   157  		printMsg(ilmListMessage{
   158  			Status:    "success",
   159  			Target:    urlStr,
   160  			Context:   cliCtx,
   161  			Config:    ilmCfg,
   162  			UpdatedAt: updatedAt,
   163  		})
   164  		return nil
   165  	}
   166  
   167  	for _, tbl := range ilm.ToTables(ilmCfg) {
   168  		rows := tbl.Rows()
   169  		if len(rows) == 0 {
   170  			continue
   171  		}
   172  		t := table.NewWriter()
   173  		t.SetOutputMirror(os.Stdout)
   174  		var colCfgs []table.ColumnConfig
   175  		for i := 0; i < len(rows[0]); i++ {
   176  			colCfgs = append(colCfgs, table.ColumnConfig{
   177  				Align: text.AlignCenter,
   178  			})
   179  		}
   180  		t.SetColumnConfigs(colCfgs)
   181  		t.SetTitle(tbl.Title())
   182  		t.AppendHeader(tbl.ColumnHeaders())
   183  		t.AppendRows(rows)
   184  		t.SetStyle(table.StyleLight)
   185  		t.Render()
   186  	}
   187  
   188  	return nil
   189  }