mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Merge pull request #95736 from Jefftree/reuse-parser
Reuse SSA type converter for resources in the same API Group
This commit is contained in:
commit
8456a514f1
@ -669,6 +669,14 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
openAPIModels = nil
|
||||
}
|
||||
|
||||
var typeConverter fieldmanager.TypeConverter = fieldmanager.DeducedTypeConverter{}
|
||||
if openAPIModels != nil {
|
||||
typeConverter, err = fieldmanager.NewTypeConverter(openAPIModels, crd.Spec.PreserveUnknownFields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
safeConverter, unsafeConverter, err := r.converterFactory.NewConverter(crd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -842,13 +850,12 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
|
||||
reqScope := *requestScopes[v.Name]
|
||||
reqScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager(
|
||||
openAPIModels,
|
||||
typeConverter,
|
||||
reqScope.Convertor,
|
||||
reqScope.Defaulter,
|
||||
reqScope.Creater,
|
||||
reqScope.Kind,
|
||||
reqScope.HubGroupVersion,
|
||||
crd.Spec.PreserveUnknownFields,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
@ -879,13 +886,12 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
|
||||
statusScope := *requestScopes[v.Name]
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
|
||||
statusScope.FieldManager, err = fieldmanager.NewDefaultCRDFieldManager(
|
||||
openAPIModels,
|
||||
typeConverter,
|
||||
statusScope.Convertor,
|
||||
statusScope.Defaulter,
|
||||
statusScope.Creater,
|
||||
statusScope.Kind,
|
||||
statusScope.HubGroupVersion,
|
||||
crd.Spec.PreserveUnknownFields,
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
|
||||
)
|
||||
@ -71,6 +72,7 @@ type APIGroupVersion struct {
|
||||
Defaulter runtime.ObjectDefaulter
|
||||
Linker runtime.SelfLinker
|
||||
UnsafeConvertor runtime.ObjectConvertor
|
||||
TypeConverter fieldmanager.TypeConverter
|
||||
|
||||
EquivalentResourceRegistry runtime.EquivalentResourceRegistry
|
||||
|
||||
|
@ -12,6 +12,8 @@ go_library(
|
||||
"skipnonapplied.go",
|
||||
"stripmeta.go",
|
||||
"structuredmerge.go",
|
||||
"typeconverter.go",
|
||||
"versionconverter.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/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/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/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",
|
||||
"managedfieldsupdater_test.go",
|
||||
"skipnonapplied_test.go",
|
||||
"typeconverter_test.go",
|
||||
"versionconverter_test.go",
|
||||
],
|
||||
data = [
|
||||
"endpoints.yaml",
|
||||
"node.yaml",
|
||||
"pod.yaml",
|
||||
"testdata/swagger.json",
|
||||
"//api/openapi-spec",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -29,19 +29,18 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
type fakeManager struct{}
|
||||
|
||||
var _ fieldmanager.Manager = &fakeManager{}
|
||||
var _ Manager = &fakeManager{}
|
||||
|
||||
func (*fakeManager) Update(_, newObj runtime.Object, managed fieldmanager.Managed, _ string) (runtime.Object, fieldmanager.Managed, error) {
|
||||
func (*fakeManager) Update(_, newObj runtime.Object, managed Managed, _ string) (runtime.Object, Managed, error) {
|
||||
return newObj, managed, nil
|
||||
}
|
||||
|
||||
func (*fakeManager) Apply(_, _ runtime.Object, _ fieldmanager.Managed, _ string, _ bool) (runtime.Object, fieldmanager.Managed, error) {
|
||||
func (*fakeManager) Apply(_, _ runtime.Object, _ Managed, _ string, _ bool) (runtime.Object, Managed, error) {
|
||||
panic("not implemented")
|
||||
return nil, nil, nil
|
||||
}
|
||||
@ -49,8 +48,8 @@ func (*fakeManager) Apply(_, _ runtime.Object, _ fieldmanager.Managed, _ string,
|
||||
func TestCapManagersManagerMergesEntries(t *testing.T) {
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"),
|
||||
false,
|
||||
func(m fieldmanager.Manager) fieldmanager.Manager {
|
||||
return fieldmanager.NewCapManagersManager(m, 3)
|
||||
func(m Manager) Manager {
|
||||
return NewCapManagersManager(m, 3)
|
||||
})
|
||||
|
||||
podWithLabels := func(labels ...string) runtime.Object {
|
||||
@ -115,8 +114,8 @@ func TestCapManagersManagerMergesEntries(t *testing.T) {
|
||||
func TestCapUpdateManagers(t *testing.T) {
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"),
|
||||
false,
|
||||
func(m fieldmanager.Manager) fieldmanager.Manager {
|
||||
return fieldmanager.NewCapManagersManager(m, 3)
|
||||
func(m Manager) Manager {
|
||||
return NewCapManagersManager(m, 3)
|
||||
})
|
||||
|
||||
set := func(fields ...string) *metav1.FieldsV1 {
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
|
||||
"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/merge"
|
||||
)
|
||||
@ -79,12 +78,7 @@ func NewFieldManager(f Manager, ignoreManagedFieldsFromRequestObject bool) *Fiel
|
||||
|
||||
// NewDefaultFieldManager creates a new FieldManager that merges apply 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) {
|
||||
typeConverter, err := internal.NewTypeConverter(models, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewDefaultFieldManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, ignoreManagedFieldsFromRequestObject bool) (*FieldManager, error) {
|
||||
f, err := NewStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
|
||||
if err != nil {
|
||||
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
|
||||
// CRDs. This allows for the possibility of fields which are not defined
|
||||
// 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) {
|
||||
var typeConverter internal.TypeConverter = internal.DeducedTypeConverter{}
|
||||
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)
|
||||
func NewDefaultCRDFieldManager(typeConverter TypeConverter, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, objectCreater runtime.ObjectCreater, kind schema.GroupVersionKind, hub schema.GroupVersion, ignoreManagedFieldsFromRequestObject bool) (_ *FieldManager, err error) {
|
||||
f, err := NewCRDStructuredMergeManager(typeConverter, objectConverter, objectDefaulter, kind.GroupVersion(), hub)
|
||||
if err != nil {
|
||||
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.
|
||||
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 = NewManagedFieldsUpdater(f)
|
||||
f = NewBuildManagerInfoManager(f, kind.GroupVersion())
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -36,8 +36,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
@ -46,7 +44,7 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
var fakeSchema = prototesting.Fake{
|
||||
var kubernetesSwaggerSchema = prototesting.Fake{
|
||||
Path: filepath.Join(
|
||||
strings.Repeat(".."+string(filepath.Separator), 8),
|
||||
"api", "openapi-spec", "swagger.json"),
|
||||
@ -80,7 +78,7 @@ type fakeObjectDefaulter struct{}
|
||||
func (d *fakeObjectDefaulter) Default(in runtime.Object) {}
|
||||
|
||||
type TestFieldManager struct {
|
||||
fieldManager *fieldmanager.FieldManager
|
||||
fieldManager *FieldManager
|
||||
emptyObj runtime.Object
|
||||
liveObj runtime.Object
|
||||
}
|
||||
@ -93,13 +91,13 @@ func NewSubresourceTestFieldManager(gvk schema.GroupVersionKind) TestFieldManage
|
||||
return NewTestFieldManager(gvk, true, nil)
|
||||
}
|
||||
|
||||
func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool, chainFieldManager func(fieldmanager.Manager) fieldmanager.Manager) TestFieldManager {
|
||||
func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromRequestObject bool, chainFieldManager func(Manager) Manager) TestFieldManager {
|
||||
m := NewFakeOpenAPIModels()
|
||||
typeConverter := NewFakeTypeConverter(m)
|
||||
converter := internal.NewVersionConverter(typeConverter, &fakeObjectConvertor{}, gvk.GroupVersion())
|
||||
converter := newVersionConverter(typeConverter, &fakeObjectConvertor{}, gvk.GroupVersion())
|
||||
apiVersion := fieldpath.APIVersion(gvk.GroupVersion().String())
|
||||
objectConverter := &fakeObjectConvertor{converter, apiVersion}
|
||||
f, err := fieldmanager.NewStructuredMergeManager(
|
||||
f, err := NewStructuredMergeManager(
|
||||
typeConverter,
|
||||
objectConverter,
|
||||
&fakeObjectDefaulter{},
|
||||
@ -112,24 +110,24 @@ func NewTestFieldManager(gvk schema.GroupVersionKind, ignoreManagedFieldsFromReq
|
||||
live := &unstructured.Unstructured{}
|
||||
live.SetKind(gvk.Kind)
|
||||
live.SetAPIVersion(gvk.GroupVersion().String())
|
||||
f = fieldmanager.NewStripMetaManager(f)
|
||||
f = fieldmanager.NewManagedFieldsUpdater(f)
|
||||
f = fieldmanager.NewBuildManagerInfoManager(f, gvk.GroupVersion())
|
||||
f = fieldmanager.NewProbabilisticSkipNonAppliedManager(f, &fakeObjectCreater{gvk: gvk}, gvk, fieldmanager.DefaultTrackOnCreateProbability)
|
||||
f = fieldmanager.NewLastAppliedManager(f, typeConverter, objectConverter, gvk.GroupVersion())
|
||||
f = fieldmanager.NewLastAppliedUpdater(f)
|
||||
f = NewStripMetaManager(f)
|
||||
f = NewManagedFieldsUpdater(f)
|
||||
f = NewBuildManagerInfoManager(f, gvk.GroupVersion())
|
||||
f = NewProbabilisticSkipNonAppliedManager(f, &fakeObjectCreater{gvk: gvk}, gvk, DefaultTrackOnCreateProbability)
|
||||
f = NewLastAppliedManager(f, typeConverter, objectConverter, gvk.GroupVersion())
|
||||
f = NewLastAppliedUpdater(f)
|
||||
if chainFieldManager != nil {
|
||||
f = chainFieldManager(f)
|
||||
}
|
||||
return TestFieldManager{
|
||||
fieldManager: fieldmanager.NewFieldManager(f, ignoreManagedFieldsFromRequestObject),
|
||||
fieldManager: NewFieldManager(f, ignoreManagedFieldsFromRequestObject),
|
||||
emptyObj: live,
|
||||
liveObj: live.DeepCopyObject(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewFakeTypeConverter(m proto.Models) internal.TypeConverter {
|
||||
tc, err := internal.NewTypeConverter(m, false)
|
||||
func NewFakeTypeConverter(m proto.Models) TypeConverter {
|
||||
tc, err := NewTypeConverter(m, false)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to build TypeConverter: %v", err))
|
||||
}
|
||||
@ -137,7 +135,7 @@ func NewFakeTypeConverter(m proto.Models) internal.TypeConverter {
|
||||
}
|
||||
|
||||
func NewFakeOpenAPIModels() proto.Models {
|
||||
d, err := fakeSchema.OpenAPISchema()
|
||||
d, err := kubernetesSwaggerSchema.OpenAPISchema()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -1207,20 +1205,6 @@ func setLastAppliedFromEncoded(obj runtime.Object, lastApplied []byte) error {
|
||||
return setLastApplied(obj, lastAppliedJSON)
|
||||
}
|
||||
|
||||
func setLastApplied(obj runtime.Object, lastApplied string) error {
|
||||
accessor := meta.NewAccessor()
|
||||
annotations, err := accessor.Annotations(obj)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to access annotations: %v", err)
|
||||
}
|
||||
if annotations == nil {
|
||||
annotations = map[string]string{}
|
||||
}
|
||||
annotations[corev1.LastAppliedConfigAnnotation] = lastApplied
|
||||
accessor.SetAnnotations(obj, annotations)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLastApplied(obj runtime.Object) (string, error) {
|
||||
accessor := meta.NewAccessor()
|
||||
annotations, err := accessor.Annotations(obj)
|
||||
|
@ -9,8 +9,6 @@ go_library(
|
||||
"gvkparser.go",
|
||||
"managedfields.go",
|
||||
"pathelement.go",
|
||||
"typeconverter.go",
|
||||
"versionconverter.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/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/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/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/schemaconv:go_default_library",
|
||||
@ -39,22 +36,14 @@ go_test(
|
||||
"fields_test.go",
|
||||
"managedfields_test.go",
|
||||
"pathelement_test.go",
|
||||
"typeconverter_test.go",
|
||||
"versionconverter_test.go",
|
||||
],
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//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/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/merge:go_default_library",
|
||||
"//vendor/sigs.k8s.io/structured-merge-diff/v4/typed:go_default_library",
|
||||
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -30,12 +30,15 @@ import (
|
||||
// definition's "extensions" map.
|
||||
const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
|
||||
|
||||
type gvkParser struct {
|
||||
// GvkParser contains a Parser that allows introspecting the schema.
|
||||
type GvkParser struct {
|
||||
gvks map[schema.GroupVersionKind]string
|
||||
parser typed.Parser
|
||||
}
|
||||
|
||||
func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
|
||||
// Type returns a helper which can produce objects of the given type. Any
|
||||
// errors are deferred until a further function is called.
|
||||
func (p *GvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
|
||||
typeName, ok := p.gvks[gvk]
|
||||
if !ok {
|
||||
return nil
|
||||
@ -44,12 +47,15 @@ func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
|
||||
return &t
|
||||
}
|
||||
|
||||
func newGVKParser(models proto.Models, preserveUnknownFields bool) (*gvkParser, error) {
|
||||
// NewGVKParser builds a GVKParser from a proto.Models. This
|
||||
// will automatically find the proper version of the object, and the
|
||||
// corresponding schema information.
|
||||
func NewGVKParser(models proto.Models, preserveUnknownFields bool) (*GvkParser, error) {
|
||||
typeSchema, err := schemaconv.ToSchemaWithPreserveUnknownFields(models, preserveUnknownFields)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert models to schema: %v", err)
|
||||
}
|
||||
parser := gvkParser{
|
||||
parser := GvkParser{
|
||||
gvks: map[schema.GroupVersionKind]string{},
|
||||
}
|
||||
parser.parser = typed.Parser{Schema: *typeSchema}
|
||||
|
@ -25,14 +25,13 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"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/merge"
|
||||
)
|
||||
|
||||
type lastAppliedManager struct {
|
||||
fieldManager Manager
|
||||
typeConverter internal.TypeConverter
|
||||
typeConverter TypeConverter
|
||||
objectConverter runtime.ObjectConvertor
|
||||
groupVersion schema.GroupVersion
|
||||
}
|
||||
@ -41,7 +40,7 @@ var _ Manager = &lastAppliedManager{}
|
||||
|
||||
// NewLastAppliedManager converts the client-side apply annotation to
|
||||
// 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{
|
||||
fieldManager: fieldManager,
|
||||
typeConverter: typeConverter,
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@ -22,15 +22,14 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func TestLastAppliedUpdater(t *testing.T) {
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("apps/v1", "Deployment"),
|
||||
false,
|
||||
func(m fieldmanager.Manager) fieldmanager.Manager {
|
||||
return fieldmanager.NewLastAppliedUpdater(m)
|
||||
func(m Manager) Manager {
|
||||
return NewLastAppliedUpdater(m)
|
||||
})
|
||||
|
||||
originalLastApplied := `nonempty`
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fieldmanager_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@ -25,7 +25,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@ -43,8 +42,8 @@ func (f *fakeObjectCreater) New(_ schema.GroupVersionKind) (runtime.Object, erro
|
||||
}
|
||||
|
||||
func TestNoUpdateBeforeFirstApply(t *testing.T) {
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"), false, func(m fieldmanager.Manager) fieldmanager.Manager {
|
||||
return fieldmanager.NewSkipNonAppliedManager(
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"), false, func(m Manager) Manager {
|
||||
return NewSkipNonAppliedManager(
|
||||
m,
|
||||
&fakeObjectCreater{gvk: schema.GroupVersionKind{Version: "v1", Kind: "Pod"}},
|
||||
schema.GroupVersionKind{},
|
||||
@ -83,8 +82,8 @@ func TestNoUpdateBeforeFirstApply(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateBeforeFirstApply(t *testing.T) {
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"), false, func(m fieldmanager.Manager) fieldmanager.Manager {
|
||||
return fieldmanager.NewSkipNonAppliedManager(
|
||||
f := NewTestFieldManager(schema.FromAPIVersionAndKind("v1", "Pod"), false, func(m Manager) Manager {
|
||||
return NewSkipNonAppliedManager(
|
||||
m,
|
||||
&fakeObjectCreater{gvk: schema.GroupVersionKind{Version: "v1", Kind: "Pod"}},
|
||||
schema.GroupVersionKind{},
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
type structuredMergeManager struct {
|
||||
typeConverter internal.TypeConverter
|
||||
typeConverter TypeConverter
|
||||
objectConverter runtime.ObjectConvertor
|
||||
objectDefaulter runtime.ObjectDefaulter
|
||||
groupVersion schema.GroupVersion
|
||||
@ -41,7 +41,7 @@ var _ Manager = &structuredMergeManager{}
|
||||
|
||||
// NewStructuredMergeManager creates a new Manager that merges apply 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{
|
||||
typeConverter: typeConverter,
|
||||
objectConverter: objectConverter,
|
||||
@ -49,7 +49,7 @@ func NewStructuredMergeManager(typeConverter internal.TypeConverter, objectConve
|
||||
groupVersion: gv,
|
||||
hubVersion: hub,
|
||||
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
|
||||
}
|
||||
@ -57,7 +57,7 @@ func NewStructuredMergeManager(typeConverter internal.TypeConverter, objectConve
|
||||
// NewCRDStructuredMergeManager creates a new Manager specifically for
|
||||
// CRDs. This allows for the possibility of fields which are not defined
|
||||
// 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{
|
||||
typeConverter: typeConverter,
|
||||
objectConverter: objectConverter,
|
||||
@ -65,7 +65,7 @@ func NewCRDStructuredMergeManager(typeConverter internal.TypeConverter, objectCo
|
||||
groupVersion: gv,
|
||||
hubVersion: hub,
|
||||
updater: merge.Updater{
|
||||
Converter: internal.NewCRDVersionConverter(typeConverter, objectConverter, hub),
|
||||
Converter: newCRDVersionConverter(typeConverter, objectConverter, hub),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -22,6 +22,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/typed"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/value"
|
||||
@ -64,7 +65,7 @@ func (DeducedTypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Obje
|
||||
}
|
||||
|
||||
type typeConverter struct {
|
||||
parser *gvkParser
|
||||
parser *internal.GvkParser
|
||||
}
|
||||
|
||||
var _ TypeConverter = &typeConverter{}
|
||||
@ -73,7 +74,7 @@ var _ TypeConverter = &typeConverter{}
|
||||
// will automatically find the proper version of the object, and the
|
||||
// corresponding schema information.
|
||||
func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConverter, error) {
|
||||
parser, err := newGVKParser(models, preserveUnknownFields)
|
||||
parser, err := internal.NewGVKParser(models, preserveUnknownFields)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal_test
|
||||
package fieldmanager_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -26,17 +26,17 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"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"
|
||||
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||
)
|
||||
|
||||
var fakeSchema = prototesting.Fake{
|
||||
var testSchema = prototesting.Fake{
|
||||
Path: filepath.Join("testdata", "swagger.json"),
|
||||
}
|
||||
|
||||
func TestTypeConverter(t *testing.T) {
|
||||
d, err := fakeSchema.OpenAPISchema()
|
||||
d, err := testSchema.OpenAPISchema()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
tc, err := internal.NewTypeConverter(m, false)
|
||||
tc, err := fieldmanager.NewTypeConverter(m, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to build TypeConverter: %v", err)
|
||||
}
|
||||
|
||||
dtc := internal.DeducedTypeConverter{}
|
||||
dtc := fieldmanager.DeducedTypeConverter{}
|
||||
|
||||
testCases := []struct {
|
||||
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{}{}}
|
||||
if err := yaml.Unmarshal([]byte(y), &obj.Object); err != nil {
|
||||
t.Fatalf("Failed to parse yaml object: %v", err)
|
||||
@ -177,7 +177,7 @@ spec:
|
||||
b.Fatalf("Failed to parse yaml object: %v", err)
|
||||
}
|
||||
|
||||
d, err := fakeSchema.OpenAPISchema()
|
||||
d, err := testSchema.OpenAPISchema()
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to parse OpenAPI schema: %v", err)
|
||||
}
|
||||
@ -186,7 +186,7 @@ spec:
|
||||
b.Fatalf("Failed to build OpenAPI models: %v", err)
|
||||
}
|
||||
|
||||
tc, err := internal.NewTypeConverter(m, false)
|
||||
tc, err := fieldmanager.NewTypeConverter(m, false)
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to build TypeConverter: %v", err)
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -35,7 +35,7 @@ type versionConverter struct {
|
||||
var _ merge.Converter = &versionConverter{}
|
||||
|
||||
// NewVersionConverter builds a VersionConverter from a TypeConverter and an ObjectConvertor.
|
||||
func NewVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
|
||||
func newVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
|
||||
return &versionConverter{
|
||||
typeConverter: t,
|
||||
objectConvertor: o,
|
||||
@ -49,7 +49,7 @@ func NewVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.Gr
|
||||
}
|
||||
|
||||
// NewCRDVersionConverter builds a VersionConverter for CRDs from a TypeConverter and an ObjectConvertor.
|
||||
func NewCRDVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
|
||||
func newCRDVersionConverter(t TypeConverter, o runtime.ObjectConvertor, h schema.GroupVersion) merge.Converter {
|
||||
return &versionConverter{
|
||||
typeConverter: t,
|
||||
objectConvertor: o,
|
@ -14,24 +14,29 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal_test
|
||||
package fieldmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal"
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
prototesting "k8s.io/kube-openapi/pkg/util/proto/testing"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
var testSchema = prototesting.Fake{
|
||||
Path: filepath.Join("testdata", "swagger.json"),
|
||||
}
|
||||
|
||||
// TestVersionConverter tests the version converter
|
||||
func TestVersionConverter(t *testing.T) {
|
||||
d, err := fakeSchema.OpenAPISchema()
|
||||
d, err := testSchema.OpenAPISchema()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse OpenAPI schema: %v", err)
|
||||
}
|
||||
@ -39,15 +44,15 @@ func TestVersionConverter(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to build OpenAPI models: %v", err)
|
||||
}
|
||||
tc, err := internal.NewTypeConverter(m, false)
|
||||
tc, err := NewTypeConverter(m, false)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to build TypeConverter: %v", err)
|
||||
}
|
||||
oc := fakeObjectConvertor{
|
||||
oc := fakeObjectConvertorForTestSchema{
|
||||
gvkForVersion("v1beta1"): objForGroupVersion("apps/v1beta1"),
|
||||
gvkForVersion("v1"): objForGroupVersion("apps/v1"),
|
||||
}
|
||||
vc := internal.NewVersionConverter(tc, oc, schema.GroupVersion{Group: "apps", Version: runtime.APIVersionInternal})
|
||||
vc := newVersionConverter(tc, oc, schema.GroupVersion{Group: "apps", Version: runtime.APIVersionInternal})
|
||||
|
||||
input, err := tc.ObjectToTyped(objForGroupVersion("apps/v1beta1"))
|
||||
if err != nil {
|
||||
@ -85,11 +90,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)
|
||||
for kind := range c {
|
||||
allKinds = append(allKinds, kind)
|
||||
@ -98,10 +103,10 @@ func (c fakeObjectConvertor) ConvertToVersion(_ runtime.Object, gv runtime.Group
|
||||
return c[gvk], nil
|
||||
}
|
||||
|
||||
func (fakeObjectConvertor) Convert(_, _, _ interface{}) error {
|
||||
func (fakeObjectConvertorForTestSchema) Convert(_, _, _ interface{}) error {
|
||||
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")
|
||||
}
|
@ -564,7 +564,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
}
|
||||
if a.group.OpenAPIModels != nil && utilfeature.DefaultFeatureGate.Enabled(features.ServerSideApply) {
|
||||
reqScope.FieldManager, err = fieldmanager.NewDefaultFieldManager(
|
||||
a.group.OpenAPIModels,
|
||||
a.group.TypeConverter,
|
||||
a.group.UnsafeConvertor,
|
||||
a.group.Defaulter,
|
||||
a.group.Creater,
|
||||
|
@ -101,6 +101,7 @@ go_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/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/metrics:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
|
||||
|
@ -40,9 +40,12 @@ import (
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
genericapi "k8s.io/apiserver/pkg/endpoints"
|
||||
"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/server/healthz"
|
||||
"k8s.io/apiserver/pkg/server/routes"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilopenapi "k8s.io/apiserver/pkg/util/openapi"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
@ -418,6 +421,15 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
||||
apiGroupVersion.OptionsExternalVersion = apiGroupInfo.OptionsExternalVersion
|
||||
}
|
||||
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
|
||||
|
||||
if err := apiGroupVersion.InstallREST(s.Handler.GoRestfulContainer); err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user