Skip to content

Commit 404ee9b

Browse files
author
Casey Callendrello
committed
image: accept arbitrary file streams
This allows the image library to handle any ReadSeeker, enabling on-the-fly uncompression. Also, refactor the validate methods to avoid unnecessary copies. Signed-off-by: Casey Callendrello <[email protected]>
1 parent a4708e3 commit 404ee9b

File tree

8 files changed

+125
-126
lines changed

8 files changed

+125
-126
lines changed

cmd/oci-image-tool/create.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ func createHandle(context *cli.Context) error {
4747
v.ref = context.String("ref")
4848
}
4949
if context.IsSet("rootfs") {
50-
v.root = context.String("roofs")
50+
v.root = context.String("rootfs")
51+
} else {
52+
v.root = "rootfs"
5153
}
5254

5355
if v.typ == "" {
@@ -64,7 +66,7 @@ func createHandle(context *cli.Context) error {
6466
err = image.CreateRuntimeBundleLayout(context.Args()[0], context.Args()[1], v.ref, v.root)
6567

6668
case image.TypeImage:
67-
err = image.CreateRuntimeBundle(context.Args()[0], context.Args()[1], v.ref, v.root)
69+
err = image.CreateRuntimeBundleFile(context.Args()[0], context.Args()[1], v.ref, v.root)
6870

6971
default:
7072
err = fmt.Errorf("cannot create %q", v.typ)

cmd/oci-image-tool/unpack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func unpackHandle(context *cli.Context) error {
6060
err = image.UnpackLayout(context.Args()[0], context.Args()[1], v.ref)
6161

6262
case image.TypeImage:
63-
err = image.Unpack(context.Args()[0], context.Args()[1], v.ref)
63+
err = image.UnpackFile(context.Args()[0], context.Args()[1], v.ref)
6464

6565
default:
6666
err = fmt.Errorf("cannot unpack %q", v.typ)

cmd/oci-image-tool/validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func validatePath(name string) error {
100100
case image.TypeImageLayout:
101101
return image.ValidateLayout(name, v.refs, v.stdout)
102102
case image.TypeImage:
103-
return image.Validate(name, v.refs, v.stdout)
103+
return image.ValidateFile(name, v.refs, v.stdout)
104104
}
105105

106106
if len(v.refs) != 0 {

image/descriptor.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,28 +105,23 @@ func (d *descriptor) validate(w walker, mts []string) error {
105105
return fmt.Errorf("invalid descriptor MediaType %q", d.MediaType)
106106
}
107107

108-
rc, err := w.Get(*d)
108+
parsed, err := digest.Parse(d.Digest)
109109
if err != nil {
110110
return err
111111
}
112-
defer rc.Close()
113-
114-
return d.validateContent(rc)
115-
}
116112

117-
func (d *descriptor) validateContent(r io.Reader) error {
118-
parsed, err := digest.Parse(d.Digest)
113+
// Copy the contents of the layer in to the verifier
114+
verifier := parsed.Verifier()
115+
numBytes, err := w.get(*d, verifier)
119116
if err != nil {
120117
return err
121118
}
122119

123-
verifier := parsed.Verifier()
124-
n, err := io.Copy(verifier, r)
125120
if err != nil {
126121
return errors.Wrap(err, "error generating hash")
127122
}
128123

129-
if n != d.Size {
124+
if numBytes != d.Size {
130125
return errors.New("size mismatch")
131126
}
132127

image/image.go

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package image
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"io"
2021
"log"
2122
"os"
2223
"path/filepath"
@@ -31,16 +32,24 @@ func ValidateLayout(src string, refs []string, out *log.Logger) error {
3132
return validate(newPathWalker(src), refs, out)
3233
}
3334

34-
// Validate walks through the given .tar file and validates the manifest
35-
// pointed to by the given refs or returns an error if the validation failed.
36-
func Validate(tarFile string, refs []string, out *log.Logger) error {
35+
// ValidateFile opens the tar file given by the filename, then calls ValidateReader
36+
func ValidateFile(tarFile string, refs []string, out *log.Logger) error {
3737
f, err := os.Open(tarFile)
3838
if err != nil {
3939
return errors.Wrap(err, "unable to open file")
4040
}
4141
defer f.Close()
4242

43-
return validate(newTarWalker(tarFile, f), refs, out)
43+
return Validate(f, refs, out)
44+
}
45+
46+
// Validate walks through a tar stream and validates the manifest.
47+
// * Check that all refs point to extant blobs
48+
// * Checks that all referred blobs are valid
49+
// * Checks that mime-types are correct
50+
// returns error on validation failure
51+
func Validate(r io.ReadSeeker, refs []string, out *log.Logger) error {
52+
return validate(newTarWalker(r), refs, out)
4453
}
4554

4655
var validRefMediaTypes = []string{
@@ -101,17 +110,23 @@ func UnpackLayout(src, dest, ref string) error {
101110
return unpack(newPathWalker(src), dest, ref)
102111
}
103112

104-
// Unpack walks through the given .tar file and, using the layers specified in
105-
// the manifest pointed to by the given ref, unpacks all layers in the given
106-
// destination directory or returns an error if the unpacking failed.
107-
func Unpack(tarFile, dest, ref string) error {
108-
f, err := os.Open(tarFile)
113+
// UnpackFile opens the file pointed by tarFileName and calls Unpack on it.
114+
func UnpackFile(tarFileName, dest, ref string) error {
115+
f, err := os.Open(tarFileName)
109116
if err != nil {
110117
return errors.Wrap(err, "unable to open file")
111118
}
112119
defer f.Close()
113120

114-
return unpack(newTarWalker(tarFile, f), dest, ref)
121+
return Unpack(f, dest, ref)
122+
}
123+
124+
// Unpack walks through the tar stream and, using the layers specified in
125+
// the manifest pointed to by the given ref, unpacks all layers in the given
126+
// destination directory or returns an error if the unpacking failed.
127+
// The destination will be created if it does not exist.
128+
func Unpack(r io.ReadSeeker, dest, refName string) error {
129+
return unpack(newTarWalker(r), dest, refName)
115130
}
116131

117132
func unpack(w walker, dest, refName string) error {
@@ -143,17 +158,23 @@ func CreateRuntimeBundleLayout(src, dest, ref, root string) error {
143158
return createRuntimeBundle(newPathWalker(src), dest, ref, root)
144159
}
145160

146-
// CreateRuntimeBundle walks through the given .tar file and
147-
// creates an OCI runtime bundle in the given destination dest
148-
// or returns an error if the unpacking failed.
149-
func CreateRuntimeBundle(tarFile, dest, ref, root string) error {
161+
// CreateRuntimeBundleFile opens the file pointed by tarFile and calls
162+
// CreateRuntimeBundle.
163+
func CreateRuntimeBundleFile(tarFile, dest, ref, root string) error {
150164
f, err := os.Open(tarFile)
151165
if err != nil {
152166
return errors.Wrap(err, "unable to open file")
153167
}
154168
defer f.Close()
155169

156-
return createRuntimeBundle(newTarWalker(tarFile, f), dest, ref, root)
170+
return createRuntimeBundle(newTarWalker(f), dest, ref, root)
171+
}
172+
173+
// CreateRuntimeBundle walks through the given tar stream and
174+
// creates an OCI runtime bundle in the given destination dest
175+
// or returns an error if the unpacking failed.
176+
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string) error {
177+
return createRuntimeBundle(newTarWalker(r), dest, ref, root)
157178
}
158179

159180
func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
@@ -190,8 +211,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
190211
}
191212
}
192213

193-
err = m.unpack(w, filepath.Join(dest, rootfs))
194-
if err != nil {
214+
if err = m.unpack(w, filepath.Join(dest, rootfs)); err != nil {
195215
return err
196216
}
197217

image/manifest.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ func (m *manifest) validate(w walker) error {
9494
func (m *manifest) unpack(w walker, dest string) (retErr error) {
9595
// error out if the dest directory is not empty
9696
s, err := ioutil.ReadDir(dest)
97-
if err != nil && !os.IsNotExist(err) {
98-
return errors.Wrap(err, "unable to open file") // err contains dest
97+
if err != nil && !os.IsNotExist(err) { // We'll create the dir later
98+
return errors.Wrap(err, "unpack: unable to open dest") // err contains dest
9999
}
100100
if len(s) > 0 {
101101
return fmt.Errorf("%s is not empty", dest)
@@ -121,7 +121,7 @@ func (m *manifest) unpack(w walker, dest string) (retErr error) {
121121
}
122122

123123
if err := unpackLayer(dest, r); err != nil {
124-
return errors.Wrap(err, "error extracting layer")
124+
return errors.Wrap(err, "unpack: error extracting layer")
125125
}
126126

127127
return errEOW

image/reader.go

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)