diff options
-rw-r--r-- | cmd/podman/containers/start.go | 3 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_tag.go | 5 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 4 | ||||
-rw-r--r-- | test/e2e/manifest_test.go | 19 | ||||
-rw-r--r-- | test/system/015-help.bats | 6 | ||||
-rw-r--r-- | test/system/045-start.bats | 4 | ||||
-rw-r--r-- | test/system/272-system-connection.bats | 159 |
7 files changed, 194 insertions, 6 deletions
diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index 1163b9093..8813fc273 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -87,6 +87,9 @@ func validateStart(cmd *cobra.Command, args []string) error { if len(args) == 0 && !startOptions.Latest && !startOptions.All { return errors.New("start requires at least one argument") } + if startOptions.All && startOptions.Latest { + return errors.Errorf("--all and --latest cannot be used together") + } if len(args) > 0 && startOptions.Latest { return errors.Errorf("--latest and containers cannot be used together") } diff --git a/pkg/api/handlers/compat/images_tag.go b/pkg/api/handlers/compat/images_tag.go index 7858298be..5d413a821 100644 --- a/pkg/api/handlers/compat/images_tag.go +++ b/pkg/api/handlers/compat/images_tag.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" + "github.com/containers/common/libimage" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers/utils" api "github.com/containers/podman/v3/pkg/api/types" @@ -16,7 +17,9 @@ func TagImage(w http.ResponseWriter, r *http.Request) { // /v1.xx/images/(name)/tag name := utils.GetName(r) - newImage, _, err := runtime.LibimageRuntime().LookupImage(name, nil) + // Allow tagging manifest list instead of resolving instances from manifest + lookupOptions := &libimage.LookupImageOptions{ManifestList: true} + newImage, _, err := runtime.LibimageRuntime().LookupImage(name, lookupOptions) if err != nil { utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) return diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index d2222c017..8878bf128 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -331,7 +331,9 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri } func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, options entities.ImageTagOptions) error { - image, _, err := ir.Libpod.LibimageRuntime().LookupImage(nameOrID, nil) + // Allow tagging manifest list instead of resolving instances from manifest + lookupOptions := &libimage.LookupImageOptions{ManifestList: true} + image, _, err := ir.Libpod.LibimageRuntime().LookupImage(nameOrID, lookupOptions) if err != nil { return err } diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index 27aaaba48..5978214ff 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -93,6 +93,25 @@ var _ = Describe("Podman manifest", func() { Expect(session.OutputToString()).To(ContainSubstring(imageListARM64InstanceDigest)) }) + It("podman manifest tag", func() { + session := podmanTest.Podman([]string{"manifest", "create", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "add", "foobar", "quay.io/libpod/busybox"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"tag", "foobar", "foobar2"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "inspect", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session2 := podmanTest.Podman([]string{"manifest", "inspect", "foobar2"}) + session2.WaitWithDefaultTimeout() + Expect(session2).Should(Exit(0)) + Expect(session2.OutputToString()).To(Equal(session.OutputToString())) + }) + It("podman manifest add --all", func() { session := podmanTest.Podman([]string{"manifest", "create", "foo"}) session.WaitWithDefaultTimeout() diff --git a/test/system/015-help.bats b/test/system/015-help.bats index 5f38c34a1..b0795b524 100644 --- a/test/system/015-help.bats +++ b/test/system/015-help.bats @@ -86,6 +86,12 @@ function check_help() { run_podman 125 "$@" $cmd -l nonexistent-container is "$output" "Error: .*--latest and \(containers\|pods\|arguments\) cannot be used together" \ "'$command_string' with both -l and container" + + # Combine -l and -a, too (but spell it as --all, because "-a" + # means "attach" in podman container start) + run_podman 125 "$@" $cmd --all --latest + is "$output" "Error: \(--all and --latest cannot be used together\|--all, --latest and containers cannot be used together\|--all, --latest and arguments cannot be used together\|unknown flag\)" \ + "'$command_string' with both --all and --latest" fi fi diff --git a/test/system/045-start.bats b/test/system/045-start.bats index 7e4bbde8d..2ea057cd3 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -36,10 +36,6 @@ load helpers expected="Error: either start all containers or the container(s) provided in the arguments" run_podman 125 start --all 12333 is "$output" "$expected" "start --all, with args, throws error" - if ! is_remote; then - run_podman 125 start --all --latest - is "$output" "$expected" "podman start --all --latest" - fi } @test "podman start --filter - start only containers that match the filter" { diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats new file mode 100644 index 000000000..5a90d9398 --- /dev/null +++ b/test/system/272-system-connection.bats @@ -0,0 +1,159 @@ +#!/usr/bin/env bats -*- bats -*- +# +# tests for podman system connection +# + +load helpers + +# This will be set if we start a local service +_SERVICE_PID= + +function setup() { + if ! is_remote; then + skip "only applicable when running remote" + fi + + basic_setup +} + +function teardown() { + if ! is_remote; then + return + fi + + # In case test function failed to clean up + if [[ -n $_SERVICE_PID ]]; then + run kill $_SERVICE_PID + fi + + # Aaaaargh! When running as root, 'system service' creates a tmpfs + # mount on $root/overlay. This in turn causes cleanup to fail. + mount \ + | grep $PODMAN_TMPDIR \ + | awk '{print $3}' \ + | xargs -l1 --no-run-if-empty umount + + # Remove all system connections + run_podman system connection ls --format json + while read name; do + run_podman system connection rm "$name" + done < <(jq -r '.[].Name' <<<"$output") + + basic_teardown +} + +# Helper function: invokes $PODMAN (which is podman-remote) _without_ --url opt +# +# Needed because, in CI, PODMAN="/path/to/podman-remote --url /path/to/socket" +# which of course overrides podman's detection and use of a connection. +function _run_podman_remote() { + PODMAN=${PODMAN%%--url*} run_podman "$@" +} + +# Very basic test, does not actually connect at any time +@test "podman system connection - basic add / ls / remove" { + run_podman system connection ls + is "$output" "" "system connection ls: no connections" + + c1="c1_$(random_string 15)" + c2="c2_$(random_string 15)" + + run_podman system connection add $c1 tcp://localhost:12345 + run_podman system connection add --default $c2 tcp://localhost:54321 + run_podman system connection ls + is "$output" \ + ".*$c1[ ]\+tcp://localhost:12345[ ]\+false +$c2[ ]\+tcp://localhost:54321[ ]\+true" \ + "system connection ls" + + # Remove default connection; the remaining one should still not be default + run_podman system connection rm $c2 + run_podman system connection ls + is "$output" ".*$c1[ ]\+tcp://localhost:12345[ ]\+false" \ + "system connection ls (after removing default connection)" + + run_podman system connection rm $c1 +} + +# Test tcp socket; requires starting a local server +@test "podman system connection - tcp" { + # Start server + _SERVICE_PORT=$(random_free_port 63000-64999) + + # Add the connection, and run podman info *before* starting the service. + # This should fail. + run_podman system connection add myconnect tcp://localhost:$_SERVICE_PORT + # IMPORTANT NOTE: in CI, podman-remote is tested by setting PODMAN + # to "podman-remote --url sdfsdf". This of course overrides the default + # podman-remote action. Our solution: strip off the "--url xyz" part + # when invoking podman. + _run_podman_remote 125 info + is "$output" \ + "Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \ + "podman info, without active service" + + # Start service. Now podman info should work fine. The %%-remote* + # converts "podman-remote --opts" to just "podman", which is what + # we need for the server. + ${PODMAN%%-remote*} --root ${PODMAN_TMPDIR}/root \ + --runroot ${PODMAN_TMPDIR}/runroot \ + system service -t 99 tcp:localhost:$_SERVICE_PORT & + _SERVICE_PID=$! + wait_for_port localhost $_SERVICE_PORT + + # FIXME: #12023, RemoteSocket is always /run/something +# run_podman info --format '{{.Host.RemoteSocket.Path}}' +# is "$output" "tcp:localhost:$_SERVICE_PORT" \ +# "podman info works, and talks to the correct server" + + _run_podman_remote info --format '{{.Store.GraphRoot}}' + is "$output" "${PODMAN_TMPDIR}/root" \ + "podman info, talks to the right service" + + # Add another connection; make sure it does not get set as default + _run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1)) + _run_podman_remote info --format '{{.Store.GraphRoot}}' + # (Don't bother checking output; we just care about exit status) + + # Stop server. Use 'run' to avoid failing on nonzero exit status + run kill $_SERVICE_PID + run wait $_SERVICE_PID + _SERVICE_PID= + + run_podman system connection rm fakeconnect + run_podman system connection rm myconnect +} + +# If we have ssh access to localhost (unlikely in CI), test that. +@test "podman system connection - ssh" { + rand=$(random_string 20) + echo $rand >$PODMAN_TMPDIR/testfile + + # Can we actually ssh to localhost? + run ssh -q -o BatchMode=yes \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -o CheckHostIP=no \ + localhost \ + cat $PODMAN_TMPDIR/testfile + test "$status" -eq 0 || skip "cannot ssh to localhost" + is "$output" "$rand" "weird! ssh worked, but could not cat local file" + + # OK, ssh works. + # Create a new connection, over ssh, but using existing socket file + # (Remember, we're already podman-remote, there's a service running) + run_podman info --format '{{.Host.RemoteSocket.Path}}' + local socketpath="$output" + run_podman system connection add --socket-path "$socketpath" \ + mysshcon ssh://localhost + is "$output" "" "output from system connection add" + + # debug logs will confirm that we use ssh connection + _run_podman_remote --log-level=debug info --format '{{.Host.RemoteSocket.Path}}' + is "$output" ".*msg=\"SSH Agent Key .*" "we are truly using ssh" + + # Clean up + run_podman system connection rm mysshconn +} + +# vim: filetype=sh |