diff --git a/schema/validator.go b/schema/validator.go index 3c640e7ef..432e7b992 100644 --- a/schema/validator.go +++ b/schema/validator.go @@ -16,10 +16,12 @@ package schema import ( "bytes" + "encoding/json" "fmt" "io" "io/ioutil" + "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/xeipuuv/gojsonschema" ) @@ -28,6 +30,12 @@ import ( // and implements validation against a JSON schema. type Validator string +type validateDescendantsFunc func(r io.Reader) error + +var mapValidateDescendants = map[Validator]validateDescendantsFunc{ + MediaTypeManifest: validateManifestDescendants, +} + // ValidationError contains all the errors that happened during validation. type ValidationError struct { Errs []error @@ -44,6 +52,16 @@ func (v Validator) Validate(src io.Reader) error { return errors.Wrap(err, "unable to read the document file") } + if f, ok := mapValidateDescendants[v]; ok { + if f == nil { + return fmt.Errorf("internal error: mapValidateDescendents[%q] is nil", v) + } + err = f(bytes.NewReader(buf)) + if err != nil { + return err + } + } + sl := gojsonschema.NewReferenceLoaderFileSystem("file:///"+specs[v], fs) ml := gojsonschema.NewStringLoader(string(buf)) @@ -73,3 +91,29 @@ type unimplemented string func (v unimplemented) Validate(src io.Reader) error { return fmt.Errorf("%s: unimplemented", v) } + +func validateManifestDescendants(r io.Reader) error { + header := v1.Manifest{} + + buf, err := ioutil.ReadAll(r) + if err != nil { + return errors.Wrapf(err, "error reading the io stream") + } + + err = json.Unmarshal(buf, &header) + if err != nil { + return errors.Wrap(err, "manifest format mismatch") + } + + 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) + } + + 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) + } + } + return nil +}