From d24ce0a33f99411330d5d0686f6ee63c9dfdb68c Mon Sep 17 00:00:00 2001
From: Ed Santiago <santiago@redhat.com>
Date: Mon, 18 Oct 2021 15:00:35 -0600
Subject: [PATCH] Add test for system connection

First a basic (connectionless) one to make sure we 'add', 'ls',
and 'rm' work; then an actual one with a service; then (if
ssh to localhost is set up and works) test ssh

Requires a little trickery to work around the CI definition
of $PODMAN, which includes "--url /path/to/sock", which
overrides podman's detection of whether to use a connection
or not.

Signed-off-by: Ed Santiago <santiago@redhat.com>
---
 test/system/272-system-connection.bats | 159 +++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100644 test/system/272-system-connection.bats

diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats
new file mode 100644
index 0000000000..5a90d93989
--- /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