k8s.io/apiserver@v0.31.1/pkg/endpoints/groupversion.go (about)

     1  /*
     2  Copyright 2014 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 endpoints
    18  
    19  import (
    20  	"path"
    21  	"time"
    22  
    23  	restful "github.com/emicklei/go-restful/v3"
    24  
    25  	apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    30  	"k8s.io/apimachinery/pkg/util/managedfields"
    31  	"k8s.io/apimachinery/pkg/util/sets"
    32  	"k8s.io/apiserver/pkg/admission"
    33  	"k8s.io/apiserver/pkg/authorization/authorizer"
    34  	"k8s.io/apiserver/pkg/endpoints/discovery"
    35  	"k8s.io/apiserver/pkg/registry/rest"
    36  	"k8s.io/apiserver/pkg/storageversion"
    37  )
    38  
    39  // ConvertabilityChecker indicates what versions a GroupKind is available in.
    40  type ConvertabilityChecker interface {
    41  	// VersionsForGroupKind indicates what versions are available to convert a group kind. This determines
    42  	// what our decoding abilities are.
    43  	VersionsForGroupKind(gk schema.GroupKind) []schema.GroupVersion
    44  }
    45  
    46  // APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful
    47  // It handles URLs of the form:
    48  // /${storage_key}[/${object_name}]
    49  // Where 'storage_key' points to a rest.Storage object stored in storage.
    50  // This object should contain all parameterization necessary for running a particular API version
    51  type APIGroupVersion struct {
    52  	Storage map[string]rest.Storage
    53  
    54  	Root string
    55  
    56  	// GroupVersion is the external group version
    57  	GroupVersion schema.GroupVersion
    58  
    59  	// AllServedVersionsByResource is indexed by resource and maps to a list of versions that resource exists in.
    60  	// This was created so that StorageVersion for APIs can include a list of all version that are served for each
    61  	// GroupResource tuple.
    62  	AllServedVersionsByResource map[string][]string
    63  
    64  	// OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver
    65  	// schema like api.Status, api.DeleteOptions, and metav1.ListOptions. Other implementors may
    66  	// define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If
    67  	// empty, defaults to GroupVersion.
    68  	OptionsExternalVersion *schema.GroupVersion
    69  	// MetaGroupVersion defaults to "meta.k8s.io/v1" and is the scheme group version used to decode
    70  	// common API implementations like ListOptions. Future changes will allow this to vary by group
    71  	// version (for when the inevitable meta/v2 group emerges).
    72  	MetaGroupVersion *schema.GroupVersion
    73  
    74  	// RootScopedKinds are the root scoped kinds for the primary GroupVersion
    75  	RootScopedKinds sets.String
    76  
    77  	// Serializer is used to determine how to convert responses from API methods into bytes to send over
    78  	// the wire.
    79  	Serializer     runtime.NegotiatedSerializer
    80  	ParameterCodec runtime.ParameterCodec
    81  
    82  	Typer                 runtime.ObjectTyper
    83  	Creater               runtime.ObjectCreater
    84  	Convertor             runtime.ObjectConvertor
    85  	ConvertabilityChecker ConvertabilityChecker
    86  	Defaulter             runtime.ObjectDefaulter
    87  	Namer                 runtime.Namer
    88  	UnsafeConvertor       runtime.ObjectConvertor
    89  	TypeConverter         managedfields.TypeConverter
    90  
    91  	EquivalentResourceRegistry runtime.EquivalentResourceRegistry
    92  
    93  	// Authorizer determines whether a user is allowed to make a certain request. The Handler does a preliminary
    94  	// authorization check using the request URI but it may be necessary to make additional checks, such as in
    95  	// the create-on-update case
    96  	Authorizer authorizer.Authorizer
    97  
    98  	Admit admission.Interface
    99  
   100  	MinRequestTimeout time.Duration
   101  
   102  	// The limit on the request body size that would be accepted and decoded in a write request.
   103  	// 0 means no limit.
   104  	MaxRequestBodyBytes int64
   105  }
   106  
   107  // InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container.
   108  // It is expected that the provided path root prefix will serve all operations. Root MUST NOT end
   109  // in a slash.
   110  func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]apidiscoveryv2.APIResourceDiscovery, []*storageversion.ResourceInfo, error) {
   111  	prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)
   112  	installer := &APIInstaller{
   113  		group:             g,
   114  		prefix:            prefix,
   115  		minRequestTimeout: g.MinRequestTimeout,
   116  	}
   117  
   118  	apiResources, resourceInfos, ws, registrationErrors := installer.Install()
   119  	versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, staticLister{apiResources})
   120  	versionDiscoveryHandler.AddToWebService(ws)
   121  	container.Add(ws)
   122  	aggregatedDiscoveryResources, err := ConvertGroupVersionIntoToDiscovery(apiResources)
   123  	if err != nil {
   124  		registrationErrors = append(registrationErrors, err)
   125  	}
   126  	return aggregatedDiscoveryResources, removeNonPersistedResources(resourceInfos), utilerrors.NewAggregate(registrationErrors)
   127  }
   128  
   129  func removeNonPersistedResources(infos []*storageversion.ResourceInfo) []*storageversion.ResourceInfo {
   130  	var filtered []*storageversion.ResourceInfo
   131  	for _, info := range infos {
   132  		// if EncodingVersion is empty, then the apiserver does not
   133  		// need to register this resource via the storage version API,
   134  		// thus we can remove it.
   135  		if info != nil && len(info.EncodingVersion) > 0 {
   136  			filtered = append(filtered, info)
   137  		}
   138  	}
   139  	return filtered
   140  }
   141  
   142  // staticLister implements the APIResourceLister interface
   143  type staticLister struct {
   144  	list []metav1.APIResource
   145  }
   146  
   147  func (s staticLister) ListAPIResources() []metav1.APIResource {
   148  	return s.list
   149  }
   150  
   151  var _ discovery.APIResourceLister = &staticLister{}