From 81bbf9fab860baf23c508dda5ef13aff5c78974d Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Thu, 17 Jan 2019 16:57:58 -0800 Subject: [PATCH] Plug deduced type in --- .../handlers/fieldmanager/fieldmanager.go | 16 ++++++++ .../fieldmanager/internal/typeconverter.go | 39 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go index 20e359d3f87..080baafb642 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/fieldmanager.go @@ -61,6 +61,22 @@ func NewFieldManager(models openapiproto.Models, objectConverter runtime.ObjectC }, nil } +// NewCRDFieldManager creates a new FieldManager specifically for +// CRDs. This doesn't use openapi models (and it doesn't support the +// validation field right now). +func NewCRDFieldManager(objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) *FieldManager { + return &FieldManager{ + typeConverter: internal.DeducedTypeConverter{}, + objectConverter: objectConverter, + objectDefaulter: objectDefaulter, + groupVersion: gv, + hubVersion: hub, + updater: merge.Updater{ + Converter: internal.NewVersionConverter(internal.DeducedTypeConverter{}, objectConverter, hub), + }, + } +} + // Update is used when the object has already been merged (non-apply // use-case), and simply updates the managed fields in the output // object. diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/typeconverter.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/typeconverter.go index 9b149b32221..7bc1249dc24 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/typeconverter.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal/typeconverter.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/kube-openapi/pkg/util/proto" "sigs.k8s.io/structured-merge-diff/typed" + "sigs.k8s.io/structured-merge-diff/value" "sigs.k8s.io/yaml" ) @@ -34,6 +35,38 @@ type TypeConverter interface { TypedToObject(typed.TypedValue) (runtime.Object, error) } +// DeducedTypeConverter is a TypeConverter for CRDs that don't have a +// schema. It does implement the same interface though (and create the +// same types of objects), so that everything can still work the same. +// CRDs are merged with all their fields being "atomic" (lists +// included). +// +// Note that this is not going to be sufficient for converting to/from +// CRDs that have a schema defined (we don't support that schema yet). +type DeducedTypeConverter struct{} + +var _ TypeConverter = DeducedTypeConverter{} + +// ObjectToTyped converts an object into a TypedValue with a "deduced type". +func (DeducedTypeConverter) ObjectToTyped(obj runtime.Object) (typed.TypedValue, error) { + u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) + if err != nil { + return typed.TypedValue{}, err + } + return typed.DeducedParseableType{}.FromUnstructured(u) +} + +// YAMLToTyped parses a yaml object into a TypedValue with a "deduced type". +func (DeducedTypeConverter) YAMLToTyped(from []byte) (typed.TypedValue, error) { + return typed.DeducedParseableType{}.FromYAML(typed.YAMLObject(from)) +} + +// TypedToObject transforms the typed value into a runtime.Object. That +// is not specific to deduced type. +func (DeducedTypeConverter) TypedToObject(value typed.TypedValue) (runtime.Object, error) { + return valueToObject(value.AsValue()) +} + type typeConverter struct { parser *gvkParser } @@ -75,7 +108,11 @@ func (c *typeConverter) YAMLToTyped(from []byte) (typed.TypedValue, error) { } func (c *typeConverter) TypedToObject(value typed.TypedValue) (runtime.Object, error) { - vu := value.AsValue().ToUnstructured(false) + return valueToObject(value.AsValue()) +} + +func valueToObject(value *value.Value) (runtime.Object, error) { + vu := value.ToUnstructured(false) u, ok := vu.(map[string]interface{}) if !ok { return nil, fmt.Errorf("failed to convert typed to unstructured: want map, got %T", vu)