Skip to content

Commit 677b171

Browse files
committed
Add support for shutdownAt in sandbox.spec
* Add .spec.shutdownAt string in RFC 3339 format that parses to a time * The sandbox is deleted once the current time >= shutdownAt time
1 parent 5ee237e commit 677b171

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

api/v1alpha1/sandbox_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ type SandboxSpec struct {
6666
// PodTemplate describes the pod spec that will be used to create an agent sandbox.
6767
// +kubebuilder:validation:Required
6868
PodTemplate PodTemplate `json:"podTemplate" protobuf:"bytes,3,opt,name=podTemplate"`
69+
70+
// ShutdownTime - Absolute time (RFC 3339) when the sandbox is deleted.
71+
// If a time in the past is provided, the sandbox will be deleted immediately.
72+
// +kubebuilder:validation:Format="date-time"
73+
ShutdownTime *metav1.Time `json:"shutdownTime,omitempty"`
6974
}
7075

7176
// SandboxStatus defines the observed state of Sandbox.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

controllers/sandbox_controller.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"hash/fnv"
2222
"reflect"
23+
"time"
2324

2425
corev1 "k8s.io/api/core/v1"
2526
k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -33,6 +34,7 @@ import (
3334
"sigs.k8s.io/controller-runtime/pkg/handler"
3435
"sigs.k8s.io/controller-runtime/pkg/log"
3536
"sigs.k8s.io/controller-runtime/pkg/predicate"
37+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3638

3739
sandboxv1alpha1 "sigs.k8s.io/agent-sandbox/api/v1alpha1"
3840
)
@@ -98,12 +100,15 @@ func (r *SandboxReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
98100
readyCondition := r.computeReadyCondition(sandbox.Generation, allErrors, svc, pod)
99101
meta.SetStatusCondition(&sandbox.Status.Conditions, readyCondition)
100102

103+
result, err := r.reconcileSandboxExpiry(ctx, sandbox)
104+
allErrors = errors.Join(allErrors, err)
105+
101106
// Update status
102107
err = r.updateStatus(ctx, oldStatus, sandbox)
103108
allErrors = errors.Join(allErrors, err)
104109

105110
// return errors seen
106-
return ctrl.Result{}, allErrors
111+
return result, allErrors
107112
}
108113

109114
func (r *SandboxReconciler) computeReadyCondition(generation int64, err error, svc *corev1.Service, pod *corev1.Pod) metav1.Condition {
@@ -280,6 +285,36 @@ func (r *SandboxReconciler) reconcilePod(ctx context.Context, sandbox *sandboxv1
280285
return pod, nil
281286
}
282287

288+
// reconcileSandboxExpiry will check if a sandbox has expired, and if so, delete it.
289+
// If the sandbox has not expired, it will requeue the request for the remaining time.
290+
291+
func (r *SandboxReconciler) reconcileSandboxExpiry(ctx context.Context, sandbox *sandboxv1alpha1.Sandbox) (ctrl.Result, error) {
292+
log := log.FromContext(ctx)
293+
294+
var expiryTime time.Time
295+
if sandbox.Spec.ShutdownTime == nil {
296+
log.Info("Sandbox ShutdownTime is not set, skipping.")
297+
return reconcile.Result{}, nil
298+
}
299+
300+
expiryTime = sandbox.Spec.ShutdownTime.Time
301+
302+
// Calculate remaining time
303+
remainingTime := time.Until(expiryTime)
304+
if remainingTime <= 0 {
305+
log.Info("Sandbox has expired, deleting")
306+
if err := r.Delete(ctx, sandbox); err != nil {
307+
return ctrl.Result{}, fmt.Errorf("failed to delete sandbox: %w", err)
308+
}
309+
return ctrl.Result{}, nil
310+
}
311+
312+
requeueAfter := max(remainingTime/2, 2*time.Second) // Requeue at most every 2 seconds
313+
log.Info("Requeuing sandbox for shutdown", "remaining time", remainingTime, "requeue after", requeueAfter,
314+
"expiry time", expiryTime)
315+
return reconcile.Result{RequeueAfter: requeueAfter}, nil
316+
}
317+
283318
// SetupWithManager sets up the controller with the Manager.
284319
func (r *SandboxReconciler) SetupWithManager(mgr ctrl.Manager) error {
285320
labelSelectorPredicate, err := predicate.LabelSelectorPredicate(metav1.LabelSelector{

k8s/crds/agents.x-k8s.io_sandboxes.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3814,6 +3814,9 @@ spec:
38143814
required:
38153815
- spec
38163816
type: object
3817+
shutdownTime:
3818+
format: date-time
3819+
type: string
38173820
required:
38183821
- podTemplate
38193822
type: object

0 commit comments

Comments
 (0)