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