k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/registry/core/rest/storage_core_generic.go (about)

     1  /*
     2  Copyright 2023 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 rest
    18  
    19  import (
    20  	"context"
    21  	"time"
    22  
    23  	corev1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/errors"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime"
    27  	"k8s.io/apimachinery/pkg/runtime/schema"
    28  	"k8s.io/apiserver/pkg/authentication/authenticator"
    29  	"k8s.io/apiserver/pkg/registry/generic"
    30  	"k8s.io/apiserver/pkg/registry/rest"
    31  	genericapiserver "k8s.io/apiserver/pkg/server"
    32  	serverstorage "k8s.io/apiserver/pkg/server/storage"
    33  	"k8s.io/client-go/informers"
    34  	restclient "k8s.io/client-go/rest"
    35  
    36  	"k8s.io/kubernetes/pkg/api/legacyscheme"
    37  	api "k8s.io/kubernetes/pkg/apis/core"
    38  	configmapstore "k8s.io/kubernetes/pkg/registry/core/configmap/storage"
    39  	eventstore "k8s.io/kubernetes/pkg/registry/core/event/storage"
    40  	namespacestore "k8s.io/kubernetes/pkg/registry/core/namespace/storage"
    41  	resourcequotastore "k8s.io/kubernetes/pkg/registry/core/resourcequota/storage"
    42  	secretstore "k8s.io/kubernetes/pkg/registry/core/secret/storage"
    43  	serviceaccountstore "k8s.io/kubernetes/pkg/registry/core/serviceaccount/storage"
    44  	"k8s.io/kubernetes/pkg/serviceaccount"
    45  )
    46  
    47  // GenericConfig provides information needed to build RESTStorage
    48  // for generic resources in core. It implements the "normal" RESTStorageProvider interface.
    49  type GenericConfig struct {
    50  	StorageFactory serverstorage.StorageFactory
    51  	EventTTL       time.Duration
    52  
    53  	ServiceAccountIssuer        serviceaccount.TokenGenerator
    54  	ServiceAccountMaxExpiration time.Duration
    55  	ExtendExpiration            bool
    56  
    57  	APIAudiences authenticator.Audiences
    58  
    59  	LoopbackClientConfig *restclient.Config
    60  	Informers            informers.SharedInformerFactory
    61  }
    62  
    63  func (c *GenericConfig) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) {
    64  	apiGroupInfo := genericapiserver.APIGroupInfo{
    65  		PrioritizedVersions:          legacyscheme.Scheme.PrioritizedVersionsForGroup(""),
    66  		VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},
    67  		Scheme:                       legacyscheme.Scheme,
    68  		ParameterCodec:               legacyscheme.ParameterCodec,
    69  		NegotiatedSerializer:         legacyscheme.Codecs,
    70  	}
    71  
    72  	eventStorage, err := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds()))
    73  	if err != nil {
    74  		return genericapiserver.APIGroupInfo{}, err
    75  	}
    76  
    77  	resourceQuotaStorage, resourceQuotaStatusStorage, err := resourcequotastore.NewREST(restOptionsGetter)
    78  	if err != nil {
    79  		return genericapiserver.APIGroupInfo{}, err
    80  	}
    81  	secretStorage, err := secretstore.NewREST(restOptionsGetter)
    82  	if err != nil {
    83  		return genericapiserver.APIGroupInfo{}, err
    84  	}
    85  
    86  	configMapStorage, err := configmapstore.NewREST(restOptionsGetter)
    87  	if err != nil {
    88  		return genericapiserver.APIGroupInfo{}, err
    89  	}
    90  
    91  	namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage, err := namespacestore.NewREST(restOptionsGetter)
    92  	if err != nil {
    93  		return genericapiserver.APIGroupInfo{}, err
    94  	}
    95  
    96  	var serviceAccountStorage *serviceaccountstore.REST
    97  	if c.ServiceAccountIssuer != nil {
    98  		serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, c.ServiceAccountIssuer, c.APIAudiences, c.ServiceAccountMaxExpiration, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), secretStorage.Store, newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), c.ExtendExpiration)
    99  	} else {
   100  		serviceAccountStorage, err = serviceaccountstore.NewREST(restOptionsGetter, nil, nil, 0, newNotFoundGetter(schema.GroupResource{Resource: "pods"}), newNotFoundGetter(schema.GroupResource{Resource: "secrets"}), newNotFoundGetter(schema.GroupResource{Resource: "nodes"}), false)
   101  	}
   102  	if err != nil {
   103  		return genericapiserver.APIGroupInfo{}, err
   104  	}
   105  
   106  	storage := map[string]rest.Storage{}
   107  	if resource := "events"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   108  		storage[resource] = eventStorage
   109  	}
   110  
   111  	if resource := "resourcequotas"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   112  		storage[resource] = resourceQuotaStorage
   113  		storage[resource+"/status"] = resourceQuotaStatusStorage
   114  	}
   115  
   116  	if resource := "namespaces"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   117  		storage[resource] = namespaceStorage
   118  		storage[resource+"/status"] = namespaceStatusStorage
   119  		storage[resource+"/finalize"] = namespaceFinalizeStorage
   120  	}
   121  
   122  	if resource := "secrets"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   123  		storage[resource] = secretStorage
   124  	}
   125  
   126  	if resource := "serviceaccounts"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   127  		storage[resource] = serviceAccountStorage
   128  		if serviceAccountStorage.Token != nil {
   129  			storage[resource+"/token"] = serviceAccountStorage.Token
   130  		}
   131  	}
   132  
   133  	if resource := "configmaps"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {
   134  		storage[resource] = configMapStorage
   135  	}
   136  
   137  	if len(storage) > 0 {
   138  		apiGroupInfo.VersionedResourcesStorageMap["v1"] = storage
   139  	}
   140  
   141  	return apiGroupInfo, nil
   142  }
   143  
   144  func (c *GenericConfig) GroupName() string {
   145  	return api.GroupName
   146  }
   147  
   148  func newNotFoundGetter(gr schema.GroupResource) rest.Getter {
   149  	return notFoundGetter{gr: gr}
   150  }
   151  
   152  type notFoundGetter struct {
   153  	gr schema.GroupResource
   154  }
   155  
   156  func (g notFoundGetter) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
   157  	return nil, errors.NewNotFound(g.gr, name)
   158  }