@@ -17,6 +17,20 @@ import (
1717 "sigs.k8s.io/controller-runtime/pkg/client"
1818)
1919
20+ // ApplyResult contains the result of applying a commitment state.
21+ type ApplyResult struct {
22+ // Created is the number of reservations created
23+ Created int
24+ // Deleted is the number of reservations deleted
25+ Deleted int
26+ // Repaired is the number of reservations repaired (metadata sync or recreated due to wrong config)
27+ Repaired int
28+ // TouchedReservations are reservations that were created or updated
29+ TouchedReservations []v1alpha1.Reservation
30+ // RemovedReservations are reservations that were deleted
31+ RemovedReservations []v1alpha1.Reservation
32+ }
33+
2034// ReservationManager handles CRUD operations for Reservation CRDs.
2135type ReservationManager struct {
2236 client.Client
@@ -42,14 +56,16 @@ func NewReservationManager(k8sClient client.Client) *ReservationManager {
4256// - Deleting unused/excess slots when capacity decreases
4357// - Syncing reservation metadata for all remaining slots
4458//
45- // Returns touched reservations (created/updated) and removed reservations for caller tracking .
59+ // Returns ApplyResult containing touched/ removed reservations and counts for metrics .
4660func (m * ReservationManager ) ApplyCommitmentState (
4761 ctx context.Context ,
4862 log logr.Logger ,
4963 desiredState * CommitmentState ,
5064 flavorGroups map [string ]compute.FlavorGroupFeature ,
5165 creator string ,
52- ) (touchedReservations , removedReservations []v1alpha1.Reservation , err error ) {
66+ ) (* ApplyResult , error ) {
67+
68+ result := & ApplyResult {}
5369
5470 log = log .WithName ("ReservationManager" )
5571
@@ -58,7 +74,7 @@ func (m *ReservationManager) ApplyCommitmentState(
5874 if err := m .List (ctx , & allReservations , client.MatchingLabels {
5975 v1alpha1 .LabelReservationType : v1alpha1 .ReservationTypeLabelCommittedResource ,
6076 }); err != nil {
61- return nil , nil , fmt .Errorf ("failed to list reservations: %w" , err )
77+ return nil , fmt .Errorf ("failed to list reservations: %w" , err )
6278 }
6379
6480 // Filter by name prefix to find reservations for this commitment
@@ -74,7 +90,7 @@ func (m *ReservationManager) ApplyCommitmentState(
7490 flavorGroup , exists := flavorGroups [desiredState .FlavorGroupName ]
7591
7692 if ! exists {
77- return nil , nil , fmt .Errorf ("flavor group not found: %s" , desiredState .FlavorGroupName )
93+ return nil , fmt .Errorf ("flavor group not found: %s" , desiredState .FlavorGroupName )
7894 }
7995 deltaMemoryBytes := desiredState .TotalMemoryBytes
8096 for _ , res := range existing {
@@ -90,7 +106,6 @@ func (m *ReservationManager) ApplyCommitmentState(
90106 // Phase 3 (DELETE): Delete inconsistent reservations (wrong flavor group/project)
91107 // They will be recreated with correct metadata in subsequent phases.
92108 var validReservations []v1alpha1.Reservation
93- var repairedCount int
94109 for _ , res := range existing {
95110 if res .Spec .CommittedResourceReservation .ResourceGroup != desiredState .FlavorGroupName ||
96111 res .Spec .CommittedResourceReservation .ProjectID != desiredState .ProjectID {
@@ -101,13 +116,13 @@ func (m *ReservationManager) ApplyCommitmentState(
101116 "actualFlavorGroup" , res .Spec .CommittedResourceReservation .ResourceGroup ,
102117 "expectedProjectID" , desiredState .ProjectID ,
103118 "actualProjectID" , res .Spec .CommittedResourceReservation .ProjectID )
104- repairedCount ++
105- removedReservations = append (removedReservations , res )
119+ result . Repaired ++
120+ result . RemovedReservations = append (result . RemovedReservations , res )
106121 memValue := res .Spec .Resources [hv1 .ResourceMemory ]
107122 deltaMemoryBytes += memValue .Value ()
108123
109124 if err := m .Delete (ctx , & res ); err != nil {
110- return touchedReservations , removedReservations , fmt .Errorf ("failed to delete reservation %s: %w" , res .Name , err )
125+ return result , fmt .Errorf ("failed to delete reservation %s: %w" , res .Name , err )
111126 }
112127 } else {
113128 validReservations = append (validReservations , res )
@@ -139,33 +154,33 @@ func (m *ReservationManager) ApplyCommitmentState(
139154 reservationToDelete = & existing [len (existing )- 1 ]
140155 existing = existing [:len (existing )- 1 ] // remove from existing list
141156 }
142- removedReservations = append (removedReservations , * reservationToDelete )
157+ result .RemovedReservations = append (result .RemovedReservations , * reservationToDelete )
158+ result .Deleted ++
143159 memValue := reservationToDelete .Spec .Resources [hv1 .ResourceMemory ]
144160 deltaMemoryBytes += memValue .Value ()
145161
146162 if err := m .Delete (ctx , reservationToDelete ); err != nil {
147- return touchedReservations , removedReservations , fmt .Errorf ("failed to delete reservation %s: %w" , reservationToDelete .Name , err )
163+ return result , fmt .Errorf ("failed to delete reservation %s: %w" , reservationToDelete .Name , err )
148164 }
149165 }
150166
151167 // Phase 5 (CREATE): Create new reservations (capacity increased)
152- var createdCount int
153168 for deltaMemoryBytes > 0 {
154169 // Need to create new reservation slots, always prefer largest flavor within the group
155170 // TODO more sophisticated flavor selection, especially with flavors of different cpu/memory ratio
156171 reservation := m .newReservation (desiredState , nextSlotIndex , deltaMemoryBytes , flavorGroup , creator )
157- touchedReservations = append (touchedReservations , * reservation )
172+ result . TouchedReservations = append (result . TouchedReservations , * reservation )
158173 memValue := reservation .Spec .Resources [hv1 .ResourceMemory ]
159174 deltaMemoryBytes -= memValue .Value ()
160- createdCount ++
175+ result . Created ++
161176
162177 if err := m .Create (ctx , reservation ); err != nil {
163178 if apierrors .IsAlreadyExists (err ) {
164- return touchedReservations , removedReservations , fmt .Errorf (
179+ return result , fmt .Errorf (
165180 "reservation %s already exists (collision detected): %w" ,
166181 reservation .Name , err )
167182 }
168- return touchedReservations , removedReservations , fmt .Errorf (
183+ return result , fmt .Errorf (
169184 "failed to create reservation slot %d: %w" ,
170185 nextSlotIndex , err )
171186 }
@@ -177,24 +192,25 @@ func (m *ReservationManager) ApplyCommitmentState(
177192 for i := range existing {
178193 updated , err := m .syncReservationMetadata (ctx , log , & existing [i ], desiredState )
179194 if err != nil {
180- return touchedReservations , removedReservations , err
195+ return result , err
181196 }
182197 if updated != nil {
183- touchedReservations = append (touchedReservations , * updated )
198+ result .TouchedReservations = append (result .TouchedReservations , * updated )
199+ result .Repaired ++
184200 }
185201 }
186202
187203 // Only log if there were actual changes
188- if hasChanges || createdCount > 0 || len (removedReservations ) > 0 || repairedCount > 0 {
204+ if hasChanges || result . Created > 0 || len (result . RemovedReservations ) > 0 || result . Repaired > 0 {
189205 log .Info ("commitment state sync completed" ,
190206 "commitmentUUID" , desiredState .CommitmentUUID ,
191- "created" , createdCount ,
192- "deleted" , len ( removedReservations ) ,
193- "repaired" , repairedCount ,
194- "total" , len (existing )+ createdCount )
207+ "created" , result . Created ,
208+ "deleted" , result . Deleted ,
209+ "repaired" , result . Repaired ,
210+ "total" , len (existing )+ result . Created )
195211 }
196212
197- return touchedReservations , removedReservations , nil
213+ return result , nil
198214}
199215
200216// syncReservationMetadata updates reservation metadata if it differs from desired state.
0 commit comments