@@ -18,10 +18,11 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
- "fmt"
22
21
"strings"
23
22
"time"
24
23
24
+ ocmsdk "github.com/openshift-online/ocm-sdk-go"
25
+
25
26
"github.com/project-codeflare/instascale/pkg/config"
26
27
arbv1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1"
27
28
corev1 "k8s.io/api/core/v1"
@@ -37,15 +38,19 @@ import (
37
38
"sigs.k8s.io/controller-runtime/pkg/log"
38
39
)
39
40
41
+ type MachineType string
42
+
40
43
// AppWrapperReconciler reconciles a AppWrapper object
41
44
type AppWrapperReconciler struct {
42
45
client.Client
43
- Scheme * runtime.Scheme
44
- Config config.InstaScaleConfiguration
45
- kubeClient * kubernetes.Clientset
46
- ocmClusterID string
47
- ocmToken string
48
- useMachineSets bool
46
+ Scheme * runtime.Scheme
47
+ Config config.InstaScaleConfiguration
48
+ kubeClient * kubernetes.Clientset
49
+ ocmClusterID string
50
+ ocmToken string
51
+ ocmConnection * ocmsdk.Connection
52
+ MachineType MachineType
53
+ machineCheck bool
49
54
}
50
55
51
56
var (
54
59
)
55
60
56
61
const (
57
- namespaceToList = "openshift-machine-api"
58
- minResyncPeriod = 10 * time .Minute
59
- finalizerName = "instascale.codeflare.dev/finalizer"
62
+ namespaceToList = "openshift-machine-api"
63
+ minResyncPeriod = 10 * time .Minute
64
+ finalizerName = "instascale.codeflare.dev/finalizer"
65
+ MachineTypeMachineSet MachineType = "MachineSet"
66
+ MachineTypeMachinePool MachineType = "MachinePool"
67
+ MachineTypeNodePool MachineType = "NodePool"
60
68
)
61
69
62
70
// +kubebuilder:rbac:groups=workload.codeflare.dev,resources=appwrappers,verbs=get;list;watch;create;update;patch;delete
@@ -81,14 +89,17 @@ const (
81
89
// - https://pkg.go.dev/sigs.k8s.io/[email protected] /pkg/reconcile
82
90
func (r * AppWrapperReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
83
91
_ = log .FromContext (ctx )
84
- // todo: Move the getOCMClusterID call out of reconcile loop.
92
+ // todo: Move the setMachineType call out of reconcile loop.
85
93
// Only reason we are calling it here is that the client is not able to make
86
94
// calls until it is started, so SetupWithManager is not working.
87
- if ! r . useMachineSets && r .ocmClusterID == "" {
88
- if err := r .getOCMClusterID (ctx ); err != nil {
89
- return ctrl.Result {Requeue : true , RequeueAfter : timeFiveSeconds }, err
95
+ if r . machineCheck == false && r .MachineType != MachineTypeMachineSet {
96
+ if err := r .setMachineType (ctx ); err != nil {
97
+ return ctrl.Result {}, err
90
98
}
91
99
}
100
+
101
+ r .machineCheck = true
102
+
92
103
var appwrapper arbv1.AppWrapper
93
104
94
105
if err := r .Get (ctx , req .NamespacedName , & appwrapper ); err != nil {
@@ -125,8 +136,14 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
125
136
if status == "Pending" && containsInsufficientCondition (allconditions ) {
126
137
demandPerInstanceType := r .discoverInstanceTypes (ctx , & appwrapper )
127
138
if ocmSecretRef := r .Config .OCMSecretRef ; ocmSecretRef != nil {
128
- return r .scaleMachinePool (ctx , & appwrapper , demandPerInstanceType )
139
+ switch r .MachineType {
140
+ case MachineTypeNodePool :
141
+ return r .scaleNodePool (ctx , & appwrapper , demandPerInstanceType )
142
+ case MachineTypeMachinePool :
143
+ return r .scaleMachinePool (ctx , & appwrapper , demandPerInstanceType )
144
+ }
129
145
} else {
146
+ // use MachineSets
130
147
switch strings .ToLower (r .Config .MachineSetsStrategy ) {
131
148
case "reuse" :
132
149
return r .reconcileReuseMachineSet (ctx , & appwrapper , demandPerInstanceType )
@@ -146,7 +163,8 @@ func (r *AppWrapperReconciler) finalizeScalingDownMachines(ctx context.Context,
146
163
} else {
147
164
deletionMessage = "deleted"
148
165
}
149
- if r .useMachineSets {
166
+ switch r .MachineType {
167
+ case MachineTypeMachineSet :
150
168
switch strings .ToLower (r .Config .MachineSetsStrategy ) {
151
169
case "reuse" :
152
170
matchedAw := r .findExactMatch (ctx , appwrapper )
@@ -158,6 +176,9 @@ func (r *AppWrapperReconciler) finalizeScalingDownMachines(ctx context.Context,
158
176
"newAppWrapper" , matchedAw ,
159
177
)
160
178
if err := r .swapNodeLabels (ctx , appwrapper , matchedAw ); err != nil {
179
+ logger .Error (err , "Error swapping node labels for AppWrapper" ,
180
+ "appwrapper" , appwrapper ,
181
+ )
161
182
return err
162
183
}
163
184
} else {
@@ -167,6 +188,9 @@ func (r *AppWrapperReconciler) finalizeScalingDownMachines(ctx context.Context,
167
188
"deletionMessage" , deletionMessage ,
168
189
)
169
190
if err := r .annotateToDeleteMachine (ctx , appwrapper ); err != nil {
191
+ logger .Error (err , "Error annotating to delete machine for AppWrapper" ,
192
+ "appwrapper" , appwrapper ,
193
+ )
170
194
return err
171
195
}
172
196
}
@@ -177,19 +201,53 @@ func (r *AppWrapperReconciler) finalizeScalingDownMachines(ctx context.Context,
177
201
"deletionMessage" , deletionMessage ,
178
202
)
179
203
if err := r .deleteMachineSet (ctx , appwrapper ); err != nil {
204
+ logger .Error (err , "Error deleting MachineSet for AppWrapper" ,
205
+ "appwrapper" , appwrapper )
180
206
return err
181
207
}
182
208
}
183
- } else {
209
+ case MachineTypeNodePool :
210
+ logger .Info (
211
+ "AppWrapper deleted, scaling down nodepool" ,
212
+ "appWrapper" , appwrapper ,
213
+ "deletionMessage" , deletionMessage ,
214
+ )
215
+ if _ , err := r .deleteNodePool (ctx , appwrapper ); err != nil {
216
+ logger .Error (err , "Error deleting NodePool for AppWrapper" ,
217
+ "appwrapper" , appwrapper )
218
+ return err
219
+ }
220
+
221
+ case MachineTypeMachinePool :
184
222
logger .Info (
185
223
"AppWrapper deleted, scaling down machine pool" ,
186
224
"appWrapper" , appwrapper ,
187
225
"deletionMessage" , deletionMessage ,
188
226
)
189
227
if _ , err := r .deleteMachinePool (ctx , appwrapper ); err != nil {
228
+ logger .Error (err , "Error deleting MachinePool for AppWrapper" ,
229
+ "appwrapper" , appwrapper )
230
+ return err
231
+ }
232
+ }
233
+ return nil
234
+ }
235
+
236
+ func (r * AppWrapperReconciler ) setMachineType (ctx context.Context ) error {
237
+ logger := ctrl .LoggerFrom (ctx )
238
+ if r .ocmClusterID == "" {
239
+ if err := r .getOCMClusterID (ctx ); err != nil {
190
240
return err
191
241
}
192
242
}
243
+ hypershiftEnabled , err := r .checkHypershiftEnabled (ctx )
244
+ if err != nil {
245
+ logger .Error (err , "error checking if hypershift is enabled" )
246
+ return err
247
+ }
248
+ if hypershiftEnabled {
249
+ r .MachineType = MachineTypeNodePool
250
+ }
193
251
return nil
194
252
}
195
253
@@ -206,20 +264,19 @@ func (r *AppWrapperReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma
206
264
}
207
265
208
266
maxScaleNodesAllowed = int (r .Config .MaxScaleoutAllowed )
209
- r .useMachineSets = true
267
+ r .MachineType = MachineTypeMachineSet // default to MachineSet
210
268
if ocmSecretRef := r .Config .OCMSecretRef ; ocmSecretRef != nil {
211
- r .useMachineSets = false
212
269
if ocmSecret , err := r .getOCMSecret (ctx , ocmSecretRef ); err != nil {
213
- return fmt .Errorf ("error reading OCM Secret from ref %q: %w" , ocmSecretRef , err )
270
+ logger .Error (err , "error reading OCM Secret from ref" ,
271
+ "ref" , ocmSecretRef )
272
+ return err
214
273
} else if token := ocmSecret .Data ["token" ]; len (token ) > 0 {
215
274
r .ocmToken = string (token )
275
+ r .MachineType = MachineTypeMachinePool
216
276
} else {
217
- return fmt .Errorf ("token is missing from OCM Secret %q" , ocmSecretRef )
218
- }
219
- if ok , err := r .machinePoolExists (); err != nil {
277
+ logger .Error (err , "token is missing from OCM Secret" ,
278
+ "ref" , ocmSecretRef )
220
279
return err
221
- } else if ok {
222
- logger .Info ("Using machine pools for cluster auto-scaling" )
223
280
}
224
281
}
225
282
@@ -235,12 +292,8 @@ func (r *AppWrapperReconciler) getOCMSecret(ctx context.Context, secretRef *core
235
292
func (r * AppWrapperReconciler ) discoverInstanceTypes (ctx context.Context , aw * arbv1.AppWrapper ) map [string ]int {
236
293
logger := ctrl .LoggerFrom (ctx )
237
294
demandMapPerInstanceType := make (map [string ]int )
238
- var instanceRequired []string
239
- for k , v := range aw .Labels {
240
- if k == "orderedinstance" {
241
- instanceRequired = strings .Split (v , "_" )
242
- }
243
- }
295
+
296
+ instanceRequired := getInstanceRequired (aw .Labels )
244
297
245
298
if len (instanceRequired ) < 1 {
246
299
logger .Info (
0 commit comments