// DefaultKeyFunctions sets the default behavior for storage key generation onto a Store. func DefaultKeyFunctions(store *registry.Store, prefix string, isNamespaced bool) { if isNamespaced { if store.KeyRootFunc == nil { store.KeyRootFunc = func(ctx kapi.Context) string { return registry.NamespaceKeyRootFunc(ctx, prefix) } } if store.KeyFunc == nil { store.KeyFunc = func(ctx kapi.Context, name string) (string, error) { return registry.NamespaceKeyFunc(ctx, prefix, name) } } } else { if store.KeyRootFunc == nil { store.KeyRootFunc = func(ctx kapi.Context) string { return prefix } } if store.KeyFunc == nil { store.KeyFunc = func(ctx kapi.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) } } } }
// NewREST returns a registry which will store ThirdPartyResource in the given helper func NewREST(opts generic.RESTOptions) *REST { prefix := "/" + opts.ResourcePrefix // We explicitly do NOT do any decoration here yet. storageInterface, dFunc := generic.NewRawStorage(opts.StorageConfig) store := ®istry.Store{ NewFunc: func() runtime.Object { return &extensions.ThirdPartyResource{} }, NewListFunc: func() runtime.Object { return &extensions.ThirdPartyResourceList{} }, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, id string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.ThirdPartyResource).Name, nil }, PredicateFunc: thirdpartyresource.Matcher, QualifiedResource: extensions.Resource("thirdpartyresources"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: thirdpartyresource.Strategy, UpdateStrategy: thirdpartyresource.Strategy, DeleteStrategy: thirdpartyresource.Strategy, Storage: storageInterface, DestroyFunc: dFunc, } return &REST{store} }
// NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects. func NewREST(opts generic.RESTOptions) *REST { newListFunc := func() runtime.Object { return &extensions.PodSecurityPolicyList{} } storageInterface := opts.Decorator( opts.Storage, 100, &extensions.PodSecurityPolicy{}, Prefix, podsecuritypolicy.Strategy, newListFunc) store := ®istry.Store{ NewFunc: func() runtime.Object { return &extensions.PodSecurityPolicy{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return Prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, Prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.PodSecurityPolicy).Name, nil }, PredicateFunc: podsecuritypolicy.MatchPodSecurityPolicy, QualifiedResource: extensions.Resource("podsecuritypolicies"), DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: podsecuritypolicy.Strategy, UpdateStrategy: podsecuritypolicy.Strategy, DeleteStrategy: podsecuritypolicy.Strategy, ReturnDeletedObject: true, Storage: storageInterface, } return &REST{store} }
// NewREST returns a RESTStorage object that will work against subnets func NewREST(optsGetter restoptions.Getter) (*REST, error) { store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.ClusterNetwork{} }, NewListFunc: func() runtime.Object { return &api.ClusterNetworkList{} }, KeyRootFunc: func(ctx kapi.Context) string { return etcdPrefix }, KeyFunc: func(ctx kapi.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, etcdPrefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.ClusterNetwork).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return clusternetwork.Matcher(label, field) }, QualifiedResource: api.Resource("clusternetworks"), CreateStrategy: clusternetwork.Strategy, UpdateStrategy: clusternetwork.Strategy, } if err := restoptions.ApplyOptions(optsGetter, store, etcdPrefix); err != nil { return nil, err } return &REST{*store}, nil }
// NewREST returns a registry which will store CertificateSigningRequest in the given helper func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *ApprovalREST) { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &certificates.CertificateSigningRequestList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.CertificateSigningRequests), &certificates.CertificateSigningRequest{}, prefix, csrregistry.Strategy, newListFunc, storage.NoTriggerPublisher, ) store := ®istry.Store{ NewFunc: func() runtime.Object { return &certificates.CertificateSigningRequest{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, id string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*certificates.CertificateSigningRequest).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) storage.SelectionPredicate { return csrregistry.Matcher(label, field) }, QualifiedResource: certificates.Resource("certificatesigningrequests"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: csrregistry.Strategy, UpdateStrategy: csrregistry.Strategy, DeleteStrategy: csrregistry.Strategy, Storage: storageInterface, DestroyFunc: dFunc, } // Subresources use the same store and creation strategy, which only // allows empty subs. Updates to an existing subresource are handled by // dedicated strategies. statusStore := *store statusStore.UpdateStrategy = csrregistry.StatusStrategy approvalStore := *store approvalStore.UpdateStrategy = csrregistry.ApprovalStrategy return &REST{store}, &StatusREST{store: &statusStore}, &ApprovalREST{store: &approvalStore} }
// NewREST returns a RESTStorage object that will work against network policies. func NewREST(opts generic.RESTOptions) *REST { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &apiregistration.APIServiceList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, 1000, // cache size &apiregistration.APIService{}, prefix, strategy, newListFunc, getAttrs, storage.NoTriggerPublisher, ) store := ®istry.Store{ NewFunc: func() runtime.Object { return &apiregistration.APIService{} }, // NewListFunc returns an object capable of storing results of an etcd list. NewListFunc: newListFunc, // Produces a APIService that etcd understands, to the root of the resource // by combining the namespace in the context with the given prefix KeyRootFunc: func(ctx api.Context) string { return prefix }, // Produces a APIService that etcd understands, to the resource by combining // the namespace in the context with the given prefix KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, // Retrieve the name field of an apiserver ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*apiregistration.APIService).Name, nil }, // Used to match objects based on labels/fields for list and watch PredicateFunc: MatchAPIService, QualifiedResource: apiregistration.Resource("apiservers"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, // Used to validate controller creation CreateStrategy: strategy, // Used to validate controller updates UpdateStrategy: strategy, DeleteStrategy: strategy, Storage: storageInterface, DestroyFunc: dFunc, } return &REST{store} }
// NewStorage returns a NodeStorage object that will work against nodes. func NewStorage(opts generic.RESTOptions, connection client.KubeletClient, proxyTransport http.RoundTripper) NodeStorage { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &api.NodeList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.Nodes), &api.Node{}, prefix, node.Strategy, newListFunc, node.NodeNameTriggerFunc) store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.Node{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Node).Name, nil }, PredicateFunc: node.MatchNode, QualifiedResource: api.Resource("nodes"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: node.Strategy, UpdateStrategy: node.Strategy, DeleteStrategy: node.Strategy, ExportStrategy: node.Strategy, Storage: storageInterface, DestroyFunc: dFunc, } statusStore := *store statusStore.UpdateStrategy = node.StatusStrategy nodeREST := &REST{store, connection, proxyTransport} return NodeStorage{ Node: nodeREST, Status: &StatusREST{store: &statusStore}, Proxy: &noderest.ProxyREST{Store: store, Connection: client.ConnectionInfoGetter(nodeREST), ProxyTransport: proxyTransport}, } }
// NewREST returns a RESTStorage object that will work against namespaces. func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *FinalizeREST) { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &api.NamespaceList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.Namespaces), &api.Namespace{}, prefix, namespace.Strategy, newListFunc, namespace.GetAttrs, storage.NoTriggerPublisher, ) store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Namespace{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Namespace).Name, nil }, PredicateFunc: namespace.MatchNamespace, QualifiedResource: api.Resource("namespaces"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: namespace.Strategy, UpdateStrategy: namespace.Strategy, DeleteStrategy: namespace.Strategy, ReturnDeletedObject: true, Storage: storageInterface, DestroyFunc: dFunc, } statusStore := *store statusStore.UpdateStrategy = namespace.StatusStrategy finalizeStore := *store finalizeStore.UpdateStrategy = namespace.FinalizeStrategy return &REST{Store: store, status: &statusStore}, &StatusREST{store: &statusStore}, &FinalizeREST{store: &finalizeStore} }
// NewREST returns a RESTStorage object that will work against clusters. func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &federation.ClusterList{} } storageInterface, _ := opts.Decorator( opts.StorageConfig, 100, &federation.Cluster{}, prefix, cluster.Strategy, newListFunc, cluster.GetAttrs, storage.NoTriggerPublisher, ) store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &federation.Cluster{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*federation.Cluster).Name, nil }, PredicateFunc: cluster.MatchCluster, QualifiedResource: federation.Resource("clusters"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: cluster.Strategy, UpdateStrategy: cluster.Strategy, DeleteStrategy: cluster.Strategy, ReturnDeletedObject: true, Storage: storageInterface, } statusStore := *store statusStore.UpdateStrategy = cluster.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} }
// NewREST returns a new REST. func NewREST(optsGetter restoptions.Getter) (*REST, error) { prefix := "/images" store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.Image{} }, // NewListFunc returns an object capable of storing results of an etcd list. NewListFunc: func() runtime.Object { return &api.ImageList{} }, // Produces a path that etcd understands, to the root of the resource // by combining the namespace in the context with the given prefix. // Yet images are not namespace scoped, so we're returning just prefix here. KeyRootFunc: func(ctx kapi.Context) string { return prefix }, // Produces a path that etcd understands, to the resource by combining // the namespace in the context with the given prefix // Yet images are not namespace scoped, so we're returning just prefix here. KeyFunc: func(ctx kapi.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, // Retrieve the name field of an image ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Image).Name, nil }, // Used to match objects based on labels/fields for list and watch PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return image.MatchImage(label, field) }, QualifiedResource: api.Resource("images"), // Used to validate image creation CreateStrategy: image.Strategy, // Used to validate image updates UpdateStrategy: image.Strategy, ReturnDeletedObject: false, } if err := restoptions.ApplyOptions(optsGetter, store, prefix); err != nil { return nil, err } return &REST{store}, nil }
// NewREST returns a RESTStorage object that will work against persistent volumes. func NewREST(opts generic.RESTOptions) *REST { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &storageapi.StorageClassList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.StorageClasses), &storageapi.StorageClass{}, prefix, storageclass.Strategy, newListFunc, storageclass.GetAttrs, storage.NoTriggerPublisher, ) store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &storageapi.StorageClass{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*storageapi.StorageClass).Name, nil }, PredicateFunc: storageclass.MatchStorageClasses, QualifiedResource: storageapi.Resource("storageclasses"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: storageclass.Strategy, UpdateStrategy: storageclass.Strategy, DeleteStrategy: storageclass.Strategy, ReturnDeletedObject: true, Storage: storageInterface, DestroyFunc: dFunc, } return &REST{store} }
// NewREST returns a RESTStorage object that will work against persistent volumes. func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &api.PersistentVolumeList{} } storageInterface := opts.Decorator( opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.PersistentVolumes), &api.PersistentVolume{}, prefix, persistentvolume.Strategy, newListFunc, storage.NoTriggerPublisher, ) store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.PersistentVolume{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.PersistentVolume).Name, nil }, PredicateFunc: persistentvolume.MatchPersistentVolumes, QualifiedResource: api.Resource("persistentvolumes"), DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: persistentvolume.Strategy, UpdateStrategy: persistentvolume.Strategy, DeleteStrategy: persistentvolume.Strategy, ReturnDeletedObject: true, Storage: storageInterface, } statusStore := *store statusStore.UpdateStrategy = persistentvolume.StatusStrategy return &REST{store}, &StatusREST{store: &statusStore} }
// NewREST returns a RESTStorage object that will work against ClusterRole objects. func NewREST(opts generic.RESTOptions) *REST { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &rbac.ClusterRoleList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.ClusterRoles), &rbac.ClusterRole{}, prefix, clusterrole.Strategy, newListFunc, clusterrole.GetAttrs, storage.NoTriggerPublisher, ) store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &rbac.ClusterRole{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return genericregistry.NamespaceKeyRootFunc(ctx, prefix) }, KeyFunc: func(ctx api.Context, id string) (string, error) { return genericregistry.NoNamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.ClusterRole).Name, nil }, PredicateFunc: clusterrole.Matcher, QualifiedResource: rbac.Resource("clusterroles"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: clusterrole.Strategy, UpdateStrategy: clusterrole.Strategy, DeleteStrategy: clusterrole.Strategy, Storage: storageInterface, DestroyFunc: dFunc, } return &REST{store} }
// NewREST returns a RESTStorage object that will work against namespaces. func NewREST(opts generic.RESTOptions) (*REST, *StatusREST, *FinalizeREST) { prefix := "/namespaces" newListFunc := func() runtime.Object { return &api.NamespaceList{} } storageInterface := opts.Decorator( opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.Namespaces), &api.Namespace{}, prefix, namespace.Strategy, newListFunc) store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.Namespace{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Namespace).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return namespace.MatchNamespace(label, field) }, QualifiedResource: api.Resource("namespaces"), DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: namespace.Strategy, UpdateStrategy: namespace.Strategy, DeleteStrategy: namespace.Strategy, ReturnDeletedObject: true, Storage: storageInterface, } statusStore := *store statusStore.UpdateStrategy = namespace.StatusStrategy finalizeStore := *store finalizeStore.UpdateStrategy = namespace.FinalizeStrategy return &REST{Store: store, status: &statusStore}, &StatusREST{store: &statusStore}, &FinalizeREST{store: &finalizeStore} }
// NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects. func NewREST(opts generic.RESTOptions) *REST { prefix := "/clusterrolebindings" newListFunc := func() runtime.Object { return &rbac.ClusterRoleBindingList{} } storageInterface := opts.Decorator( opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.ClusterRoleBindings), &rbac.ClusterRoleBinding{}, prefix, clusterrolebinding.Strategy, newListFunc, ) store := ®istry.Store{ NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return registry.NamespaceKeyRootFunc(ctx, prefix) }, KeyFunc: func(ctx api.Context, id string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*rbac.ClusterRoleBinding).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return clusterrolebinding.Matcher(label, field) }, QualifiedResource: rbac.Resource("clusterrolebindings"), DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: clusterrolebinding.Strategy, UpdateStrategy: clusterrolebinding.Strategy, DeleteStrategy: clusterrolebinding.Strategy, Storage: storageInterface, } return &REST{store} }
// NewREST returns a RESTStorage object that will work against persistent volumes. func NewREST(opts generic.RESTOptions) *REST { prefix := "/storageclasses" newListFunc := func() runtime.Object { return &extensions.StorageClassList{} } storageInterface := opts.Decorator( opts.Storage, 100, &extensions.StorageClass{}, prefix, storageclass.Strategy, newListFunc, storage.NoTriggerPublisher, ) store := ®istry.Store{ NewFunc: func() runtime.Object { return &extensions.StorageClass{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return registry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*extensions.StorageClass).Name, nil }, PredicateFunc: storageclass.MatchStorageClasses, QualifiedResource: api.Resource("storageclasses"), DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: storageclass.Strategy, UpdateStrategy: storageclass.Strategy, DeleteStrategy: storageclass.Strategy, ReturnDeletedObject: true, Storage: storageInterface, } return &REST{store} }
// NewStorage returns a NodeStorage object that will work against nodes. func NewStorage(opts generic.RESTOptions, kubeletClientConfig client.KubeletClientConfig, proxyTransport http.RoundTripper) (*NodeStorage, error) { prefix := "/" + opts.ResourcePrefix newListFunc := func() runtime.Object { return &api.NodeList{} } storageInterface, dFunc := opts.Decorator( opts.StorageConfig, cachesize.GetWatchCacheSizeByResource(cachesize.Nodes), &api.Node{}, prefix, node.Strategy, newListFunc, node.GetAttrs, node.NodeNameTriggerFunc) store := &genericregistry.Store{ NewFunc: func() runtime.Object { return &api.Node{} }, NewListFunc: newListFunc, KeyRootFunc: func(ctx api.Context) string { return prefix }, KeyFunc: func(ctx api.Context, name string) (string, error) { return genericregistry.NoNamespaceKeyFunc(ctx, prefix, name) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Node).Name, nil }, PredicateFunc: node.MatchNode, QualifiedResource: api.Resource("nodes"), EnableGarbageCollection: opts.EnableGarbageCollection, DeleteCollectionWorkers: opts.DeleteCollectionWorkers, CreateStrategy: node.Strategy, UpdateStrategy: node.Strategy, DeleteStrategy: node.Strategy, ExportStrategy: node.Strategy, Storage: storageInterface, DestroyFunc: dFunc, } statusStore := *store statusStore.UpdateStrategy = node.StatusStrategy // Set up REST handlers nodeREST := &REST{Store: store, proxyTransport: proxyTransport} statusREST := &StatusREST{store: &statusStore} proxyREST := &noderest.ProxyREST{Store: store, ProxyTransport: proxyTransport} // Build a NodeGetter that looks up nodes using the REST handler nodeGetter := client.NodeGetterFunc(func(nodeName string) (*v1.Node, error) { obj, err := nodeREST.Get(api.NewContext(), nodeName, &metav1.GetOptions{}) if err != nil { return nil, err } node, ok := obj.(*api.Node) if !ok { return nil, fmt.Errorf("unexpected type %T", obj) } // TODO: Remove the conversion. Consider only return the NodeAddresses externalNode := &v1.Node{} err = v1.Convert_api_Node_To_v1_Node(node, externalNode, nil) if err != nil { return nil, fmt.Errorf("failed to convert to v1.Node: %v", err) } return externalNode, nil }) connectionInfoGetter, err := client.NewNodeConnectionInfoGetter(nodeGetter, kubeletClientConfig) if err != nil { return nil, err } nodeREST.connection = connectionInfoGetter proxyREST.Connection = connectionInfoGetter return &NodeStorage{ Node: nodeREST, Status: statusREST, Proxy: proxyREST, KubeletConnectionInfo: connectionInfoGetter, }, nil }