...

Source file src/k8s.io/kubernetes/pkg/registry/core/node/storage/storage.go

Documentation: k8s.io/kubernetes/pkg/registry/core/node/storage

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package storage
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net/http"
    23  	"net/url"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	"k8s.io/apiserver/pkg/registry/generic"
    29  	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
    30  	"k8s.io/apiserver/pkg/registry/rest"
    31  	api "k8s.io/kubernetes/pkg/apis/core"
    32  	k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
    33  	"k8s.io/kubernetes/pkg/kubelet/client"
    34  	"k8s.io/kubernetes/pkg/printers"
    35  	printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
    36  	printerstorage "k8s.io/kubernetes/pkg/printers/storage"
    37  	"k8s.io/kubernetes/pkg/registry/core/node"
    38  	noderest "k8s.io/kubernetes/pkg/registry/core/node/rest"
    39  	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
    40  )
    41  
    42  // NodeStorage includes storage for nodes and all sub resources.
    43  type NodeStorage struct {
    44  	Node   *REST
    45  	Status *StatusREST
    46  	Proxy  *noderest.ProxyREST
    47  
    48  	KubeletConnectionInfo client.ConnectionInfoGetter
    49  }
    50  
    51  // REST implements a RESTStorage for nodes.
    52  type REST struct {
    53  	*genericregistry.Store
    54  	connection     client.ConnectionInfoGetter
    55  	proxyTransport http.RoundTripper
    56  }
    57  
    58  // StatusREST implements the REST endpoint for changing the status of a node.
    59  type StatusREST struct {
    60  	store *genericregistry.Store
    61  }
    62  
    63  // New creates a new Node object.
    64  func (r *StatusREST) New() runtime.Object {
    65  	return &api.Node{}
    66  }
    67  
    68  // Destroy cleans up resources on shutdown.
    69  func (r *StatusREST) Destroy() {
    70  	// Given that underlying store is shared with REST,
    71  	// we don't destroy it here explicitly.
    72  }
    73  
    74  // Get retrieves the object from the storage. It is required to support Patch.
    75  func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
    76  	return r.store.Get(ctx, name, options)
    77  }
    78  
    79  // Update alters the status subset of an object.
    80  func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
    81  	// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
    82  	// subresources should never allow create on update.
    83  	return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
    84  }
    85  
    86  // GetResetFields implements rest.ResetFieldsStrategy
    87  func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
    88  	return r.store.GetResetFields()
    89  }
    90  
    91  func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
    92  	return r.store.ConvertToTable(ctx, object, tableOptions)
    93  }
    94  
    95  // NewStorage returns a NodeStorage object that will work against nodes.
    96  func NewStorage(optsGetter generic.RESTOptionsGetter, kubeletClientConfig client.KubeletClientConfig, proxyTransport http.RoundTripper) (*NodeStorage, error) {
    97  	store := &genericregistry.Store{
    98  		NewFunc:                   func() runtime.Object { return &api.Node{} },
    99  		NewListFunc:               func() runtime.Object { return &api.NodeList{} },
   100  		PredicateFunc:             node.MatchNode,
   101  		DefaultQualifiedResource:  api.Resource("nodes"),
   102  		SingularQualifiedResource: api.Resource("node"),
   103  
   104  		CreateStrategy:      node.Strategy,
   105  		UpdateStrategy:      node.Strategy,
   106  		DeleteStrategy:      node.Strategy,
   107  		ResetFieldsStrategy: node.Strategy,
   108  
   109  		TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
   110  	}
   111  	options := &generic.StoreOptions{
   112  		RESTOptions: optsGetter,
   113  		AttrFunc:    node.GetAttrs,
   114  	}
   115  	if err := store.CompleteWithOptions(options); err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	statusStore := *store
   120  	statusStore.UpdateStrategy = node.StatusStrategy
   121  	statusStore.ResetFieldsStrategy = node.StatusStrategy
   122  
   123  	// Set up REST handlers
   124  	nodeREST := &REST{Store: store, proxyTransport: proxyTransport}
   125  	statusREST := &StatusREST{store: &statusStore}
   126  	proxyREST := &noderest.ProxyREST{Store: store, ProxyTransport: proxyTransport}
   127  
   128  	// Build a NodeGetter that looks up nodes using the REST handler
   129  	nodeGetter := client.NodeGetterFunc(func(ctx context.Context, nodeName string, options metav1.GetOptions) (*v1.Node, error) {
   130  		obj, err := nodeREST.Get(ctx, nodeName, &options)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  		node, ok := obj.(*api.Node)
   135  		if !ok {
   136  			return nil, fmt.Errorf("unexpected type %T", obj)
   137  		}
   138  		// TODO: Remove the conversion. Consider only return the NodeAddresses
   139  		externalNode := &v1.Node{}
   140  		err = k8s_api_v1.Convert_core_Node_To_v1_Node(node, externalNode, nil)
   141  		if err != nil {
   142  			return nil, fmt.Errorf("failed to convert to v1.Node: %v", err)
   143  		}
   144  		return externalNode, nil
   145  	})
   146  	connectionInfoGetter, err := client.NewNodeConnectionInfoGetter(nodeGetter, kubeletClientConfig)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	nodeREST.connection = connectionInfoGetter
   151  	proxyREST.Connection = connectionInfoGetter
   152  
   153  	return &NodeStorage{
   154  		Node:                  nodeREST,
   155  		Status:                statusREST,
   156  		Proxy:                 proxyREST,
   157  		KubeletConnectionInfo: connectionInfoGetter,
   158  	}, nil
   159  }
   160  
   161  // Implement Redirector.
   162  var _ = rest.Redirector(&REST{})
   163  
   164  // ResourceLocation returns a URL to which one can send traffic for the specified node.
   165  func (r *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http.RoundTripper, error) {
   166  	return node.ResourceLocation(r, r.connection, r.proxyTransport, ctx, id)
   167  }
   168  
   169  // ShortNames implements the ShortNamesProvider interface. Returns a list of short names for a resource.
   170  func (r *REST) ShortNames() []string {
   171  	return []string{"no"}
   172  }
   173  

View as plain text