Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ab3944d
bench: warm-pool event fan-out to claims
CMGS Jul 27, 2026
1463bbd
perf: pool events no longer re-enqueue bound claims
CMGS Jul 27, 2026
506e770
bench: warm-pool driver global pass cost
CMGS Jul 27, 2026
e6eda85
perf: driver ignores its own pool status writes
CMGS Jul 27, 2026
9a73309
bench: warm-pool steady-state reconcile and member deep-copy
CMGS Jul 27, 2026
eb9ac04
perf: warm pool filters member events and reads the cache copy-free
CMGS Jul 27, 2026
e8561c6
bench: store Get and warm-candidate sweep at fleet shapes
CMGS Jul 27, 2026
8c272d4
perf: Get and warm-candidate sweeps fan out per node like List
CMGS Jul 27, 2026
698045c
bench: e2b single-id lookup at the fleet projection
CMGS Jul 27, 2026
5d640f7
perf: e2b single-id verbs resolve via claim-id sweep, not a fleet List
CMGS Jul 27, 2026
2523ece
bench: v1alpha1 conversion round trip
CMGS Jul 27, 2026
688ffd8
perf: v1alpha1 round-trip annotation carries only the lossy fields
CMGS Jul 27, 2026
52ce21b
review: dedupe the store's first-hit fan-out; tighten batch comments
CMGS Jul 27, 2026
c3daa08
review: apply simplify-round findings
CMGS Jul 27, 2026
cbd923d
review: tighten hot-path round comments
CMGS Jul 27, 2026
f84a7a7
review: compare controller refs, not the owner slice, in the member p…
CMGS Jul 27, 2026
41213cc
fix: e2b detail reports paused for hibernated sandboxes
CMGS Jul 27, 2026
407a94c
review: apply the loc-justify cut-list
CMGS Jul 27, 2026
cf7244d
docs: align L2 authorization contract
CMGS Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,9 @@ hermes-sandbox-knowledge.md
/sandbox-loadgen
/sandbox-apiserver
/sandbox-sdk-loadgen
/e2ebench
/l2bench
/l3bench
/poolbench
/scalebench
/scalestress
136 changes: 44 additions & 92 deletions api/v1alpha1/sandbox_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,34 @@ import (

const v1alpha1SandboxStateAnnotation = "api.agents.x-k8s.io/v1alpha1-sandbox-state"

// v1alpha1State is the round-trip payload: the fields v1beta1 cannot represent
// (replica counts collapse into OperatingMode). Legacy annotations carrying a
// full v1alpha1 Sandbox JSON decode into this shape too.
type v1alpha1State struct {
Spec struct {
Replicas *int32 `json:"replicas,omitempty"`
} `json:"spec"`
Status struct {
Replicas int32 `json:"replicas,omitempty"`
} `json:"status"`
}

// ConvertTo converts this Sandbox to the Hub version (v1beta1).
func (s *Sandbox) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v1beta1.Sandbox)

// Copy object metadata
s.ObjectMeta.DeepCopyInto(&dst.ObjectMeta)
ConvertSpecTo(&s.Spec, &dst.Spec)
ConvertStatusTo(&s.Status, &dst.Status)

// Convert Spec
if err := ConvertSpecTo(&s.Spec, &dst.Spec); err != nil {
return err
}

// Convert Status
if err := ConvertStatusTo(&s.Status, &dst.Status); err != nil {
return err
}

// Preserve the original v1alpha1 object state for lossless round-tripping
// Preserve the fields v1beta1 cannot represent for lossless round-tripping
if dst.Annotations == nil {
dst.Annotations = make(map[string]string)
}
sCopy := s.DeepCopy()
if sCopy.Annotations != nil {
delete(sCopy.Annotations, v1alpha1SandboxStateAnnotation)
}
stateJSON, err := json.Marshal(sCopy)
var state v1alpha1State
state.Spec.Replicas = s.Spec.Replicas
state.Status.Replicas = s.Status.Replicas
stateJSON, err := json.Marshal(state)
if err != nil {
return fmt.Errorf("failed to marshal v1alpha1 Sandbox state: %w", err)
}
Expand All @@ -63,18 +65,9 @@ func (s *Sandbox) ConvertTo(dstRaw conversion.Hub) error {
func (s *Sandbox) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v1beta1.Sandbox)

