diff --git a/internal/cmdrootfs/cmdrootfs.go b/internal/cmdrootfs/cmdrootfs.go index 7c81eef..dea9c4e 100644 --- a/internal/cmdrootfs/cmdrootfs.go +++ b/internal/cmdrootfs/cmdrootfs.go @@ -13,11 +13,6 @@ import ( ) type ( - flattener interface { - Flatten(io.Writer) error - } - - rootfsFactory func(io.ReadSeeker) flattener // Command is "rootfs" command Command struct { @@ -28,7 +23,7 @@ type ( Outfile string `long:"outfile" description:"Output path, stdout is '-'"` } `positional-args:"yes" required:"yes"` - rootfsNew rootfsFactory + flattener func(io.ReadSeeker, io.Writer) error } ) @@ -37,7 +32,7 @@ func (c *Command) Execute(args []string) (err error) { if len(args) != 0 { return errors.New("too many args") } - if c.rootfsNew == nil { + if c.flattener == nil { c.init() } @@ -59,7 +54,7 @@ func (c *Command) Execute(args []string) (err error) { out = outf } - return c.rootfsNew(rd).Flatten(out) + return c.flattener(rd, out) } // init() initializes Command with the default options. @@ -68,7 +63,5 @@ func (c *Command) Execute(args []string) (err error) { // command will initialize itself. func (c *Command) init() { c.BaseCommand.Init() - c.rootfsNew = func(r io.ReadSeeker) flattener { - return rootfs.New(r) - } + c.flattener = rootfs.Flatten } diff --git a/internal/cmdrootfs/cmdrootfs_test.go b/internal/cmdrootfs/cmdrootfs_test.go index 5d207ae..303459c 100644 --- a/internal/cmdrootfs/cmdrootfs_test.go +++ b/internal/cmdrootfs/cmdrootfs_test.go @@ -67,9 +67,7 @@ func TestExecute(t *testing.T) { inf := filepath.Join(dir, tt.infile) c.PositionalArgs.Infile = goflags.Filename(inf) c.PositionalArgs.Outfile = tt.outfile - c.rootfsNew = func(r io.ReadSeeker) flattener { - return &passthrough{r} - } + c.flattener = flattenPassthrough err := c.Execute(nil) if tt.wantErr != "" { @@ -90,9 +88,7 @@ func TestExecute(t *testing.T) { } } -type passthrough struct{ r io.Reader } - -func (p *passthrough) Flatten(w io.Writer) error { - _, err := io.Copy(w, p.r) +func flattenPassthrough(r io.ReadSeeker, w io.Writer) error { + _, err := io.Copy(w, r) return err } diff --git a/lxcconfig/lxcconfig_test.go b/lxcconfig/lxcconfig_test.go index 58ef33f..96230f4 100644 --- a/lxcconfig/lxcconfig_test.go +++ b/lxcconfig/lxcconfig_test.go @@ -13,7 +13,6 @@ import ( ) func TestLXCConfig(t *testing.T) { - tests := []struct { name string docker dockerConfig diff --git a/rootfs/rootfs.go b/rootfs/rootfs.go index c474980..0a44ac5 100644 --- a/rootfs/rootfs.go +++ b/rootfs/rootfs.go @@ -27,11 +27,6 @@ var ( ) type ( - // RootFS accepts a docker layer tarball and flattens it. - RootFS struct { - rd io.ReadSeeker - } - dockerManifestJSON []struct { Layers []string `json:"Layers"` } @@ -42,14 +37,11 @@ type ( } ) -// New creates a new RootFS'er. -func New(rd io.ReadSeeker) *RootFS { - return &RootFS{rd: rd} -} - -// Flatten flattens a docker image to an open tarball. -func (r *RootFS) Flatten(w io.Writer) (err error) { - tr := tar.NewReader(r.rd) +// Flatten flattens a docker image to a tarball. The underlying io.Writer +// should be an open file handle, which the caller is responsible for closing +// themselves +func Flatten(rd io.ReadSeeker, w io.Writer) (err error) { + tr := tar.NewReader(rd) var closer func() error // layerOffsets maps a layer name (a9b123c0daa/layer.tar) to it's offset @@ -74,7 +66,7 @@ func (r *RootFS) Flatten(w io.Writer) (err error) { return fmt.Errorf("decode %s: %w", _manifestJSON, err) } case strings.HasSuffix(hdr.Name, _layerSuffix): - here, err := r.rd.Seek(0, io.SeekCurrent) + here, err := rd.Seek(0, io.SeekCurrent) if err != nil { return err } @@ -107,10 +99,10 @@ func (r *RootFS) Flatten(w io.Writer) (err error) { // iterate over all files, construct `file2layer`, `whreaddir`, `wh` for i, no := range layers { - if _, err := r.rd.Seek(no.offset, io.SeekStart); err != nil { + if _, err := rd.Seek(no.offset, io.SeekStart); err != nil { return err } - tr, closer = openTargz(r.rd) + tr, closer = openTargz(rd) for { hdr, err := tr.Next() if err == io.EOF { @@ -154,10 +146,10 @@ func (r *RootFS) Flatten(w io.Writer) (err error) { }() // iterate through all layers, all files, and write files. for i, no := range layers { - if _, err := r.rd.Seek(no.offset, io.SeekStart); err != nil { + if _, err := rd.Seek(no.offset, io.SeekStart); err != nil { return err } - tr, closer = openTargz(r.rd) + tr, closer = openTargz(rd) for { hdr, err := tr.Next() if err == io.EOF { diff --git a/rootfs/rootfs_test.go b/rootfs/rootfs_test.go index 686e012..f22ba25 100644 --- a/rootfs/rootfs_test.go +++ b/rootfs/rootfs_test.go @@ -186,7 +186,7 @@ func TestRootFS(t *testing.T) { in := bytes.NewReader(tt.image.Buffer().Bytes()) out := bytes.Buffer{} - err := New(in).Flatten(&out) + err := Flatten(in, &out) if tt.wantErr != "" { assert.EqualError(t, err, tt.wantErr) return