Skip to content

Commit 5d64f22

Browse files
committed
fix: delegate resources Condition update to the handler
1 parent 3d0d11e commit 5d64f22

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ A Kubernetes controller for managing ResourceSlice resources with customizable b
66

77
The Resource Slice Classes controller is designed to manage ResourceSlice resources in a Kubernetes cluster. Each controller instance handles ResourceSlices of a specific class, allowing you to run multiple controllers with different behaviors for different classes.
88

9-
The controller manages the ResourceSlice status updates and conditions, while the handler is responsible for implementing the resource allocation strategy.
9+
The controller manages the ResourceSlice status updates, while the handler is responsible for implementing the resource allocation strategy.
10+
In particular the handler should:
11+
12+
- set the list of resources allocated for that resourceslice in the status
13+
- set a Condition of type `Resources` to indicate if the resources have been accepted or denied.
14+
- return an error if it fails to process the ResourceSlice, thus the reconciliation should be retried.
15+
Note: it should not return an error if the resourceslice has been correctly processed,
16+
but the resources have been denied.
1017

1118
## Features
1219

@@ -76,6 +83,7 @@ To implement a custom handler for your ResourceSlice class:
7683
func (h *MyHandler) Handle(ctx context.Context, resourceSlice *authv1beta1.ResourceSlice) (ctrl.Result, error) {
7784
// Implement your custom resource allocation logic here
7885
// Update resourceSlice.Status.Resources with your allocated resources
86+
// and set the status Condition of type "Resources" accordingly
7987

8088
return ctrl.Result{}, nil
8189
}
@@ -122,12 +130,12 @@ Your handler implementation should:
122130

123131
1. Implement your resource allocation strategy
124132
2. Set the allocated resources in `resourceSlice.Status.Resources`
125-
3. Return appropriate reconciliation results and errors
133+
3. Set the `Resources` Condition to accept or deny the resources requested
134+
4. Return appropriate reconciliation results and errors
126135

127136
Note: The controller, not the handler, is responsible for:
128137

129138
- Updating the ResourceSlice status in the API server
130-
- Managing ResourceSlice conditions
131139
- Recording events
132140
- Error handling and logging
133141

@@ -140,6 +148,7 @@ Note: The controller, not the handler, is responsible for:
140148

141149
2. **Handler Implementation**:
142150
- Keep handlers focused on resource calculation logic
151+
- Explicitly accept or deny the resources through the appropriate Condition
143152
- Return meaningful errors for proper event recording
144153
- Use logging for debugging purposes
145154

examples/cappedresources/handler.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import (
44
"context"
55

66
authv1beta1 "github.com/liqotech/liqo/apis/authentication/v1beta1"
7+
"github.com/liqotech/liqo/pkg/liqo-controller-manager/authentication"
78
corev1 "k8s.io/api/core/v1"
89
"k8s.io/klog/v2"
910
ctrl "sigs.k8s.io/controller-runtime"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
1012

1113
rshandler "github.com/liqotech/resource-slice-class-controller-template/pkg/resourceslice/handler"
1214
)
@@ -27,15 +29,25 @@ func NewHandler(maxResources corev1.ResourceList) rshandler.Handler {
2729
func (h *Handler) Handle(_ context.Context, resourceSlice *authv1beta1.ResourceSlice) (ctrl.Result, error) {
2830
// Generate and update resources in status
2931
resources := h.getCappedResources(resourceSlice.Spec.Resources)
30-
3132
resourceSlice.Status.Resources = resources
3233

33-
klog.InfoS("Updated ResourceSlice status",
34+
klog.InfoS("Processed ResourceSlice resources",
3435
"name", resourceSlice.Name,
3536
"namespace", resourceSlice.Namespace,
3637
"cpu", resources.Cpu().String(),
3738
"memory", resources.Memory().String(),
38-
"pods", resources.Pods().String())
39+
"pods", resources.Pods().String(),
40+
"ephemeral-storage", resources.StorageEphemeral().String())
41+
42+
// Ensure the "Resources" condition is set.
43+
authentication.EnsureCondition(
44+
resourceSlice,
45+
authv1beta1.ResourceSliceConditionTypeResources,
46+
authv1beta1.ResourceSliceConditionAccepted,
47+
"ResourceSliceResourcesAccepted",
48+
"ResourceSlice resources accepted",
49+
)
50+
klog.Infof("ResourceSlice %q resources condition accepted", client.ObjectKeyFromObject(resourceSlice))
3951

4052
return ctrl.Result{}, nil
4153
}

pkg/controller/resource_slice_controller.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,13 @@ func (r *ResourceSliceReconciler) Reconcile(ctx context.Context, req ctrl.Reques
8484
res, err = r.handler.Handle(ctx, &resourceSlice)
8585
if err != nil {
8686
r.recorder.Eventf(&resourceSlice, "Warning", "Failed", "Failed to handle ResourceSlice: %v", err)
87-
return ctrl.Result{}, err
87+
return ctrl.Result{}, fmt.Errorf("failed to handle ResourceSlice %q: %w", req.NamespacedName, err)
88+
}
89+
90+
// check the "Resources" condition is set.
91+
resCond := authentication.GetCondition(&resourceSlice, authv1beta1.ResourceSliceConditionTypeResources)
92+
if resCond == nil {
93+
return ctrl.Result{}, fmt.Errorf("failed to handle ResourceSlice %q: missing \"Resources\" condition", req.NamespacedName)
8894
}
8995

9096
defer func() {
@@ -94,22 +100,12 @@ func (r *ResourceSliceReconciler) Reconcile(ctx context.Context, req ctrl.Reques
94100
klog.Error(err)
95101
}
96102
r.recorder.Eventf(&resourceSlice, "Warning", "Failed", "Failed to update ResourceSlice status: %v", err)
97-
err = fmt.Errorf("failed to update ResourceSlice status: %w", newErr)
103+
err = fmt.Errorf("failed to update ResourceSlice %q status: %w", req.NamespacedName, newErr)
104+
return
98105
}
106+
klog.Infof("ResourceSlice %q status correctly updated", req.NamespacedName)
99107
}()
100108

101-
// Update the conditions
102-
if resourceSlice.Status.Conditions == nil {
103-
resourceSlice.Status.Conditions = []authv1beta1.ResourceSliceCondition{}
104-
}
105-
authentication.EnsureCondition(
106-
&resourceSlice,
107-
authv1beta1.ResourceSliceConditionTypeResources,
108-
authv1beta1.ResourceSliceConditionAccepted,
109-
"ResourceSliceResourcesAccepted",
110-
"ResourceSlice resources accepted",
111-
)
112-
113109
// Return the reconciliation result
114110
return res, nil
115111
}

pkg/resourceslice/handler/interface.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import (
1010

1111
// Handler defines the interface for handling ResourceSlice operations.
1212
type Handler interface {
13-
// Handle processes a ResourceSlice and returns a reconciliation result
13+
// Handle processes a ResourceSlice and returns a reconciliation result.
14+
// The handler should also update the ResourceSlice status. In particular, it should:
15+
// - set the list of resources that have been allocated in `status.resources`
16+
// - set a Condition of type "Resources" in `status.conditions` to indicate
17+
// if the resources have been accepted or denied.
18+
// An error should be returned if the handler fails to process the ResourceSlice
19+
// and the reconciliation should be retried.
20+
// Note: it should not return an error if the resourceslice has been correctly processed,
21+
// but the resources have been denied.
1422
Handle(ctx context.Context, resourceSlice *authv1beta1.ResourceSlice) (ctrl.Result, error)
1523
}

0 commit comments

Comments
 (0)