in controllers/scale.go [89:127]
func (r *EtcdadmClusterReconciler) removeEtcdMemberAndDeleteMachine(ctx context.Context, etcdClient EtcdClient, peerURL string, machineToDelete *clusterv1.Machine) error {
log := r.Log
// Etcdadm has a "reset" command to remove an etcd member. But we can't run that command on the CAPI machine object after it's provisioned.
// so the following logic is based on how etcdadm performs "reset" https://github.com/kubernetes-sigs/etcdadm/blob/master/cmd/reset.go#L65
etcdCtx, cancel := context.WithTimeout(ctx, constants.DefaultEtcdRequestTimeout)
mresp, err := etcdClient.MemberList(etcdCtx)
cancel()
if err != nil {
return fmt.Errorf("error listing members: %v", err)
}
localMember, ok := memberForPeerURLs(mresp, []string{peerURL})
if ok {
if len(mresp.Members) > 1 {
log.Info("Removing", "member", localMember.Name)
etcdCtx, cancel = context.WithTimeout(ctx, constants.DefaultEtcdRequestTimeout)
_, err = etcdClient.MemberRemove(etcdCtx, localMember.ID)
cancel()
if err != nil {
return fmt.Errorf("failed to remove etcd member %s with error %v", localMember.Name, err)
}
if machineToDelete != nil {
if err := r.Client.Delete(ctx, machineToDelete); err != nil && !apierrors.IsNotFound(err) && !apierrors.IsGone(err) {
return fmt.Errorf("failed to delete etcd machine %s with error %v", machineToDelete.Name, err)
}
}
} else {
log.Info("Not removing last member in the cluster", "member", localMember.Name)
}
} else {
log.Info("Member was removed")
if machineToDelete != nil {
// this could happen if the etcd member was removed through etcdctl calls, ensure that the machine gets deleted too
if err := r.Client.Delete(ctx, machineToDelete); err != nil && !apierrors.IsNotFound(err) && !apierrors.IsGone(err) {
return fmt.Errorf("failed to delete etcd machine %s with error %v", machineToDelete.Name, err)
}
}
}
return nil
}