func (r nodes) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
	return r.client.resources.Watch(ctx, opts, libapiv3.KindNode, nil)
}
Watch returns a watch.Interface that watches the Nodes that match the
supplied options.
package clientv3
import (
	"context"
	"fmt"
	log "github.com/sirupsen/logrus"
	libapiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/names"
	"github.com/projectcalico/libcalico-go/lib/net"
	cnet "github.com/projectcalico/libcalico-go/lib/net"
	"github.com/projectcalico/libcalico-go/lib/options"
	validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
	"github.com/projectcalico/libcalico-go/lib/watch"
)
type NodeInterface interface {
	Create(ctx context.Context, res *libapiv3.Node, opts options.SetOptions) (*libapiv3.Node, error)
	Update(ctx context.Context, res *libapiv3.Node, opts options.SetOptions) (*libapiv3.Node, error)
	Delete(ctx context.Context, name string, opts options.DeleteOptions) (*libapiv3.Node, error)
	Get(ctx context.Context, name string, opts options.GetOptions) (*libapiv3.Node, error)
	List(ctx context.Context, opts options.ListOptions) (*libapiv3.NodeList, error)
	Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
}
type nodes struct {
	client client
}
func (r nodes) Create(ctx context.Context, res *libapiv3.Node, opts options.SetOptions) (*libapiv3.Node, error) {
	if err := validator.Validate(res); err != nil {
		return nil, err
	}
	err := r.client.EnsureInitialized(ctx, "", "")
	if err != nil {
		return nil, err
	}
	out, err := r.client.resources.Create(ctx, opts, libapiv3.KindNode, res)
	if out != nil {
		return out.(*libapiv3.Node), err
	}
	return nil, err
}
func (r nodes) Update(ctx context.Context, res *libapiv3.Node, opts options.SetOptions) (*libapiv3.Node, error) {
	if err := validator.Validate(res); err != nil {
		return nil, err
	}
	out, err := r.client.resources.Update(ctx, opts, libapiv3.KindNode, res)
	if out != nil {
		return out.(*libapiv3.Node), err
	}
	return nil, err
}
func (r nodes) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*libapiv3.Node, error) {
	pname, err := names.WorkloadEndpointIdentifiers{Node: name}.CalculateWorkloadEndpointName(true)
	if err != nil {
		return nil, err
	}
	weps, err := r.client.WorkloadEndpoints().List(ctx, options.ListOptions{
		Prefix: true,
		Name:   pname,
	})
	if err != nil {
		return nil, err
	}
	ips := []net.IP{}
	for _, wep := range weps.Items {
		if wep.Spec.Node != name {
			continue
		}
		for _, ip := range wep.Spec.IPNetworks {
			ipAddr, _, err := cnet.ParseCIDROrIP(ip)
			if err == nil {
				ips = append(ips, *ipAddr)
			} else {
				log.WithError(err).Warnf("Failed to parse CIDR: %s", ip)
			}
		}
	}
	if n, err := r.client.Nodes().Get(ctx, name, options.GetOptions{}); err != nil {
		if _, ok := err.(errors.ErrorResourceDoesNotExist); !ok {
			return nil, err
		}
	} else {
		if n.Spec.BGP != nil && n.Spec.BGP.IPv4IPIPTunnelAddr != "" {
			ipAddr, _, err := cnet.ParseCIDROrIP(n.Spec.BGP.IPv4IPIPTunnelAddr)
			if err == nil {
				ips = append(ips, *ipAddr)
			} else {
				log.WithError(err).Warnf("Failed to parse IPIP tunnel address CIDR: %s", n.Spec.BGP.IPv4IPIPTunnelAddr)
			}
		}
		if n.Spec.IPv4VXLANTunnelAddr != "" {
			ipAddr, _, err := cnet.ParseCIDROrIP(n.Spec.IPv4VXLANTunnelAddr)
			if err == nil {
				ips = append(ips, *ipAddr)
			} else {
				log.WithError(err).Warnf("Failed to parse VXLAN tunnel address CIDR: %s", n.Spec.IPv4VXLANTunnelAddr)
			}
		}
		if n.Spec.Wireguard != nil && n.Spec.Wireguard.InterfaceIPv4Address != "" {
			ipAddr, _, err := cnet.ParseCIDROrIP(n.Spec.Wireguard.InterfaceIPv4Address)
			if err == nil {
				ips = append(ips, *ipAddr)
			} else {
				log.WithError(err).Warnf("Failed to parse Wireguard tunnel address CIDR: %s", n.Spec.Wireguard.InterfaceIPv4Address)
			}
		}
	}
	_, err = r.client.IPAM().ReleaseIPs(context.Background(), ips)
	switch err.(type) {
	case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
	default:
		return nil, err
	}
	for _, wep := range weps.Items {
		if wep.Spec.Node != name {
			continue
		}
		_, err = r.client.WorkloadEndpoints().Delete(ctx, wep.Namespace, wep.Name, options.DeleteOptions{})
		switch err.(type) {
		case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
		default:
			return nil, err
		}
	}
	err = r.client.IPAM().RemoveIPAMHost(ctx, name)
	switch err.(type) {
	case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
	default:
		return nil, err
	}
	bgpPeers, err := r.client.BGPPeers().List(ctx, options.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, peer := range bgpPeers.Items {
		if peer.Spec.Node != name {
			continue
		}
		_, err = r.client.BGPPeers().Delete(ctx, peer.Name, options.DeleteOptions{})
		switch err.(type) {
		case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
		default:
			return nil, err
		}
	}
	nodeConfName := fmt.Sprintf("node.%s", name)
	_, err = r.client.FelixConfigurations().Delete(ctx, nodeConfName, options.DeleteOptions{})
	switch err.(type) {
	case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
	default:
		return nil, err
	}
	_, err = r.client.BGPConfigurations().Delete(ctx, nodeConfName, options.DeleteOptions{})
	switch err.(type) {
	case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
	default:
		return nil, err
	}
	heps, err := r.client.HostEndpoints().List(ctx, options.ListOptions{})
	if err != nil {
		return nil, err
	}
	for _, hep := range heps.Items {
		if hep.Spec.Node != name {
			continue
		}
		_, err = r.client.HostEndpoints().Delete(ctx, hep.Name, options.DeleteOptions{})
		switch err.(type) {
		case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
		default:
			return nil, err
		}
	}
	out, err := r.client.resources.Delete(ctx, opts, libapiv3.KindNode, noNamespace, name)
	if out != nil {
		return out.(*libapiv3.Node), err
	}
	return nil, err
}
func (r nodes) Get(ctx context.Context, name string, opts options.GetOptions) (*libapiv3.Node, error) {
	out, err := r.client.resources.Get(ctx, opts, libapiv3.KindNode, noNamespace, name)
	if out != nil {
		return out.(*libapiv3.Node), err
	}
	return nil, err
}
func (r nodes) List(ctx context.Context, opts options.ListOptions) (*libapiv3.NodeList, error) {
	res := &libapiv3.NodeList{}
	if err := r.client.resources.List(ctx, opts, libapiv3.KindNode, libapiv3.KindNodeList, res); err != nil {
		return nil, err
	}
	return res, nil
}