 8d9b62daf3
			
		
	
	8d9b62daf3
	
	
	
		
			
			This commit implements Phase 2 of the CHORUS Task Execution Engine development plan, providing a comprehensive execution environment abstraction layer with Docker container sandboxing support. ## New Features ### Core Sandbox Interface - Comprehensive ExecutionSandbox interface with isolated task execution - Support for command execution, file I/O, environment management - Resource usage monitoring and sandbox lifecycle management - Standardized error handling with SandboxError types and categories ### Docker Container Sandbox Implementation - Full Docker API integration with secure container creation - Transparent repository mounting with configurable read/write access - Advanced security policies with capability dropping and privilege controls - Comprehensive resource limits (CPU, memory, disk, processes, file handles) - Support for tmpfs mounts, masked paths, and read-only bind mounts - Container lifecycle management with proper cleanup and health monitoring ### Security & Resource Management - Configurable security policies with SELinux, AppArmor, and Seccomp support - Fine-grained capability management with secure defaults - Network isolation options with configurable DNS and proxy settings - Resource monitoring with real-time CPU, memory, and network usage tracking - Comprehensive ulimits configuration for process and file handle limits ### Repository Integration - Seamless repository mounting from local paths to container workspaces - Git configuration support with user credentials and global settings - File inclusion/exclusion patterns for selective repository access - Configurable permissions and ownership for mounted repositories ### Testing Infrastructure - Comprehensive test suite with 60+ test cases covering all functionality - Docker integration tests with Alpine Linux containers (skipped in short mode) - Mock sandbox implementation for unit testing without Docker dependencies - Security policy validation tests with read-only filesystem enforcement - Resource usage monitoring and cleanup verification tests ## Technical Details ### Dependencies Added - github.com/docker/docker v28.4.0+incompatible - Docker API client - github.com/docker/go-connections v0.6.0 - Docker connection utilities - github.com/docker/go-units v0.5.0 - Docker units and formatting - Associated Docker API dependencies for complete container management ### Architecture - Interface-driven design enabling multiple sandbox implementations - Comprehensive configuration structures for all sandbox aspects - Resource usage tracking with detailed metrics collection - Error handling with retryable error classification - Proper cleanup and resource management throughout sandbox lifecycle ### Compatibility - Maintains backward compatibility with existing CHORUS architecture - Designed for future integration with Phase 3 Core Task Execution Engine - Extensible design supporting additional sandbox implementations (VM, process) This Phase 2 implementation provides the foundation for secure, isolated task execution that will be integrated with the AI model providers from Phase 1 in the upcoming Phase 3 development. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			136 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright The OpenTelemetry Authors
 | |
| // SPDX-License-Identifier: Apache-2.0
 | |
| 
 | |
| package attribute // import "go.opentelemetry.io/otel/attribute"
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"sync"
 | |
| 	"sync/atomic"
 | |
| )
 | |
| 
 | |
| type (
 | |
| 	// Encoder is a mechanism for serializing an attribute set into a specific
 | |
| 	// string representation that supports caching, to avoid repeated
 | |
| 	// serialization. An example could be an exporter encoding the attribute
 | |
| 	// set into a wire representation.
 | |
| 	Encoder interface {
 | |
| 		// Encode returns the serialized encoding of the attribute set using
 | |
| 		// its Iterator. This result may be cached by a attribute.Set.
 | |
| 		Encode(iterator Iterator) string
 | |
| 
 | |
| 		// ID returns a value that is unique for each class of attribute
 | |
| 		// encoder. Attribute encoders allocate these using `NewEncoderID`.
 | |
| 		ID() EncoderID
 | |
| 	}
 | |
| 
 | |
| 	// EncoderID is used to identify distinct Encoder
 | |
| 	// implementations, for caching encoded results.
 | |
| 	EncoderID struct {
 | |
| 		value uint64
 | |
| 	}
 | |
| 
 | |
| 	// defaultAttrEncoder uses a sync.Pool of buffers to reduce the number of
 | |
| 	// allocations used in encoding attributes. This implementation encodes a
 | |
| 	// comma-separated list of key=value, with '/'-escaping of '=', ',', and
 | |
| 	// '\'.
 | |
| 	defaultAttrEncoder struct {
 | |
| 		// pool is a pool of attribute set builders. The buffers in this pool
 | |
| 		// grow to a size that most attribute encodings will not allocate new
 | |
| 		// memory.
 | |
| 		pool sync.Pool // *bytes.Buffer
 | |
| 	}
 | |
| )
 | |
