Repository: kubernetes/kubernetes
File: cmd/kubeadm/app/util/etcd/etcd.go (Go)

Code before:
				klog.V(5).Infof("Member was already removed, because member %s was not found", strconv.FormatUint(id, 16))
				listResp, err = cli.MemberList(ctx)
				if err == nil {
					respMembers = listResp.Members
					return true, nil
				}
			}
			klog.V(5).Infof("Failed to remove etcd member: %v", err)
			lastError = err
			return false, nil
		})
	if err != nil {
		return nil, lastError
	}

	// Returns the updated list of etcd members
	ret := []Member{}
	for _, m := range respMembers {
		ret = append(ret, Member{Name: m.Name, PeerURL: m.PeerURLs[0]})
	}

	return ret, nil
}

// RemoveMemberByPeerURL removes a member from the etcd cluster by its peer URL.
func (c *Client) RemoveMemberByPeerURL(peerURL string) error {
	id, err := c.GetMemberID(peerURL)
	if err != nil {
		if errors.Is(ErrNoMemberIDForPeerURL, err) {
			klog.V(5).Infof("[etcd] Member was already removed, because no member id exists for peer %s", peerURL)
			return nil
		}
		return err
	}

	klog.V(1).Infof("[etcd] Removing member: %s, id: %d", peerURL, id)
	_, err = c.RemoveMember(id)
	if err != nil {
		return err
	}
	klog.V(1).Infof("[etcd] Removed member %s successfully", peerURL)
	return nil
}

// AddMember adds a new member into the etcd cluster
func (c *Client) AddMember(name string, peerAddrs string) ([]Member, error) {
	return c.addMember(name, peerAddrs, false)
}

// AddMemberAsLearner adds a new learner member into the etcd cluster.
func (c *Client) AddMemberAsLearner(name string, peerAddrs string) ([]Member, error) {

Review comment (refactor):
The function `RemoveStackedEtcdMemberFromCluster()` can also utilize this utility function, located at cmd/kubeadm/app/phases/etcd/local.go:94.

Code after:
				respMembers = listResp.Members
				return true, nil
			}

			resp, err := cli.MemberRemove(ctx, id)
			if err == nil {
				respMembers = resp.Members
				return true, nil
			}
			if errors.Is(rpctypes.ErrMemberNotFound, err) {
				klog.V(5).Infof("Member was already removed, because member %s was not found", strconv.FormatUint(id, 16))
				listResp, err = cli.MemberList(ctx)
				if err == nil {
					respMembers = listResp.Members
					return true, nil
				}
			}
			klog.V(5).Infof("Failed to remove etcd member: %v", err)
			lastError = err
			return false, nil
		})
	if err != nil {
		return nil, lastError
	}

	// Returns the updated list of etcd members
	ret := []Member{}
	for _, m := range respMembers {
		ret = append(ret, Member{Name: m.Name, PeerURL: m.PeerURLs[0]})
	}

	return ret, nil
}

// AddMember adds a new member into the etcd cluster
func (c *Client) AddMember(name string, peerAddrs string) ([]Member, error) {
	return c.addMember(name, peerAddrs, false)
}

// AddMemberAsLearner adds a new learner member into the etcd cluster.
func (c *Client) AddMemberAsLearner(name string, peerAddrs string) ([]Member, error) {
	return c.addMember(name, peerAddrs, true)
}

// addMember notifies an existing etcd cluster that a new member is joining, and
// return the updated list of members. If the member has already been added to the
// cluster, this will return the existing list of etcd members.
func (c *Client) addMember(name string, peerAddrs string, isLearner bool) ([]Member, error) {
	// Parse the peer address, required to add the client URL later to the list
	// of endpoints for this client. Parsing as a first operation to make sure that
	// if this fails no member addition is performed on the etcd cluster.