diff --git a/image/config.go b/image/config.go index 7ef0ac2..3ba66b5 100644 --- a/image/config.go +++ b/image/config.go @@ -33,9 +33,9 @@ import ( type config v1.Image -func findConfig(w walker, d *descriptor) (*config, error) { +func findConfig(w walker, d *v1.Descriptor) (*config, error) { var c config - cpath := filepath.Join("blobs", d.algo(), d.hash()) + cpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex()) switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { if info.IsDir() || filepath.Clean(path) != cpath { diff --git a/image/descriptor.go b/image/descriptor.go index cb7aa14..6d16fd6 100644 --- a/image/descriptor.go +++ b/image/descriptor.go @@ -20,33 +20,13 @@ import ( "io" "os" "path/filepath" - "strings" - "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) -type descriptor v1.Descriptor - -func (d *descriptor) algo() string { - pts := strings.SplitN(string(d.Digest), ":", 2) - if len(pts) != 2 { - return "" - } - return pts[0] -} - -func (d *descriptor) hash() string { - pts := strings.SplitN(string(d.Digest), ":", 2) - if len(pts) != 2 { - return "" - } - return pts[1] -} - -func listReferences(w walker) (map[string]*descriptor, error) { - refs := make(map[string]*descriptor) +func listReferences(w walker) (map[string]*v1.Descriptor, error) { + refs := make(map[string]*v1.Descriptor) var index v1.ImageIndex if err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { @@ -60,7 +40,7 @@ func listReferences(w walker) (map[string]*descriptor, error) { for i := 0; i < len(index.Manifests); i++ { if index.Manifests[i].Descriptor.Annotations["org.opencontainers.ref.name"] != "" { - refs[index.Manifests[i].Descriptor.Annotations["org.opencontainers.ref.name"]] = (*descriptor)(&index.Manifests[i].Descriptor) + refs[index.Manifests[i].Descriptor.Annotations["org.opencontainers.ref.name"]] = &index.Manifests[i].Descriptor } } @@ -71,8 +51,8 @@ func listReferences(w walker) (map[string]*descriptor, error) { return refs, nil } -func findDescriptor(w walker, name string) (*descriptor, error) { - var d descriptor +func findDescriptor(w walker, name string) (*v1.Descriptor, error) { + var d v1.Descriptor var index v1.ImageIndex switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { @@ -86,7 +66,7 @@ func findDescriptor(w walker, name string) (*descriptor, error) { for i := 0; i < len(index.Manifests); i++ { if index.Manifests[i].Descriptor.Annotations["org.opencontainers.ref.name"] == name { - d = (descriptor)(index.Manifests[i].Descriptor) + d = index.Manifests[i].Descriptor return errEOW } } @@ -102,7 +82,7 @@ func findDescriptor(w walker, name string) (*descriptor, error) { } } -func (d *descriptor) validate(w walker, mts []string) error { +func validateDescriptor(d *v1.Descriptor, w walker, mts []string) error { var found bool for _, mt := range mts { if d.MediaType == mt { @@ -114,13 +94,12 @@ func (d *descriptor) validate(w walker, mts []string) error { return fmt.Errorf("invalid descriptor MediaType %q", d.MediaType) } - parsed, err := digest.Parse(string(d.Digest)) - if err != nil { + if err := d.Digest.Validate(); err != nil { return err } // Copy the contents of the layer in to the verifier - verifier := parsed.Verifier() + verifier := d.Digest.Verifier() numBytes, err := w.get(*d, verifier) if err != nil { return err diff --git a/image/image.go b/image/image.go index 4ff345c..9318af1 100644 --- a/image/image.go +++ b/image/image.go @@ -84,7 +84,7 @@ func validate(w walker, refs []string, out *log.Logger) error { return fmt.Errorf("reference %s not found", ref) } - if err = d.validate(w, validRefMediaTypes); err != nil { + if err = validateDescriptor(d, w, validRefMediaTypes); err != nil { return err } @@ -135,7 +135,7 @@ func unpack(w walker, dest, refName string) error { return err } - if err = ref.validate(w, validRefMediaTypes); err != nil { + if err = validateDescriptor(ref, w, validRefMediaTypes); err != nil { return err } @@ -183,7 +183,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs string) error { return err } - if err = ref.validate(w, validRefMediaTypes); err != nil { + if err = validateDescriptor(ref, w, validRefMediaTypes); err != nil { return err } diff --git a/image/image_test.go b/image/image_test.go index a8182a5..e83440b 100644 --- a/image/image_test.go +++ b/image/image_test.go @@ -238,7 +238,7 @@ func createLayoutFile(root string) error { return err } -func createIndexFile(root string, mft descriptor) error { +func createIndexFile(root string, mft v1.Descriptor) error { indexpath := filepath.Join(root, "index.json") f, err := os.Create(indexpath) if err != nil { @@ -251,48 +251,48 @@ func createIndexFile(root string, mft descriptor) error { return err } -func createManifestFile(root, str string) (descriptor, error) { +func createManifestFile(root, str string) (v1.Descriptor, error) { name := filepath.Join(root, "blobs", "sha256", "test-manifest") f, err := os.Create(name) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } defer f.Close() _, err = io.Copy(f, bytes.NewBuffer([]byte(str))) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } return createHashedBlob(name) } -func createConfigFile(root, config string) (descriptor, error) { +func createConfigFile(root, config string) (v1.Descriptor, error) { name := filepath.Join(root, "blobs", "sha256", "test-config") f, err := os.Create(name) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } defer f.Close() _, err = io.Copy(f, bytes.NewBuffer([]byte(config))) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } return createHashedBlob(name) } -func createImageLayerFile(root string, list []tarContent) (descriptor, error) { +func createImageLayerFile(root string, list []tarContent) (v1.Descriptor, error) { name := filepath.Join(root, "blobs", "sha256", "test-layer") err := createTarBlob(name, list) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } desc, err := createHashedBlob(name) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } desc.MediaType = v1.MediaTypeImageLayer @@ -321,40 +321,39 @@ func createTarBlob(name string, list []tarContent) error { return nil } -func createHashedBlob(name string) (descriptor, error) { +func createHashedBlob(name string) (v1.Descriptor, error) { desc, err := newDescriptor(name) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } - parsed, err := digest.Parse(string(desc.Digest)) - if err != nil { - return descriptor{}, err + if err := desc.Digest.Validate(); err != nil { + return v1.Descriptor{}, err } // Rename the file to hashed-digest name. - err = os.Rename(name, filepath.Join(filepath.Dir(name), parsed.Hex())) + err = os.Rename(name, filepath.Join(filepath.Dir(name), desc.Digest.Hex())) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } return desc, nil } -func newDescriptor(name string) (descriptor, error) { +func newDescriptor(name string) (v1.Descriptor, error) { file, err := os.Open(name) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } defer file.Close() digester := digest.SHA256.Digester() size, err := io.Copy(digester.Hash(), file) if err != nil { - return descriptor{}, err + return v1.Descriptor{}, err } - return descriptor{ + return v1.Descriptor{ Digest: digester.Digest(), Size: size, }, nil diff --git a/image/manifest.go b/image/manifest.go index 8834c1e..a827ab6 100644 --- a/image/manifest.go +++ b/image/manifest.go @@ -36,13 +36,13 @@ import ( ) type manifest struct { - Config descriptor `json:"config"` - Layers []descriptor `json:"layers"` + Config v1.Descriptor `json:"config"` + Layers []v1.Descriptor `json:"layers"` } -func findManifest(w walker, d *descriptor) (*manifest, error) { +func findManifest(w walker, d *v1.Descriptor) (*manifest, error) { var m manifest - mpath := filepath.Join("blobs", d.algo(), d.hash()) + mpath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex()) switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { if info.IsDir() || filepath.Clean(path) != mpath { @@ -74,7 +74,7 @@ func findManifest(w walker, d *descriptor) (*manifest, error) { } func (m *manifest) validate(w walker) error { - if err := m.Config.validate(w, []string{v1.MediaTypeImageConfig}); err != nil { + if err := validateDescriptor(&m.Config, w, []string{v1.MediaTypeImageConfig}); err != nil { return errors.Wrap(err, "config validation failed") } @@ -86,7 +86,7 @@ func (m *manifest) validate(w walker) error { } for _, d := range m.Layers { - if err := d.validate(w, validLayerMediaTypes); err != nil { + if err := validateDescriptor(&d, w, validLayerMediaTypes); err != nil { return errors.Wrap(err, "layer validation failed") } } @@ -118,8 +118,8 @@ func (m *manifest) unpack(w walker, dest string) (retErr error) { return nil } - dd, err := filepath.Rel(filepath.Join("blobs", d.algo()), filepath.Clean(path)) - if err != nil || d.hash() != dd { + dd, err := filepath.Rel(filepath.Join("blobs", string(d.Digest.Algorithm())), filepath.Clean(path)) + if err != nil || d.Digest.Hex() != dd { return nil } diff --git a/image/manifest_test.go b/image/manifest_test.go index 1a6ee21..1657ad0 100644 --- a/image/manifest_test.go +++ b/image/manifest_test.go @@ -27,6 +27,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/opencontainers/go-digest" + "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" bz2 "github.com/dsnet/compress/bzip2" @@ -141,7 +142,7 @@ func testUnpackLayer(t *testing.T, compression string, invalid bool) { } testManifest := manifest{ - Layers: []descriptor{descriptor{ + Layers: []v1.Descriptor{v1.Descriptor{ MediaType: mediatype, Digest: digester.Digest(), }}, @@ -210,7 +211,7 @@ func TestUnpackLayerRemovePartialyUnpackedFile(t *testing.T) { } testManifest := manifest{ - Layers: []descriptor{descriptor{ + Layers: []v1.Descriptor{v1.Descriptor{ MediaType: "application/vnd.oci.image.layer.v1.tar+gzip", Digest: digester.Digest(), }}, diff --git a/image/walker.go b/image/walker.go index 3ef5e8b..8bf369f 100644 --- a/image/walker.go +++ b/image/walker.go @@ -22,6 +22,7 @@ import ( "path/filepath" "sync" + "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) @@ -40,7 +41,7 @@ type walker interface { // get will copy an arbitrary blob, defined by desc, in to dst. returns // the number of bytes copied on success. - get(desc descriptor, dst io.Writer) (int64, error) + get(desc v1.Descriptor, dst io.Writer) (int64, error) } // tarWalker exposes access to image layouts in a tar file. @@ -87,11 +88,11 @@ loop: return nil } -func (w *tarWalker) get(desc descriptor, dst io.Writer) (int64, error) { +func (w *tarWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) { var bytes int64 done := false - expectedPath := filepath.Join("blobs", desc.algo(), desc.hash()) + expectedPath := filepath.Join("blobs", string(desc.Digest.Algorithm()), desc.Digest.Hex()) f := func(path string, info os.FileInfo, rdr io.Reader) error { var err error @@ -161,8 +162,8 @@ func (w *pathWalker) walk(f walkFunc) error { }) } -func (w *pathWalker) get(desc descriptor, dst io.Writer) (int64, error) { - name := filepath.Join(w.root, "blobs", desc.algo(), desc.hash()) +func (w *pathWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) { + name := filepath.Join(w.root, "blobs", string(desc.Digest.Algorithm()), desc.Digest.Hex()) info, err := os.Stat(name) if err != nil {