| 
 | |
| // escapeChar is used to ensure uniqueness of the attribute encoding where
 | |
| // keys or values contain either '=' or ','.  Since there is no parser needed
 | |
| // for this encoding and its only requirement is to be unique, this choice is
 | |
| // arbitrary.  Users will see these in some exporters (e.g., stdout), so the
 | |
| // backslash ('\') is used as a conventional choice.
 | |
| const escapeChar = '\\'
 | |
| 
 | |
| var (
 | |
| 	_ Encoder = &defaultAttrEncoder{}
 | |
| 
 | |
| 	// encoderIDCounter is for generating IDs for other attribute encoders.
 | |
| 	encoderIDCounter uint64
 | |
| 
 | |
| 	defaultEncoderOnce     sync.Once
 | |
| 	defaultEncoderID       = NewEncoderID()
 | |
| 	defaultEncoderInstance *defaultAttrEncoder
 | |
| )
 | |
| 
 | |
| // NewEncoderID returns a unique attribute encoder ID. It should be called
 | |
| // once per each type of attribute encoder. Preferably in init() or in var
 | |
| // definition.
 | |
| func NewEncoderID() EncoderID {
 | |
| 	return EncoderID{value: atomic.AddUint64(&encoderIDCounter, 1)}
 | |
| }
 | |
| 
 | |
| // DefaultEncoder returns an attribute encoder that encodes attributes in such
 | |
| // a way that each escaped attribute's key is followed by an equal sign and
 | |
| // then by an escaped attribute's value. All key-value pairs are separated by
 | |
| // a comma.
 | |
| //
 | |
| // Escaping is done by prepending a backslash before either a backslash, equal
 | |
| // sign or a comma.
 | |
| func DefaultEncoder() Encoder {
 | |
| 	defaultEncoderOnce.Do(func() {
 | |
| 		defaultEncoderInstance = &defaultAttrEncoder{
 | |
| 			pool: sync.Pool{
 | |
| 				New: func() any {
 | |
| 					return &bytes.Buffer{}
 | |
| 				},
 | |
| 			},
 | |
| 		}
 | |
| 	})
 | |
| 	return defaultEncoderInstance
 | |
| }
 | |
| 
 | |
| // Encode is a part of an implementation of the AttributeEncoder interface.
 | |
| func (d *defaultAttrEncoder) Encode(iter Iterator) string {
 | |
| 	buf := d.pool.Get().(*bytes.Buffer)
 | |
| 	defer d.pool.Put(buf)
 | |
| 	buf.Reset()
 | |
| 
 | |
| 	for iter.Next() {
 | |
| 		i, keyValue := iter.IndexedAttribute()
 | |
| 		if i > 0 {
 | |
| 			_ = buf.WriteByte(',')
 | |
| 		}
 | |
| 		copyAndEscape(buf, string(keyValue.Key))
 | |
| 
 | |
| 		_ = buf.WriteByte('=')
 | |
| 
 | |
| 		if keyValue.Value.Type() == STRING {
 | |
| 			copyAndEscape(buf, keyValue.Value.AsString())
 | |
| 		} else {
 | |
| 			_, _ = buf.WriteString(keyValue.Value.Emit())
 | |
| 		}
 | |
| 	}
 | |
| 	return buf.String()
 | |
| }
 | |
| 
 | |
| // ID is a part of an implementation of the AttributeEncoder interface.
 | |
| func (*defaultAttrEncoder) ID() EncoderID {
 | |
| 	return defaultEncoderID
 | |
| }
 | |
| 
 | |
| // copyAndEscape escapes `=`, `,` and its own escape character (`\`),
 | |
| // making the default encoding unique.
 | |
| func copyAndEscape(buf *bytes.Buffer, val string) {
 | |
| 	for _, ch := range val {
 | |
| 		switch ch {
 | |
| 		case '=', ',', escapeChar:
 | |
| 			_ = buf.WriteByte(escapeChar)
 | |
| 		}
 | |
| 		_, _ = buf.WriteRune(ch)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Valid reports whether this encoder ID was allocated by
 | |
| // [NewEncoderID]. Invalid encoder IDs will not be cached.
 | |
| func (id EncoderID) Valid() bool {
 | |
| 	return id.value != 0
 | |
| }
 |