Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/image-builder-bob/cmd/runc-facade/main.go
2498 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package main
6
7
import (
8
"encoding/json"
9
"os"
10
"os/exec"
11
"path/filepath"
12
"syscall"
13
14
"github.com/gitpod-io/gitpod/common-go/log"
15
"github.com/opencontainers/runtime-spec/specs-go"
16
"github.com/sirupsen/logrus"
17
"golang.org/x/xerrors"
18
)
19
20
const RETRY = 3
21
22
func main() {
23
log := logrus.New()
24
log.SetLevel(logrus.DebugLevel)
25
26
var (
27
candidates = []string{"bob-runc", "runc"}
28
runcPath string
29
bundle string
30
err error
31
)
32
for _, c := range candidates {
33
runcPath, err = exec.LookPath(c)
34
if runcPath != "" {
35
break
36
}
37
}
38
if err != nil {
39
log.WithError(err).Fatal("runc not found")
40
}
41
42
var useFacade bool
43
for i, arg := range os.Args {
44
if arg == "run" {
45
useFacade = true
46
}
47
if arg == "--bundle" && i+1 < len(os.Args) {
48
bundle = os.Args[i+1]
49
}
50
}
51
52
if useFacade && bundle != "" {
53
err = createAndRunc(runcPath, bundle)
54
} else {
55
err = syscall.Exec(runcPath, os.Args, os.Environ())
56
}
57
if err != nil {
58
log.WithError(err).Fatal("failed")
59
}
60
}
61
62
func createAndRunc(runcPath, bundle string) error {
63
fn := filepath.Join(bundle, "config.json")
64
fc, err := os.ReadFile(fn)
65
if err != nil {
66
return xerrors.Errorf("cannot read config.json: %w", err)
67
}
68
69
var cfg specs.Spec
70
err = json.Unmarshal(fc, &cfg)
71
if err != nil {
72
return xerrors.Errorf("cannot decode config.json: %w", err)
73
}
74
75
var hasSysMount bool
76
for _, m := range cfg.Mounts {
77
if m.Destination == "/sys" {
78
hasSysMount = true
79
break
80
}
81
}
82
if !hasSysMount {
83
cfg.Mounts = append(cfg.Mounts, specs.Mount{
84
Destination: "/sys",
85
Type: "sysfs",
86
Source: "sysfs",
87
})
88
}
89
90
fc, err = json.Marshal(cfg)
91
if err != nil {
92
return xerrors.Errorf("cannot encode config.json: %w", err)
93
}
94
for _, fn := range []string{fn, "/tmp/debug.json"} {
95
err = os.WriteFile(fn, fc, 0644)
96
if err != nil {
97
return xerrors.Errorf("cannot encode config.json: %w", err)
98
}
99
}
100
101
// See here for more details on why retries are necessary.
102
// https://github.com/gitpod-io/gitpod/issues/12365
103
for i := 0; i <= RETRY; i++ {
104
err = syscall.Exec(runcPath, os.Args, os.Environ())
105
if err == nil {
106
return err
107
} else {
108
log.WithError(err).Warn("runc failed")
109
}
110
}
111
112
return xerrors.Errorf("exec %s: %w", runcPath, err)
113
}
114
115