func (c *resources) Get(ctx context.Context, opts options.GetOptions, kind, ns, name string) (resource, error) {
	if err := c.checkNamespace(ns, kind); err != nil {
		return nil, err
	}
	key := model.ResourceKey{
		Kind:      kind,
		Name:      name,
		Namespace: ns,
	}
	kvp, err := c.backend.Get(ctx, key, opts.ResourceVersion)
	if err != nil {
		return nil, err
	}
	out := c.kvPairToResource(kvp)
	return out, nil
}
Get gets a resource from the backend datastore.
package clientv3
import (
	"context"
	"sync/atomic"
	log "github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/api/meta"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/util/uuid"
	apiv3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3"
	bapi "github.com/projectcalico/libcalico-go/lib/backend/api"
	"github.com/projectcalico/libcalico-go/lib/backend/model"
	cerrors "github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/namespace"
	"github.com/projectcalico/libcalico-go/lib/options"
	"github.com/projectcalico/libcalico-go/lib/watch"
)
const (
	noNamespace      = ""
	defaultNamespace = "default"
	maxApplyRetries  = 10
)
type resource interface {
	runtime.Object
	v1.ObjectMetaAccessor
}
type resourceList interface {
	runtime.Object
	v1.ListMetaAccessor
}
type resourceInterface interface {
	Create(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error)
	Update(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error)
	Delete(ctx context.Context, opts options.DeleteOptions, kind, ns, name string) (resource, error)
	Get(ctx context.Context, opts options.GetOptions, kind, ns, name string) (resource, error)
	List(ctx context.Context, opts options.ListOptions, kind, listkind string, inout resourceList) error
	Watch(ctx context.Context, opts options.ListOptions, kind string, converter watcherConverter) (watch.Interface, error)
}
type resources struct {
	backend bapi.Client
}
func (c *resources) Create(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error) {
	if len(in.GetObjectMeta().GetName()) == 0 {
		var generateNameMessage string
		if len(in.GetObjectMeta().GetGenerateName()) != 0 {
			generateNameMessage = " (GenerateName is not supported)"
		}
		return nil, cerrors.ErrorValidation{
			ErroredFields: []cerrors.ErroredField{{
				Name:   "Metadata.Name",
				Reason: "field must be set for a Create request" + generateNameMessage,
				Value:  in.GetObjectMeta().GetName(),
			}},
		}
	}
	if len(in.GetObjectMeta().GetResourceVersion()) != 0 {
		logWithResource(in).Info("Rejecting Create request with non-empty resource version")
		return nil, cerrors.ErrorValidation{
			ErroredFields: []cerrors.ErroredField{{
				Name:   "Metadata.ResourceVersion",
				Reason: "field must not be set for a Create request",
				Value:  in.GetObjectMeta().GetResourceVersion(),
			}},
		}
	}
	if err := c.checkNamespace(in.GetObjectMeta().GetNamespace(), kind); err != nil {
		return nil, err
	}
	creationTimestamp := in.GetObjectMeta().GetCreationTimestamp()
	if creationTimestamp.IsZero() {
		in.GetObjectMeta().SetCreationTimestamp(v1.Now())
	}
	if in.GetObjectMeta().GetUID() == "" {
		in.GetObjectMeta().SetUID(uuid.NewUUID())
	}
	kvp, err := c.backend.Create(ctx, c.resourceToKVPair(opts, kind, in))
	if kvp != nil {
		return c.kvPairToResource(kvp), err
	}
	return nil, err
}
func (c *resources) Update(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error) {
	if len(in.GetObjectMeta().GetResourceVersion()) == 0 {
		logWithResource(in).Info("Rejecting Update request with empty resource version")
		return nil, cerrors.ErrorValidation{
			ErroredFields: []cerrors.ErroredField{{
				Name:   "Metadata.ResourceVersion",
				Reason: "field must be set for an Update request",
				Value:  in.GetObjectMeta().GetResourceVersion(),
			}},
		}
	}
	if err := c.checkNamespace(in.GetObjectMeta().GetNamespace(), kind); err != nil {
		return nil, err
	}
	creationTimestamp := in.GetObjectMeta().GetCreationTimestamp()
	if creationTimestamp.IsZero() {
		return nil, cerrors.ErrorValidation{
			ErroredFields: []cerrors.ErroredField{{
				Name:   "Metadata.CreationTimestamp",
				Reason: "field must be set for an Update request",
				Value:  in.GetObjectMeta().GetCreationTimestamp(),
			}},
		}
	}
	if in.GetObjectMeta().GetUID() == "" {
		return nil, cerrors.ErrorValidation{
			ErroredFields: []cerrors.ErroredField{{
				Name:   "Metadata.UID",
				Reason: "field must be set for an Update request",
				Value:  in.GetObjectMeta().GetUID(),
			}},
		}
	}
	kvp, err := c.backend.Update(ctx, c.resourceToKVPair(opts, kind, in))
	if kvp != nil {
		return c.kvPairToResource(kvp), err
	}
	return nil, err
}
func (c *resources) Delete(ctx context.Context, opts options.DeleteOptions, kind, ns, name string) (resource, error) {
	if err := c.checkNamespace(ns, kind); err != nil {
		return nil, err
	}
	key := model.ResourceKey{
		Kind:      kind,
		Name:      name,
		Namespace: ns,
	}
	kvpIn := model.KVPair{
		Key:      key,
		Revision: opts.ResourceVersion,
		UID:      opts.UID,
	}
	kvp, err := c.backend.DeleteKVP(ctx, &kvpIn)
	if kvp != nil {
		return c.kvPairToResource(kvp), err
	}
	return nil, err
}