more robust manifest <-> tarball handling
This commit is contained in:
parent
10dc856e92
commit
7f2293859b
@ -15,13 +15,13 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
_manifestJSON = "manifest.json"
|
_manifestJSON = "manifest.json"
|
||||||
_layerSuffix = "/layer.tar"
|
_tarSuffix = ".tar"
|
||||||
_whReaddir = ".wh..wh..opq"
|
_whReaddir = ".wh..wh..opq"
|
||||||
_whPrefix = ".wh."
|
_whPrefix = ".wh."
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errBadManifest = errors.New("bad or missing manifest.json")
|
errBadManifest = errors.New("bad manifest.json")
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -63,7 +63,7 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) {
|
|||||||
if err := dec.Decode(&manifest); err != nil {
|
if err := dec.Decode(&manifest); err != nil {
|
||||||
return fmt.Errorf("decode %s: %w", _manifestJSON, err)
|
return fmt.Errorf("decode %s: %w", _manifestJSON, err)
|
||||||
}
|
}
|
||||||
case strings.HasSuffix(hdr.Name, _layerSuffix):
|
case strings.HasSuffix(hdr.Name, _tarSuffix):
|
||||||
here, err := rd.Seek(0, io.SeekCurrent)
|
here, err := rd.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -72,8 +72,8 @@ func Flatten(rd io.ReadSeeker, w io.Writer) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(manifest) == 0 || len(layerOffsets) != len(manifest[0].Layers) {
|
if err := validateManifest(layerOffsets, manifest); err != nil {
|
||||||
return errBadManifest
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumerate layers the way they would be laid down in the image
|
// enumerate layers the way they would be laid down in the image
|
||||||
@ -228,6 +228,21 @@ func whiteoutDirs(whreaddir map[string]int, nlayers int) []*tree {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateManifest
|
||||||
|
func validateManifest(layerOffsets map[string]int64, manifest dockerManifestJSON) error {
|
||||||
|
if len(manifest) == 0 {
|
||||||
|
return fmt.Errorf("empty or missing manifest")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, layer := range manifest[0].Layers {
|
||||||
|
if _, ok := layerOffsets[layer]; !ok {
|
||||||
|
return fmt.Errorf("%s defined in manifest, missing in tarball", layer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// openTargz creates a tar reader from a targzip or tar.
|
// openTargz creates a tar reader from a targzip or tar.
|
||||||
//
|
//
|
||||||
// It will try to open a gzip stream, and, if that fails, silently fall back to
|
// It will try to open a gzip stream, and, if that fails, silently fall back to
|
||||||
|
@ -44,10 +44,15 @@ func TestRootFS(t *testing.T) {
|
|||||||
image: tarball{manifest{}},
|
image: tarball{manifest{}},
|
||||||
want: []extractable{},
|
want: []extractable{},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "no manifest",
|
||||||
|
image: tarball{},
|
||||||
|
wantErr: "empty or missing manifest",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "missing layer",
|
name: "missing layer",
|
||||||
image: tarball{manifest{"layer0/layer.tar"}},
|
image: tarball{manifest{"layer0/layer.tar"}},
|
||||||
wantErr: "bad or missing manifest.json",
|
wantErr: "layer0/layer.tar defined in manifest, missing in tarball",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "basic file overwrite, layer order mixed",
|
name: "basic file overwrite, layer order mixed",
|
||||||
|
Loading…
Reference in New Issue
Block a user