- Add new gRPC endpoint for Heartbeat in the Yao service, enabling communication with the sandbox. - Update Makefile to include a dedicated unit test target for Sandbox V2, ensuring proper testing of new features. - Enhance CI workflows to incorporate Sandbox V2 tests, allowing for dual-mode testing (local and remote) with Docker. - Modify .gitignore to exclude specific Docker files while allowing shell scripts for Sandbox V2. - Update documentation in DESIGN.md to reflect the new architecture and capabilities of the Sandbox V2. These changes enhance the Yao SDK's functionality, providing improved support for sandbox operations and testing.
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/docker/docker/client"
|
|
)
|
|
|
|
type local struct {
|
|
core dockerCore
|
|
}
|
|
|
|
// NewLocal creates a Sandbox backed by a direct Docker daemon connection.
|
|
// addr can be "unix:///var/run/docker.sock", "tcp://host:port", or "" for platform default.
|
|
func NewLocal(addr string) (Sandbox, error) {
|
|
opts := []client.Opt{client.WithAPIVersionNegotiation()}
|
|
if addr != "" {
|
|
opts = append(opts, client.WithHost(addr))
|
|
} else {
|
|
opts = append(opts, client.FromEnv)
|
|
}
|
|
cli, err := client.NewClientWithOpts(opts...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("docker client: %w", err)
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
if _, err := cli.Ping(ctx); err != nil {
|
|
cli.Close()
|
|
return nil, fmt.Errorf("docker ping: %w", err)
|
|
}
|
|
return &local{core: dockerCore{cli: cli}}, nil
|
|
}
|
|
|
|
func (l *local) Create(ctx context.Context, opts CreateOptions) (string, error) {
|
|
return l.core.create(ctx, opts, opts.VNC && needsPortMapping())
|
|
}
|
|
|
|
func (l *local) Start(ctx context.Context, id string) error {
|
|
return l.core.start(ctx, id)
|
|
}
|
|
|
|
func (l *local) Stop(ctx context.Context, id string, timeout time.Duration) error {
|
|
return l.core.stop(ctx, id, int(timeout.Seconds()))
|
|
}
|
|
|
|
func (l *local) Remove(ctx context.Context, id string, force bool) error {
|
|
return l.core.remove(ctx, id, force)
|
|
}
|
|
|
|
func (l *local) Exec(ctx context.Context, id string, cmd []string, opts ExecOptions) (*ExecResult, error) {
|
|
return l.core.exec(ctx, id, cmd, opts)
|
|
}
|
|
|
|
func (l *local) ExecStream(ctx context.Context, id string, cmd []string, opts ExecOptions) (*StreamHandle, error) {
|
|
return l.core.execStream(ctx, id, cmd, opts)
|
|
}
|
|
|
|
func (l *local) Inspect(ctx context.Context, id string) (*ContainerInfo, error) {
|
|
return l.core.inspect(ctx, id)
|
|
}
|
|
|
|
func (l *local) List(ctx context.Context, opts ListOptions) ([]ContainerInfo, error) {
|
|
return l.core.list(ctx, opts)
|
|
}
|
|
|
|
func (l *local) Close() error {
|
|
return l.core.cli.Close()
|
|
}
|
|
|
|
// needsPortMapping returns true on platforms where container IPs are not
|
|
// directly reachable (macOS Docker Desktop, Windows).
|
|
func needsPortMapping() bool {
|
|
return runtime.GOOS == "darwin" || runtime.GOOS == "windows"
|
|
}
|
|
|
|
func portStr(p int) string {
|
|
if p == 0 {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("%d", p)
|
|
}
|