github.com/minio/mc@v0.0.0-20240507152021-646712d5e5fb/cmd/replicate-remove.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/minio-go/v7/pkg/replication"
    28  	"github.com/minio/pkg/v2/console"
    29  )
    30  
    31  var replicateRemoveFlags = []cli.Flag{
    32  	cli.StringFlag{
    33  		Name:  "id",
    34  		Usage: "id for the rule, should be a unique value",
    35  	},
    36  	cli.BoolFlag{
    37  		Name:  "force",
    38  		Usage: "force remove all the replication configuration rules on the bucket",
    39  	},
    40  	cli.BoolFlag{
    41  		Name:  "all",
    42  		Usage: "remove all replication configuration rules of the bucket, force flag enforced",
    43  	},
    44  }
    45  
    46  var replicateRemoveCmd = cli.Command{
    47  	Name:         "remove",
    48  	ShortName:    "rm",
    49  	Usage:        "remove a server side replication configuration rule",
    50  	Action:       mainReplicateRemove,
    51  	OnUsageError: onUsageError,
    52  	Before:       setGlobalsFromContext,
    53  	Flags:        append(globalFlags, replicateRemoveFlags...),
    54  	CustomHelpTemplate: `NAME:
    55    {{.HelpName}} - {{.Usage}}
    56  
    57  USAGE:
    58    {{.HelpName}} TARGET
    59  
    60  FLAGS:
    61    {{range .VisibleFlags}}{{.}}
    62    {{end}}
    63  EXAMPLES:
    64    1. Remove replication configuration rule on bucket "mybucket" for alias "myminio" with rule id "bsib5mgt874bi56l0fmg".
    65       {{.Prompt}} {{.HelpName}} --id "bsib5mgt874bi56l0fmg" myminio/mybucket
    66  
    67    2. Remove all the replication configuration rules on bucket "mybucket" for alias "myminio". --force flag is required.
    68       {{.Prompt}} {{.HelpName}} --all --force myminio/mybucket
    69  `,
    70  }
    71  
    72  // checkReplicateRemoveSyntax - validate all the passed arguments
    73  func checkReplicateRemoveSyntax(ctx *cli.Context) {
    74  	if len(ctx.Args()) != 1 {
    75  		showCommandHelpAndExit(ctx, 1) // last argument is exit code
    76  	}
    77  	rmAll := ctx.Bool("all")
    78  	rmForce := ctx.Bool("force")
    79  	rID := ctx.String("id")
    80  
    81  	rmChk := (rmAll && rmForce) || (!rmAll && !rmForce)
    82  	if !rmChk {
    83  		fatalIf(errInvalidArgument(),
    84  			"It is mandatory to specify --all and --force flag together for mc "+ctx.Command.FullName()+".")
    85  	}
    86  	if rmAll && rmForce {
    87  		return
    88  	}
    89  
    90  	if rID == "" {
    91  		fatalIf(errInvalidArgument().Trace(rID), "rule ID cannot be empty")
    92  	}
    93  }
    94  
    95  type replicateRemoveMessage struct {
    96  	Op     string `json:"op"`
    97  	Status string `json:"status"`
    98  	URL    string `json:"url"`
    99  	ID     string `json:"id"`
   100  }
   101  
   102  func (l replicateRemoveMessage) JSON() string {
   103  	l.Status = "success"
   104  	jsonMessageBytes, e := json.MarshalIndent(l, "", " ")
   105  	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
   106  	return string(jsonMessageBytes)
   107  }
   108  
   109  func (l replicateRemoveMessage) String() string {
   110  	if l.ID != "" {
   111  		return console.Colorize("replicateRemoveMessage", "Replication configuration rule with ID `"+l.ID+"`removed from "+l.URL+".")
   112  	}
   113  	return console.Colorize("replicateRemoveMessage", "Replication configuration removed from "+l.URL+" successfully.")
   114  }
   115  
   116  func mainReplicateRemove(cliCtx *cli.Context) error {
   117  	ctx, cancelReplicateRemove := context.WithCancel(globalContext)
   118  	defer cancelReplicateRemove()
   119  
   120  	console.SetColor("replicateRemoveMessage", color.New(color.FgGreen))
   121  
   122  	checkReplicateRemoveSyntax(cliCtx)
   123  
   124  	// Get the alias parameter from cli
   125  	args := cliCtx.Args()
   126  	aliasedURL := args.Get(0)
   127  	// Create a new Client
   128  	client, err := newClient(aliasedURL)
   129  	fatalIf(err, "Unable to initialize connection.")
   130  	rcfg, err := client.GetReplication(ctx)
   131  	fatalIf(err.Trace(args...), "Unable to get replication configuration")
   132  
   133  	rmAll := cliCtx.Bool("all")
   134  	rmForce := cliCtx.Bool("force")
   135  	ruleID := cliCtx.String("id")
   136  
   137  	if rcfg.Empty() && !rmAll {
   138  		printMsg(replicateRemoveMessage{
   139  			Op:     cliCtx.Command.Name,
   140  			Status: "success",
   141  			URL:    aliasedURL,
   142  		})
   143  		return nil
   144  	}
   145  	if rmAll && rmForce {
   146  		fatalIf(client.RemoveReplication(ctx), "Unable to remove replication configuration")
   147  	} else {
   148  		var removeArn string
   149  		for _, rule := range rcfg.Rules {
   150  			if rule.ID == ruleID {
   151  				removeArn = rule.Destination.Bucket
   152  			}
   153  		}
   154  		opts := replication.Options{
   155  			ID: ruleID,
   156  			Op: replication.RemoveOption,
   157  		}
   158  		fatalIf(client.SetReplication(ctx, &rcfg, opts), "Could not remove replication rule")
   159  		admclient, cerr := newAdminClient(aliasedURL)
   160  		fatalIf(cerr.Trace(aliasedURL), "Unable to initialize admin connection.")
   161  		_, sourceBucket := url2Alias(args[0])
   162  		fatalIf(probe.NewError(admclient.RemoveRemoteTarget(globalContext, sourceBucket, removeArn)).Trace(args...), "Unable to remove remote target")
   163  
   164  	}
   165  	printMsg(replicateRemoveMessage{
   166  		Op:     cliCtx.Command.Name,
   167  		Status: "success",
   168  		URL:    aliasedURL,
   169  		ID:     ruleID,
   170  	})
   171  	return nil
   172  }