From 56410674b7725aad284a4fbf2490e9478d70d465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Wed, 28 May 2025 22:17:58 +0200 Subject: [PATCH 1/3] Fix some comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miloslav Trmač --- integration/utils_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/integration/utils_test.go b/integration/utils_test.go index ecd89c5e..326a4507 100644 --- a/integration/utils_test.go +++ b/integration/utils_test.go @@ -55,7 +55,7 @@ func consumeAndLogOutputs(t *testing.T, id string, cmd *exec.Cmd) { } // combinedOutputOfCommand runs a command as if exec.Command().CombinedOutput(), verifies that the exit status is 0, and returns the output, -// or terminates c on failure. +// or terminates t on failure. func combinedOutputOfCommand(t *testing.T, name string, args ...string) string { t.Logf("Running %s %s", name, strings.Join(args, " ")) out, err := exec.Command(name, args...).CombinedOutput() @@ -64,8 +64,7 @@ func combinedOutputOfCommand(t *testing.T, name string, args ...string) string { } // assertSkopeoSucceeds runs a skopeo command as if exec.Command().CombinedOutput, verifies that the exit status is 0, -// and optionally that the output matches a multi-line regexp if it is nonempty; -// or terminates c on failure +// and optionally that the output matches a multi-line regexp if it is nonempty func assertSkopeoSucceeds(t *testing.T, regexp string, args ...string) { t.Logf("Running %s %s", skopeoBinary, strings.Join(args, " ")) out, err := exec.Command(skopeoBinary, args...).CombinedOutput() @@ -75,9 +74,8 @@ func assertSkopeoSucceeds(t *testing.T, regexp string, args ...string) { } } -// assertSkopeoFails runs a skopeo command as if exec.Command().CombinedOutput, verifies that the exit status is 0, -// and that the output matches a multi-line regexp; -// or terminates c on failure +// assertSkopeoFails runs a skopeo command as if exec.Command().CombinedOutput, verifies that the exit status is not 0, +// and that the output matches a multi-line regexp func assertSkopeoFails(t *testing.T, regexp string, args ...string) { t.Logf("Running %s %s", skopeoBinary, strings.Join(args, " ")) out, err := exec.Command(skopeoBinary, args...).CombinedOutput() @@ -86,14 +84,14 @@ func assertSkopeoFails(t *testing.T, regexp string, args ...string) { } // runCommandWithInput runs a command as if exec.Command(), sending it the input to stdin, -// and verifies that the exit status is 0, or terminates c on failure. +// and verifies that the exit status is 0, or terminates t on failure. func runCommandWithInput(t *testing.T, input string, name string, args ...string) { cmd := exec.Command(name, args...) runExecCmdWithInput(t, cmd, input) } // runExecCmdWithInput runs an exec.Cmd, sending it the input to stdin, -// and verifies that the exit status is 0, or terminates c on failure. +// and verifies that the exit status is 0, or terminates t on failure. func runExecCmdWithInput(t *testing.T, cmd *exec.Cmd, input string) { t.Logf("Running %s %s", cmd.Path, strings.Join(cmd.Args, " ")) consumeAndLogOutputs(t, cmd.Path+" "+strings.Join(cmd.Args, " "), cmd) From 8be40c376ba65c77900a7ce09724e94eddbb84a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Wed, 28 May 2025 22:26:25 +0200 Subject: [PATCH 2/3] Fix the "missing image" check when reading oci: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miloslav Trmač --- cmd/skopeo/utils.go | 3 ++- integration/copy_test.go | 2 ++ integration/utils_test.go | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index bf277e3a..a14e0a08 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -419,9 +419,10 @@ func promptForPassphrase(privateKeyFile string, stdin, stdout *os.File) (string, // authentication error, an I/O error etc.) // TODO drive this into containers/image properly func isNotFoundImageError(err error) bool { + var layoutImageNotFoundError ocilayout.ImageNotFoundError return isDockerManifestUnknownError(err) || errors.Is(err, storage.ErrNoSuchImage) || - errors.Is(err, ocilayout.ImageNotFoundError{}) + errors.As(err, &layoutImageNotFoundError) } // isDockerManifestUnknownError is a copy of code from containers/image, diff --git a/integration/copy_test.go b/integration/copy_test.go index 8f7667c4..56f30c5f 100644 --- a/integration/copy_test.go +++ b/integration/copy_test.go @@ -497,6 +497,8 @@ func (s *copySuite) TestCopySimple() { assertSkopeoSucceeds(t, "", "copy", "docker://registry.k8s.io/pause:latest", "oci:"+ociDest+":"+ociImgName) _, err := os.Stat(ociDest) require.NoError(t, err) + // copy exits with status 2 if the image is not found within the container, in some transports. + assertSkopeoFailsWithStatus(t, 2, "copy", "oci:"+ociDest+":thisdoesnotexist", "dir:"+t.TempDir()) // docker v2s2 -> OCI image layout without image name ociDest = "pause-latest-noimage" diff --git a/integration/utils_test.go b/integration/utils_test.go index 326a4507..1d8dfc55 100644 --- a/integration/utils_test.go +++ b/integration/utils_test.go @@ -83,6 +83,16 @@ func assertSkopeoFails(t *testing.T, regexp string, args ...string) { assert.Regexp(t, "(?s)"+regexp, string(out)) // (?s) : '.' will also match newlines } +// assertSkopeoFailsWithStatus runs a skopeo command as if exec.Command().CombinedOutput, +// and verifies that it fails with a specific exit status. +func assertSkopeoFailsWithStatus(t *testing.T, status int, args ...string) { + t.Logf("Running %s %s", skopeoBinary, strings.Join(args, " ")) + _, err := exec.Command(skopeoBinary, args...).CombinedOutput() + var exitErr *exec.ExitError + require.ErrorAs(t, err, &exitErr) + assert.Equal(t, status, exitErr.ExitCode()) +} + // runCommandWithInput runs a command as if exec.Command(), sending it the input to stdin, // and verifies that the exit status is 0, or terminates t on failure. func runCommandWithInput(t *testing.T, input string, name string, args ...string) { From bc3c2c8246310da1516c9948c8b826207b48b2d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Wed, 28 May 2025 22:30:23 +0200 Subject: [PATCH 3/3] Also exit with status 2 for missing tags in oci-archive: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No tests because we aren't testing oci-archive: anywhere else either. Signed-off-by: Miloslav Trmač --- cmd/skopeo/utils.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/skopeo/utils.go b/cmd/skopeo/utils.go index a14e0a08..77ce7704 100644 --- a/cmd/skopeo/utils.go +++ b/cmd/skopeo/utils.go @@ -13,6 +13,7 @@ import ( "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/directory" "github.com/containers/image/v5/manifest" + ociarchive "github.com/containers/image/v5/oci/archive" ocilayout "github.com/containers/image/v5/oci/layout" "github.com/containers/image/v5/pkg/compression" "github.com/containers/image/v5/storage" @@ -420,9 +421,11 @@ func promptForPassphrase(privateKeyFile string, stdin, stdout *os.File) (string, // TODO drive this into containers/image properly func isNotFoundImageError(err error) bool { var layoutImageNotFoundError ocilayout.ImageNotFoundError + var archiveImageNotFoundError ociarchive.ImageNotFoundError return isDockerManifestUnknownError(err) || errors.Is(err, storage.ErrNoSuchImage) || - errors.As(err, &layoutImageNotFoundError) + errors.As(err, &layoutImageNotFoundError) || + errors.As(err, &archiveImageNotFoundError) } // isDockerManifestUnknownError is a copy of code from containers/image,