mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
99 lines
3.0 KiB
Go
99 lines
3.0 KiB
Go
// Copyright (c) 2020 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 container
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
// NodeMountsLookupConfig confiugures the node mount/fs access
|
|
type NodeMountsLookupConfig struct {
|
|
// ProcLoc is the path to the node's /proc/mounts -
|
|
ProcLoc string `json:"proc"`
|
|
}
|
|
|
|
// Config configures the container runtime interface
|
|
type Config struct {
|
|
// Mounts configures the node mounts lookup
|
|
Mounts NodeMountsLookupConfig `json:"mounts"`
|
|
|
|
// Mapping mapps a path from the node to the container by stripping the key and prepending the value of this map.
|
|
// For example {"/var/lib/containerd": "/mnt/snapshots"} would translate /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/ to /mnt/snapshots/io.containerd.snapshotter.v1.overlayfs/snapshots/
|
|
Mapping map[string]string `json:"nodeToContainerMapping"`
|
|
|
|
// Runtime marks the container runtime we ought to connect to.
|
|
// Depending on the value set here we expect the corresponding config struct to have a value.
|
|
Runtime RuntimeType `json:"runtime"`
|
|
|
|
// Containerd contains the containerd CRI config if runtime == RuntimeContainerd
|
|
Containerd *ContainerdConfig `json:"containerd,omitempty"`
|
|
}
|
|
|
|
// RuntimeType lists the supported container runtimes
|
|
type RuntimeType string
|
|
|
|
const (
|
|
// RuntimeContainerd connects to containerd
|
|
RuntimeContainerd RuntimeType = "containerd"
|
|
)
|
|
|
|
// ContainerdConfig configures access to containerd
|
|
type ContainerdConfig struct {
|
|
// SocketPath is the path in the local file system pointing to the containerd socket.
|
|
// If this field is not set, full workspace backups are not available.
|
|
SocketPath string `json:"socket"`
|
|
}
|
|
|
|
// FromConfig produces a container runtime interface instance from the configuration
|
|
func FromConfig(cfg *Config) (rt Runtime, err error) {
|
|
if cfg == nil {
|
|
return
|
|
}
|
|
|
|
mounts, err := NewNodeMountsLookup(&cfg.Mounts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch cfg.Runtime {
|
|
case RuntimeContainerd:
|
|
if cfg.Containerd == nil {
|
|
return nil, xerrors.Errorf("runtime is set to containerd, but not containerd config is provided")
|
|
}
|
|
return NewContainerd(cfg.Containerd, mounts, cfg.Mapping)
|
|
default:
|
|
return nil, xerrors.Errorf("unknown runtime type: %s", cfg.Runtime)
|
|
}
|
|
}
|
|
|
|
// PathMapping maps a node path to a path in the container
|
|
type PathMapping map[string]string
|
|
|
|
// Translate maps a node-level (root mount namespace) path to a container-level path
|
|
func (mapping PathMapping) Translate(from string) (result string, err error) {
|
|
for np, cp := range mapping {
|
|
if !strings.HasPrefix(from, np) {
|
|
continue
|
|
}
|
|
pth := filepath.Join(cp, strings.TrimPrefix(from, np))
|
|
|
|
if _, err := os.Stat(pth); errors.Is(err, fs.ErrNotExist) {
|
|
return "", xerrors.Errorf("path does not exist in container at %s", pth)
|
|
} else if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return pth, nil
|
|
}
|
|
|
|
return "", xerrors.Errorf("mount entry %s has no appropriate mapping", from)
|
|
}
|