Use CRD validation field in server-side apply

Kubernetes-commit: c0617933d4bec5b00dbbfcd24edb7d7e7fc5509d
This commit is contained in:
jennybuckley 2019-08-28 15:28:49 -07:00 committed by Kubernetes Publisher
parent c6d374fefe
commit b1cbdafe99
7 changed files with 32 additions and 15 deletions

View File

@ -48,7 +48,7 @@ type FieldManager struct {
// NewFieldManager creates a new FieldManager that merges apply requests // NewFieldManager 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 NewFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) (*FieldManager, error) { func NewFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) (*FieldManager, error) {
typeConverter, err := internal.NewTypeConverter(models) typeConverter, err := internal.NewTypeConverter(models, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -66,19 +66,26 @@ func NewFieldManager(models openapiproto.Models, objectConverter runtime.ObjectC
} }
// NewCRDFieldManager creates a new FieldManager specifically for // NewCRDFieldManager creates a new FieldManager specifically for
// CRDs. This doesn't use openapi models (and it doesn't support the // CRDs. This allows for the possibility of fields which are not defined
// validation field right now). // in models, as well as having no models defined at all.
func NewCRDFieldManager(objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion) *FieldManager { func NewCRDFieldManager(models openapiproto.Models, objectConverter runtime.ObjectConvertor, objectDefaulter runtime.ObjectDefaulter, gv schema.GroupVersion, hub schema.GroupVersion, preserveUnknownFields 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
}
}
return &FieldManager{ return &FieldManager{
typeConverter: internal.DeducedTypeConverter{}, typeConverter: typeConverter,
objectConverter: objectConverter, objectConverter: objectConverter,
objectDefaulter: objectDefaulter, objectDefaulter: objectDefaulter,
groupVersion: gv, groupVersion: gv,
hubVersion: hub, hubVersion: hub,
updater: merge.Updater{ updater: merge.Updater{
Converter: internal.NewCRDVersionConverter(internal.DeducedTypeConverter{}, objectConverter, hub), Converter: internal.NewCRDVersionConverter(typeConverter, objectConverter, hub),
}, },
} }, nil
} }
// Update is used when the object has already been merged (non-apply // Update is used when the object has already been merged (non-apply

View File

@ -58,12 +58,15 @@ func NewTestFieldManager() *fieldmanager.FieldManager {
Version: "v1", Version: "v1",
} }
return fieldmanager.NewCRDFieldManager( f, _ := fieldmanager.NewCRDFieldManager(
nil,
&fakeObjectConvertor{}, &fakeObjectConvertor{},
&fakeObjectDefaulter{}, &fakeObjectDefaulter{},
gv, gv,
gv, gv,
true,
) )
return f
} }
func TestFieldManagerCreation(t *testing.T) { func TestFieldManagerCreation(t *testing.T) {

View File

@ -44,8 +44,8 @@ func (p *gvkParser) Type(gvk schema.GroupVersionKind) *typed.ParseableType {
return &t return &t
} }
func newGVKParser(models proto.Models) (*gvkParser, error) { func newGVKParser(models proto.Models, preserveUnknownFields bool) (*gvkParser, error) {
typeSchema, err := schemaconv.ToSchema(models) 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)
} }

View File

@ -78,8 +78,8 @@ var _ TypeConverter = &typeConverter{}
// NewTypeConverter builds a TypeConverter from a proto.Models. This // NewTypeConverter builds a TypeConverter from a proto.Models. This
// 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) (TypeConverter, error) { func NewTypeConverter(models proto.Models, preserveUnknownFields bool) (TypeConverter, error) {
parser, err := newGVKParser(models) parser, err := newGVKParser(models, preserveUnknownFields)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -48,7 +48,7 @@ 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) tc, err := internal.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)
} }
@ -214,7 +214,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) tc, err := internal.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

@ -39,7 +39,7 @@ 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) tc, err := internal.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)
} }

View File

@ -77,6 +77,10 @@ type APIGroupInfo struct {
NegotiatedSerializer runtime.NegotiatedSerializer NegotiatedSerializer runtime.NegotiatedSerializer
// ParameterCodec performs conversions for query parameters passed to API calls // ParameterCodec performs conversions for query parameters passed to API calls
ParameterCodec runtime.ParameterCodec ParameterCodec runtime.ParameterCodec
// StaticOpenAPISpec is the spec derived from the definitions of all resources installed together.
// It is set during InstallAPIGroups, InstallAPIGroup, and InstallLegacyAPIGroup.
StaticOpenAPISpec *spec.Swagger
} }
// GenericAPIServer contains state for a Kubernetes cluster api server. // GenericAPIServer contains state for a Kubernetes cluster api server.
@ -562,6 +566,9 @@ func (s *GenericAPIServer) getOpenAPIModels(apiPrefix string, apiGroupInfos ...*
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, apiGroupInfo := range apiGroupInfos {
apiGroupInfo.StaticOpenAPISpec = openAPISpec
}
return utilopenapi.ToProtoModels(openAPISpec) return utilopenapi.ToProtoModels(openAPISpec)
} }