github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/systemd_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 10 . "github.com/hanks177/podman/v4/test/utils" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/gexec" 14 ) 15 16 var _ = Describe("Podman systemd", func() { 17 var ( 18 tempdir string 19 err error 20 podmanTest *PodmanTestIntegration 21 systemdUnitFile string 22 ) 23 24 BeforeEach(func() { 25 tempdir, err = CreateTempDirInTempDir() 26 if err != nil { 27 os.Exit(1) 28 } 29 podmanTest = PodmanTestCreate(tempdir) 30 podmanTest.Setup() 31 systemdUnitFile = `[Unit] 32 Description=redis container 33 [Service] 34 Restart=always 35 ExecStart=/usr/bin/podman start -a redis 36 ExecStop=/usr/bin/podman stop -t 10 redis 37 KillMode=process 38 [Install] 39 WantedBy=default.target 40 ` 41 }) 42 43 AfterEach(func() { 44 podmanTest.Cleanup() 45 f := CurrentGinkgoTestDescription() 46 processTestResult(f) 47 48 }) 49 50 It("podman start container by systemd", func() { 51 SkipIfRootless("rootless can not write to /etc") 52 SkipIfContainerized("test does not have systemd as pid 1") 53 54 sysFile := ioutil.WriteFile("/etc/systemd/system/redis.service", []byte(systemdUnitFile), 0644) 55 Expect(sysFile).To(BeNil()) 56 defer func() { 57 stop := SystemExec("bash", []string{"-c", "systemctl stop redis"}) 58 os.Remove("/etc/systemd/system/redis.service") 59 SystemExec("bash", []string{"-c", "systemctl daemon-reload"}) 60 Expect(stop).Should(Exit(0)) 61 }() 62 63 create := podmanTest.Podman([]string{"create", "--name", "redis", redis}) 64 create.WaitWithDefaultTimeout() 65 Expect(create).Should(Exit(0)) 66 67 enable := SystemExec("bash", []string{"-c", "systemctl daemon-reload"}) 68 Expect(enable).Should(Exit(0)) 69 70 start := SystemExec("bash", []string{"-c", "systemctl start redis"}) 71 Expect(start).Should(Exit(0)) 72 73 logs := SystemExec("bash", []string{"-c", "journalctl -n 20 -u redis"}) 74 Expect(logs).Should(Exit(0)) 75 76 status := SystemExec("bash", []string{"-c", "systemctl status redis"}) 77 Expect(status.OutputToString()).To(ContainSubstring("active (running)")) 78 }) 79 80 It("podman run container with systemd PID1", func() { 81 ctrName := "testSystemd" 82 run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", UBI_INIT, "/sbin/init"}) 83 run.WaitWithDefaultTimeout() 84 Expect(run).Should(Exit(0)) 85 86 logs := podmanTest.Podman([]string{"logs", ctrName}) 87 logs.WaitWithDefaultTimeout() 88 Expect(logs).Should(Exit(0)) 89 90 // Give container 10 seconds to start 91 started := podmanTest.WaitContainerReady(ctrName, "Reached target Multi-User System.", 30, 1) 92 Expect(started).To(BeTrue()) 93 94 systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"}) 95 systemctl.WaitWithDefaultTimeout() 96 Expect(systemctl).Should(Exit(0)) 97 Expect(systemctl.OutputToString()).To(ContainSubstring("State:")) 98 99 result := podmanTest.Podman([]string{"inspect", ctrName}) 100 result.WaitWithDefaultTimeout() 101 Expect(result).Should(Exit(0)) 102 conData := result.InspectContainerToJSON() 103 Expect(conData).To(HaveLen(1)) 104 Expect(conData[0].Config.SystemdMode).To(BeTrue()) 105 106 // stats not supported w/ CGv1 rootless or containerized 107 if isCgroupsV1() && (isRootless() || isContainerized()) { 108 return 109 } 110 stats := podmanTest.Podman([]string{"stats", "--no-stream", ctrName}) 111 stats.WaitWithDefaultTimeout() 112 Expect(stats).Should(Exit(0)) 113 114 cgroupPath := podmanTest.Podman([]string{"inspect", "--format='{{.State.CgroupPath}}'", ctrName}) 115 cgroupPath.WaitWithDefaultTimeout() 116 Expect(cgroupPath).Should(Exit(0)) 117 Expect(result.OutputToString()).To(Not(ContainSubstring("init.scope"))) 118 }) 119 120 It("podman create container with systemd entrypoint triggers systemd mode", func() { 121 ctrName := "testCtr" 122 run := podmanTest.Podman([]string{"create", "--name", ctrName, "--entrypoint", "/sbin/init", UBI_INIT}) 123 run.WaitWithDefaultTimeout() 124 Expect(run).Should(Exit(0)) 125 126 result := podmanTest.Podman([]string{"inspect", ctrName}) 127 result.WaitWithDefaultTimeout() 128 Expect(result).Should(Exit(0)) 129 conData := result.InspectContainerToJSON() 130 Expect(conData).To(HaveLen(1)) 131 Expect(conData[0].Config.SystemdMode).To(BeTrue()) 132 }) 133 134 It("podman systemd in command triggers systemd mode", func() { 135 containerfile := fmt.Sprintf(`FROM %s 136 RUN mkdir -p /usr/lib/systemd/; touch /usr/lib/systemd/systemd 137 CMD /usr/lib/systemd/systemd`, ALPINE) 138 139 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 140 err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755) 141 Expect(err).To(BeNil()) 142 session := podmanTest.Podman([]string{"build", "-t", "systemd", "--file", containerfilePath, podmanTest.TempDir}) 143 session.WaitWithDefaultTimeout() 144 Expect(session).Should(Exit(0)) 145 146 ctrName := "testCtr" 147 run := podmanTest.Podman([]string{"create", "--name", ctrName, "systemd"}) 148 run.WaitWithDefaultTimeout() 149 Expect(run).Should(Exit(0)) 150 151 result := podmanTest.Podman([]string{"inspect", ctrName}) 152 result.WaitWithDefaultTimeout() 153 Expect(result).Should(Exit(0)) 154 conData := result.InspectContainerToJSON() 155 Expect(conData).To(HaveLen(1)) 156 Expect(conData[0].Config.SystemdMode).To(BeTrue()) 157 }) 158 159 It("podman create container with --uidmap and conmon PidFile accessible", func() { 160 ctrName := "testCtrUidMap" 161 run := podmanTest.Podman([]string{"run", "-d", "--uidmap=0:1:1000", "--name", ctrName, ALPINE, "top"}) 162 run.WaitWithDefaultTimeout() 163 Expect(run).Should(Exit(0)) 164 165 session := podmanTest.Podman([]string{"inspect", "--format", "{{.ConmonPidFile}}", ctrName}) 166 session.WaitWithDefaultTimeout() 167 Expect(session).Should(Exit(0)) 168 169 pidFile := strings.TrimSuffix(session.OutputToString(), "\n") 170 _, err := ioutil.ReadFile(pidFile) 171 Expect(err).To(BeNil()) 172 }) 173 174 It("podman create container with systemd=always triggers systemd mode", func() { 175 ctrName := "testCtr" 176 run := podmanTest.Podman([]string{"create", "--name", ctrName, "--systemd", "always", ALPINE}) 177 run.WaitWithDefaultTimeout() 178 Expect(run).Should(Exit(0)) 179 180 result := podmanTest.Podman([]string{"inspect", ctrName}) 181 result.WaitWithDefaultTimeout() 182 Expect(result).Should(Exit(0)) 183 conData := result.InspectContainerToJSON() 184 Expect(conData).To(HaveLen(1)) 185 Expect(conData[0].Config.SystemdMode).To(BeTrue()) 186 }) 187 188 It("podman run --systemd container should NOT mount /run noexec", func() { 189 session := podmanTest.Podman([]string{"run", "--systemd", "always", ALPINE, "sh", "-c", "mount | grep \"/run \""}) 190 session.WaitWithDefaultTimeout() 191 Expect(session).Should(Exit(0)) 192 193 Expect(session.OutputToString()).To(Not(ContainSubstring("noexec"))) 194 }) 195 196 It("podman run --systemd arg is case insensitive", func() { 197 session := podmanTest.Podman([]string{"run", "--rm", "--systemd", "Always", ALPINE, "echo", "test"}) 198 session.WaitWithDefaultTimeout() 199 Expect(session).Should(Exit(0)) 200 Expect(session.OutputToString()).Should(Equal("test")) 201 202 session = podmanTest.Podman([]string{"run", "--rm", "--systemd", "True", ALPINE, "echo", "test"}) 203 session.WaitWithDefaultTimeout() 204 Expect(session).Should(Exit(0)) 205 Expect(session.OutputToString()).Should(Equal("test")) 206 207 session = podmanTest.Podman([]string{"run", "--rm", "--systemd", "False", ALPINE, "echo", "test"}) 208 session.WaitWithDefaultTimeout() 209 Expect(session).Should(Exit(0)) 210 Expect(session.OutputToString()).Should(Equal("test")) 211 }) 212 })