go.etcd.io/etcd@v3.3.27+incompatible/etcdctl/ctlv3/command/member_command.go (about) 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 15 package command 16 17 import ( 18 "fmt" 19 "strconv" 20 "strings" 21 22 "github.com/spf13/cobra" 23 ) 24 25 var memberPeerURLs string 26 27 // NewMemberCommand returns the cobra command for "member". 28 func NewMemberCommand() *cobra.Command { 29 mc := &cobra.Command{ 30 Use: "member <subcommand>", 31 Short: "Membership related commands", 32 } 33 34 mc.AddCommand(NewMemberAddCommand()) 35 mc.AddCommand(NewMemberRemoveCommand()) 36 mc.AddCommand(NewMemberUpdateCommand()) 37 mc.AddCommand(NewMemberListCommand()) 38 39 return mc 40 } 41 42 // NewMemberAddCommand returns the cobra command for "member add". 43 func NewMemberAddCommand() *cobra.Command { 44 cc := &cobra.Command{ 45 Use: "add <memberName> [options]", 46 Short: "Adds a member into the cluster", 47 48 Run: memberAddCommandFunc, 49 } 50 51 cc.Flags().StringVar(&memberPeerURLs, "peer-urls", "", "comma separated peer URLs for the new member.") 52 53 return cc 54 } 55 56 // NewMemberRemoveCommand returns the cobra command for "member remove". 57 func NewMemberRemoveCommand() *cobra.Command { 58 cc := &cobra.Command{ 59 Use: "remove <memberID>", 60 Short: "Removes a member from the cluster", 61 62 Run: memberRemoveCommandFunc, 63 } 64 65 return cc 66 } 67 68 // NewMemberUpdateCommand returns the cobra command for "member update". 69 func NewMemberUpdateCommand() *cobra.Command { 70 cc := &cobra.Command{ 71 Use: "update <memberID> [options]", 72 Short: "Updates a member in the cluster", 73 74 Run: memberUpdateCommandFunc, 75 } 76 77 cc.Flags().StringVar(&memberPeerURLs, "peer-urls", "", "comma separated peer URLs for the updated member.") 78 79 return cc 80 } 81 82 // NewMemberListCommand returns the cobra command for "member list". 83 func NewMemberListCommand() *cobra.Command { 84 cc := &cobra.Command{ 85 Use: "list", 86 Short: "Lists all members in the cluster", 87 Long: `When --write-out is set to simple, this command prints out comma-separated member lists for each endpoint. 88 The items in the lists are ID, Status, Name, Peer Addrs, Client Addrs. 89 `, 90 91 Run: memberListCommandFunc, 92 } 93 94 return cc 95 } 96 97 // memberAddCommandFunc executes the "member add" command. 98 func memberAddCommandFunc(cmd *cobra.Command, args []string) { 99 if len(args) != 1 { 100 ExitWithError(ExitBadArgs, fmt.Errorf("member name not provided.")) 101 } 102 newMemberName := args[0] 103 104 if len(memberPeerURLs) == 0 { 105 ExitWithError(ExitBadArgs, fmt.Errorf("member peer urls not provided.")) 106 } 107 108 urls := strings.Split(memberPeerURLs, ",") 109 ctx, cancel := commandCtx(cmd) 110 cli := mustClientFromCmd(cmd) 111 resp, err := cli.MemberAdd(ctx, urls) 112 cancel() 113 if err != nil { 114 ExitWithError(ExitError, err) 115 } 116 newID := resp.Member.ID 117 118 display.MemberAdd(*resp) 119 120 if _, ok := (display).(*simplePrinter); ok { 121 conf := []string{} 122 for _, memb := range resp.Members { 123 for _, u := range memb.PeerURLs { 124 n := memb.Name 125 if memb.ID == newID { 126 n = newMemberName 127 } 128 conf = append(conf, fmt.Sprintf("%s=%s", n, u)) 129 } 130 } 131 132 fmt.Print("\n") 133 fmt.Printf("ETCD_NAME=%q\n", newMemberName) 134 fmt.Printf("ETCD_INITIAL_CLUSTER=%q\n", strings.Join(conf, ",")) 135 fmt.Printf("ETCD_INITIAL_ADVERTISE_PEER_URLS=%q\n", memberPeerURLs) 136 fmt.Printf("ETCD_INITIAL_CLUSTER_STATE=\"existing\"\n") 137 } 138 } 139 140 // memberRemoveCommandFunc executes the "member remove" command. 141 func memberRemoveCommandFunc(cmd *cobra.Command, args []string) { 142 if len(args) != 1 { 143 ExitWithError(ExitBadArgs, fmt.Errorf("member ID is not provided")) 144 } 145 146 id, err := strconv.ParseUint(args[0], 16, 64) 147 if err != nil { 148 ExitWithError(ExitBadArgs, fmt.Errorf("bad member ID arg (%v), expecting ID in Hex", err)) 149 } 150 151 ctx, cancel := commandCtx(cmd) 152 resp, err := mustClientFromCmd(cmd).MemberRemove(ctx, id) 153 cancel() 154 if err != nil { 155 ExitWithError(ExitError, err) 156 } 157 display.MemberRemove(id, *resp) 158 } 159 160 // memberUpdateCommandFunc executes the "member update" command. 161 func memberUpdateCommandFunc(cmd *cobra.Command, args []string) { 162 if len(args) != 1 { 163 ExitWithError(ExitBadArgs, fmt.Errorf("member ID is not provided")) 164 } 165 166 id, err := strconv.ParseUint(args[0], 16, 64) 167 if err != nil { 168 ExitWithError(ExitBadArgs, fmt.Errorf("bad member ID arg (%v), expecting ID in Hex", err)) 169 } 170 171 if len(memberPeerURLs) == 0 { 172 ExitWithError(ExitBadArgs, fmt.Errorf("member peer urls not provided.")) 173 } 174 175 urls := strings.Split(memberPeerURLs, ",") 176 177 ctx, cancel := commandCtx(cmd) 178 resp, err := mustClientFromCmd(cmd).MemberUpdate(ctx, id, urls) 179 cancel() 180 if err != nil { 181 ExitWithError(ExitError, err) 182 } 183 184 display.MemberUpdate(id, *resp) 185 } 186 187 // memberListCommandFunc executes the "member list" command. 188 func memberListCommandFunc(cmd *cobra.Command, args []string) { 189 ctx, cancel := commandCtx(cmd) 190 resp, err := mustClientFromCmd(cmd).MemberList(ctx) 191 cancel() 192 if err != nil { 193 ExitWithError(ExitError, err) 194 } 195 196 display.MemberList(*resp) 197 }