diff --git a/schema/config_test.go b/schema/config_test.go index 27c14875c..98c760adf 100644 --- a/schema/config_test.go +++ b/schema/config_test.go @@ -156,7 +156,7 @@ func TestConfig(t *testing.T) { }, } { r := strings.NewReader(tt.config) - err := schema.MediaTypeImageConfig.Validate(r) + err := schema.MediaTypeImageConfig.Validate(r, false) if got := err != nil; tt.fail != got { t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) diff --git a/schema/manifest_backwards_compatibility_test.go b/schema/manifest_backwards_compatibility_test.go index 4bd055cbf..80b2a73ec 100644 --- a/schema/manifest_backwards_compatibility_test.go +++ b/schema/manifest_backwards_compatibility_test.go @@ -118,7 +118,7 @@ func TestBackwardsCompatibilityManifestList(t *testing.T) { manifest := convertFormats(tt.manifest) r := strings.NewReader(manifest) - err := schema.MediaTypeManifestList.Validate(r) + err := schema.MediaTypeManifestList.Validate(r, false) if got := err != nil; tt.fail != got { t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) @@ -181,7 +181,7 @@ func TestBackwardsCompatibilityManifest(t *testing.T) { manifest := convertFormats(tt.manifest) r := strings.NewReader(manifest) - err := schema.MediaTypeManifest.Validate(r) + err := schema.MediaTypeManifest.Validate(r, false) if got := err != nil; tt.fail != got { t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) @@ -221,7 +221,7 @@ func TestBackwardsCompatibilityConfig(t *testing.T) { config := convertFormats(tt.config) r := strings.NewReader(config) - err := schema.MediaTypeImageConfig.Validate(r) + err := schema.MediaTypeImageConfig.Validate(r, false) if got := err != nil; tt.fail != got { t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) diff --git a/schema/manifest_test.go b/schema/manifest_test.go index f1cb51d02..addd1d424 100644 --- a/schema/manifest_test.go +++ b/schema/manifest_test.go @@ -23,11 +23,13 @@ import ( func TestManifest(t *testing.T) { for i, tt := range []struct { + strict bool manifest string fail bool }{ // expected failure: mediaType does not match pattern { + strict: false, manifest: ` { "schemaVersion": 2, @@ -39,6 +41,7 @@ func TestManifest(t *testing.T) { // expected failure: config.size is a string, expected integer { + strict: false, manifest: ` { "schemaVersion": 2, @@ -56,6 +59,7 @@ func TestManifest(t *testing.T) { // expected failure: layers.size is string, expected integer { + strict: false, manifest: ` { "schemaVersion": 2, @@ -79,6 +83,7 @@ func TestManifest(t *testing.T) { // valid manifest { + strict: true, manifest: ` { "schemaVersion": 2, @@ -115,7 +120,7 @@ func TestManifest(t *testing.T) { }, } { r := strings.NewReader(tt.manifest) - err := schema.MediaTypeManifest.Validate(r) + err := schema.MediaTypeManifest.Validate(r, tt.strict) if got := err != nil; tt.fail != got { t.Errorf("test %d: expected validation failure %t but got %t, err %v", i, tt.fail, got, err) diff --git a/schema/spec_test.go b/schema/spec_test.go index 2a6f4a493..c84c3fa7b 100644 --- a/schema/spec_test.go +++ b/schema/spec_test.go @@ -73,7 +73,7 @@ func validate(t *testing.T, name string) { continue } - err = schema.Validator(example.Mediatype).Validate(strings.NewReader(example.Body)) + err = schema.Validator(example.Mediatype).Validate(strings.NewReader(example.Body), false) if err == nil { printFields(t, "ok", example.Mediatype, example.Title) t.Log(example.Body, "---") diff --git a/schema/validator.go b/schema/validator.go index 432e7b992..0b491a320 100644 --- a/schema/validator.go +++ b/schema/validator.go @@ -30,7 +30,7 @@ import ( // and implements validation against a JSON schema. type Validator string -type validateDescendantsFunc func(r io.Reader) error +type validateDescendantsFunc func(r io.Reader, strict bool) error var mapValidateDescendants = map[Validator]validateDescendantsFunc{ MediaTypeManifest: validateManifestDescendants, @@ -46,7 +46,8 @@ func (e ValidationError) Error() string { } // Validate validates the given reader against the schema of the wrapped media type. -func (v Validator) Validate(src io.Reader) error { +// strict: accept the customized media type when value is false, or reject when true. +func (v Validator) Validate(src io.Reader, strict bool) error { buf, err := ioutil.ReadAll(src) if err != nil { return errors.Wrap(err, "unable to read the document file") @@ -56,7 +57,7 @@ func (v Validator) Validate(src io.Reader) error { if f == nil { return fmt.Errorf("internal error: mapValidateDescendents[%q] is nil", v) } - err = f(bytes.NewReader(buf)) + err = f(bytes.NewReader(buf), strict) if err != nil { return err } @@ -88,11 +89,11 @@ func (v Validator) Validate(src io.Reader) error { type unimplemented string -func (v unimplemented) Validate(src io.Reader) error { +func (v unimplemented) Validate(src io.Reader, strict bool) error { return fmt.Errorf("%s: unimplemented", v) } -func validateManifestDescendants(r io.Reader) error { +func validateManifestDescendants(r io.Reader, strict bool) error { header := v1.Manifest{} buf, err := ioutil.ReadAll(r) @@ -106,13 +107,21 @@ func validateManifestDescendants(r io.Reader) error { } if header.Config.MediaType != string(v1.MediaTypeImageConfig) { - fmt.Printf("warning: config %s has an unknown media type: %s\n", header.Config.Digest, header.Config.MediaType) + msg := fmt.Sprintf("config %s has an unknown media type: %s", header.Config.Digest, header.Config.MediaType) + if strict { + return fmt.Errorf("%s", msg) + } + fmt.Printf("warning: %s\n", msg) } for _, layer := range header.Layers { if layer.MediaType != string(v1.MediaTypeImageLayer) && layer.MediaType != string(v1.MediaTypeImageLayerNonDistributable) { - fmt.Printf("warning: layer %s has an unknown media type: %s\n", layer.Digest, layer.MediaType) + msg := fmt.Sprintf("layer %s has an unknown media type: %s", layer.Digest, layer.MediaType) + if strict { + return fmt.Errorf("%s", msg) + } + fmt.Printf("warning: %s\n", msg) } } return nil