mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
114 lines
2.4 KiB
Go
114 lines
2.4 KiB
Go
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"github.com/gitpod-io/gitpod/common-go/log"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
const RETRY = 3
|
|
|
|
func main() {
|
|
log := logrus.New()
|
|
log.SetLevel(logrus.DebugLevel)
|
|
|
|
var (
|
|
candidates = []string{"bob-runc", "runc"}
|
|
runcPath string
|
|
bundle string
|
|
err error
|
|
)
|
|
for _, c := range candidates {
|
|
runcPath, err = exec.LookPath(c)
|
|
if runcPath != "" {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
log.WithError(err).Fatal("runc not found")
|
|
}
|
|
|
|
var useFacade bool
|
|
for i, arg := range os.Args {
|
|
if arg == "run" {
|
|
useFacade = true
|
|
}
|
|
if arg == "--bundle" && i+1 < len(os.Args) {
|
|
bundle = os.Args[i+1]
|
|
}
|
|
}
|
|
|
|
if useFacade && bundle != "" {
|
|
err = createAndRunc(runcPath, bundle)
|
|
} else {
|
|
err = syscall.Exec(runcPath, os.Args, os.Environ())
|
|
}
|
|
if err != nil {
|
|
log.WithError(err).Fatal("failed")
|
|
}
|
|
}
|
|
|
|
func createAndRunc(runcPath, bundle string) error {
|
|
fn := filepath.Join(bundle, "config.json")
|
|
fc, err := os.ReadFile(fn)
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot read config.json: %w", err)
|
|
}
|
|
|
|
var cfg specs.Spec
|
|
err = json.Unmarshal(fc, &cfg)
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot decode config.json: %w", err)
|
|
}
|
|
|
|
var hasSysMount bool
|
|
for _, m := range cfg.Mounts {
|
|
if m.Destination == "/sys" {
|
|
hasSysMount = true
|
|
break
|
|
}
|
|
}
|
|
if !hasSysMount {
|
|
cfg.Mounts = append(cfg.Mounts, specs.Mount{
|
|
Destination: "/sys",
|
|
Type: "sysfs",
|
|
Source: "sysfs",
|
|
})
|
|
}
|
|
|
|
fc, err = json.Marshal(cfg)
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot encode config.json: %w", err)
|
|
}
|
|
for _, fn := range []string{fn, "/tmp/debug.json"} {
|
|
err = os.WriteFile(fn, fc, 0644)
|
|
if err != nil {
|
|
return xerrors.Errorf("cannot encode config.json: %w", err)
|
|
}
|
|
}
|
|
|
|
// See here for more details on why retries are necessary.
|
|
// https://github.com/gitpod-io/gitpod/issues/12365
|
|
for i := 0; i <= RETRY; i++ {
|
|
err = syscall.Exec(runcPath, os.Args, os.Environ())
|
|
if err == nil {
|
|
return err
|
|
} else {
|
|
log.WithError(err).Warn("runc failed")
|
|
}
|
|
}
|
|
|
|
return xerrors.Errorf("exec %s: %w", runcPath, err)
|
|
}
|