// Copy object metadata
src.ObjectMeta.DeepCopyInto(&s.ObjectMeta)

// Convert Spec
if err := ConvertSpecFrom(&src.Spec, &s.Spec); err != nil {
return err
}

// Convert Status
if err := ConvertStatusFrom(&src.Status, &s.Status); err != nil {
return err
}
ConvertSpecFrom(&src.Spec, &s.Spec)
ConvertStatusFrom(&src.Status, &s.Status)

// Set best-effort default for Status.Replicas based on OperatingMode.
// This will be overridden by the restoration logic if the annotation exists.
Expand All @@ -89,56 +82,42 @@ func (s *Sandbox) ConvertFrom(srcRaw conversion.Hub) error {
// Strip the state annotation so it doesn't leak to clients and get sent back on updates
delete(s.Annotations, v1alpha1SandboxStateAnnotation)

var original Sandbox
var original v1alpha1State
if err := json.Unmarshal([]byte(stateJSON), &original); err != nil {
return fmt.Errorf("failed to unmarshal v1alpha1 Sandbox state: %w", err)
}

// Restore replicas field from original if OperatingMode matches original intent
switch src.Spec.OperatingMode {
case v1beta1.SandboxOperatingModeSuspended:
zero := int32(0)
s.Spec.Replicas = &zero
s.Spec.Replicas = new(int32(0))
case v1beta1.SandboxOperatingModeRunning:
if original.Spec.Replicas == nil || *original.Spec.Replicas != 0 {
s.Spec.Replicas = original.Spec.Replicas
} else {
one := int32(1)
s.Spec.Replicas = &one
s.Spec.Replicas = new(int32(1))
}
}

// Restore Status replicas
s.Status.Replicas = original.Status.Replicas
}

return nil
}

