mirror of
https://github.com/anchore/syft.git
synced 2026-11-03 16:06:36 +01:00
revert: drop the squash-only image read and bump stereoscope
stereoscope is replacing `image.WithImageSquashOnly` with lazy layer squashes, where every layer keeps a usable squash. That removes the need for `GetSourceConfig.WithImageSquashOnly` and the scope guard in `FileResolver`, so both go. - bumps stereoscope to `feat/lazy-layer-squashes` (anchore/stereoscope `43c8f7e`), pending that PR merging Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
@@ -57,14 +57,6 @@ func (c *GetSourceConfig) WithBasePath(basePath string) *GetSourceConfig {
|
||||
return c
|
||||
}
|
||||
|
||||
// WithImageSquashOnly reads container images keeping only the image squash, which cuts memory sharply on
|
||||
// images with many layers. Only use it when the source will be resolved with source.SquashedScope:
|
||||
// any other scope returns an error from FileResolver.
|
||||
func (c *GetSourceConfig) WithImageSquashOnly(squashOnly bool) *GetSourceConfig {
|
||||
c.SourceProviderConfig = c.SourceProviderConfig.WithImageSquashOnly(squashOnly)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *GetSourceConfig) WithSources(sources ...string) *GetSourceConfig {
|
||||
c.Sources = sources
|
||||
return c
|
||||
|
||||
@@ -15,10 +15,6 @@ type Config struct {
|
||||
Exclude source.ExcludeConfig
|
||||
DigestAlgorithms []crypto.Hash
|
||||
BasePath string
|
||||
// ImageSquashOnly reads container images keeping only the image squash, dropping the squash every
|
||||
// lower layer would otherwise hold. This cuts memory sharply on images with many layers, but the
|
||||
// resulting source only supports the squashed scope.
|
||||
ImageSquashOnly bool
|
||||
}
|
||||
|
||||
func (c *Config) WithAlias(alias source.Alias) *Config {
|
||||
@@ -51,11 +47,6 @@ func (c *Config) WithBasePath(basePath string) *Config {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) WithImageSquashOnly(squashOnly bool) *Config {
|
||||
c.ImageSquashOnly = squashOnly
|
||||
return c
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
DigestAlgorithms: []crypto.Hash{
|
||||
|
||||
@@ -67,9 +67,8 @@ func stereoscopeSourceProviders(userInput string, cfg *Config) collections.Tagge
|
||||
Platform: cfg.Platform,
|
||||
Registry: registry,
|
||||
},
|
||||
Alias: cfg.Alias,
|
||||
Exclude: cfg.Exclude,
|
||||
ImageSquashOnly: cfg.ImageSquashOnly,
|
||||
Alias: cfg.Alias,
|
||||
Exclude: cfg.Exclude,
|
||||
})
|
||||
return stereoscopeProviders
|
||||
}
|
||||
|
||||
@@ -99,10 +99,6 @@ func (s stereoscopeImageSource) FileResolver(scope source.Scope) (file.Resolver,
|
||||
var res file.Resolver
|
||||
var err error
|
||||
|
||||
if scope != source.SquashedScope && !hasLayerSquashes(s.image) {
|
||||
return nil, fmt.Errorf("the %q scope needs every layer's squashed tree, but the image was read keeping only the image squash", scope)
|
||||
}
|
||||
|
||||
switch scope {
|
||||
case source.SquashedScope:
|
||||
res, err = fileresolver.NewFromContainerImageSquash(s.image)
|
||||
@@ -126,17 +122,6 @@ func (s stereoscopeImageSource) FileResolver(scope source.Scope) (file.Resolver,
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// hasLayerSquashes reports whether every layer kept its squashed tree, which is not the case for an image
|
||||
// read with image.WithImageSquashOnly (only the top layer keeps one).
|
||||
func hasLayerSquashes(img *image.Image) bool {
|
||||
for _, l := range img.Layers {
|
||||
if l.SquashedTree == nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s stereoscopeImageSource) Close() error {
|
||||
if s.image == nil {
|
||||
return nil
|
||||
|
||||
@@ -15,8 +15,6 @@ type ProviderConfig struct {
|
||||
StereoscopeImageProviderConfig stereoscope.ImageProviderConfig
|
||||
Exclude source.ExcludeConfig
|
||||
Alias source.Alias
|
||||
// ImageSquashOnly reads the image keeping only the image squash, see image.WithImageSquashOnly
|
||||
ImageSquashOnly bool
|
||||
}
|
||||
|
||||
type stereoscopeImageSourceProvider struct {
|
||||
@@ -31,10 +29,6 @@ func (l stereoscopeImageSourceProvider) Name() string {
|
||||
}
|
||||
|
||||
func (l stereoscopeImageSourceProvider) Provide(ctx context.Context) (source.Source, error) {
|
||||
if l.cfg.ImageSquashOnly {
|
||||
// scoped to this read only, the caller's ctx may be shared with reads that need every layer squash
|
||||
ctx = image.WithImageSquashOnly(ctx)
|
||||
}
|
||||
img, err := l.stereoscopeProvider.Provide(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package stereoscopesource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/v1/random"
|
||||
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/stereoscope"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func Test_stereoscopeImageSourceProvider_imageSquashOnly(t *testing.T) {
|
||||
img, err := random.Image(1024, 3)
|
||||
require.NoError(t, err)
|
||||
tag, err := name.NewTag("localhost/squash-only:latest")
|
||||
require.NoError(t, err)
|
||||
archive := filepath.Join(t.TempDir(), "image.tar")
|
||||
require.NoError(t, tarball.WriteToFile(archive, tag, img))
|
||||
|
||||
provide := func(t *testing.T, squashOnly bool) source.Source {
|
||||
providers := Providers(ProviderConfig{
|
||||
StereoscopeImageProviderConfig: stereoscope.ImageProviderConfig{UserInput: archive},
|
||||
ImageSquashOnly: squashOnly,
|
||||
})
|
||||
for _, p := range providers {
|
||||
if p.Value.Name() != image.DockerTarballSource {
|
||||
continue
|
||||
}
|
||||
src, err := p.Value.Provide(context.Background())
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { require.NoError(t, src.Close()) })
|
||||
return src
|
||||
}
|
||||
t.Fatalf("no %s provider", image.DockerTarballSource)
|
||||
return nil
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
squashOnly bool
|
||||
scope source.Scope
|
||||
wantErr require.ErrorAssertionFunc
|
||||
}{
|
||||
{name: "full read, squashed", scope: source.SquashedScope, wantErr: require.NoError},
|
||||
{name: "full read, all layers", scope: source.AllLayersScope, wantErr: require.NoError},
|
||||
{name: "full read, deep squashed", scope: source.DeepSquashedScope, wantErr: require.NoError},
|
||||
{name: "squash only, squashed", squashOnly: true, scope: source.SquashedScope, wantErr: require.NoError},
|
||||
// the per-layer resolvers would dereference the dropped layer squashes, so refuse up front
|
||||
{name: "squash only, all layers", squashOnly: true, scope: source.AllLayersScope, wantErr: require.Error},
|
||||
{name: "squash only, deep squashed", squashOnly: true, scope: source.DeepSquashedScope, wantErr: require.Error},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := provide(t, tt.squashOnly).FileResolver(tt.scope)
|
||||
tt.wantErr(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user