Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle ancient empty docker layers #522

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
addStackerLogSentinel(log.NewEntry(log.Log.(*log.Logger))).Infof(msg, v...)
}

func Warnf(msg string, v ...interface{}) {
addStackerLogSentinel(log.NewEntry(log.Log.(*log.Logger))).Warnf(msg, v...)

Check warning on line 50 in pkg/log/log.go

View check run for this annotation

Codecov / codecov/patch

pkg/log/log.go#L49-L50

Added lines #L49 - L50 were not covered by tests
}

func Errorf(msg string, v ...interface{}) {
addStackerLogSentinel(log.NewEntry(log.Log.(*log.Logger))).Errorf(msg, v...)
}
Expand Down
11 changes: 10 additions & 1 deletion pkg/overlay/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import (
"bytes"
"encoding/json"
"io/fs"
"os"
"path"

Expand Down Expand Up @@ -117,7 +118,15 @@
for _, layer := range manifest.Layers {
contents := overlayPath(config.RootFSDir, layer.Digest, "overlay")
if _, err := os.Stat(contents); err != nil {
return "", errors.Wrapf(err, "%s does not exist", contents)
if errors.Is(err, fs.ErrNotExist) {
// some docker layers may be empty tars, so ignore these
// https://github.com/moby/moby/issues/20917#issuecomment-191901912
log.Warnf("%s skipping empty tar layer", layer.Digest)

continue

Check warning on line 126 in pkg/overlay/metadata.go

View check run for this annotation

Codecov / codecov/patch

pkg/overlay/metadata.go#L121-L126

Added lines #L121 - L126 were not covered by tests
}

return "", errors.Wrapf(err, "%s unable to stat", contents)

Check warning on line 129 in pkg/overlay/metadata.go

View check run for this annotation

Codecov / codecov/patch

pkg/overlay/metadata.go#L129

Added line #L129 was not covered by tests
}
lowerdirs = append(lowerdirs, contents)
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/stacker/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@
case types.OCILayer:
fallthrough
case types.DockerLayer:
return setupContainersImageRootfs(o)
err := setupContainersImageRootfs(o)
if err != nil && errors.Is(err, types.ErrEmptyLayers) {
return o.Storage.SetupEmptyRootfs(o.Name)
}
return err

Check warning on line 94 in pkg/stacker/base.go

View check run for this annotation

Codecov / codecov/patch

pkg/stacker/base.go#L90-L94

Added lines #L90 - L94 were not covered by tests
default:
return errors.Errorf("unknown layer type: %v", o.Layer.From.Type)
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/types/layer_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"stackerbuild.io/stacker/pkg/squashfs"
)

var ErrEmptyLayers = errors.New("empty layers")

type LayerType struct {
Type string
Verity squashfs.VerityMetadata
Expand Down Expand Up @@ -60,7 +62,7 @@

func NewLayerTypeManifest(manifest ispec.Manifest) (LayerType, error) {
if len(manifest.Layers) == 0 {
return LayerType{}, errors.Errorf("no existing layers to determine layer type")
return NewLayerType("tar", squashfs.VerityMetadataMissing)

Check warning on line 65 in pkg/types/layer_type.go

View check run for this annotation

Codecov / codecov/patch

pkg/types/layer_type.go#L65

Added line #L65 was not covered by tests
}

switch manifest.Layers[0].MediaType {
Expand Down
25 changes: 25 additions & 0 deletions test/empty-layers.bats
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,28 @@ EOF

[ "$layers0" = "$layers1" ]
}

@test "an image with empty layers" {
umoci init --layout oci
umoci new --image oci:emptylayer
chmod -R a+rw oci

cat > stacker.yaml <<EOF
test_empty_layer:
from:
type: oci
url: oci:emptylayer
EOF
stacker build
}

@test "a real-world docker image with empty/filler layer" {
cat > stacker.yaml <<EOF
image:
from:
type: docker
url: docker://ghcr.io/project-stacker/grafana-oss:10.1.2-ubuntu
EOF
stacker build
}

Loading