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 })