1// Copyright 2016 The etcd Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package command 16 17import ( 18 "fmt" 19 "os" 20 21 "github.com/spf13/cobra" 22 "go.etcd.io/etcd/etcdutl/v3/etcdutl" 23 "go.etcd.io/etcd/pkg/v3/cobrautl" 24) 25 26var ( 27 defragDataDir string 28) 29 30// NewDefragCommand returns the cobra command for "Defrag". 31func NewDefragCommand() *cobra.Command { 32 cmd := &cobra.Command{ 33 Use: "defrag", 34 Short: "Defragments the storage of the etcd members with given endpoints", 35 Run: defragCommandFunc, 36 } 37 cmd.PersistentFlags().BoolVar(&epClusterEndpoints, "cluster", false, "use all endpoints from the cluster member list") 38 cmd.Flags().StringVar(&defragDataDir, "data-dir", "", "Optional. If present, defragments a data directory not in use by etcd.") 39 return cmd 40} 41 42func defragCommandFunc(cmd *cobra.Command, args []string) { 43 if len(defragDataDir) > 0 { 44 fmt.Fprintf(os.Stderr, "Use `etcdutl defrag` instead. The --data-dir is going to be decomissioned in v3.6.\n\n") 45 err := etcdutl.DefragData(defragDataDir) 46 if err != nil { 47 cobrautl.ExitWithError(cobrautl.ExitError, err) 48 } 49 } 50 51 failures := 0 52 c := mustClientFromCmd(cmd) 53 for _, ep := range endpointsFromCluster(cmd) { 54 ctx, cancel := commandCtx(cmd) 55 _, err := c.Defragment(ctx, ep) 56 cancel() 57 if err != nil { 58 fmt.Fprintf(os.Stderr, "Failed to defragment etcd member[%s] (%v)\n", ep, err) 59 failures++ 60 } else { 61 fmt.Printf("Finished defragmenting etcd member[%s]\n", ep) 62 } 63 } 64 65 if failures != 0 { 66 os.Exit(cobrautl.ExitError) 67 } 68} 69