diff --git a/image/config.go b/image/config.go index fba599c..ce0d5da 100644 --- a/image/config.go +++ b/image/config.go @@ -18,10 +18,7 @@ import ( "bytes" "encoding/json" "fmt" - "io" "io/ioutil" - "os" - "path/filepath" "strconv" "strings" @@ -33,36 +30,28 @@ import ( type config v1.Image -func findConfig(w walker, d *descriptor) (*config, error) { - var c config - cpath := filepath.Join("blobs", d.algo(), d.hash()) - - switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { - if info.IsDir() || filepath.Clean(path) != cpath { - return nil - } - buf, err := ioutil.ReadAll(r) - if err != nil { - return errors.Wrapf(err, "%s: error reading config", path) - } +func findConfig(get reader, d *descriptor) (*config, error) { + reader, err := get.Get(*d) + if err != nil { + return nil, err + } + defer reader.Close() - if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil { - return errors.Wrapf(err, "%s: config validation failed", path) - } + buf, err := ioutil.ReadAll(reader) + if err != nil { + return nil, errors.Wrapf(err, "%s: error reading config", d.Digest) + } - if err := json.Unmarshal(buf, &c); err != nil { - return err - } + if err := schema.MediaTypeImageConfig.Validate(bytes.NewReader(buf)); err != nil { + return nil, errors.Wrapf(err, "%s: config validation failed", d.Digest) + } - return errEOW - }); err { - case nil: - return nil, fmt.Errorf("%s: config not found", cpath) - case errEOW: - return &c, nil - default: + var c config + if err := json.Unmarshal(buf, &c); err != nil { return nil, err } + + return &c, nil } func (c *config) runtimeSpec(rootfs string) (*specs.Spec, error) { diff --git a/image/descriptor.go b/image/descriptor.go index f19642c..11238b0 100644 --- a/image/descriptor.go +++ b/image/descriptor.go @@ -93,7 +93,7 @@ func findDescriptor(w walker, name string) (*descriptor, error) { } } -func (d *descriptor) validate(w walker, mts []string) error { +func (d *descriptor) validate(get reader, mts []string) error { var found bool for _, mt := range mts { if d.MediaType == mt { @@ -105,7 +105,7 @@ func (d *descriptor) validate(w walker, mts []string) error { return fmt.Errorf("invalid descriptor MediaType %q", d.MediaType) } - rc, err := w.Get(*d) + rc, err := get.Get(*d) if err != nil { return err } diff --git a/image/manifest.go b/image/manifest.go index 39d4395..00368d0 100644 --- a/image/manifest.go +++ b/image/manifest.go @@ -37,41 +37,31 @@ type manifest struct { Layers []descriptor `json:"layers"` } -func findManifest(w walker, d *descriptor) (*manifest, error) { - var m manifest - mpath := filepath.Join("blobs", d.algo(), d.hash()) - - switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { - if info.IsDir() || filepath.Clean(path) != mpath { - return nil - } - - buf, err := ioutil.ReadAll(r) - if err != nil { - return errors.Wrapf(err, "%s: error reading manifest", path) - } +func findManifest(get reader, d *descriptor) (*manifest, error) { + reader, err := get.Get(*d) + if err != nil { + return nil, err + } + defer reader.Close() - if err := schema.MediaTypeManifest.Validate(bytes.NewReader(buf)); err != nil { - return errors.Wrapf(err, "%s: manifest validation failed", path) - } + buf, err := ioutil.ReadAll(reader) + if err != nil { + return nil, errors.Wrapf(err, "%s: error reading manifest", d.Digest) + } - if err := json.Unmarshal(buf, &m); err != nil { - return err - } + if err := schema.MediaTypeManifest.Validate(bytes.NewReader(buf)); err != nil { + return nil, errors.Wrapf(err, "%s: manifest validation failed", d.Digest) + } - return errEOW - }); err { - case nil: - return nil, fmt.Errorf("%s: manifest not found", mpath) - case errEOW: - return &m, nil - default: + var m manifest + if err := json.Unmarshal(buf, &m); err != nil { return nil, err } + return &m, nil } -func (m *manifest) validate(w walker) error { - if err := m.Config.validate(w, []string{v1.MediaTypeImageConfig}); err != nil { +func (m *manifest) validate(get reader) error { + if err := m.Config.validate(get, []string{v1.MediaTypeImageConfig}); err != nil { return errors.Wrap(err, "config validation failed") } @@ -83,7 +73,7 @@ func (m *manifest) validate(w walker) error { } for _, d := range m.Layers { - if err := d.validate(w, validLayerMediaTypes); err != nil { + if err := d.validate(get, validLayerMediaTypes); err != nil { return errors.Wrap(err, "layer validation failed") } } @@ -91,7 +81,7 @@ func (m *manifest) validate(w walker) error { return nil } -func (m *manifest) unpack(w walker, dest string) (retErr error) { +func (m *manifest) unpack(get reader, dest string) (retErr error) { // error out if the dest directory is not empty s, err := ioutil.ReadDir(dest) if err != nil && !os.IsNotExist(err) { @@ -110,26 +100,18 @@ func (m *manifest) unpack(w walker, dest string) (retErr error) { } }() for _, d := range m.Layers { - switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error { - if info.IsDir() { - return nil - } - - dd, err := filepath.Rel(filepath.Join("blobs", d.algo()), filepath.Clean(path)) - if err != nil || d.hash() != dd { - return nil - } + reader, err := get.Get(d) + if err != nil { + return err + } + defer reader.Close() - if err := unpackLayer(dest, r); err != nil { - return errors.Wrap(err, "error extracting layer") - } + if err = unpackLayer(dest, reader); err != nil { + return errors.Wrap(err, "error extracting layer") + } - return errEOW - }); err { - case nil: - return fmt.Errorf("%s: layer not found", dest) - case errEOW: - default: + err = reader.Close() + if err != nil { return err } } diff --git a/image/manifest_test.go b/image/manifest_test.go index b75ac0a..1fa3df0 100644 --- a/image/manifest_test.go +++ b/image/manifest_test.go @@ -111,7 +111,8 @@ func TestUnpackLayer(t *testing.T) { Digest: digester.Digest().String(), }}, } - err = testManifest.unpack(newPathWalker(tmp1), filepath.Join(tmp1, "rootfs")) + get := &layoutReader{root: tmp1} + err = testManifest.unpack(get, filepath.Join(tmp1, "rootfs")) if err != nil { t.Fatal(err) } @@ -171,7 +172,8 @@ func TestUnpackLayerRemovePartialyUnpackedFile(t *testing.T) { Digest: digester.Digest().String(), }}, } - err = testManifest.unpack(newPathWalker(tmp1), filepath.Join(tmp1, "rootfs")) + get := &layoutReader{root: tmp1} + err = testManifest.unpack(get, filepath.Join(tmp1, "rootfs")) if err != nil && !strings.Contains(err.Error(), "duplicate entry for") { t.Fatal(err) }