Skip to content

Commit 2bc484e

Browse files
committed
pkg/cdi: split out Spec JSON Schema validation.
Don't forcibly pull in the Spec JSON Schema validation bits, since the external package we depend on for that is huge. For instance in cmd/cdi it results in a size increase of cc. 3000 kB. We neither want nor can force such a penalty on anybody who imports CDI. To avoid this, we split out the Schema- validation glue code bits to a validate subpackage and add an externally settable Spec validation function. Using this new setup, simply importing pkg/cdi keeps the offending bits at bay. Yet it allows a willing client to enable automatic validation by JSON Schema using only a few lines of code. Signed-off-by: Krisztian Litkey <[email protected]>
1 parent 4b00593 commit 2bc484e

File tree

3 files changed

+81
-47
lines changed

3 files changed

+81
-47
lines changed

pkg/cdi/schema.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

pkg/cdi/spec.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ var (
3535
"0.2.0": {},
3636
"0.3.0": {},
3737
}
38+
39+
// Externally set CDI Spec validation function.
40+
specValidator func(*cdi.Spec) error
3841
)
3942

4043
// Spec represents a single CDI Spec. It is usually loaded from a
@@ -85,7 +88,7 @@ func ReadSpec(path string, priority int) (*Spec, error) {
8588
// priority. If Spec data validation fails NewSpec returns a nil
8689
// Spec and an error.
8790
func NewSpec(raw *cdi.Spec, path string, priority int) (*Spec, error) {
88-
err := validateWithSchema(raw)
91+
err := validateSpec(raw)
8992
if err != nil {
9093
return nil, err
9194
}
@@ -188,3 +191,22 @@ func parseSpec(data []byte) (*cdi.Spec, error) {
188191
}
189192
return raw, nil
190193
}
194+
195+
// SetSpecValidator sets a CDI Spec validator function. This function
196+
// is used for extra CDI Spec content validation whenever a Spec file
197+
// loaded (using ReadSpec() or NewSpec()) or written (Spec.Write()).
198+
func SetSpecValidator(fn func(*cdi.Spec) error) {
199+
specValidator = fn
200+
}
201+
202+
// validateSpec validates the Spec using the extneral validator.
203+
func validateSpec(raw *cdi.Spec) error {
204+
if specValidator == nil {
205+
return nil
206+
}
207+
err := specValidator(raw)
208+
if err != nil {
209+
return errors.Wrap(err, "Spec validation failed")
210+
}
211+
return nil
212+
}

pkg/cdi/validate/schema.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright © 2022 The CDI Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package validate
18+
19+
import (
20+
"github.com/container-orchestrated-devices/container-device-interface/schema"
21+
raw "github.com/container-orchestrated-devices/container-device-interface/specs-go"
22+
)
23+
24+
const (
25+
// DefaultExternalSchema is the default JSON schema to load for validation.
26+
DefaultExternalSchema = "/etc/cdi/schema/schema.json"
27+
)
28+
29+
// WithSchema returns a CDI Spec validator that uses the given Schema.
30+
func WithSchema(s *schema.Schema) func(*raw.Spec) error {
31+
if s == nil {
32+
return func(*raw.Spec) error {
33+
return nil
34+
}
35+
}
36+
return func(spec *raw.Spec) error {
37+
return s.ValidateType(spec)
38+
}
39+
}
40+
41+
// WithNamedSchema loads the named JSON schema and returns a CDI Spec
42+
// validator for it. If loading the schema fails a dummy validator is
43+
// returned.
44+
func WithNamedSchema(name string) func(*raw.Spec) error {
45+
s, _ := schema.Load(name)
46+
return WithSchema(s)
47+
}
48+
49+
// WithDefaultSchema returns a CDI Spec validator that uses the default
50+
// external JSON schema, or the default builtin one if the external one
51+
// fails to load.
52+
func WithDefaultSchema() func(*raw.Spec) error {
53+
s, err := schema.Load(DefaultExternalSchema)
54+
if err == nil {
55+
return WithSchema(s)
56+
}
57+
return WithSchema(schema.BuiltinSchema())
58+
}

0 commit comments

Comments
 (0)