diff --git a/cmd/oci-image-tool/validate.go b/cmd/oci-image-tool/validate.go index c2b42e2ef..7c265f47f 100644 --- a/cmd/oci-image-tool/validate.go +++ b/cmd/oci-image-tool/validate.go @@ -39,7 +39,7 @@ type validateCmd struct { stdout *log.Logger stderr *log.Logger typ string // the type to validate, can be empty string - ref string + refs []string } func newValidateCmd(stdout, stderr *log.Logger) *cobra.Command { @@ -62,9 +62,9 @@ func newValidateCmd(stdout, stderr *log.Logger) *cobra.Command { ), ) - cmd.Flags().StringVar( - &v.ref, "ref", "v1.0", - `The ref pointing to the manifest to be validated. This must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout.`, + cmd.Flags().StringSliceVar( + &v.refs, "ref", []string{"v1.0"}, + `A set of refs pointing to the manifests to be validated. Each reference must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout.`, ) return cmd @@ -112,8 +112,10 @@ func (v *validateCmd) Run(cmd *cobra.Command, args []string) { } func (v *validateCmd) validatePath(name string) error { - var err error - typ := v.typ + var ( + err error + typ = v.typ + ) if typ == "" { if typ, err = autodetect(name); err != nil { @@ -123,9 +125,9 @@ func (v *validateCmd) validatePath(name string) error { switch typ { case typeImageLayout: - return image.ValidateLayout(name, v.ref) + return image.ValidateLayout(name, v.refs, v.stdout) case typeImage: - return image.Validate(name, v.ref) + return image.Validate(name, v.refs, v.stdout) } f, err := os.Open(name) @@ -137,10 +139,8 @@ func (v *validateCmd) validatePath(name string) error { switch typ { case typeManifest: return schema.MediaTypeManifest.Validate(f) - case typeManifestList: return schema.MediaTypeManifestList.Validate(f) - case typeConfig: return schema.MediaTypeImageConfig.Validate(f) } diff --git a/image/image.go b/image/image.go index 04ce278ee..c2b1df17d 100644 --- a/image/image.go +++ b/image/image.go @@ -16,6 +16,7 @@ package image import ( "encoding/json" + "log" "os" "path/filepath" @@ -23,41 +24,49 @@ import ( ) // ValidateLayout walks through the file tree given by src and -// validates the manifest pointed to by the given ref +// validates the manifest pointed to by the given refs // or returns an error if the validation failed. -func ValidateLayout(src, ref string) error { - return validate(newPathWalker(src), ref) +func ValidateLayout(src string, refs []string, out *log.Logger) error { + return validate(newPathWalker(src), refs, out) } // Validate walks through the given .tar file and -// validates the manifest pointed to by the given ref +// validates the manifest pointed to by the given refs // or returns an error if the validation failed. -func Validate(tarFile, ref string) error { +func Validate(tarFile string, refs []string, out *log.Logger) error { f, err := os.Open(tarFile) if err != nil { return errors.Wrap(err, "unable to open file") } defer f.Close() - return validate(newTarWalker(f), ref) + return validate(newTarWalker(f), refs, out) } -func validate(w walker, refName string) error { - ref, err := findDescriptor(w, refName) - if err != nil { - return err - } - - if err = ref.validate(w); err != nil { - return err - } - - m, err := findManifest(w, ref) - if err != nil { - return err - } - - return m.validate(w) +func validate(w walker, refs []string, out *log.Logger) error { + for _, r := range refs { + ref, err := findDescriptor(w, r) + if err != nil { + return err + } + + if err = ref.validate(w); err != nil { + return err + } + + m, err := findManifest(w, ref) + if err != nil { + return err + } + + if err := m.validate(w); err != nil { + return err + } + if out != nil { + out.Printf("reference %q: OK", r) + } + } + return nil } // UnpackLayout walks through the file tree given by src and