// Helper functions for Sandbox conversion
func ConvertSpecTo(src *SandboxSpec, dst *v1beta1.SandboxSpec) {
ConvertPodTemplateTo(&src.PodTemplate, &dst.PodTemplate)

func ConvertSpecTo(src *SandboxSpec, dst *v1beta1.SandboxSpec) error {
// PodTemplate
if err := ConvertPodTemplateTo(&src.PodTemplate, &dst.PodTemplate); err != nil {
return err
}

// VolumeClaimTemplates
if src.VolumeClaimTemplates != nil {
dst.VolumeClaimTemplates = make([]v1beta1.PersistentVolumeClaimTemplate, len(src.VolumeClaimTemplates))
for i := range src.VolumeClaimTemplates {
if err := ConvertPVCClaimTemplateTo(&src.VolumeClaimTemplates[i], &dst.VolumeClaimTemplates[i]); err != nil {
return err
}
ConvertPVCClaimTemplateTo(&src.VolumeClaimTemplates[i], &dst.VolumeClaimTemplates[i])
}
} else {
dst.VolumeClaimTemplates = nil
}

// Lifecycle
if err := ConvertLifecycleTo(&src.Lifecycle, &dst.Lifecycle); err != nil {
return err
}
ConvertLifecycleTo(&src.Lifecycle, &dst.Lifecycle)

// Replicas -> OperatingMode
if src.Replicas != nil && *src.Replicas == 0 {
Expand All @@ -147,79 +126,58 @@ func ConvertSpecTo(src *SandboxSpec, dst *v1beta1.SandboxSpec) error {
dst.OperatingMode = v1beta1.SandboxOperatingModeRunning
}

// Service
dst.Service = src.Service

return nil
}

func ConvertSpecFrom(src *v1beta1.SandboxSpec, dst *SandboxSpec) error {
// PodTemplate
if err := ConvertPodTemplateFrom(&src.PodTemplate, &dst.PodTemplate); err != nil {
return err
}
func ConvertSpecFrom(src *v1beta1.SandboxSpec, dst *SandboxSpec) {
ConvertPodTemplateFrom(&src.PodTemplate, &dst.PodTemplate)

// VolumeClaimTemplates
if src.VolumeClaimTemplates != nil {
dst.VolumeClaimTemplates = make([]PersistentVolumeClaimTemplate, len(src.VolumeClaimTemplates))
for i := range src.VolumeClaimTemplates {
if err := ConvertPVCClaimTemplateFrom(&src.VolumeClaimTemplates[i], &dst.VolumeClaimTemplates[i]); err != nil {
return err
}
ConvertPVCClaimTemplateFrom(&src.VolumeClaimTemplates[i], &dst.VolumeClaimTemplates[i])
}
} else {
dst.VolumeClaimTemplates = nil
}

// Lifecycle
if err := ConvertLifecycleFrom(&src.Lifecycle, &dst.Lifecycle); err != nil {
return err
}
ConvertLifecycleFrom(&src.Lifecycle, &dst.Lifecycle)

// OperatingMode -> Replicas
one := int32(1)
zero := int32(0)
if src.OperatingMode == v1beta1.SandboxOperatingModeSuspended {
dst.Replicas = &zero
dst.Replicas = new(int32(0))
} else {
dst.Replicas = &one
dst.Replicas = new(int32(1))
}

// Service
dst.Service = src.Service

return nil
}

func ConvertStatusTo(src *SandboxStatus, dst *v1beta1.SandboxStatus) error {
func ConvertStatusTo(src *SandboxStatus, dst *v1beta1.SandboxStatus) {
dst.ServiceFQDN = src.ServiceFQDN
dst.Service = src.Service
dst.Conditions = src.Conditions
dst.LabelSelector = src.LabelSelector
dst.PodIPs = src.PodIPs
dst.NodeName = "" // NodeName is new in v1beta1 and does not exist in v1alpha1
return nil
}

func ConvertStatusFrom(src *v1beta1.SandboxStatus, dst *SandboxStatus) error {
func ConvertStatusFrom(src *v1beta1.SandboxStatus, dst *SandboxStatus) {
dst.ServiceFQDN = src.ServiceFQDN
dst.Service = src.Service
dst.Conditions = src.Conditions
dst.LabelSelector = src.LabelSelector
dst.PodIPs = src.PodIPs
return nil
}

func ConvertPodTemplateTo(src *PodTemplate, dst *v1beta1.PodTemplate) error {
func ConvertPodTemplateTo(src *PodTemplate, dst *v1beta1.PodTemplate) {
dst.Spec = src.Spec
ConvertPodMetadataTo(&src.ObjectMeta, &dst.ObjectMeta)
return nil
}

func ConvertPodTemplateFrom(src *v1beta1.PodTemplate, dst *PodTemplate) error {
func ConvertPodTemplateFrom(src *v1beta1.PodTemplate, dst *PodTemplate) {
dst.Spec = src.Spec
ConvertPodMetadataFrom(&src.ObjectMeta, &dst.ObjectMeta)
return nil
}

func ConvertPodMetadataTo(src *PodMetadata, dst *v1beta1.PodMetadata) {
Expand All @@ -232,16 +190,14 @@ func ConvertPodMetadataFrom(src *v1beta1.PodMetadata, dst *PodMetadata) {
dst.Annotations = src.Annotations
}

func ConvertPVCClaimTemplateTo(src *PersistentVolumeClaimTemplate, dst *v1beta1.PersistentVolumeClaimTemplate) error {
func ConvertPVCClaimTemplateTo(src *PersistentVolumeClaimTemplate, dst *v1beta1.PersistentVolumeClaimTemplate) {
dst.Spec = src.Spec
ConvertEmbeddedMetadataTo(&src.EmbeddedObjectMetadata, &dst.EmbeddedObjectMetadata)
return nil
}

func ConvertPVCClaimTemplateFrom(src *v1beta1.PersistentVolumeClaimTemplate, dst *PersistentVolumeClaimTemplate) error {
func ConvertPVCClaimTemplateFrom(src *v1beta1.PersistentVolumeClaimTemplate, dst *PersistentVolumeClaimTemplate) {
dst.Spec = src.Spec
ConvertEmbeddedMetadataFrom(&src.EmbeddedObjectMetadata, &dst.EmbeddedObjectMetadata)
return nil
}

func ConvertEmbeddedMetadataTo(src *EmbeddedObjectMetadata, dst *v1beta1.EmbeddedObjectMetadata) {
Expand All @@ -256,24 +212,20 @@ func ConvertEmbeddedMetadataFrom(src *v1beta1.EmbeddedObjectMetadata, dst *Embed
dst.Annotations = src.Annotations
}

func ConvertLifecycleTo(src *Lifecycle, dst *v1beta1.Lifecycle) error {
func ConvertLifecycleTo(src *Lifecycle, dst *v1beta1.Lifecycle) {
dst.ShutdownTime = src.ShutdownTime
if src.ShutdownPolicy != nil {
policy := v1beta1.ShutdownPolicy(*src.ShutdownPolicy)
dst.ShutdownPolicy = &policy
dst.ShutdownPolicy = new(v1beta1.ShutdownPolicy(*src.ShutdownPolicy))
} else {
dst.ShutdownPolicy = nil
}
return nil
}

func ConvertLifecycleFrom(src *v1beta1.Lifecycle, dst *Lifecycle) error {
func ConvertLifecycleFrom(src *v1beta1.Lifecycle, dst *Lifecycle) {
dst.ShutdownTime = src.ShutdownTime
if src.ShutdownPolicy != nil {
policy := ShutdownPolicy(*src.ShutdownPolicy)
dst.ShutdownPolicy = &policy
dst.ShutdownPolicy = new(ShutdownPolicy(*src.ShutdownPolicy))
} else {
dst.ShutdownPolicy = nil
}
return nil
}
85 changes: 85 additions & 0 deletions api/v1alpha1/sandbox_conversion_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package v1alpha1

import (
"testing"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

v1beta1 "github.com/cocoonstack/sandbox-operator/api/v1beta1"
)

// BenchmarkConvertRoundTrip converts a realistically sized v1alpha1 Sandbox to
// the hub and back — the per-object cost every v1alpha1 read/write pays in the
// conversion webhook, N times per LIST. bytes/ann is the round-trip annotation
// the object carries afterwards.
func BenchmarkConvertRoundTrip(b *testing.B) {
src := benchSandbox()
b.ReportAllocs()
var annBytes int
for b.Loop() {
dst := &v1beta1.Sandbox{}
if err := src.ConvertTo(dst); err != nil {
b.Fatalf("convert to: %v", err)
}
annBytes = len(dst.Annotations[v1alpha1SandboxStateAnnotation])
back := &Sandbox{}
if err := back.ConvertFrom(dst); err != nil {
b.Fatalf("convert from: %v", err)
}
}
b.ReportMetric(float64(annBytes), "bytes/ann")
}

func benchSandbox() *Sandbox {
replicas := int32(1)
return &Sandbox{
ObjectMeta: metav1.ObjectMeta{
Name: "bench-sandbox",
Namespace: "default",
Labels: map[string]string{"app": "agent", "team": "bench"},
Annotations: map[string]string{
"prometheus.io/scrape": "true",
},
},
Spec: SandboxSpec{
Replicas: &replicas,
PodTemplate: PodTemplate{
ObjectMeta: PodMetadata{Labels: map[string]string{"pod": "agent"}},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "agent",
Image: "ghcr.io/cocoonstack/sandbox/rt:24.04",
Command: []string{"/bin/agent", "--serve"},
Env: []corev1.EnvVar{
{Name: "MODE", Value: "warm"},
{Name: "REGION", Value: "sg"},
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("2"),
corev1.ResourceMemory: resource.MustParse("8Gi"),
},
},
},
{Name: "sidecar", Image: "ghcr.io/cocoonstack/sandbox/proxy:1.2"},
},
},
},
},
Status: SandboxStatus{
ServiceFQDN: "bench-sandbox.default.svc.cluster.local",
LabelSelector: "sandbox=bench-sandbox",
PodIPs: []string{"10.244.1.17"},
Replicas: 1,
Conditions: []metav1.Condition{{
Type: "Ready",
Status: metav1.ConditionTrue,
Reason: "Ready",
LastTransitionTime: metav1.Now(),
}},
},
}
}
Loading