OpenAPIResourcesGetter allows lazy-loading OpenAPI V2

Kubernetes-commit: 6614a29f470f802915d1467f5050dbca1f8bc562
This commit is contained in:
Sean Sullivan 2023-03-13 20:28:40 -07:00 committed by Kubernetes Publisher
parent e22d02e126
commit 348bd97228
5 changed files with 34 additions and 18 deletions

View File

@ -62,8 +62,10 @@ type Factory interface {
// Returns a schema that can validate objects stored on disk.
Validator(validationDirective string) (validation.Schema, error)
// OpenAPISchema returns the parsed openapi schema definition
OpenAPISchema() (openapi.Resources, error)
// Used for retrieving openapi v2 resources.
openapi.OpenAPIResourcesGetter
// OpenAPIV3Schema returns a client for fetching parsed schemas for
// any group version
OpenAPIV3Client() (openapiclient.Client, error)

View File

@ -154,13 +154,8 @@ func (f *factoryImpl) Validator(validationDirective string) (validation.Schema,
return validation.NullSchema{}, nil
}
resources, err := f.OpenAPISchema()
if err != nil {
return nil, err
}
schema := validation.ConjunctiveSchema{
validation.NewSchemaValidation(resources),
validation.NewSchemaValidation(f),
validation.NoDoubleKeySchema{},
}

View File

@ -24,6 +24,13 @@ import (
"sigs.k8s.io/yaml"
)
// OpenAPIResourcesGetter represents a function to return
// OpenAPI V2 resource specifications. Used for lazy-loading
// these resource specifications.
type OpenAPIResourcesGetter interface {
OpenAPISchema() (Resources, error)
}
// Resources interface describe a resources provider, that can give you
// resource based on group-version-kind.
type Resources interface {

View File

@ -29,14 +29,14 @@ import (
// schemaValidation validates the object against an OpenAPI schema.
type schemaValidation struct {
resources openapi.Resources
resourcesGetter openapi.OpenAPIResourcesGetter
}
// NewSchemaValidation creates a new Schema that can be used
// to validate objects.
func NewSchemaValidation(resources openapi.Resources) Schema {
func NewSchemaValidation(resourcesGetter openapi.OpenAPIResourcesGetter) Schema {
return &schemaValidation{
resources: resources,
resourcesGetter: resourcesGetter,
}
}
@ -56,7 +56,6 @@ func (v *schemaValidation) ValidateBytes(data []byte) error {
if (gvk == schema.GroupVersionKind{Version: "v1", Kind: "List"}) {
return utilerrors.NewAggregate(v.validateList(obj))
}
return utilerrors.NewAggregate(v.validateResource(obj, gvk))
}
@ -81,7 +80,12 @@ func (v *schemaValidation) validateList(object interface{}) []error {
}
func (v *schemaValidation) validateResource(obj interface{}, gvk schema.GroupVersionKind) []error {
resource := v.resources.LookupResource(gvk)
// This lazy-loads the OpenAPI V2 specifications, caching the specs.
resources, err := v.resourcesGetter.OpenAPISchema()
if err != nil {
return []error{err}
}
resource := resources.LookupResource(gvk)
if resource == nil {
// resource is not present, let's just skip validation.
return nil

View File

@ -32,14 +32,22 @@ import (
var fakeSchema = testing.Fake{Path: filepath.Join("..", "..", "testdata", "openapi", "swagger.json")}
// fakeResourcesGetter implements the OpenAPIResourcesGetter interface, returning the
// openapi resources from the swagger.json (above).
type fakeResourcesGetter struct{}
func (r *fakeResourcesGetter) OpenAPISchema() (openapi.Resources, error) {
doc, err := fakeSchema.OpenAPISchema()
if err != nil {
return nil, err
}
return openapi.NewOpenAPIData(doc)
}
var _ = Describe("resource validation using OpenAPI Schema", func() {
var validator Schema
BeforeEach(func() {
s, err := fakeSchema.OpenAPISchema()
Expect(err).ToNot(HaveOccurred())
resources, err := openapi.NewOpenAPIData(s)
Expect(err).ToNot(HaveOccurred())
validator = NewSchemaValidation(resources)
validator = NewSchemaValidation(&fakeResourcesGetter{})
Expect(validator).ToNot(BeNil())
})