mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Create new conversion Factory interface
Create a new conversion Factory interface for CRDs, and split out NewDelegatingConverter as a standalone package-level function, instead of being part of CRConverterFactory. Signed-off-by: Andy Goldstein <andy.goldstein@redhat.com>
This commit is contained in:
parent
02f8c48f75
commit
0bdcb93b06
@ -23,6 +23,7 @@ import (
|
|||||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||||
|
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||||
apiextensionsoptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
apiextensionsoptions "k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@ -71,10 +72,17 @@ func createAPIExtensionsConfig(
|
|||||||
apiextensionsapiserver.Scheme); err != nil {
|
apiextensionsapiserver.Scheme); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
crdRESTOptionsGetter, err := apiextensionsoptions.NewCRDRESTOptionsGetter(etcdOptions)
|
crdRESTOptionsGetter, err := apiextensionsoptions.NewCRDRESTOptionsGetter(etcdOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conversionFactory, err := conversion.NewCRConverterFactory(serviceResolver, authResolverWrapper)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
apiextensionsConfig := &apiextensionsapiserver.Config{
|
apiextensionsConfig := &apiextensionsapiserver.Config{
|
||||||
GenericConfig: &genericapiserver.RecommendedConfig{
|
GenericConfig: &genericapiserver.RecommendedConfig{
|
||||||
Config: genericConfig,
|
Config: genericConfig,
|
||||||
@ -83,8 +91,7 @@ func createAPIExtensionsConfig(
|
|||||||
ExtraConfig: apiextensionsapiserver.ExtraConfig{
|
ExtraConfig: apiextensionsapiserver.ExtraConfig{
|
||||||
CRDRESTOptionsGetter: crdRESTOptionsGetter,
|
CRDRESTOptionsGetter: crdRESTOptionsGetter,
|
||||||
MasterCount: masterCount,
|
MasterCount: masterCount,
|
||||||
AuthResolverWrapper: authResolverWrapper,
|
ConversionFactory: conversionFactory,
|
||||||
ServiceResolver: serviceResolver,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
|
||||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
|
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
externalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
|
externalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/controller/apiapproval"
|
"k8s.io/apiextensions-apiserver/pkg/controller/apiapproval"
|
||||||
@ -48,7 +49,6 @@ import (
|
|||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -83,10 +83,8 @@ type ExtraConfig struct {
|
|||||||
// the CRD Establishing will be hold by 5 seconds.
|
// the CRD Establishing will be hold by 5 seconds.
|
||||||
MasterCount int
|
MasterCount int
|
||||||
|
|
||||||
// ServiceResolver is used in CR webhook converters to resolve webhook's service names
|
// ConversionFactory is used to provider converters for CRs.
|
||||||
ServiceResolver webhook.ServiceResolver
|
ConversionFactory conversion.Factory
|
||||||
// AuthResolverWrapper is used in CR webhook converters
|
|
||||||
AuthResolverWrapper webhook.AuthenticationInfoResolverWrapper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -197,8 +195,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
|
|||||||
c.ExtraConfig.CRDRESTOptionsGetter,
|
c.ExtraConfig.CRDRESTOptionsGetter,
|
||||||
c.GenericConfig.AdmissionControl,
|
c.GenericConfig.AdmissionControl,
|
||||||
establishingController,
|
establishingController,
|
||||||
c.ExtraConfig.ServiceResolver,
|
c.ExtraConfig.ConversionFactory,
|
||||||
c.ExtraConfig.AuthResolverWrapper,
|
|
||||||
c.ExtraConfig.MasterCount,
|
c.ExtraConfig.MasterCount,
|
||||||
s.GenericAPIServer.Authorizer,
|
s.GenericAPIServer.Authorizer,
|
||||||
c.GenericConfig.RequestTimeout,
|
c.GenericConfig.RequestTimeout,
|
||||||
|
@ -28,6 +28,18 @@ import (
|
|||||||
typedscheme "k8s.io/client-go/kubernetes/scheme"
|
typedscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Factory is able to create a new CRConverter for crd.
|
||||||
|
type Factory interface {
|
||||||
|
// NewConverter returns a CRConverter capable of converting crd's versions.
|
||||||
|
//
|
||||||
|
// For proper conversion, the returned CRConverter must be used via NewDelegatingConverter.
|
||||||
|
//
|
||||||
|
// When implementing a CRConverter, you do not need to: test for valid API versions or no-op
|
||||||
|
// conversions, handle field selector logic, or handle scale conversions; these are all handled
|
||||||
|
// via NewDelegatingConverter.
|
||||||
|
NewConverter(crd *apiextensionsv1.CustomResourceDefinition) (CRConverter, error)
|
||||||
|
}
|
||||||
|
|
||||||
// CRConverterFactory is the factory for all CR converters.
|
// CRConverterFactory is the factory for all CR converters.
|
||||||
type CRConverterFactory struct {
|
type CRConverterFactory struct {
|
||||||
// webhookConverterFactory is the factory for webhook converters.
|
// webhookConverterFactory is the factory for webhook converters.
|
||||||
@ -39,7 +51,7 @@ type CRConverterFactory struct {
|
|||||||
// apiextensions-apiserver runs.
|
// apiextensions-apiserver runs.
|
||||||
var converterMetricFactorySingleton = newConverterMetricFactory()
|
var converterMetricFactorySingleton = newConverterMetricFactory()
|
||||||
|
|
||||||
// NewCRConverterFactory creates a new CRConverterFactory
|
// NewCRConverterFactory creates a new CRConverterFactory that supports none and webhook conversion strategies.
|
||||||
func NewCRConverterFactory(serviceResolver webhook.ServiceResolver, authResolverWrapper webhook.AuthenticationInfoResolverWrapper) (*CRConverterFactory, error) {
|
func NewCRConverterFactory(serviceResolver webhook.ServiceResolver, authResolverWrapper webhook.AuthenticationInfoResolverWrapper) (*CRConverterFactory, error) {
|
||||||
converterFactory := &CRConverterFactory{}
|
converterFactory := &CRConverterFactory{}
|
||||||
webhookConverterFactory, err := newWebhookConverterFactory(serviceResolver, authResolverWrapper)
|
webhookConverterFactory, err := newWebhookConverterFactory(serviceResolver, authResolverWrapper)
|
||||||
@ -50,30 +62,32 @@ func NewCRConverterFactory(serviceResolver webhook.ServiceResolver, authResolver
|
|||||||
return converterFactory, nil
|
return converterFactory, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConverter returns a new CR converter based on the conversion settings in crd object.
|
// NewConverter creates a new CRConverter based on the crd's conversion strategy. Supported strategies are none and
|
||||||
func (m *CRConverterFactory) NewConverter(crd *apiextensionsv1.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor, err error) {
|
// webhook.
|
||||||
|
func (f *CRConverterFactory) NewConverter(crd *apiextensionsv1.CustomResourceDefinition) (CRConverter, error) {
|
||||||
|
switch crd.Spec.Conversion.Strategy {
|
||||||
|
case apiextensionsv1.NoneConverter:
|
||||||
|
return NewNOPConverter(), nil
|
||||||
|
case apiextensionsv1.WebhookConverter:
|
||||||
|
converter, err := f.webhookConverterFactory.NewWebhookConverter(crd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return converterMetricFactorySingleton.addMetrics(crd.Name, converter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDelegatingConverter returns new safe and unsafe converters based on the conversion settings in
|
||||||
|
// crd. These converters contain logic common to all converters, and they delegate the actual
|
||||||
|
// specific version-to-version conversion logic to the delegate.
|
||||||
|
func NewDelegatingConverter(crd *apiextensionsv1.CustomResourceDefinition, delegate CRConverter) (safe, unsafe runtime.ObjectConvertor, err error) {
|
||||||
validVersions := map[schema.GroupVersion]bool{}
|
validVersions := map[schema.GroupVersion]bool{}
|
||||||
for _, version := range crd.Spec.Versions {
|
for _, version := range crd.Spec.Versions {
|
||||||
validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true
|
validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var converter CRConverter
|
|
||||||
switch crd.Spec.Conversion.Strategy {
|
|
||||||
case apiextensionsv1.NoneConverter:
|
|
||||||
converter = &nopConverter{}
|
|
||||||
case apiextensionsv1.WebhookConverter:
|
|
||||||
converter, err = m.webhookConverterFactory.NewWebhookConverter(crd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
converter, err = converterMetricFactorySingleton.addMetrics(crd.Name, converter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nil, nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
|
// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
|
||||||
convertScale := false
|
convertScale := false
|
||||||
for _, version := range crd.Spec.Versions {
|
for _, version := range crd.Spec.Versions {
|
||||||
@ -82,11 +96,11 @@ func (m *CRConverterFactory) NewConverter(crd *apiextensionsv1.CustomResourceDef
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe = &crConverter{
|
unsafe = &delegatingCRConverter{
|
||||||
convertScale: convertScale,
|
convertScale: convertScale,
|
||||||
validVersions: validVersions,
|
validVersions: validVersions,
|
||||||
clusterScoped: crd.Spec.Scope == apiextensionsv1.ClusterScoped,
|
clusterScoped: crd.Spec.Scope == apiextensionsv1.ClusterScoped,
|
||||||
converter: converter,
|
converter: delegate,
|
||||||
}
|
}
|
||||||
return &safeConverterWrapper{unsafe}, unsafe, nil
|
return &safeConverterWrapper{unsafe}, unsafe, nil
|
||||||
}
|
}
|
||||||
@ -99,16 +113,16 @@ type CRConverter interface {
|
|||||||
Convert(in runtime.Object, targetGVK schema.GroupVersion) (runtime.Object, error)
|
Convert(in runtime.Object, targetGVK schema.GroupVersion) (runtime.Object, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// crConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
|
// delegatingCRConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
|
||||||
// user defined conversion strategy given in the CustomResourceDefinition.
|
// user defined conversion strategy given in the CustomResourceDefinition.
|
||||||
type crConverter struct {
|
type delegatingCRConverter struct {
|
||||||
convertScale bool
|
convertScale bool
|
||||||
converter CRConverter
|
converter CRConverter
|
||||||
validVersions map[schema.GroupVersion]bool
|
validVersions map[schema.GroupVersion]bool
|
||||||
clusterScoped bool
|
clusterScoped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *crConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
func (c *delegatingCRConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
||||||
// We currently only support metadata.namespace and metadata.name.
|
// We currently only support metadata.namespace and metadata.name.
|
||||||
switch {
|
switch {
|
||||||
case label == "metadata.name":
|
case label == "metadata.name":
|
||||||
@ -120,7 +134,7 @@ func (c *crConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *crConverter) Convert(in, out, context interface{}) error {
|
func (c *delegatingCRConverter) Convert(in, out, context interface{}) error {
|
||||||
// Special-case typed scale conversion if this custom resource supports a scale endpoint
|
// Special-case typed scale conversion if this custom resource supports a scale endpoint
|
||||||
if c.convertScale {
|
if c.convertScale {
|
||||||
_, isInScale := in.(*autoscalingv1.Scale)
|
_, isInScale := in.(*autoscalingv1.Scale)
|
||||||
@ -158,7 +172,7 @@ func (c *crConverter) Convert(in, out, context interface{}) error {
|
|||||||
// The in object can be a single object or a UnstructuredList. CRD storage implementation creates an
|
// The in object can be a single object or a UnstructuredList. CRD storage implementation creates an
|
||||||
// UnstructuredList with the request's GV, populates it from storage, then calls conversion to convert
|
// UnstructuredList with the request's GV, populates it from storage, then calls conversion to convert
|
||||||
// the individual items. This function assumes it never gets a v1.List.
|
// the individual items. This function assumes it never gets a v1.List.
|
||||||
func (c *crConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
|
func (c *delegatingCRConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
|
||||||
fromGVK := in.GetObjectKind().GroupVersionKind()
|
fromGVK := in.GetObjectKind().GroupVersionKind()
|
||||||
toGVK, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{fromGVK})
|
toGVK, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{fromGVK})
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConversion(t *testing.T) {
|
func TestConversion(t *testing.T) {
|
||||||
@ -154,10 +153,6 @@ func TestConversion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
CRConverterFactory, err := NewCRConverterFactory(nil, func(resolver webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver { return nil })
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot create conversion factory: %v", err)
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
testCRD := apiextensionsv1.CustomResourceDefinition{
|
testCRD := apiextensionsv1.CustomResourceDefinition{
|
||||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
@ -171,7 +166,7 @@ func TestConversion(t *testing.T) {
|
|||||||
testCRD.Spec.Versions = append(testCRD.Spec.Versions, apiextensionsv1.CustomResourceDefinitionVersion{Name: gv.Version, Served: true})
|
testCRD.Spec.Versions = append(testCRD.Spec.Versions, apiextensionsv1.CustomResourceDefinitionVersion{Name: gv.Version, Served: true})
|
||||||
testCRD.Spec.Group = gv.Group
|
testCRD.Spec.Group = gv.Group
|
||||||
}
|
}
|
||||||
safeConverter, _, err := CRConverterFactory.NewConverter(&testCRD)
|
safeConverter, _, err := NewDelegatingConverter(&testCRD, NewNOPConverter())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Cannot create converter: %v", err)
|
t.Fatalf("Cannot create converter: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,12 @@ import (
|
|||||||
type nopConverter struct {
|
type nopConverter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewNOPConverter creates a new no-op converter. The only "conversion" it performs is to set the group and version to
|
||||||
|
// targetGV.
|
||||||
|
func NewNOPConverter() *nopConverter {
|
||||||
|
return &nopConverter{}
|
||||||
|
}
|
||||||
|
|
||||||
var _ CRConverter = &nopConverter{}
|
var _ CRConverter = &nopConverter{}
|
||||||
|
|
||||||
// ConvertToVersion converts in object to the given gv in place and returns the same `in` object.
|
// ConvertToVersion converts in object to the given gv in place and returns the same `in` object.
|
||||||
|
@ -72,7 +72,6 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/generic"
|
"k8s.io/apiserver/pkg/registry/generic"
|
||||||
genericfilters "k8s.io/apiserver/pkg/server/filters"
|
genericfilters "k8s.io/apiserver/pkg/server/filters"
|
||||||
utilopenapi "k8s.io/apiserver/pkg/util/openapi"
|
utilopenapi "k8s.io/apiserver/pkg/util/openapi"
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
|
||||||
"k8s.io/apiserver/pkg/warning"
|
"k8s.io/apiserver/pkg/warning"
|
||||||
"k8s.io/client-go/scale"
|
"k8s.io/client-go/scale"
|
||||||
"k8s.io/client-go/scale/scheme/autoscalingv1"
|
"k8s.io/client-go/scale/scheme/autoscalingv1"
|
||||||
@ -109,7 +108,7 @@ type crdHandler struct {
|
|||||||
// CRD establishing process for HA clusters.
|
// CRD establishing process for HA clusters.
|
||||||
masterCount int
|
masterCount int
|
||||||
|
|
||||||
converterFactory *conversion.CRConverterFactory
|
converterFactory conversion.Factory
|
||||||
|
|
||||||
// so that we can do create on update.
|
// so that we can do create on update.
|
||||||
authorizer authorizer.Authorizer
|
authorizer authorizer.Authorizer
|
||||||
@ -172,14 +171,18 @@ func NewCustomResourceDefinitionHandler(
|
|||||||
restOptionsGetter generic.RESTOptionsGetter,
|
restOptionsGetter generic.RESTOptionsGetter,
|
||||||
admission admission.Interface,
|
admission admission.Interface,
|
||||||
establishingController *establish.EstablishingController,
|
establishingController *establish.EstablishingController,
|
||||||
serviceResolver webhook.ServiceResolver,
|
converterFactory conversion.Factory,
|
||||||
authResolverWrapper webhook.AuthenticationInfoResolverWrapper,
|
|
||||||
masterCount int,
|
masterCount int,
|
||||||
authorizer authorizer.Authorizer,
|
authorizer authorizer.Authorizer,
|
||||||
requestTimeout time.Duration,
|
requestTimeout time.Duration,
|
||||||
minRequestTimeout time.Duration,
|
minRequestTimeout time.Duration,
|
||||||
staticOpenAPISpec *spec.Swagger,
|
staticOpenAPISpec *spec.Swagger,
|
||||||
maxRequestBodyBytes int64) (*crdHandler, error) {
|
maxRequestBodyBytes int64) (*crdHandler, error) {
|
||||||
|
|
||||||
|
if converterFactory == nil {
|
||||||
|
return nil, fmt.Errorf("converterFactory is required")
|
||||||
|
}
|
||||||
|
|
||||||
ret := &crdHandler{
|
ret := &crdHandler{
|
||||||
versionDiscoveryHandler: versionDiscoveryHandler,
|
versionDiscoveryHandler: versionDiscoveryHandler,
|
||||||
groupDiscoveryHandler: groupDiscoveryHandler,
|
groupDiscoveryHandler: groupDiscoveryHandler,
|
||||||
@ -189,6 +192,7 @@ func NewCustomResourceDefinitionHandler(
|
|||||||
restOptionsGetter: restOptionsGetter,
|
restOptionsGetter: restOptionsGetter,
|
||||||
admission: admission,
|
admission: admission,
|
||||||
establishingController: establishingController,
|
establishingController: establishingController,
|
||||||
|
converterFactory: converterFactory,
|
||||||
masterCount: masterCount,
|
masterCount: masterCount,
|
||||||
authorizer: authorizer,
|
authorizer: authorizer,
|
||||||
requestTimeout: requestTimeout,
|
requestTimeout: requestTimeout,
|
||||||
@ -203,11 +207,6 @@ func NewCustomResourceDefinitionHandler(
|
|||||||
ret.removeDeadStorage()
|
ret.removeDeadStorage()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
crConverterFactory, err := conversion.NewCRConverterFactory(serviceResolver, authResolverWrapper)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret.converterFactory = crConverterFactory
|
|
||||||
|
|
||||||
ret.customStorage.Store(crdStorageMap{})
|
ret.customStorage.Store(crdStorageMap{})
|
||||||
|
|
||||||
@ -690,7 +689,12 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd)
|
converter, err := r.converterFactory.NewConverter(crd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating converter for %s: %w", crd.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
safeConverter, unsafeConverter, err := conversion.NewDelegatingConverter(crd, converter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -60,7 +57,6 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/apiserver/pkg/server/options"
|
"k8s.io/apiserver/pkg/server/options"
|
||||||
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
)
|
)
|
||||||
@ -120,11 +116,7 @@ func TestConvertFieldLabel(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
crd.Spec.Scope = apiextensionsv1.NamespaceScoped
|
crd.Spec.Scope = apiextensionsv1.NamespaceScoped
|
||||||
}
|
}
|
||||||
f, err := conversion.NewCRConverterFactory(nil, nil)
|
_, c, err := conversion.NewDelegatingConverter(&crd, conversion.NewNOPConverter())
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
_, c, err := f.NewConverter(&crd)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create CR converter. error: %v", err)
|
t.Fatalf("Failed to create CR converter. error: %v", err)
|
||||||
}
|
}
|
||||||
@ -466,6 +458,12 @@ func TestHandlerConversionWithoutWatchCache(t *testing.T) {
|
|||||||
testHandlerConversion(t, false)
|
testHandlerConversion(t, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type noneConverterFactory struct{}
|
||||||
|
|
||||||
|
func (f *noneConverterFactory) NewConverter(_ *apiextensionsv1.CustomResourceDefinition) (conversion.CRConverter, error) {
|
||||||
|
return conversion.NewNOPConverter(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func testHandlerConversion(t *testing.T, enableWatchCache bool) {
|
func testHandlerConversion(t *testing.T, enableWatchCache bool) {
|
||||||
cl := fake.NewSimpleClientset()
|
cl := fake.NewSimpleClientset()
|
||||||
informers := informers.NewSharedInformerFactory(fake.NewSimpleClientset(), 0)
|
informers := informers.NewSharedInformerFactory(fake.NewSimpleClientset(), 0)
|
||||||
@ -506,8 +504,7 @@ func testHandlerConversion(t *testing.T, enableWatchCache bool) {
|
|||||||
restOptionsGetter,
|
restOptionsGetter,
|
||||||
dummyAdmissionImpl{},
|
dummyAdmissionImpl{},
|
||||||
&establish.EstablishingController{},
|
&establish.EstablishingController{},
|
||||||
dummyServiceResolverImpl{},
|
&noneConverterFactory{},
|
||||||
func(r webhook.AuthenticationInfoResolver) webhook.AuthenticationInfoResolver { return r },
|
|
||||||
1,
|
1,
|
||||||
dummyAuthorizerImpl{},
|
dummyAuthorizerImpl{},
|
||||||
time.Minute, time.Minute, nil, 3*1024*1024)
|
time.Minute, time.Minute, nil, 3*1024*1024)
|
||||||
@ -847,12 +844,6 @@ func (dummyAuthorizerImpl) Authorize(ctx context.Context, a authorizer.Attribute
|
|||||||
return authorizer.DecisionAllow, "", nil
|
return authorizer.DecisionAllow, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type dummyServiceResolverImpl struct{}
|
|
||||||
|
|
||||||
func (dummyServiceResolverImpl) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
|
|
||||||
return &url.URL{Scheme: "https", Host: net.JoinHostPort(name+"."+namespace+".svc", strconv.Itoa(int(port)))}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var multiVersionFixture = &apiextensionsv1.CustomResourceDefinition{
|
var multiVersionFixture = &apiextensionsv1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "multiversion.stable.example.com", UID: types.UID("12345")},
|
ObjectMeta: metav1.ObjectMeta{Name: "multiversion.stable.example.com", UID: types.UID("12345")},
|
||||||
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
Spec: apiextensionsv1.CustomResourceDefinitionSpec{
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
oteltrace "go.opentelemetry.io/otel/trace"
|
oteltrace "go.opentelemetry.io/otel/trace"
|
||||||
|
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||||
|
|
||||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
@ -107,6 +108,14 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err
|
|||||||
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
|
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceResolver := &serviceResolver{serverConfig.SharedInformerFactory.Core().V1().Services().Lister()}
|
||||||
|
authResolverWrapper := webhook.NewDefaultAuthenticationInfoResolverWrapper(nil, nil, serverConfig.LoopbackClientConfig, oteltrace.NewNoopTracerProvider())
|
||||||
|
conversionFactory, err := conversion.NewCRConverterFactory(serviceResolver, authResolverWrapper)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
crdRESTOptionsGetter, err := NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd)
|
crdRESTOptionsGetter, err := NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -115,8 +124,7 @@ func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, err
|
|||||||
GenericConfig: serverConfig,
|
GenericConfig: serverConfig,
|
||||||
ExtraConfig: apiserver.ExtraConfig{
|
ExtraConfig: apiserver.ExtraConfig{
|
||||||
CRDRESTOptionsGetter: crdRESTOptionsGetter,
|
CRDRESTOptionsGetter: crdRESTOptionsGetter,
|
||||||
ServiceResolver: &serviceResolver{serverConfig.SharedInformerFactory.Core().V1().Services().Lister()},
|
ConversionFactory: conversionFactory,
|
||||||
AuthResolverWrapper: webhook.NewDefaultAuthenticationInfoResolverWrapper(nil, nil, serverConfig.LoopbackClientConfig, oteltrace.NewNoopTracerProvider()),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user