Skip to content

Commit 425f694

Browse files
committed
DRA CEL: log actual cost
This may be useful for validating the cost estimate.
1 parent 7b0071d commit 425f694

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

staging/src/k8s.io/dynamic-resource-allocation/cel/compile.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,14 @@ func getAttributeValue(attr resourceapi.DeviceAttribute) (any, error) {
198198

199199
var boolType = reflect.TypeOf(true)
200200

201-
func (c CompilationResult) DeviceMatches(ctx context.Context, input Device) (bool, error) {
201+
func (c CompilationResult) DeviceMatches(ctx context.Context, input Device) (bool, *cel.EvalDetails, error) {
202202
// TODO (future): avoid building these maps and instead use a proxy
203203
// which wraps the underlying maps and directly looks up values.
204204
attributes := make(map[string]any)
205205
for name, attr := range input.Attributes {
206206
value, err := getAttributeValue(attr)
207207
if err != nil {
208-
return false, fmt.Errorf("attribute %s: %w", name, err)
208+
return false, nil, fmt.Errorf("attribute %s: %w", name, err)
209209
}
210210
domain, id := parseQualifiedName(name, input.Driver)
211211
if attributes[domain] == nil {
@@ -231,19 +231,19 @@ func (c CompilationResult) DeviceMatches(ctx context.Context, input Device) (boo
231231
},
232232
}
233233

234-
result, _, err := c.Program.ContextEval(ctx, variables)
234+
result, details, err := c.Program.ContextEval(ctx, variables)
235235
if err != nil {
236-
return false, err
236+
return false, details, err
237237
}
238238
resultAny, err := result.ConvertToNative(boolType)
239239
if err != nil {
240-
return false, fmt.Errorf("CEL result of type %s could not be converted to bool: %w", result.Type().TypeName(), err)
240+
return false, details, fmt.Errorf("CEL result of type %s could not be converted to bool: %w", result.Type().TypeName(), err)
241241
}
242242
resultBool, ok := resultAny.(bool)
243243
if !ok {
244-
return false, fmt.Errorf("CEL native result value should have been a bool, got instead: %T", resultAny)
244+
return false, details, fmt.Errorf("CEL native result value should have been a bool, got instead: %T", resultAny)
245245
}
246-
return resultBool, nil
246+
return resultBool, details, nil
247247
}
248248

249249
func mustBuildEnv() *environment.EnvSet {

staging/src/k8s.io/dynamic-resource-allocation/cel/compile_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,18 @@ device.attributes["dra.example.com"]["version"].isGreaterThan(semver("0.0.1"))
254254
t.Errorf("expected CEL cost %d, got %d instead", expect, actual)
255255
}
256256

257-
match, err := result.DeviceMatches(ctx, Device{Attributes: scenario.attributes, Capacity: scenario.capacity, Driver: scenario.driver})
257+
match, details, err := result.DeviceMatches(ctx, Device{Attributes: scenario.attributes, Capacity: scenario.capacity, Driver: scenario.driver})
258+
// details.ActualCost can be called for nil details, no need to check.
259+
actualCost := ptr.Deref(details.ActualCost(), 0)
260+
if scenario.expectCost > 0 {
261+
t.Logf("actual cost %d, %d%% of worst-case estimate", actualCost, actualCost*100/scenario.expectCost)
262+
} else {
263+
t.Logf("actual cost %d, expected zero costs", actualCost)
264+
if actualCost > 0 {
265+
t.Errorf("expected zero costs for (presumably) constant expression %q, got instead %d", scenario.expression, actualCost)
266+
}
267+
}
268+
258269
if err != nil {
259270
if scenario.expectMatchError == "" {
260271
t.Fatalf("unexpected evaluation error: %v", err)

staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
resourcelisters "k8s.io/client-go/listers/resource/v1alpha3"
3131
"k8s.io/dynamic-resource-allocation/cel"
3232
"k8s.io/klog/v2"
33+
"k8s.io/utils/ptr"
3334
)
3435

3536
// ClaimLister returns a subset of the claims that a
@@ -665,11 +666,11 @@ func (alloc *allocator) selectorsMatch(r requestIndices, device *resourceapi.Bas
665666
return false, fmt.Errorf("claim %s: selector #%d: CEL compile error: %w", klog.KObj(alloc.claimsToAllocate[r.claimIndex]), i, expr.Error)
666667
}
667668

668-
matches, err := expr.DeviceMatches(alloc.ctx, cel.Device{Driver: deviceID.Driver, Attributes: device.Attributes, Capacity: device.Capacity})
669+
matches, details, err := expr.DeviceMatches(alloc.ctx, cel.Device{Driver: deviceID.Driver, Attributes: device.Attributes, Capacity: device.Capacity})
669670
if class != nil {
670-
alloc.logger.V(7).Info("CEL result", "device", deviceID, "class", klog.KObj(class), "selector", i, "expression", selector.CEL.Expression, "matches", matches, "err", err)
671+
alloc.logger.V(7).Info("CEL result", "device", deviceID, "class", klog.KObj(class), "selector", i, "expression", selector.CEL.Expression, "matches", matches, "actualCost", ptr.Deref(details.ActualCost(), 0), "err", err)
671672
} else {
672-
alloc.logger.V(7).Info("CEL result", "device", deviceID, "claim", klog.KObj(alloc.claimsToAllocate[r.claimIndex]), "selector", i, "expression", selector.CEL.Expression, "matches", matches, "err", err)
673+
alloc.logger.V(7).Info("CEL result", "device", deviceID, "claim", klog.KObj(alloc.claimsToAllocate[r.claimIndex]), "selector", i, "expression", selector.CEL.Expression, "actualCost", ptr.Deref(details.ActualCost(), 0), "matches", matches, "err", err)
673674
}
674675

675676
if err != nil {

0 commit comments

Comments
 (0)