DRA: Update controller for Prioritized Alternatives in Device Requests

This commit is contained in:
Morten Torkildsen 2025-02-28 19:32:59 +00:00
parent 2229a78dfe
commit 36d8a44b9c
4 changed files with 60 additions and 29 deletions

View File

@ -408,7 +408,10 @@ func newResourceClaimControllerDescriptor() *ControllerDescriptor {
func startResourceClaimController(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) { func startResourceClaimController(ctx context.Context, controllerContext ControllerContext, controllerName string) (controller.Interface, bool, error) {
ephemeralController, err := resourceclaim.NewController( ephemeralController, err := resourceclaim.NewController(
klog.FromContext(ctx), klog.FromContext(ctx),
utilfeature.DefaultFeatureGate.Enabled(features.DRAAdminAccess), resourceclaim.Features{
AdminAccess: utilfeature.DefaultFeatureGate.Enabled(features.DRAAdminAccess),
PrioritizedList: utilfeature.DefaultFeatureGate.Enabled(features.DRAPrioritizedList),
},
controllerContext.ClientBuilder.ClientOrDie("resource-claim-controller"), controllerContext.ClientBuilder.ClientOrDie("resource-claim-controller"),
controllerContext.InformerFactory.Core().V1().Pods(), controllerContext.InformerFactory.Core().V1().Pods(),
controllerContext.InformerFactory.Resource().V1beta1().ResourceClaims(), controllerContext.InformerFactory.Resource().V1beta1().ResourceClaims(),

View File

@ -71,8 +71,8 @@ const (
// Controller creates ResourceClaims for ResourceClaimTemplates in a pod spec. // Controller creates ResourceClaims for ResourceClaimTemplates in a pod spec.
type Controller struct { type Controller struct {
// adminAccessEnabled matches the DRAAdminAccess feature gate state. // features defines the feature gates that are enabled.
adminAccessEnabled bool features Features
// kubeClient is the kube API client used to communicate with the API // kubeClient is the kube API client used to communicate with the API
// server. // server.
@ -118,17 +118,23 @@ const (
podKeyPrefix = "pod:" podKeyPrefix = "pod:"
) )
// Features defines which features should be enabled in the controller.
type Features struct {
AdminAccess bool
PrioritizedList bool
}
// NewController creates a ResourceClaim controller. // NewController creates a ResourceClaim controller.
func NewController( func NewController(
logger klog.Logger, logger klog.Logger,
adminAccessEnabled bool, features Features,
kubeClient clientset.Interface, kubeClient clientset.Interface,
podInformer v1informers.PodInformer, podInformer v1informers.PodInformer,
claimInformer resourceinformers.ResourceClaimInformer, claimInformer resourceinformers.ResourceClaimInformer,
templateInformer resourceinformers.ResourceClaimTemplateInformer) (*Controller, error) { templateInformer resourceinformers.ResourceClaimTemplateInformer) (*Controller, error) {
ec := &Controller{ ec := &Controller{
adminAccessEnabled: adminAccessEnabled, features: features,
kubeClient: kubeClient, kubeClient: kubeClient,
podLister: podInformer.Lister(), podLister: podInformer.Lister(),
podIndexer: podInformer.Informer().GetIndexer(), podIndexer: podInformer.Informer().GetIndexer(),
@ -617,10 +623,14 @@ func (ec *Controller) handleClaim(ctx context.Context, pod *v1.Pod, podClaim v1.
return fmt.Errorf("resource claim template %q: %v", *templateName, err) return fmt.Errorf("resource claim template %q: %v", *templateName, err)
} }
if !ec.adminAccessEnabled && needsAdminAccess(template) { if !ec.features.AdminAccess && needsAdminAccess(template) {
return errors.New("admin access is requested, but the feature is disabled") return errors.New("admin access is requested, but the feature is disabled")
} }
if !ec.features.PrioritizedList && hasPrioritizedList(template) {
return errors.New("template includes a prioritized list of subrequests, but the feature is disabled")
}
// Create the ResourceClaim with pod as owner, with a generated name that uses // Create the ResourceClaim with pod as owner, with a generated name that uses
// <pod>-<claim name> as base. // <pod>-<claim name> as base.
isTrue := true isTrue := true
@ -688,6 +698,15 @@ func needsAdminAccess(claimTemplate *resourceapi.ResourceClaimTemplate) bool {
return false return false
} }
func hasPrioritizedList(claimTemplate *resourceapi.ResourceClaimTemplate) bool {
for _, request := range claimTemplate.Spec.Spec.Devices.Requests {
if len(request.FirstAvailable) > 0 {
return true
}
}
return false
}
// findPodResourceClaim looks for an existing ResourceClaim with the right // findPodResourceClaim looks for an existing ResourceClaim with the right
// annotation (ties it to the pod claim) and the right ownership (ties it to // annotation (ties it to the pod claim) and the right ownership (ties it to
// the pod). // the pod).

View File

@ -85,6 +85,7 @@ func TestSyncHandler(t *testing.T) {
name string name string
key string key string
adminAccessEnabled bool adminAccessEnabled bool
prioritizedListEnabled bool
claims []*resourceapi.ResourceClaim claims []*resourceapi.ResourceClaim
claimsInCache []*resourceapi.ResourceClaim claimsInCache []*resourceapi.ResourceClaim
pods []*v1.Pod pods []*v1.Pod
@ -390,7 +391,11 @@ func TestSyncHandler(t *testing.T) {
claimInformer := informerFactory.Resource().V1beta1().ResourceClaims() claimInformer := informerFactory.Resource().V1beta1().ResourceClaims()
templateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates() templateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates()
ec, err := NewController(tCtx.Logger(), tc.adminAccessEnabled, fakeKubeClient, podInformer, claimInformer, templateInformer) features := Features{
AdminAccess: tc.adminAccessEnabled,
PrioritizedList: tc.prioritizedListEnabled,
}
ec, err := NewController(tCtx.Logger(), features, fakeKubeClient, podInformer, claimInformer, templateInformer)
if err != nil { if err != nil {
t.Fatalf("error creating ephemeral controller : %v", err) t.Fatalf("error creating ephemeral controller : %v", err)
} }
@ -465,7 +470,7 @@ func TestResourceClaimEventHandler(t *testing.T) {
templateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates() templateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates()
claimClient := fakeKubeClient.ResourceV1beta1().ResourceClaims(testNamespace) claimClient := fakeKubeClient.ResourceV1beta1().ResourceClaims(testNamespace)
_, err := NewController(tCtx.Logger(), false /* admin access */, fakeKubeClient, podInformer, claimInformer, templateInformer) _, err := NewController(tCtx.Logger(), Features{}, fakeKubeClient, podInformer, claimInformer, templateInformer)
tCtx.ExpectNoError(err, "creating ephemeral controller") tCtx.ExpectNoError(err, "creating ephemeral controller")
informerFactory.Start(tCtx.Done()) informerFactory.Start(tCtx.Done())

View File

@ -132,7 +132,11 @@ func CreateResourceClaimController(ctx context.Context, tb ktesting.TB, clientSe
podInformer := informerFactory.Core().V1().Pods() podInformer := informerFactory.Core().V1().Pods()
claimInformer := informerFactory.Resource().V1beta1().ResourceClaims() claimInformer := informerFactory.Resource().V1beta1().ResourceClaims()
claimTemplateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates() claimTemplateInformer := informerFactory.Resource().V1beta1().ResourceClaimTemplates()
claimController, err := resourceclaim.NewController(klog.FromContext(ctx), true /* admin access */, clientSet, podInformer, claimInformer, claimTemplateInformer) features := resourceclaim.Features{
AdminAccess: true,
PrioritizedList: true,
}
claimController, err := resourceclaim.NewController(klog.FromContext(ctx), features, clientSet, podInformer, claimInformer, claimTemplateInformer)
if err != nil { if err != nil {
tb.Fatalf("Error creating claim controller: %v", err) tb.Fatalf("Error creating claim controller: %v", err)
} }