From af97950a0678205041e93115b711b7b5c81ab229 Mon Sep 17 00:00:00 2001 From: Eljees <3.14hell@gmail.com> Date: Wed, 29 Jul 2026 21:57:07 +0300 Subject: [PATCH] fix: fall back after image transport init failure Signed-off-by: Eljees <3.14hell@gmail.com> --- pkg/deckoder/extractor/image/image.go | 7 ++++- pkg/deckoder/extractor/image/image_test.go | 36 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/pkg/deckoder/extractor/image/image.go b/pkg/deckoder/extractor/image/image.go index 172e7fd..af6d7cb 100644 --- a/pkg/deckoder/extractor/image/image.go +++ b/pkg/deckoder/extractor/image/image.go @@ -116,7 +116,12 @@ func newSource(ctx context.Context, imageName string, transports []string, sys * var src imageTypes.ImageCloser src, err = image.FromSource(ctx, sys, rawSource) if err != nil { - return nil, nil, fmt.Errorf("failed to initialize: %w", err) + err = fmt.Errorf("failed to initialize: %w", err) + if closeErr := rawSource.Close(); closeErr != nil { + err = fmt.Errorf("%w; failed to close source: %v", err, closeErr) + } + // try next transport + continue } return rawSource, src, nil diff --git a/pkg/deckoder/extractor/image/image_test.go b/pkg/deckoder/extractor/image/image_test.go index f097d63..5509fc2 100644 --- a/pkg/deckoder/extractor/image/image_test.go +++ b/pkg/deckoder/extractor/image/image_test.go @@ -10,6 +10,7 @@ import ( "strings" "testing" + imageTypes "github.com/containers/image/v5/types" "github.com/goodwithtech/dockle/pkg/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -172,6 +173,41 @@ func TestNewImage(t *testing.T) { } } +func TestNewSourceFallsBackAfterInitializationFailure(t *testing.T) { + invalid := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.distribution.manifest.v2+json") + _, _ = w.Write([]byte(`{invalid}`)) + })) + defer invalid.Close() + + manifest, err := ioutil.ReadFile("testdata/manifest.json") + require.NoError(t, err) + valid := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/vnd.docker.distribution.manifest.v2+json") + _, _ = w.Write(manifest) + })) + defer valid.Close() + + transports := []string{ + fmt.Sprintf("docker://%s/", strings.TrimPrefix(invalid.URL, "http://")), + fmt.Sprintf("docker://%s/", strings.TrimPrefix(valid.URL, "http://")), + } + sys := &imageTypes.SystemContext{ + DockerDisableV1Ping: true, + DockerInsecureSkipTLSVerify: imageTypes.OptionalBoolTrue, + } + + rawSource, source, err := newSource( + context.Background(), + "foobar:latest", + transports, + sys, + ) + require.NoError(t, err) + require.NoError(t, source.Close()) + require.NoError(t, rawSource.Close()) +} + func TestRealImage_LayerIDs(t *testing.T) { tests := []struct { name string