Skip to content

Commit 9ed2482

Browse files
committed
Fix nil pointer panic and spurious Auto Mode updates
- Add isAutoModeCluster() function to detect valid Auto Mode configurations - Add validateAutoModeConfig() to enforce AWS requirement that compute, storage, and load balancing must all be enabled/disabled together - Only call updateComputeConfig() for actual Auto Mode clusters - Ignore elasticLoadBalancing absent vs false diffs for non-Auto Mode clusters Fixes aws-controllers-k8s/community#2619
1 parent c5f0dd6 commit 9ed2482

File tree

1 file changed

+90
-14
lines changed

1 file changed

+90
-14
lines changed

pkg/resource/cluster/hook.go

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,72 @@ func (rm *resourceManager) clusterInUse(ctx context.Context, r *resource) (bool,
184184
return (nodes != nil && len(nodes.Nodegroups) > 0), nil
185185
}
186186

187+
// isAutoModeCluster returns true if the cluster is configured for EKS Auto Mode.
188+
// According to AWS documentation, compute, block storage, and load balancing capabilities
189+
// must all be enabled or disabled together. Any partial configuration is invalid.
190+
func isAutoModeCluster(r *resource) bool {
191+
if r == nil || r.ko == nil {
192+
return false
193+
}
194+
195+
// If ComputeConfig is not specified, this is not an Auto Mode cluster
196+
if r.ko.Spec.ComputeConfig == nil {
197+
return false
198+
}
199+
200+
// Check compute configuration
201+
computeEnabled := r.ko.Spec.ComputeConfig.Enabled != nil && *r.ko.Spec.ComputeConfig.Enabled
202+
203+
// Check storage configuration
204+
storageEnabled := false
205+
if r.ko.Spec.StorageConfig != nil && r.ko.Spec.StorageConfig.BlockStorage != nil {
206+
storageEnabled = r.ko.Spec.StorageConfig.BlockStorage.Enabled != nil && *r.ko.Spec.StorageConfig.BlockStorage.Enabled
207+
}
208+
209+
// Check elastic load balancing configuration
210+
elbEnabled := false
211+
if r.ko.Spec.KubernetesNetworkConfig != nil && r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing != nil {
212+
elbEnabled = r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing.Enabled != nil && *r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing.Enabled
213+
}
214+
215+
// Auto Mode requires all three capabilities to have the same state (all true or all false)
216+
// If they are all true, Auto Mode is enabled
217+
// If they are all false, Auto Mode is being disabled
218+
// Any other combination is invalid
219+
return (computeEnabled && storageEnabled && elbEnabled) || (!computeEnabled && !storageEnabled && !elbEnabled)
220+
}
221+
222+
// validateAutoModeConfig validates that Auto Mode configuration is consistent.
223+
// Returns an error if the configuration is invalid (partial enablement).
224+
func validateAutoModeConfig(r *resource) error {
225+
if r == nil || r.ko == nil || r.ko.Spec.ComputeConfig == nil {
226+
return nil // Not an Auto Mode configuration
227+
}
228+
229+
// Check compute configuration
230+
computeEnabled := r.ko.Spec.ComputeConfig.Enabled != nil && *r.ko.Spec.ComputeConfig.Enabled
231+
232+
// Check storage configuration
233+
storageEnabled := false
234+
if r.ko.Spec.StorageConfig != nil && r.ko.Spec.StorageConfig.BlockStorage != nil {
235+
storageEnabled = r.ko.Spec.StorageConfig.BlockStorage.Enabled != nil && *r.ko.Spec.StorageConfig.BlockStorage.Enabled
236+
}
237+
238+
// Check elastic load balancing configuration
239+
elbEnabled := false
240+
if r.ko.Spec.KubernetesNetworkConfig != nil && r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing != nil {
241+
elbEnabled = r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing.Enabled != nil && *r.ko.Spec.KubernetesNetworkConfig.ElasticLoadBalancing.Enabled
242+
}
243+
244+
// All three must be in the same state
245+
if computeEnabled == storageEnabled && storageEnabled == elbEnabled {
246+
return nil // Valid configuration
247+
}
248+
249+
return fmt.Errorf("invalid Auto Mode configuration: compute, block storage, and load balancing capabilities must all be enabled or disabled together (compute=%v, storage=%v, elb=%v)",
250+
computeEnabled, storageEnabled, elbEnabled)
251+
}
252+
187253
func customPreCompare(
188254
a *resource,
189255
b *resource,
@@ -380,25 +446,35 @@ func (rm *resourceManager) customUpdate(
380446
return returnClusterUpdating(updatedRes)
381447
}
382448

383-
// Handle computeConfig updates
449+
// Handle computeConfig updates - only for Auto Mode clusters
384450
if delta.DifferentAt("Spec.ComputeConfig") || delta.DifferentAt("Spec.StorageConfig") || delta.DifferentAt("Spec.KubernetesNetworkConfig") {
385-
if err := rm.updateComputeConfig(ctx, desired); err != nil {
386-
awsErr, ok := extractAWSError(err)
387-
rlog.Info("attempting to update AutoMode config",
388-
"error", err,
389-
"isAWSError", ok,
390-
"awsErrorCode", awsErr.Code)
451+
// Validate Auto Mode configuration consistency before attempting update
452+
if err := validateAutoModeConfig(desired); err != nil {
453+
return nil, ackerr.NewTerminalError(err)
454+
}
391455

392-
// Check to see if we've raced an async update call and need to requeue
393-
if ok && awsErr.Code == "ResourceInUseException" {
394-
rlog.Info("resource in use, requeueing after async update")
395-
return nil, requeueAfterAsyncUpdate()
456+
// Only proceed with Auto Mode updates if the cluster is actually configured for Auto Mode
457+
if isAutoModeCluster(desired) {
458+
if err := rm.updateComputeConfig(ctx, desired); err != nil {
459+
awsErr, ok := extractAWSError(err)
460+
rlog.Info("attempting to update AutoMode config",
461+
"error", err,
462+
"isAWSError", ok,
463+
"awsErrorCode", awsErr.Code)
464+
465+
// Check to see if we've raced an async update call and need to requeue
466+
if ok && awsErr.Code == "ResourceInUseException" {
467+
rlog.Info("resource in use, requeueing after async update")
468+
return nil, requeueAfterAsyncUpdate()
469+
}
470+
471+
return nil, fmt.Errorf("failed to update AutoMode config: %w", err)
396472
}
397473

398-
return nil, fmt.Errorf("failed to update AutoMode config: %w", err)
474+
return returnClusterUpdating(updatedRes)
399475
}
400-
401-
return returnClusterUpdating(updatedRes)
476+
// If not Auto Mode, ignore the diff (likely elasticLoadBalancing false vs absent)
477+
rlog.Debug("ignoring diff on compute/storage/network config for non-Auto Mode cluster")
402478
}
403479

404480
// Handle zonalShiftConfig updates

0 commit comments

Comments
 (0)