Reuse SSA type converter for resources in the same API Group

This commit is contained in:
Jefftree 2020-10-20 11:16:51 -07:00
parent c34a2c44a8
commit 7182d84b10
17 changed files with 76 additions and 73 deletions

View File

@ -669,6 +669,14 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
openAPIModels = nil openAPIModels = nil
} }
var typeConverter fieldmanager.TypeConverter = fieldmanager.DeducedTypeConverter{}
if openAPIModels != nil {
typeConverter, err = fieldmanager.NewTypeConverter(openAPIModels, crd.Spec.PreserveUnknownFields)
if err != nil {
typeConverter = nil
}
}
safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd) safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd)
if err != nil { if err != nil {
return nil, err return nil, err
@ -842,13 +850,12 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) { if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
reqScope := *requestScopes[v.Name] reqScope := *requestScopes[v.Name]
reqScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager( reqScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager(
openAPIModels, typeConverter,
reqScope.Convertor, reqScope.Convertor,
reqScope.Defaulter, reqScope.Defaulter,
reqScope.Creater, reqScope.Creater,
reqScope.Kind, reqScope.Kind,
reqScope.HubGroupVersion, reqScope.HubGroupVersion,
crd.Spec.PreserveUnknownFields,
false, false,
) )
if err != nil { if err != nil {
@ -879,13 +886,12 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
statusScope := *requestScopes[v.Name] statusScope := *requestScopes[v.Name]
if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) { if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
statusScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager( statusScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager(
openAPIModels, typeConverter,
statusScope.Convertor, statusScope.Convertor,
statusScope.Defaulter, statusScope.Defaulter,
statusScope.Creater, statusScope.Creater,
statusScope.Kind, statusScope.Kind,
statusScope.HubGroupVersion, statusScope.HubGroupVersion,
crd.Spec.PreserveUnknownFields,
true, true,
) )
if err != nil { if err != nil {

View File

@ -30,6 +30,7 @@ import (
"k8s.io/apiserver/pkg/admission" "k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/discovery" "k8s.io/apiserver/pkg/endpoints/discovery"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
openapiproto "k8s.io/kube-openapi/pkg/util/proto" openapiproto "k8s.io/kube-openapi/pkg/util/proto"
) )
@ -71,6 +72,7 @@ type APIGroupVersion struct {
Defaulter runtime.ObjectDefaulter Defaulter runtime.ObjectDefaulter
Linker runtime.SelfLinker Linker runtime.SelfLinker
UnsafeConvertor runtime.ObjectConvertor UnsafeConvertor runtime.ObjectConvertor
TypeConverter fieldmanager.TypeConverter
EquivalentResourceRegistry runtime.EquivalentResourceRegistry EquivalentResourceRegistry runtime.EquivalentResourceRegistry

View File

@ -12,6 +12,8 @@ go_library(
"skipnonapplied.go", "skipnonapplied.go",
"stripmeta.go", "stripmeta.go",
"structuredmerge.go", "structuredmerge.go",
"typeconverter.go",
"versionconverter.go",
], ],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager", importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager",
importpath = "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager", importpath = "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager",
@ -29,6 +31,8 @@ go_library(
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath:go_default_library", "//vendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/merge:go_default_library", "//vendor/sigs.k8s.io/structured-merge-diff/v4/merge:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/typed:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/value:go_default_library",
], ],
) )
@ -58,11 +62,14 @@ go_test(
"lastappliedupdater_test.go", "lastappliedupdater_test.go",
"managedfieldsupdater_test.go", "managedfieldsupdater_test.go",
"skipnonapplied_test.go", "skipnonapplied_test.go",
"typeconverter_test.go",
"versionconverter_test.go",
], ],
data = [ data = [
"endpoints.yaml", "endpoints.yaml",
"node.yaml", "node.yaml",
"pod.yaml", "pod.yaml",
"testdata/swagger.json",
"//api/openapi-spec", "//api/openapi-spec",
], ],
embed = [":go_default_library"], embed = [":go_default_library"],

View File

@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal" "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
"k8s.io/klog/v2" "k8s.io/klog/v2"
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
"sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/merge"
) )
@ -79,12 +78,7 @@ func NewFieldManager(f Manager, ignoreManagedFieldsFromRequestObject bool) *Fiel
// NewDefaultFieldManager creates a new FieldManager that merges apply requests // NewDefaultFieldManager creates a new FieldManager that merges apply requests
// and update managed fields for other types of requests. // and update managed fields for other types of requests.
func NewDefaultFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, ignoreManagedFieldsFromRequestObject bool) (*FieldManager, error) { func NewDefaultFieldManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, ignoreManagedFieldsFromRequestObject bool) (*FieldManager, error) {
typeConverter, err := internal.NewTypeConverter(models, false)
if err != nil {
return nil, err
}
f, err := NewStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub) f, err := NewStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create field manager: %v", err) return nil, fmt.Errorf("failed to create field manager: %v", err)
@ -95,15 +89,8 @@ func NewDefaultFieldManager(models openapiproto.Models, objectConverter runtime.
// NewDefaultCRDFieldManager creates a new FieldManager specifically for // NewDefaultCRDFieldManager creates a new FieldManager specifically for
// CRDs. This allows for the possibility of fields which are not defined // CRDs. This allows for the possibility of fields which are not defined
// in models, as well as having no models defined at all. // in models, as well as having no models defined at all.
func NewDefaultCRDFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, preserveUnknownFields, ignoreManagedFieldsFromRequestObject bool) (_ *FieldManager, err error) { func NewDefaultCRDFieldManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, ignoreManagedFieldsFromRequestObject bool) (_ *FieldManager, err error) {
var typeConverter internal.TypeConverter = internal.DeducedTypeConverter{} f, err := NewCRDStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
if models != nil {
typeConverter, err = internal.NewTypeConverter(models, preserveUnknownFields)
if err != nil {
return nil, err
}
}
f, err := NewCRDStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub, preserveUnknownFields)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create field manager: %v", err) return nil, fmt.Errorf("failed to create field manager: %v", err)
} }
@ -111,7 +98,7 @@ func NewDefaultCRDFieldManager(models openapiproto.Models, objectConverter runti
} }
// newDefaultFieldManager is a helper function which wraps a Manager with certain default logic. // newDefaultFieldManager is a helper function which wraps a Manager with certain default logic.
func newDefaultFieldManager(f Manager, typeConverter internal.TypeConverter, objectConverter runtime.ObjectConvertor, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool) *FieldManager { func newDefaultFieldManager(f Manager, typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool) *FieldManager {
f = NewStripMetaManager(f) f = NewStripMetaManager(f)
f = NewManagedFieldsUpdater(f) f = NewManagedFieldsUpdater(f)
f = NewBuildManagerInfoManager(f, kind.GroupVersion()) f = NewBuildManagerInfoManager(f, kind.GroupVersion())

View File

@ -37,7 +37,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
yamlutil "k8s.io/apimachinery/pkg/util/yaml" yamlutil "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager" "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
"k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto"
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing" prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
@ -96,7 +95,7 @@ func NewSubresourceTestFieldManager(gvk schema.GroupVersionKind) TestFieldManage
func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool, chainFieldManager func(fieldmanager.Manager) fieldmanager.Manager) TestFieldManager { func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool, chainFieldManager func(fieldmanager.Manager) fieldmanager.Manager) TestFieldManager {
m := NewFakeOpenAPIModels() m := NewFakeOpenAPIModels()
typeConverter := NewFakeTypeConverter(m) typeConverter := NewFakeTypeConverter(m)
converter := internal.NewVersionConverter(typeConverter, &fakeObjectConvertor{}, gvk.GroupVersion()) converter := fieldmanager.NewVersionConverter(typeConverter, &fakeObjectConvertor{}, gvk.GroupVersion())
apiVersion := fieldpath.APIVersion(gvk.GroupVersion().String()) apiVersion := fieldpath.APIVersion(gvk.GroupVersion().String())
objectConverter := &fakeObjectConvertor{converter, apiVersion} objectConverter := &fakeObjectConvertor{converter, apiVersion}
f, err := fieldmanager.NewStructuredMergeManager( f, err := fieldmanager.NewStructuredMergeManager(
@ -128,8 +127,8 @@ func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromReq
} }
} }
func NewFakeTypeConverter(m proto.Models) internal.TypeConverter { func NewFakeTypeConverter(m proto.Models) fieldmanager.TypeConverter {
tc, err := internal.NewTypeConverter(m, false) tc, err := fieldmanager.NewTypeConverter(m, false)
if err != nil { if err != nil {
panic(fmt.Sprintf("Failed to build TypeConverter: %v", err)) panic(fmt.Sprintf("Failed to build TypeConverter: %v", err))
} }

View File

@ -9,8 +9,6 @@ go_library(
"gvkparser.go", "gvkparser.go",
"managedfields.go", "managedfields.go",
"pathelement.go", "pathelement.go",
"typeconverter.go",
"versionconverter.go",
], ],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal", importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal",
importpath = "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal", importpath = "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal",
@ -19,7 +17,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/schemaconv:go_default_library", "//vendor/k8s.io/kube-openapi/pkg/schemaconv:go_default_library",
@ -39,22 +36,14 @@ go_test(
"fields_test.go", "fields_test.go",
"managedfields_test.go", "managedfields_test.go",
"pathelement_test.go", "pathelement_test.go",
"typeconverter_test.go",
"versionconverter_test.go",
], ],
data = glob(["testdata/**"]), data = glob(["testdata/**"]),
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
"//vendor/k8s.io/kube-openapi/pkg/util/proto/testing:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath:go_default_library", "//vendor/sigs.k8s.io/structured-merge-diff/v4/fieldpath:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/merge:go_default_library", "//vendor/sigs.k8s.io/structured-merge-diff/v4/merge:go_default_library",
"//vendor/sigs.k8s.io/structured-merge-diff/v4/typed:go_default_library",
"//vendor/sigs.k8s.io/yaml:go_default_library", "//vendor/sigs.k8s.io/yaml:go_default_library",
], ],
) )

