github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/system_connection_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"os"
     7  	"os/exec"
     8  	"os/user"
     9  	"path/filepath"
    10  
    11  	. "github.com/containers/podman/v5/test/utils"
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  	. "github.com/onsi/gomega/gbytes"
    15  	. "github.com/onsi/gomega/gexec"
    16  )
    17  
    18  func setupConnectionsConf() {
    19  	// make sure connections are not written to real user config on host
    20  	file := filepath.Join(podmanTest.TempDir, "containers.conf")
    21  	f, err := os.Create(file)
    22  	Expect(err).ToNot(HaveOccurred())
    23  	f.Close()
    24  	os.Setenv("CONTAINERS_CONF", file)
    25  
    26  	file = filepath.Join(podmanTest.TempDir, "connections.conf")
    27  	os.Setenv("PODMAN_CONNECTIONS_CONF", file)
    28  }
    29  
    30  var systemConnectionListCmd = []string{"system", "connection", "ls", "--format", "{{.Name}} {{.URI}} {{.Identity}} {{.Default}} {{.ReadWrite}}"}
    31  var farmListCmd = []string{"farm", "ls", "--format", "{{.Name}} {{.Connections}} {{.Default}} {{.ReadWrite}}"}
    32  
    33  var _ = Describe("podman system connection", func() {
    34  
    35  	BeforeEach(setupConnectionsConf)
    36  
    37  	Context("without running API service", func() {
    38  		It("add ssh://", func() {
    39  			cmd := []string{"system", "connection", "add",
    40  				"--default",
    41  				"--identity", "~/.ssh/id_rsa",
    42  				"QA",
    43  				"ssh://root@podman.test:2222/run/podman/podman.sock",
    44  			}
    45  			session := podmanTest.Podman(cmd)
    46  			session.WaitWithDefaultTimeout()
    47  			Expect(session).Should(ExitCleanly())
    48  			Expect(session.Out.Contents()).Should(BeEmpty())
    49  
    50  			session = podmanTest.Podman(systemConnectionListCmd)
    51  			session.WaitWithDefaultTimeout()
    52  			Expect(session).Should(ExitCleanly())
    53  			Expect(session.OutputToString()).To(Equal("QA ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
    54  
    55  			cmd = []string{"system", "connection", "rename",
    56  				"QA",
    57  				"QE",
    58  			}
    59  			session = podmanTest.Podman(cmd)
    60  			session.WaitWithDefaultTimeout()
    61  			Expect(session).Should(ExitCleanly())
    62  
    63  			session = podmanTest.Podman(systemConnectionListCmd)
    64  			session.WaitWithDefaultTimeout()
    65  			Expect(session).Should(ExitCleanly())
    66  			Expect(session.OutputToString()).To(Equal("QE ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
    67  		})
    68  
    69  		It("add UDS", func() {
    70  			cmd := []string{"system", "connection", "add",
    71  				"QA-UDS",
    72  				"unix:///run/podman/podman.sock",
    73  			}
    74  			session := podmanTest.Podman(cmd)
    75  			session.WaitWithDefaultTimeout()
    76  			Expect(session).Should(Exit(0))
    77  			Expect(session.Out.Contents()).Should(BeEmpty())
    78  			// stderr will probably warn (ENOENT or EACCESS) about socket
    79  			// but it's too unreliable to test for.
    80  
    81  			session = podmanTest.Podman(systemConnectionListCmd)
    82  			session.WaitWithDefaultTimeout()
    83  			Expect(session).Should(ExitCleanly())
    84  			Expect(session.OutputToString()).To(Equal("QA-UDS unix:///run/podman/podman.sock true true"))
    85  
    86  			cmd = []string{"system", "connection", "add",
    87  				"QA-UDS1",
    88  				"--socket-path", "/run/user/podman/podman.sock",
    89  				"unix:///run/podman/podman.sock",
    90  			}
    91  			session = podmanTest.Podman(cmd)
    92  			session.WaitWithDefaultTimeout()
    93  			Expect(session).Should(Exit(0))
    94  			Expect(session.Out.Contents()).Should(BeEmpty())
    95  
    96  			session = podmanTest.Podman(systemConnectionListCmd)
    97  			session.WaitWithDefaultTimeout()
    98  			Expect(session).Should(ExitCleanly())
    99  			Expect(string(session.Out.Contents())).To(Equal(`QA-UDS unix:///run/podman/podman.sock  true true
   100  QA-UDS1 unix:///run/user/podman/podman.sock  false true
   101  `))
   102  		})
   103  
   104  		It("add tcp", func() {
   105  			cmd := []string{"system", "connection", "add",
   106  				"QA-TCP",
   107  				"tcp://localhost:8888",
   108  			}
   109  			session := podmanTest.Podman(cmd)
   110  			session.WaitWithDefaultTimeout()
   111  			Expect(session).Should(ExitCleanly())
   112  			Expect(session.Out.Contents()).Should(BeEmpty())
   113  
   114  			session = podmanTest.Podman(systemConnectionListCmd)
   115  			session.WaitWithDefaultTimeout()
   116  			Expect(session).Should(ExitCleanly())
   117  			Expect(session.OutputToString()).To(Equal("QA-TCP tcp://localhost:8888 true true"))
   118  		})
   119  
   120  		It("add to new farm", func() {
   121  			cmd := []string{"system", "connection", "add",
   122  				"--default",
   123  				"--identity", "~/.ssh/id_rsa",
   124  				"--farm", "farm1",
   125  				"QA",
   126  				"ssh://root@podman.test:2222/run/podman/podman.sock",
   127  			}
   128  			session := podmanTest.Podman(cmd)
   129  			session.WaitWithDefaultTimeout()
   130  			Expect(session).Should(ExitCleanly())
   131  			Expect(session.Out.Contents()).Should(BeEmpty())
   132  
   133  			session = podmanTest.Podman(systemConnectionListCmd)
   134  			session.WaitWithDefaultTimeout()
   135  			Expect(session).Should(ExitCleanly())
   136  			Expect(session.OutputToString()).To(Equal("QA ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
   137  			session = podmanTest.Podman(farmListCmd)
   138  			session.WaitWithDefaultTimeout()
   139  			Expect(session).Should(ExitCleanly())
   140  			Expect(session.OutputToString()).To(Equal("farm1 [QA] true true"))
   141  		})
   142  
   143  		It("add to existing farm", func() {
   144  			// create empty farm
   145  			cmd := []string{"farm", "create", "empty-farm"}
   146  			session := podmanTest.Podman(cmd)
   147  			session.WaitWithDefaultTimeout()
   148  			Expect(session).Should(ExitCleanly())
   149  			Expect(session.Out.Contents()).Should(ContainSubstring("Farm \"empty-farm\" created"))
   150  
   151  			cmd = []string{"system", "connection", "add",
   152  				"--default",
   153  				"--identity", "~/.ssh/id_rsa",
   154  				"--farm", "empty-farm",
   155  				"QA",
   156  				"ssh://root@podman.test:2222/run/podman/podman.sock",
   157  			}
   158  			session = podmanTest.Podman(cmd)
   159  			session.WaitWithDefaultTimeout()
   160  			Expect(session).Should(ExitCleanly())
   161  			Expect(session.Out.Contents()).Should(BeEmpty())
   162  
   163  			session = podmanTest.Podman(systemConnectionListCmd)
   164  			session.WaitWithDefaultTimeout()
   165  			Expect(session).Should(ExitCleanly())
   166  			Expect(session.OutputToString()).To(Equal("QA ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
   167  			session = podmanTest.Podman(farmListCmd)
   168  			session.WaitWithDefaultTimeout()
   169  			Expect(session).Should(ExitCleanly())
   170  			Expect(session.OutputToString()).To(Equal("empty-farm [QA] true true"))
   171  		})
   172  
   173  		It("removing connection should remove from farm also", func() {
   174  			cmd := []string{"system", "connection", "add",
   175  				"--default",
   176  				"--identity", "~/.ssh/id_rsa",
   177  				"--farm", "farm1",
   178  				"QA",
   179  				"ssh://root@podman.test:2222/run/podman/podman.sock",
   180  			}
   181  			session := podmanTest.Podman(cmd)
   182  			session.WaitWithDefaultTimeout()
   183  			Expect(session).Should(ExitCleanly())
   184  			Expect(session.Out.Contents()).Should(BeEmpty())
   185  
   186  			session = podmanTest.Podman(systemConnectionListCmd)
   187  			session.WaitWithDefaultTimeout()
   188  			Expect(session).Should(ExitCleanly())
   189  			Expect(session.OutputToString()).To(Equal("QA ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true"))
   190  			session = podmanTest.Podman(farmListCmd)
   191  			session.WaitWithDefaultTimeout()
   192  			Expect(session).Should(ExitCleanly())
   193  			Expect(session.OutputToString()).To(Equal("farm1 [QA] true true"))
   194  
   195  			// Remove the QA connection
   196  			session = podmanTest.Podman([]string{"system", "connection", "remove", "QA"})
   197  			session.WaitWithDefaultTimeout()
   198  			Expect(session).Should(ExitCleanly())
   199  			Expect(session.Out.Contents()).Should(BeEmpty())
   200  
   201  			session = podmanTest.Podman(systemConnectionListCmd)
   202  			session.WaitWithDefaultTimeout()
   203  			Expect(session).Should(ExitCleanly())
   204  			Expect(session.OutputToString()).To(Equal(""))
   205  			session = podmanTest.Podman(farmListCmd)
   206  			session.WaitWithDefaultTimeout()
   207  			Expect(session).Should(ExitCleanly())
   208  			Expect(session.OutputToString()).To(Equal("farm1 [] true true"))
   209  		})
   210  
   211  		It("remove", func() {
   212  			session := podmanTest.Podman([]string{"system", "connection", "add",
   213  				"--default",
   214  				"--identity", "~/.ssh/id_rsa",
   215  				"QA",
   216  				"ssh://root@podman.test:2222/run/podman/podman.sock",
   217  			})
   218  			session.WaitWithDefaultTimeout()
   219  			Expect(session).Should(ExitCleanly())
   220  
   221  			// two passes to test that removing non-existent connection is not an error
   222  			for i := 0; i < 2; i++ {
   223  				session = podmanTest.Podman([]string{"system", "connection", "remove", "QA"})
   224  				session.WaitWithDefaultTimeout()
   225  				Expect(session).Should(ExitCleanly())
   226  				Expect(session.Out.Contents()).Should(BeEmpty())
   227  
   228  				session = podmanTest.Podman(systemConnectionListCmd)
   229  				session.WaitWithDefaultTimeout()
   230  				Expect(session).Should(ExitCleanly())
   231  				Expect(session.OutputToString()).To(Equal(""))
   232  			}
   233  		})
   234  
   235  		It("remove --all", func() {
   236  			session := podmanTest.Podman([]string{"system", "connection", "add",
   237  				"--default",
   238  				"--identity", "~/.ssh/id_rsa",
   239  				"QA",
   240  				"ssh://root@podman.test:2222/run/podman/podman.sock",
   241  			})
   242  			session.WaitWithDefaultTimeout()
   243  			Expect(session).Should(ExitCleanly())
   244  
   245  			session = podmanTest.Podman([]string{"system", "connection", "remove", "--all"})
   246  			session.WaitWithDefaultTimeout()
   247  			Expect(session).Should(ExitCleanly())
   248  			Expect(session.Out.Contents()).Should(BeEmpty())
   249  			Expect(session.Err.Contents()).Should(BeEmpty())
   250  
   251  			session = podmanTest.Podman([]string{"system", "connection", "list"})
   252  			session.WaitWithDefaultTimeout()
   253  			Expect(session).Should(ExitCleanly())
   254  			Expect(session.OutputToStringArray()).To(HaveLen(1))
   255  		})
   256  
   257  		It("default", func() {
   258  			for _, name := range []string{"devl", "qe"} {
   259  				cmd := []string{"system", "connection", "add",
   260  					"--default",
   261  					"--identity", "~/.ssh/id_rsa",
   262  					name,
   263  					"ssh://root@podman.test:2222/run/podman/podman.sock",
   264  				}
   265  				session := podmanTest.Podman(cmd)
   266  				session.WaitWithDefaultTimeout()
   267  				Expect(session).Should(ExitCleanly())
   268  			}
   269  
   270  			cmd := []string{"system", "connection", "default", "devl"}
   271  			session := podmanTest.Podman(cmd)
   272  			session.WaitWithDefaultTimeout()
   273  			Expect(session).Should(ExitCleanly())
   274  			Expect(session.Out.Contents()).Should(BeEmpty())
   275  
   276  			session = podmanTest.Podman(systemConnectionListCmd)
   277  			session.WaitWithDefaultTimeout()
   278  			Expect(session).Should(ExitCleanly())
   279  			Expect(string(session.Out.Contents())).To(Equal(`devl ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa true true
   280  qe ssh://root@podman.test:2222/run/podman/podman.sock ~/.ssh/id_rsa false true
   281  `))
   282  
   283  			cmd = []string{"system", "connection", "list"}
   284  			session = podmanTest.Podman(cmd)
   285  			session.WaitWithDefaultTimeout()
   286  			Expect(session).Should(ExitCleanly())
   287  			Expect(session.Out).Should(Say("Name *URI *Identity *Default"))
   288  		})
   289  
   290  		It("failed default", func() {
   291  			cmd := []string{"system", "connection", "default", "devl"}
   292  			session := podmanTest.Podman(cmd)
   293  			session.WaitWithDefaultTimeout()
   294  			Expect(session).ShouldNot(ExitCleanly())
   295  			Expect(session.Err).Should(Say("destination is not defined"))
   296  		})
   297  
   298  		It("failed rename", func() {
   299  			cmd := []string{"system", "connection", "rename", "devl", "QE"}
   300  			session := podmanTest.Podman(cmd)
   301  			session.WaitWithDefaultTimeout()
   302  			Expect(session).ShouldNot(ExitCleanly())
   303  			Expect(session.Err).Should(Say("destination is not defined"))
   304  		})
   305  
   306  		It("empty list", func() {
   307  			cmd := []string{"system", "connection", "list"}
   308  			session := podmanTest.Podman(cmd)
   309  			session.WaitWithDefaultTimeout()
   310  			Expect(session).Should(ExitCleanly())
   311  			Expect(session.OutputToStringArray()).Should(HaveLen(1))
   312  			Expect(session.Err.Contents()).Should(BeEmpty())
   313  		})
   314  	})
   315  
   316  	Context("sshd and API services required", func() {
   317  		BeforeEach(func() {
   318  			// These tests are unique in as much as they require podman, podman-remote, systemd and sshd.
   319  			// podman-remote commands will be executed by ginkgo directly.
   320  			SkipIfContainerized("sshd is not available when running in a container")
   321  			SkipIfRemote("connection heuristic requires both podman and podman-remote binaries")
   322  			SkipIfNotRootless(fmt.Sprintf("FIXME: set up ssh keys when root. uid(%d) euid(%d)", os.Getuid(), os.Geteuid()))
   323  			SkipIfSystemdNotRunning("cannot test connection heuristic if systemd is not running")
   324  			SkipIfNotActive("sshd", "cannot test connection heuristic if sshd is not running")
   325  		})
   326  
   327  		It("add ssh:// socket path using connection heuristic", func() {
   328  			u, err := user.Current()
   329  			Expect(err).ShouldNot(HaveOccurred())
   330  
   331  			// Ensure that the remote end uses our built podman
   332  			if os.Getenv("PODMAN_BINARY") == "" {
   333  				err = os.Setenv("PODMAN_BINARY", podmanTest.PodmanBinary)
   334  				Expect(err).ShouldNot(HaveOccurred())
   335  
   336  				defer func() {
   337  					os.Unsetenv("PODMAN_BINARY")
   338  				}()
   339  			}
   340  
   341  			cmd := exec.Command(podmanTest.RemotePodmanBinary,
   342  				"system", "connection", "add",
   343  				"--default",
   344  				"--identity", filepath.Join(u.HomeDir, ".ssh", "id_ed25519"),
   345  				"QA",
   346  				fmt.Sprintf("ssh://%s@localhost", u.Username))
   347  
   348  			session, err := Start(cmd, GinkgoWriter, GinkgoWriter)
   349  			Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("%q failed to execute", podmanTest.RemotePodmanBinary))
   350  			Eventually(session, DefaultWaitTimeout).Should(Exit(0))
   351  			Expect(session.Out.Contents()).Should(BeEmpty())
   352  			Expect(session.Err.Contents()).Should(BeEmpty())
   353  
   354  			cmd = exec.Command(podmanTest.RemotePodmanBinary,
   355  				"--connection", "QA", "ps")
   356  			_, err = Start(cmd, GinkgoWriter, GinkgoWriter)
   357  			Expect(err).ToNot(HaveOccurred())
   358  
   359  			// export the container_host env var and try again
   360  			err = os.Setenv("CONTAINER_HOST", fmt.Sprintf("ssh://%s@localhost", u.Username))
   361  			Expect(err).ToNot(HaveOccurred())
   362  			defer os.Unsetenv("CONTAINER_HOST")
   363  
   364  			cmd = exec.Command(podmanTest.RemotePodmanBinary, "ps")
   365  			_, err = Start(cmd, GinkgoWriter, GinkgoWriter)
   366  			Expect(err).ToNot(HaveOccurred())
   367  
   368  			uri := url.URL{
   369  				Scheme: "ssh",
   370  				User:   url.User(u.Username),
   371  				Host:   "localhost:22",
   372  				Path:   fmt.Sprintf("/run/user/%s/podman/podman.sock", u.Uid),
   373  			}
   374  
   375  			cmd = exec.Command(podmanTest.RemotePodmanBinary, systemConnectionListCmd...)
   376  			lsSession, err := Start(cmd, GinkgoWriter, GinkgoWriter)
   377  			Expect(err).ToNot(HaveOccurred())
   378  			lsSession.Wait(DefaultWaitTimeout)
   379  			Expect(lsSession).Should(Exit(0))
   380  			Expect(string(lsSession.Out.Contents())).To(Equal("QA " + uri.String() + " " + filepath.Join(u.HomeDir, ".ssh", "id_ed25519") + " true true\n"))
   381  		})
   382  	})
   383  })