Files
wehub-resource-sync e0e362d700
SDK Tests / SDK CI (push) Blocked by required conditions
SDK Tests / changes (push) Successful in 2m29s
Real E2E Tests / changes (push) Successful in 2m29s
SDK Tests / Python SDK Tests (sandbox) (push) Waiting to run
SDK Tests / CLI Quality (push) Waiting to run
SDK Tests / CLI Tests (push) Waiting to run
SDK Tests / Python SDK Quality (code-interpreter) (push) Waiting to run
SDK Tests / Python SDK Quality (sandbox) (push) Waiting to run
SDK Tests / Python SDK Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / JavaScript SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Kotlin SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (code-interpreter) (push) Waiting to run
SDK Tests / C# SDK Quality And Tests (sandbox) (push) Waiting to run
SDK Tests / Go SDK Quality And Tests (push) Waiting to run
Deploy Docs Pages / build (push) Has been cancelled
Deploy Docs Pages / deploy (push) Has been cancelled
Real E2E Tests / JavaScript E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Python E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Java E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / C# E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Go E2E (docker bridge) (push) Has been cancelled
Real E2E Tests / Real E2E CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:39:33 +08:00

184 lines
4.9 KiB
Go

// Copyright 2026 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package isolation
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/alibaba/opensandbox/execd/pkg/log"
)
// ProbeResult holds the result of startup isolation probing.
type ProbeResult struct {
Available bool
Isolator string
Version string
Message string // diagnostic message when unavailable
CommitSupported bool // Phase 2
DiffSupported bool // Phase 2
PersistAvailable bool // Phase 2 — requires emptyDir
}
// ProbeConfig controls Probe behaviour.
type ProbeConfig struct {
UpperRoot string
UpperMaxBytes int64
}
// Probe runs startup detection. Returns a ProbeResult describing what
// isolation capabilities are available in the current environment.
//
// On Linux with working bwrap:
//
// Available=true, Isolator="bwrap", Version="0.10.0"
//
// Otherwise:
//
// Available=false
func Probe(cfg ProbeConfig) ProbeResult {
result := ProbeResult{}
// Check if bwrap binary is available.
version, err := probeBwrapVersion()
if err != nil {
result.Message = fmt.Sprintf("bwrap not found: %v (searched: $PATH, /opt/opensandbox/bwrap, /usr/bin/bwrap, /usr/local/bin/bwrap)", err)
log.Warn("isolation probe: %s", result.Message)
return result
}
result.Available = true
result.Isolator = "bwrap"
result.Version = version
// Smoke test: verify bwrap can actually create a namespace.
if err := probeBwrapSmoke(); err != nil {
result.Message = fmt.Sprintf("bwrap found (v%s) but smoke test failed: %v", version, err)
log.Warn("isolation probe: %s", result.Message)
result.Available = false
return result
}
if probeOverlayMount(cfg.UpperRoot) {
result.CommitSupported = true
result.DiffSupported = true
}
return result
}
// probeBwrapVersion returns the bwrap version string if available.
func probeBwrapVersion() (string, error) {
p := findBwrap()
if p == "" {
return "", fmt.Errorf("bwrap not found")
}
var stdout bytes.Buffer
cmd := exec.Command(p, "--version")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return "", err
}
// bwrap prints version to stdout, e.g.:
// "bubblewrap 0.8.0" or "bwrap 0.10.0"
out := stdout.String()
return parseBwrapVersion(out), nil
}
var bwrapVersionRe = regexp.MustCompile(`b(?:ubble)?wrap\s+(\d+\.\d+\.\d+)`)
// parseBwrapVersion extracts the version number from bwrap --version output.
func parseBwrapVersion(out string) string {
match := bwrapVersionRe.FindStringSubmatch(out)
if len(match) < 2 {
return ""
}
return match[1]
}
// probeBwrapSmoke verifies bwrap can create a minimal namespace.
func probeBwrapSmoke() error {
p := findBwrap()
if p == "" {
return fmt.Errorf("bwrap not found")
}
cmd := exec.Command(p,
"--unshare-pid", "--unshare-uts", "--unshare-ipc", "--unshare-cgroup",
"--ro-bind", "/", "/",
"--proc", "/proc",
"--", "true",
)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("bwrap smoke test failed: %w (stderr: %s)", err, strings.TrimSpace(stderr.String()))
}
return nil
}
// probeOverlayMount tests whether bwrap can create an overlay mount.
func probeOverlayMount(upperRoot string) bool {
p := findBwrap()
if p == "" {
return false
}
// Probe on the upper root filesystem (typically tmpfs/emptyDir) rather
// than /tmp, because overlayfs cannot nest on Docker's overlay2 layer
// but works fine on tmpfs.
base := upperRoot
if base == "" {
base = os.TempDir()
}
tmpDir, err := os.MkdirTemp(base, "execd-probe-overlay-*")
if err != nil {
log.Warn("isolation probe: overlay: MkdirTemp(%s): %v", base, err)
return false
}
defer os.RemoveAll(tmpDir)
lowerDir := filepath.Join(tmpDir, "lower")
upperDir := filepath.Join(tmpDir, "upper")
workDir := filepath.Join(tmpDir, "work")
for _, d := range []string{lowerDir, upperDir, workDir} {
if err := os.MkdirAll(d, 0o755); err != nil {
log.Warn("isolation probe: overlay: MkdirAll(%s): %v", d, err)
return false
}
}
cmd := exec.Command(p,
"--ro-bind", "/", "/",
"--proc", "/proc",
"--overlay-src", lowerDir,
"--overlay", upperDir, workDir, "/mnt",
"--", "true",
)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
log.Warn("isolation probe: overlay mount failed: %v (stderr: %s)", err, strings.TrimSpace(stderr.String()))
return false
}
return true
}