Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -847,8 +847,8 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques
propagateControlPlaneVersion(hcluster, hcp)

// Set the AutoNodeEnabled condition reflecting both spec intent and actual component rollout progress.
meta.SetStatusCondition(&hcluster.Status.Conditions,
r.reconcileAutoNodeEnabledCondition(ctx, hcluster, controlPlaneNamespace.Name))
autoNodeCondition, autoNodeProgressing := r.reconcileAutoNodeEnabledCondition(ctx, hcluster, controlPlaneNamespace.Name)
meta.SetStatusCondition(&hcluster.Status.Conditions, autoNodeCondition)

// Copy the AWSDefaultSecurityGroupCreated condition from the hostedcontrolplane
if hcluster.Spec.Platform.Type == hyperv1.AWSPlatform {
Expand Down Expand Up @@ -2103,6 +2103,12 @@ func (r *HostedClusterReconciler) reconcile(ctx context.Context, req ctrl.Reques
if requeueAfter != nil {
result.RequeueAfter = *requeueAfter
}
if autoNodeProgressing {
autoNodeRequeue := 15 * time.Second
if result.RequeueAfter == 0 || autoNodeRequeue < result.RequeueAfter {
result.RequeueAfter = autoNodeRequeue
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return result, nil
}

Expand Down
22 changes: 14 additions & 8 deletions hypershift-operator/controllers/hostedcluster/karpenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ func isKASAvailable(ctx context.Context, cpNamespace string, c client.Client) (b
// - True / AsExpected — Karpenter enabled in spec AND both components fully rolled out.
// - False / AutoNodeProgressing — Enable or disable operation is in progress.
// - False / AutoNodeNotConfigured — Karpenter not in spec AND no components present.
func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.Context, hcluster *hyperv1.HostedCluster, hcpNamespace string) metav1.Condition {
//
// reconcileAutoNodeEnabledCondition returns the AutoNodeEnabled condition and whether
// the caller should requeue to poll for progress. The second return value is true when
// an enable or disable operation is still in flight; the HC reconciler does not watch
// ControlPlaneComponent resources, so a periodic requeue is needed to pick up status
// changes from the karpenter-operator's CPC updates.
func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.Context, hcluster *hyperv1.HostedCluster, hcpNamespace string) (metav1.Condition, bool) {
condition := metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
ObservedGeneration: hcluster.Generation,
Expand All @@ -178,7 +184,7 @@ func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.
condition.Status = metav1.ConditionUnknown
condition.Reason = hyperv1.AutoNodeEvaluationFailedReason
condition.Message = fmt.Sprintf("failed to list ControlPlaneComponents: %v", err)
return condition
return condition, false
}

// Grab all of our karpenter components
Expand All @@ -195,7 +201,7 @@ func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.
condition.Status = metav1.ConditionFalse
condition.Reason = hyperv1.AutoNodeProgressingReason
condition.Message = "AutoNode is being enabled: waiting for components to be created"
return condition
return condition, true
}
// Check if they're ready
var notReady []string
Expand All @@ -214,13 +220,13 @@ func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.
condition.Status = metav1.ConditionFalse
condition.Reason = hyperv1.AutoNodeProgressingReason
condition.Message = fmt.Sprintf("AutoNode is being enabled: %s", strings.Join(notReady, "; "))
return condition
return condition, true
}
// Otherwise report ready
condition.Status = metav1.ConditionTrue
condition.Reason = hyperv1.AsExpectedReason
condition.Message = "AutoNode is ready"
return condition
return condition, false
}

// Karpenter not enabled — check if Deployments are still terminating.
Expand All @@ -236,19 +242,19 @@ func (r *HostedClusterReconciler) reconcileAutoNodeEnabledCondition(ctx context.
condition.Status = metav1.ConditionUnknown
condition.Reason = hyperv1.AutoNodeEvaluationFailedReason
condition.Message = fmt.Sprintf("failed to check karpenter deployments: %v", err)
return condition
return condition, false
}
}

if len(runningDeployments) > 0 {
condition.Status = metav1.ConditionFalse
condition.Reason = hyperv1.AutoNodeProgressingReason
condition.Message = fmt.Sprintf("AutoNode is being disabled: waiting for deployments to be removed: %s", strings.Join(runningDeployments, ", "))
return condition
return condition, true
}

condition.Status = metav1.ConditionFalse
condition.Reason = hyperv1.AutoNodeNotConfiguredReason
condition.Message = "AutoNode provisioner is not configured"
return condition
return condition, false
}
25 changes: 17 additions & 8 deletions hypershift-operator/controllers/hostedcluster/karpenter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,14 +297,16 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
}

tests := map[string]struct {
autoNode hyperv1.AutoNode
components []hyperv1.ControlPlaneComponent
deployments []appsv1.Deployment
want metav1.Condition
autoNode hyperv1.AutoNode
components []hyperv1.ControlPlaneComponent
deployments []appsv1.Deployment
want metav1.Condition
wantProgessing bool
}{
"When karpenter is enabled and components not yet created it should report progressing": {
autoNode: karpenterEnabledAutoNode,
components: nil,
autoNode: karpenterEnabledAutoNode,
components: nil,
wantProgessing: true,
want: metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
Status: metav1.ConditionFalse,
Expand All @@ -319,6 +321,7 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
Status: hyperv1.ControlPlaneComponentStatus{Conditions: []metav1.Condition{rolloutCompleteTrue}},
},
},
wantProgessing: true,
want: metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
Status: metav1.ConditionFalse,
Expand All @@ -337,6 +340,7 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
Status: hyperv1.ControlPlaneComponentStatus{Conditions: []metav1.Condition{rolloutCompleteFalse}},
},
},
wantProgessing: true,
want: metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
Status: metav1.ConditionFalse,
Expand Down Expand Up @@ -367,6 +371,7 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
{ObjectMeta: metav1.ObjectMeta{Name: karpenterv2.ComponentName, Namespace: hcpNamespace}},
{ObjectMeta: metav1.ObjectMeta{Name: karpenteroperatorv2.ComponentName, Namespace: hcpNamespace}},
},
wantProgessing: true,
want: metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
Status: metav1.ConditionFalse,
Expand All @@ -378,6 +383,7 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
deployments: []appsv1.Deployment{
{ObjectMeta: metav1.ObjectMeta{Name: karpenterv2.ComponentName, Namespace: hcpNamespace}},
},
wantProgessing: true,
want: metav1.Condition{
Type: string(hyperv1.AutoNodeEnabled),
Status: metav1.ConditionFalse,
Expand Down Expand Up @@ -439,13 +445,16 @@ func TestReconcileAutoNodeEnabledCondition(t *testing.T) {
},
}

got := r.reconcileAutoNodeEnabledCondition(context.Background(), hcluster, hcpNamespace)
got, progressing := r.reconcileAutoNodeEnabledCondition(context.Background(), hcluster, hcpNamespace)
got.ObservedGeneration = 0
got.Message = ""
got.LastTransitionTime = metav1.Time{}

if !equality.Semantic.DeepEqual(tc.want, got) {
t.Errorf("expected %+v, got %+v", tc.want, got)
t.Errorf("condition: expected %+v, got %+v", tc.want, got)
}
if progressing != tc.wantProgessing {
t.Errorf("progressing: expected %v, got %v", tc.wantProgessing, progressing)
}
})
}
Expand Down
Loading