Commit 74b01ee3dc
Verified · cmc ci/build: success ci/test: failure
Layout: unified · split
cmd/gitbay-runner/env_test.go +16
| @@ -88,3 +88,19 @@ func TestStepEnvHomeIsNotTheWorkspace(t *testing.T) { | ||
| 88 | 88 | } |
| 89 | 89 | } |
| 90 | 90 | } |
| 91 | ||
| 92 | // podman runs from a system service, where the systemd cgroup manager | |
| 93 | // has no user slice to work in. Every invocation must say so, or crun | |
| 94 | // fails creating the container's scope (#144). | |
| 95 | func TestPodmanUsesCgroupfs(t *testing.T) { | |
| 96 | got := podmanGlobal() | |
| 97 | found := false | |
| 98 | for _, f := range got { | |
| 99 | if f == "--cgroup-manager=cgroupfs" { | |
| 100 | found = true | |
| 101 | } | |
| 102 | } | |
| 103 | if !found { | |
| 104 | t.Errorf("podmanGlobal() = %v, missing the cgroupfs manager", got) | |
| 105 | } | |
| 106 | } | |
cmd/gitbay-runner/isolate.go +17 −4
| @@ -104,13 +104,13 @@ func (r *runner) runStepsPodman(j job, dir string, env []string, sink io.Writer, | ||
| 104 | 104 | name := fmt.Sprintf("gitbay-build-%d", j.ID) |
| 105 | 105 | // --rm so a container cannot outlive its build; the explicit rm below |
| 106 | 106 | // covers the case where the daemon-less run itself fails. |
| 107 | start := exec.Command(podman, "run", "--detach", "--rm", | |
| 107 | start := exec.Command(podman, append(podmanGlobal(), "run", "--detach", "--rm", | |
| 108 | 108 | "--name", name, |
| 109 | 109 | "--env-file", envFile, |
| 110 | 110 | "--volume", dir+":/workspace:rw", |
| 111 | 111 | "--workdir", "/workspace", |
| 112 | 112 | "--entrypoint", "sh", |
| 113 | image, "-c", "sleep infinity") | |
| 113 | image, "-c", "sleep infinity")...) | |
| 114 | 114 | start.Env = []string{"PATH=" + os.Getenv("PATH"), "HOME=" + r.podmanHome()} |
| 115 | 115 | if out, err := start.CombinedOutput(); err != nil { |
| 116 | 116 | // A pull failure lands here. Fail the build with what podman |
| @@ -118,11 +118,11 @@ func (r *runner) runStepsPodman(j job, dir string, env []string, sink io.Writer, | ||
| 118 | 118 | fmt.Fprintf(sink, "starting the build container from %s failed:\n%s\n", image, strings.TrimSpace(string(out))) |
| 119 | 119 | return false |
| 120 | 120 | } |
| 121 | defer exec.Command(podman, "rm", "--force", name).Run() | |
| 121 | defer exec.Command(podman, append(podmanGlobal(), "rm", "--force", name)...).Run() | |
| 122 | 122 | |
| 123 | 123 | for _, step := range j.Steps { |
| 124 | 124 | fmt.Fprintf(sink, "$ %s\n", step) |
| 125 | cmd := exec.Command(podman, "exec", "--workdir", "/workspace", name, "sh", "-c", step) | |
| 125 | cmd := exec.Command(podman, append(podmanGlobal(), "exec", "--workdir", "/workspace", name, "sh", "-c", step)...) | |
| 126 | 126 | cmd.Env = []string{"PATH=" + os.Getenv("PATH"), "HOME=" + r.podmanHome()} |
| 127 | 127 | cmd.Stdout, cmd.Stderr = sink, sink |
| 128 | 128 | if ok, why := runStep(cmd, deadline); !ok { |
| @@ -133,6 +133,19 @@ func (r *runner) runStepsPodman(j job, dir string, env []string, sink io.Writer, | ||
| 133 | 133 | return true |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | // podmanGlobal are the flags every podman invocation needs, before the | |
| 137 | // subcommand. | |
| 138 | // | |
| 139 | // The cgroup manager is cgroupfs, not systemd: the runner is a *system* | |
| 140 | // service, so there is no user session and no user@<uid>.service slice | |
| 141 | // for podman to create a scope under. With the systemd manager crun | |
| 142 | // fails with "create directory .../libpod-<id>.scope/container: No such | |
| 143 | // file or directory". The service's own cgroup is delegated | |
| 144 | // (Delegate=yes in the drop-in), which is what cgroupfs needs (#144). | |
| 145 | func podmanGlobal() []string { | |
| 146 | return []string{"--cgroup-manager=cgroupfs"} | |
| 147 | } | |
| 148 | ||
| 136 | 149 | // podmanHome is where podman keeps its own storage: the runner's home, |
| 137 | 150 | // not a build's. The container store is the runner's business, and a |
| 138 | 151 | // build never sees this path. |