Path: blob/main/components/image-builder-bob/cmd/runc-facade/main.go
2498 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package main56import (7"encoding/json"8"os"9"os/exec"10"path/filepath"11"syscall"1213"github.com/gitpod-io/gitpod/common-go/log"14"github.com/opencontainers/runtime-spec/specs-go"15"github.com/sirupsen/logrus"16"golang.org/x/xerrors"17)1819const RETRY = 32021func main() {22log := logrus.New()23log.SetLevel(logrus.DebugLevel)2425var (26candidates = []string{"bob-runc", "runc"}27runcPath string28bundle string29err error30)31for _, c := range candidates {32runcPath, err = exec.LookPath(c)33if runcPath != "" {34break35}36}37if err != nil {38log.WithError(err).Fatal("runc not found")39}4041var useFacade bool42for i, arg := range os.Args {43if arg == "run" {44useFacade = true45}46if arg == "--bundle" && i+1 < len(os.Args) {47bundle = os.Args[i+1]48}49}5051if useFacade && bundle != "" {52err = createAndRunc(runcPath, bundle)53} else {54err = syscall.Exec(runcPath, os.Args, os.Environ())55}56if err != nil {57log.WithError(err).Fatal("failed")58}59}6061func createAndRunc(runcPath, bundle string) error {62fn := filepath.Join(bundle, "config.json")63fc, err := os.ReadFile(fn)64if err != nil {65return xerrors.Errorf("cannot read config.json: %w", err)66}6768var cfg specs.Spec69err = json.Unmarshal(fc, &cfg)70if err != nil {71return xerrors.Errorf("cannot decode config.json: %w", err)72}7374var hasSysMount bool75for _, m := range cfg.Mounts {76if m.Destination == "/sys" {77hasSysMount = true78break79}80}81if !hasSysMount {82cfg.Mounts = append(cfg.Mounts, specs.Mount{83Destination: "/sys",84Type: "sysfs",85Source: "sysfs",86})87}8889fc, err = json.Marshal(cfg)90if err != nil {91return xerrors.Errorf("cannot encode config.json: %w", err)92}93for _, fn := range []string{fn, "/tmp/debug.json"} {94err = os.WriteFile(fn, fc, 0644)95if err != nil {96return xerrors.Errorf("cannot encode config.json: %w", err)97}98}99100// See here for more details on why retries are necessary.101// https://github.com/gitpod-io/gitpod/issues/12365102for i := 0; i <= RETRY; i++ {103err = syscall.Exec(runcPath, os.Args, os.Environ())104if err == nil {105return err106} else {107log.WithError(err).Warn("runc failed")108}109}110111return xerrors.Errorf("exec %s: %w", runcPath, err)112}113114115