@@ -38,9 +38,6 @@ import (
38
38
var (
39
39
SpotRequirement = scheduling .NewRequirements (scheduling .NewRequirement (v1 .CapacityTypeLabelKey , corev1 .NodeSelectorOpIn , v1 .CapacityTypeSpot ))
40
40
OnDemandRequirement = scheduling .NewRequirements (scheduling .NewRequirement (v1 .CapacityTypeLabelKey , corev1 .NodeSelectorOpIn , v1 .CapacityTypeOnDemand ))
41
-
42
- TrueStaticAvailabilityResolver OfferingAvailabilityResolver = staticAvailabilityResolver {available : true }
43
- FalseStaticAvailabilityResolver OfferingAvailabilityResolver = staticAvailabilityResolver {available : false }
44
41
)
45
42
46
43
type DriftReason string
@@ -249,81 +246,74 @@ func (i InstanceTypeOverhead) Total() corev1.ResourceList {
249
246
return resources .Merge (i .KubeReserved , i .SystemReserved , i .EvictionThreshold )
250
247
}
251
248
252
- // An OfferingAvailabilityResolver is used to determine if there is available capacity for a given offering. To ensure
253
- // consistency between multiple controllers attempting to provision a NodeClaim with a given offering, offerings should
254
- // be "reserved" by the controller. Once a launch decision has been made, all offerings which were reserved may be
255
- // released, enabling their use once again.
256
- type OfferingAvailabilityResolver interface {
257
- Available () bool
249
+ // ReservationManager is used to track the availability of a reserved offering over the course of a scheduling
250
+ // simulation. Reserved offerings may have a limited number of available instances associated with them,
251
+ // This is exposed as an interface for cloudprovider's to implement to give flexibility when dealing with separate
252
+ // offerings with associated availablility.
253
+ type ReservationManager interface {
254
+ // Reserve takes a unique identifier for a reservation, and returns a boolean indicating if the reservation was
255
+ // successful. Reserve should be idempotent, i.e. multiple calls with the same reservation ID should only count for a
256
+ // single reservation.
258
257
Reserve (string ) bool
259
- GetReservation (string ) OfferingReservation
260
- }
261
-
262
- type OfferingReservation interface {
263
- Release ()
264
- Commit ()
265
- Matches (* v1.NodeClaim ) bool
266
- }
267
-
268
- type OfferingReservations []OfferingReservation
269
-
270
- func (r OfferingReservations ) Commit () {
271
- for _ , reservation := range r {
272
- reservation .Commit ()
273
- }
274
- }
275
-
276
- func (r OfferingReservations ) Release () {
277
- for _ , reservation := range r {
278
- reservation .Release ()
279
- }
280
- }
281
-
282
- func (r OfferingReservations ) Matching (nc * v1.NodeClaim ) OfferingReservations {
283
- return lo .Filter (r , func (reservation OfferingReservation , _ int ) bool {
284
- return reservation .Matches (nc )
285
- })
258
+ // Release takes a unique identifier for a reservation, and should discard any matching reservations. If no
259
+ // reservations exist for the given id, release should be a no-op.
260
+ Release (string )
286
261
}
287
262
288
-
289
263
// An Offering describes where an InstanceType is available to be used, with the expectation that its properties
290
264
// may be tightly coupled (e.g. the availability of an instance type in some zone is scoped to a capacity type) and
291
265
// these properties are captured with labels in Requirements.
292
- // Requirements are required to contain the keys v1.CapacityTypeLabelKey and corev1.LabelTopologyZone
266
+ // Requirements are required to contain the keys v1.CapacityTypeLabelKey and corev1.LabelTopologyZone.
293
267
type Offering struct {
294
- OfferingAvailabilityResolver
268
+ // ReservationManager is used for tracking availabity of reserved offerings over the course of a scheduling loop. It
269
+ // must be non-nil for offerings with capacity type "reserved", but may be nil otherwise.
270
+ ReservationManager
295
271
296
272
Requirements scheduling.Requirements
297
273
Price float64
274
+ Available bool
298
275
}
299
276
300
277
type Offerings []Offering
301
278
302
- // Reserve attempts to make a reservation for each offering, returning true if it was successful for any.
303
- func (ofs Offerings ) Reserve (id string ) bool {
304
- success := false
305
- for i := range ofs {
306
- success = success || ofs [i ].Reserve (id )
307
- }
308
- return success
279
+ // WithCapacityType filters the offerings by the provided capacity type.
280
+ func (ofs Offerings ) WithCapacityType (capacityType string ) Offerings {
281
+ return lo .Filter (ofs , func (o Offering , _ int ) bool {
282
+ return o .Requirements .Get (v1 .CapacityTypeLabelKey ).Any () == capacityType
283
+ })
309
284
}
310
285
311
- func (ofs Offerings ) Reservations (id string ) OfferingReservations {
312
- return lo .FilterMap (ofs , func (o Offering , _ int ) (OfferingReservation , bool ) {
313
- if reservation := o .GetReservation (id ); reservation != nil {
314
- return reservation , true
315
- }
316
- return nil , false
286
+ // Reserve attempts to make a reservation for each offering, returning true if it was successful for any.
287
+ func (ofs Offerings ) Reserve (id string ) Offerings {
288
+ return lo .Filter (ofs , func (o Offering , _ int ) bool {
289
+ return o .Reserve (id )
317
290
})
318
291
}
319
292
293
+ func (ofs Offerings ) Release (id string ) {
294
+ for i := range ofs {
295
+ ofs [i ].Release (id )
296
+ }
297
+ }
298
+
320
299
// Available filters the available offerings from the returned offerings
321
300
func (ofs Offerings ) Available () Offerings {
322
301
return lo .Filter (ofs , func (o Offering , _ int ) bool {
323
- return o .Available ()
302
+ return o .Available
324
303
})
325
304
}
326
305
306
+ func (ofs Offerings ) PartitionCompatible (reqs scheduling.Requirements ) (compatible Offerings , incompatible Offerings ) {
307
+ for _ , o := range ofs {
308
+ if reqs .IsCompatible (o .Requirements , scheduling .AllowUndefinedWellKnownLabels ) {
309
+ compatible = append (compatible , o )
310
+ } else {
311
+ incompatible = append (incompatible , o )
312
+ }
313
+ }
314
+ return
315
+ }
316
+
327
317
// Compatible returns the offerings based on the passed requirements
328
318
func (ofs Offerings ) Compatible (reqs scheduling.Requirements ) Offerings {
329
319
return lo .Filter (ofs , func (offering Offering , _ int ) bool {
@@ -465,42 +455,3 @@ func NewCreateError(err error, reason, message string) *CreateError {
465
455
ConditionMessage : message ,
466
456
}
467
457
}
468
-
469
- type staticAvailabilityResolver struct {
470
- requirements scheduling.Requirements
471
- available bool
472
- }
473
-
474
- type noopReservation struct {
475
- requirements scheduling.Requirements
476
- }
477
-
478
- func (r staticAvailabilityResolver ) Available () bool {
479
- return r .available
480
- }
481
-
482
- func (r staticAvailabilityResolver ) Reserve (_ string ) bool {
483
- return r .available
484
- }
485
-
486
- func (r staticAvailabilityResolver ) GetReservation (_ string ) OfferingReservation {
487
- return noopReservation {
488
- requirements : r .requirements ,
489
- }
490
- }
491
-
492
- func (r noopReservation ) Commit () {}
493
-
494
- func (r noopReservation ) Release () {}
495
-
496
- func (r noopReservation ) Matches (nc * v1.NodeClaim ) bool {
497
- reqs := scheduling .NewLabelRequirements (nc .Labels )
498
- return reqs .IsCompatible (r .requirements , scheduling .AllowUndefinedWellKnownLabels )
499
- }
500
-
501
- func NewStaticAvailabilityResolver (available bool , requirements scheduling.Requirements ) OfferingAvailabilityResolver {
502
- return staticAvailabilityResolver {
503
- available : available ,
504
- requirements : requirements ,
505
- }
506
- }
0 commit comments