Merge branch '19099-singularity-container-shell'
[arvados.git] / lib / crunchrun / singularity_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package crunchrun
6
7 import (
8         "os"
9         "os/exec"
10
11         . "gopkg.in/check.v1"
12         check "gopkg.in/check.v1"
13 )
14
15 var _ = Suite(&singularitySuite{})
16
17 type singularitySuite struct {
18         executorSuite
19 }
20
21 func (s *singularitySuite) SetUpSuite(c *C) {
22         _, err := exec.LookPath("singularity")
23         if err != nil {
24                 c.Skip("looks like singularity is not installed")
25         }
26         s.newExecutor = func(c *C) {
27                 var err error
28                 s.executor, err = newSingularityExecutor(c.Logf)
29                 c.Assert(err, IsNil)
30         }
31 }
32
33 func (s *singularitySuite) TearDownSuite(c *C) {
34         if s.executor != nil {
35                 s.executor.Close()
36         }
37 }
38
39 func (s *singularitySuite) TestIPAddress(c *C) {
40         // In production, executor will choose --network=bridge
41         // because uid=0 under arvados-dispatch-cloud. But in test
42         // cases, uid!=0, which means --network=bridge is conditional
43         // on --fakeroot.
44         uuc, err := os.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
45         c.Check(err, check.IsNil)
46         if string(uuc) == "0\n" {
47                 c.Skip("insufficient privileges to run this test case -- `singularity exec --fakeroot` requires /proc/sys/kernel/unprivileged_userns_clone = 1")
48         }
49         s.executor.(*singularityExecutor).fakeroot = true
50         s.executorSuite.TestIPAddress(c)
51 }
52
53 func (s *singularitySuite) TestInject(c *C) {
54         path, err := exec.LookPath("nsenter")
55         if err != nil || path != "/var/lib/arvados/bin/nsenter" {
56                 c.Skip("looks like /var/lib/arvados/bin/nsenter is not installed -- re-run `arvados-server install`?")
57         }
58         s.executorSuite.TestInject(c)
59 }
60
61 var _ = Suite(&singularityStubSuite{})
62
63 // singularityStubSuite tests don't really invoke singularity, so we
64 // can run them even if singularity is not installed.
65 type singularityStubSuite struct{}
66
67 func (s *singularityStubSuite) TestSingularityExecArgs(c *C) {
68         e, err := newSingularityExecutor(c.Logf)
69         c.Assert(err, IsNil)
70         err = e.Create(containerSpec{
71                 WorkingDir:      "/WorkingDir",
72                 Env:             map[string]string{"FOO": "bar"},
73                 BindMounts:      map[string]bindmount{"/mnt": {HostPath: "/hostpath", ReadOnly: true}},
74                 EnableNetwork:   false,
75                 CUDADeviceCount: 3,
76         })
77         c.Check(err, IsNil)
78         e.imageFilename = "/fake/image.sif"
79         cmd := e.execCmd("./singularity")
80         c.Check(cmd.Args, DeepEquals, []string{"./singularity", "exec", "--containall", "--cleanenv", "--pwd=/WorkingDir", "--net", "--network=none", "--nv", "--bind", "/hostpath:/mnt:ro", "/fake/image.sif"})
81         c.Check(cmd.Env, DeepEquals, []string{"SINGULARITYENV_FOO=bar", "SINGULARITY_NO_EVAL=1"})
82 }