View File

@ -30,12 +30,12 @@ import (
// definition's "extensions" map. // definition's "extensions" map.
const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind" const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
type gvkParser struct { type GvkParser struct {
gvks map[schema.GroupVersionKind]string gvks map[schema.GroupVersionKind]string
parser typed.Parser parser typed.Parser
} }
func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType { func (p *GvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
typeName, ok := p.gvks[gvk] typeName, ok := p.gvks[gvk]
if !ok { if !ok {
return nil return nil
@ -44,12 +44,12 @@ func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
return &t return &t
} }
func newGVKParser(models proto.Models, preserveUnknownFields bool) (*gvkParser, error) { func NewGVKParser(models proto.Models, preserveUnknownFields bool) (*GvkParser, error) {
typeSchema, err := schemaconv.ToSchemaWithPreserveUnknownFields(models, preserveUnknownFields) typeSchema, err := schemaconv.ToSchemaWithPreserveUnknownFields(models, preserveUnknownFields)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to convert models to schema: %v", err) return nil, fmt.Errorf("failed to convert models to schema: %v", err)
} }
parser := gvkParser{ parser := GvkParser{
gvks: map[schema.GroupVersionKind]string{}, gvks: map[schema.GroupVersionKind]string{},
} }
parser.parser = typed.Parser{Schema: *typeSchema} parser.parser = typed.Parser{Schema: *typeSchema}

View File

@ -25,14 +25,13 @@ 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/endpoints/handlers/fieldmanager/internal"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
"sigs.k8s.io/structured-merge-diff/v4/merge" "sigs.k8s.io/structured-merge-diff/v4/merge"
) )
type lastAppliedManager struct { type lastAppliedManager struct {
fieldManager Manager fieldManager Manager
typeConverter internal.TypeConverter typeConverter TypeConverter
objectConverter runtime.ObjectConvertor objectConverter runtime.ObjectConvertor
groupVersion schema.GroupVersion groupVersion schema.GroupVersion
} }
@ -41,7 +40,7 @@ var _ Manager = &lastAppliedManager{}
// NewLastAppliedManager converts the client-side apply annotation to // NewLastAppliedManager converts the client-side apply annotation to
// server-side apply managed fields // server-side apply managed fields
func NewLastAppliedManager(fieldManager Manager, typeConverter internal.TypeConverter, objectConverter runtime.ObjectConvertor, groupVersion schema.GroupVersion) Manager { func NewLastAppliedManager(fieldManager Manager, typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, groupVersion schema.GroupVersion) Manager {
return &lastAppliedManager{ return &lastAppliedManager{
fieldManager: fieldManager, fieldManager: fieldManager,
typeConverter: typeConverter, typeConverter: typeConverter,

View File

@ -29,7 +29,7 @@ import (
) )
type structuredMergeManager struct { type structuredMergeManager struct {
typeConverter internal.TypeConverter typeConverter TypeConverter
objectConverter runtime.ObjectConvertor objectConverter runtime.ObjectConvertor
objectDefaulter runtime.ObjectDefaulter objectDefaulter runtime.ObjectDefaulter
groupVersion schema.GroupVersion groupVersion schema.GroupVersion
@ -41,7 +41,7 @@ var _ Manager = &structuredMergeManager{}
// NewStructuredMergeManager creates a new Manager that merges apply requests // NewStructuredMergeManager creates a new Manager that merges apply requests
// and update managed fields for other types of requests. // and update managed fields for other types of requests.
func NewStructuredMergeManager(typeConverter internal.TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) (Manager, error) { func NewStructuredMergeManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) (Manager, error) {
return &structuredMergeManager{ return &structuredMergeManager{
typeConverter: typeConverter, typeConverter: typeConverter,
objectConverter: objectConverter, objectConverter: objectConverter,
@ -49,7 +49,7 @@ func NewStructuredMergeManager(typeConverter internal.TypeConverter, objectConve
groupVersion: gv, groupVersion: gv,
hubVersion: hub, hubVersion: hub,
updater: merge.Updater{ updater: merge.Updater{
Converter: internal.NewVersionConverter(typeConverter, objectConverter, hub), // This is the converter provided to SMD from k8s Converter: NewVersionConverter(typeConverter, objectConverter, hub), // This is the converter provided to SMD from k8s
}, },
}, nil }, nil
} }
@ -57,7 +57,7 @@ func NewStructuredMergeManager(typeConverter internal.TypeConverter, objectConve
// NewCRDStructuredMergeManager creates a new Manager specifically for // NewCRDStructuredMergeManager creates a new Manager specifically for
// CRDs. This allows for the possibility of fields which are not defined // CRDs. This allows for the possibility of fields which are not defined
// in models, as well as having no models defined at all. // in models, as well as having no models defined at all.
func NewCRDStructuredMergeManager(typeConverter internal.TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion, preserveUnknownFields bool) (_ Manager, err error) { func NewCRDStructuredMergeManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) (_ Manager, err error) {
return &structuredMergeManager{ return &structuredMergeManager{
typeConverter: typeConverter, typeConverter: typeConverter,
objectConverter: objectConverter, objectConverter: objectConverter,
@ -65,7 +65,7 @@ func NewCRDStructuredMergeManager(typeConverter internal.TypeConverter, objectCo
groupVersion: gv, groupVersion: gv,
hubVersion: hub, hubVersion: hub,
updater: merge.Updater{ updater: merge.Updater{
Converter: internal.NewCRDVersionConverter(typeConverter, objectConverter, hub), Converter: NewCRDVersionConverter(typeConverter, objectConverter, hub),
}, },
}, nil }, nil
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package internal package fieldmanager
import ( import (
"fmt" "fmt"
@ -22,6 +22,7 @@ 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/endpoints/handlers/fieldmanager/internal"
"k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto"
"sigs.k8s.io/structured-merge-diff/v4/typed" "sigs.k8s.io/structured-merge-diff/v4/typed"
"sigs.k8s.io/structured-merge-diff/v4/value" "sigs.k8s.io/structured-merge-diff/v4/value"
@ -64,7 +65,7 @@ func (DeducedTypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Obje
} }
type typeConverter struct { type typeConverter struct {
parser *gvkParser parser *internal.GvkParser
} }
var _ TypeConverter = &typeConverter{} var _ TypeConverter = &typeConverter{}
@ -73,7 +74,7 @@ var _ TypeConverter = &typeConverter{}
// will automatically find the proper version of the object, and the // will automatically find the proper version of the object, and the
// corresponding schema information. // corresponding schema information.
func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConverter, error) { func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConverter, error) {
parser, err := newGVKParser(models, preserveUnknownFields) parser, err := internal.NewGVKParser(models, preserveUnknownFields)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package internal_test package fieldmanager_test
import ( import (
"fmt" "fmt"
@ -26,17 +26,17 @@ import (
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal" "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto"
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing" prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
) )
var fakeSchema = prototesting.Fake{ var fakeSchema2 = prototesting.Fake{
Path: filepath.Join("testdata", "swagger.json"), Path: filepath.Join("testdata", "swagger.json"),
} }
func TestTypeConverter(t *testing.T) { func TestTypeConverter(t *testing.T) {
d, err := fakeSchema.OpenAPISchema() d, err := fakeSchema2.OpenAPISchema()
if err != nil { if err != nil {
t.Fatalf("Failed to parse OpenAPI schema: %v", err) t.Fatalf("Failed to parse OpenAPI schema: %v", err)
} }
@ -45,12 +45,12 @@ func TestTypeConverter(t *testing.T) {
t.Fatalf("Failed to build OpenAPI models: %v", err) t.Fatalf("Failed to build OpenAPI models: %v", err)
} }
tc, err := internal.NewTypeConverter(m, false) tc, err := fieldmanager.NewTypeConverter(m, false)
if err != nil { if err != nil {
t.Fatalf("Failed to build TypeConverter: %v", err) t.Fatalf("Failed to build TypeConverter: %v", err)
} }
dtc := internal.DeducedTypeConverter{} dtc := fieldmanager.DeducedTypeConverter{}
testCases := []struct { testCases := []struct {
name string name string
@ -127,7 +127,7 @@ spec:
} }
} }
func testObjectToTyped(t *testing.T, tc internal.TypeConverter, y string) { func testObjectToTyped(t *testing.T, tc fieldmanager.TypeConverter, y string) {
obj := &unstructured.Unstructured{Object: map[string]interface{}{}} obj := &unstructured.Unstructured{Object: map[string]interface{}{}}
if err := yaml.Unmarshal([]byte(y), &obj.Object); err != nil { if err := yaml.Unmarshal([]byte(y), &obj.Object); err != nil {
t.Fatalf("Failed to parse yaml object: %v", err) t.Fatalf("Failed to parse yaml object: %v", err)
@ -177,7 +177,7 @@ spec:
b.Fatalf("Failed to parse yaml object: %v", err) b.Fatalf("Failed to parse yaml object: %v", err)
} }
d, err := fakeSchema.OpenAPISchema() d, err := fakeSchema2.OpenAPISchema()
if err != nil { if err != nil {
b.Fatalf("Failed to parse OpenAPI schema: %v", err) b.Fatalf("Failed to parse OpenAPI schema: %v", err)
} }
@ -186,7 +186,7 @@ spec:
b.Fatalf("Failed to build OpenAPI models: %v", err) b.Fatalf("Failed to build OpenAPI models: %v", err)
} }
tc, err := internal.NewTypeConverter(m, false) tc, err := fieldmanager.NewTypeConverter(m, false)
if err != nil { if err != nil {
b.Fatalf("Failed to build TypeConverter: %v", err) b.Fatalf("Failed to build TypeConverter: %v", err)
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package internal package fieldmanager
import ( import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package internal_test package fieldmanager_test
import ( import (
"fmt" "fmt"
@ -24,14 +24,14 @@ 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/endpoints/handlers/fieldmanager/internal" "k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath" "sigs.k8s.io/structured-merge-diff/v4/fieldpath"
) )
// TestVersionConverter tests the version converter // TestVersionConverter tests the version converter
func TestVersionConverter(t *testing.T) { func TestVersionConverter(t *testing.T) {
d, err := fakeSchema.OpenAPISchema() d, err := fakeSchema2.OpenAPISchema()
if err != nil { if err != nil {
t.Fatalf("Failed to parse OpenAPI schema: %v", err) t.Fatalf("Failed to parse OpenAPI schema: %v", err)
} }
@ -39,15 +39,15 @@ func TestVersionConverter(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to build OpenAPI models: %v", err) t.Fatalf("Failed to build OpenAPI models: %v", err)
} }
tc, err := internal.NewTypeConverter(m, false) tc, err := fieldmanager.NewTypeConverter(m, false)
if err != nil { if err != nil {
t.Fatalf("Failed to build TypeConverter: %v", err) t.Fatalf("Failed to build TypeConverter: %v", err)
} }
oc := fakeObjectConvertor{ oc := fakeObjectConvertorForTestSchema{
gvkForVersion("v1beta1"): objForGroupVersion("apps/v1beta1"), gvkForVersion("v1beta1"): objForGroupVersion("apps/v1beta1"),
gvkForVersion("v1"): objForGroupVersion("apps/v1"), gvkForVersion("v1"): objForGroupVersion("apps/v1"),
} }
vc := internal.NewVersionConverter(tc, oc, schema.GroupVersion{Group: "apps", Version: runtime.APIVersionInternal}) vc := fieldmanager.NewVersionConverter(tc, oc, schema.GroupVersion{Group: "apps", Version: runtime.APIVersionInternal})
input, err := tc.ObjectToTyped(objForGroupVersion("apps/v1beta1")) input, err := tc.ObjectToTyped(objForGroupVersion("apps/v1beta1"))
if err != nil { if err != nil {
@ -85,11 +85,11 @@ func objForGroupVersion(gv string) runtime.Object {
} }
} }
type fakeObjectConvertor map[schema.GroupVersionKind]runtime.Object type fakeObjectConvertorForTestSchema map[schema.GroupVersionKind]runtime.Object
var _ runtime.ObjectConvertor = fakeObjectConvertor{} var _ runtime.ObjectConvertor = fakeObjectConvertorForTestSchema{}
func (c fakeObjectConvertor) ConvertToVersion(_ runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) { func (c fakeObjectConvertorForTestSchema) ConvertToVersion(_ runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) {
allKinds := make([]schema.GroupVersionKind, 0) allKinds := make([]schema.GroupVersionKind, 0)
for kind := range c { for kind := range c {
allKinds = append(allKinds, kind) allKinds = append(allKinds, kind)
@ -98,10 +98,10 @@ func (c fakeObjectConvertor) ConvertToVersion(_ runtime.Object, gv runtime.Group
return c[gvk], nil return c[gvk], nil
} }
func (fakeObjectConvertor) Convert(_, _, _ interface{}) error { func (fakeObjectConvertorForTestSchema) Convert(_, _, _ interface{}) error {
return fmt.Errorf("function not implemented") return fmt.Errorf("function not implemented")
} }
func (fakeObjectConvertor) ConvertFieldLabel(_ schema.GroupVersionKind, _, _ string) (string, string, error) { func (fakeObjectConvertorForTestSchema) ConvertFieldLabel(_ schema.GroupVersionKind, _, _ string) (string, string, error) {
return "", "", fmt.Errorf("function not implemented") return "", "", fmt.Errorf("function not implemented")
} }

View File

@ -564,7 +564,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
} }
if a.group.OpenAPIModels != nil && utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) { if a.group.OpenAPIModels != nil && utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
reqScope.FieldManager, err = fieldmanager.NewDefaultFieldManager( reqScope.FieldManager, err = fieldmanager.NewDefaultFieldManager(
a.group.OpenAPIModels, a.group.TypeConverter,
a.group.UnsafeConvertor, a.group.UnsafeConvertor,
a.group.Defaulter, a.group.Defaulter,
a.group.Creater, a.group.Creater,

View File

@ -101,6 +101,7 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/endpoints:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/filters:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/filters:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",

View File

@ -40,9 +40,12 @@ import (
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
genericapi "k8s.io/apiserver/pkg/endpoints" genericapi "k8s.io/apiserver/pkg/endpoints"
"k8s.io/apiserver/pkg/endpoints/discovery" "k8s.io/apiserver/pkg/endpoints/discovery"
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/server/healthz" "k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/routes" "k8s.io/apiserver/pkg/server/routes"
utilfeature "k8s.io/apiserver/pkg/util/feature"
utilopenapi "k8s.io/apiserver/pkg/util/openapi" utilopenapi "k8s.io/apiserver/pkg/util/openapi"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/klog/v2" "k8s.io/klog/v2"
@ -418,6 +421,15 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
} }
apiGroupVersion.OpenAPIModels = openAPIModels apiGroupVersion.OpenAPIModels = openAPIModels
if openAPIModels != nil && utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
typeConverter, err := fieldmanager.NewTypeConverter(openAPIModels, false)
if err != nil {
return err
}
apiGroupVersion.TypeConverter = typeConverter
}
apiGroupVersion.MaxRequestBodyBytes = s.maxRequestBodyBytes apiGroupVersion.MaxRequestBodyBytes = s.maxRequestBodyBytes
if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil { if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil {