github.com/containers/podman/v4@v4.9.4/test/e2e/systemd_activate_test.go (about) 1 package integration 2 3 import ( 4 "errors" 5 "io/fs" 6 "net" 7 "net/url" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strconv" 12 "syscall" 13 "time" 14 15 testUtils "github.com/containers/podman/v4/test/utils" 16 podmanUtils "github.com/containers/podman/v4/utils" 17 . "github.com/onsi/ginkgo/v2" 18 . "github.com/onsi/gomega" 19 . "github.com/onsi/gomega/gexec" 20 ) 21 22 var _ = Describe("Systemd activate", func() { 23 var activate string 24 25 BeforeEach(func() { 26 SkipIfRemote("Testing stopped service requires both podman and podman-remote binaries") 27 28 activate, err = exec.LookPath("systemd-socket-activate") 29 if err != nil { 30 activate = "/usr/bin/systemd-socket-activate" 31 } 32 stat, err := os.Stat(activate) 33 switch { 34 case errors.Is(err, fs.ErrNotExist): 35 Skip(activate + " required for systemd activation tests") 36 case stat.Mode()&0111 == 0: 37 Skip("Unable to execute " + activate) 38 case err != nil: 39 Skip(err.Error()) 40 } 41 }) 42 43 It("stop podman.service", func() { 44 // systemd-socket-activate does not support DNS lookups 45 host := "127.0.0.1" 46 port, err := podmanUtils.GetRandomPort() 47 Expect(err).ToNot(HaveOccurred()) 48 addr := net.JoinHostPort(host, strconv.Itoa(port)) 49 50 podmanOptions := podmanTest.makeOptions(nil, false, false) 51 52 systemdArgs := []string{ 53 "-E", "http_proxy", "-E", "https_proxy", "-E", "no_proxy", 54 "-E", "HTTP_PROXY", "-E", "HTTPS_PROXY", "-E", "NO_PROXY", 55 "-E", "XDG_RUNTIME_DIR", 56 "--listen", addr, 57 podmanTest.PodmanBinary} 58 systemdArgs = append(systemdArgs, podmanOptions...) 59 systemdArgs = append(systemdArgs, "system", "service", "--time=0") 60 61 activateSession := testUtils.StartSystemExec(activate, systemdArgs) 62 Expect(activateSession.Exited).ShouldNot(Receive(), "Failed to start podman service") 63 WaitForService(url.URL{Scheme: "tcp", Host: addr}) 64 defer activateSession.Signal(syscall.SIGTERM) 65 66 // Create custom functions for running podman and 67 // podman-remote. This test is a rare exception where both 68 // binaries need to be run in parallel. Usually, the remote 69 // and non-remote details are hidden. Yet we use the 70 // `podmanOptions` above to make sure all settings (root, 71 // runroot, events, tmpdir, etc.) are used as in other e2e 72 // tests. 73 podmanRemote := func(args ...string) *testUtils.PodmanSession { 74 args = append([]string{"--url", "tcp://" + addr}, args...) 75 return testUtils.SystemExec(podmanTest.RemotePodmanBinary, args) 76 } 77 78 podman := func(args ...string) *testUtils.PodmanSession { 79 args = append(podmanOptions, args...) 80 return testUtils.SystemExec(podmanTest.PodmanBinary, args) 81 } 82 83 containerName := "top_" + testUtils.RandomString(8) 84 apiSession := podmanRemote( 85 "create", "--tty", "--name", containerName, "--entrypoint", "top", 86 ALPINE, 87 ) 88 Expect(apiSession).Should(testUtils.ExitCleanly()) 89 defer podman("rm", "-f", containerName) 90 91 apiSession = podmanRemote("start", containerName) 92 Expect(apiSession).Should(testUtils.ExitCleanly()) 93 94 apiSession = podmanRemote("inspect", "--format={{.State.Running}}", containerName) 95 Expect(apiSession).Should(testUtils.ExitCleanly()) 96 Expect(apiSession.OutputToString()).To(Equal("true")) 97 98 // Emulate 'systemd stop podman.service' 99 activateSession.Signal(syscall.SIGTERM) 100 time.Sleep(100 * time.Millisecond) 101 Eventually(activateSession).Should(Exit(0)) 102 103 abiSession := podman("inspect", "--format={{.State.Running}}", containerName) 104 Expect(abiSession).To(testUtils.ExitCleanly()) 105 Expect(abiSession.OutputToString()).To(Equal("true")) 106 }) 107 108 It("invalid systemd file descriptor", func() { 109 host := "127.0.0.1" 110 port, err := podmanUtils.GetRandomPort() 111 Expect(err).ToNot(HaveOccurred()) 112 113 addr := net.JoinHostPort(host, strconv.Itoa(port)) 114 115 // start systemd activation with datagram socket 116 activateSession := testUtils.StartSystemExec(activate, []string{ 117 "--datagram", "--listen", addr, 118 podmanTest.PodmanBinary, 119 "--root=" + filepath.Join(tempdir, "server_root"), 120 "system", "service", 121 "--time=0", 122 }) 123 Expect(activateSession.Exited).ShouldNot(Receive(), "Failed to start podman service") 124 125 // we have to wait for systemd-socket-activate to become ready 126 time.Sleep(1 * time.Second) 127 128 // now dial the socket to start podman 129 conn, err := net.Dial("udp", addr) 130 Expect(err).ToNot(HaveOccurred()) 131 defer conn.Close() 132 _, err = conn.Write([]byte("test")) 133 Expect(err).ToNot(HaveOccurred()) 134 135 // wait for podman to exit 136 activateSession.Wait(10) 137 Expect(activateSession).To(Exit(125)) 138 Expect(activateSession.ErrorToString()).To(ContainSubstring("Error: unexpected fd received from systemd: cannot listen on it")) 139 }) 140 })