-
Notifications
You must be signed in to change notification settings - Fork 228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AUTH-543: Add optional operand deletion condition #1902
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,7 @@ const ( | |
// Delegate captures a set of methods that hold a custom logic | ||
type Delegate interface { | ||
// Sync a method that will be used for delegation. It should bring the desired workload into operation. | ||
Sync(ctx context.Context, controllerContext factory.SyncContext) (*appsv1.Deployment, bool, []error) | ||
Sync(ctx context.Context, controllerContext factory.SyncContext) (*appsv1.Deployment, bool, bool, []error) | ||
|
||
// PreconditionFulfilled a method that indicates whether all prerequisites are met and we can Sync. | ||
// | ||
|
@@ -83,7 +83,7 @@ func NewController(instanceName, operatorNamespace, targetNamespace, targetOpera | |
kubeClient kubernetes.Interface, | ||
podLister corev1listers.PodLister, | ||
informers []factory.Informer, | ||
tagetNamespaceInformers []factory.Informer, | ||
targetNamespaceInformers []factory.Informer, | ||
delegate Delegate, | ||
openshiftClusterConfigClient openshiftconfigclientv1.ClusterOperatorInterface, | ||
eventRecorder events.Recorder, | ||
|
@@ -102,11 +102,11 @@ func NewController(instanceName, operatorNamespace, targetNamespace, targetOpera | |
delegate: delegate, | ||
openshiftClusterConfigClient: openshiftClusterConfigClient, | ||
versionRecorder: versionRecorder, | ||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), instanceName), | ||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[any](), instanceName), | ||
} | ||
|
||
c := factory.New() | ||
for _, nsi := range tagetNamespaceInformers { | ||
for _, nsi := range targetNamespaceInformers { | ||
c.WithNamespaceInformer(nsi, targetNamespace) | ||
} | ||
|
||
|
@@ -130,14 +130,14 @@ func (c *Controller) sync(ctx context.Context, controllerContext factory.SyncCon | |
} | ||
|
||
if fulfilled, err := c.delegate.PreconditionFulfilled(ctx); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't it be better to let the delegate communicate everything as we do with the preconditions? |
||
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, []error{err}) | ||
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, false, []error{err}) | ||
} else if !fulfilled { | ||
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, nil) | ||
return c.updateOperatorStatus(ctx, operatorStatus, nil, false, false, false, nil) | ||
} | ||
|
||
workload, operatorConfigAtHighestGeneration, errs := c.delegate.Sync(ctx, controllerContext) | ||
workload, operatorConfigAtHighestGeneration, removeConditions, errs := c.delegate.Sync(ctx, controllerContext) | ||
|
||
return c.updateOperatorStatus(ctx, operatorStatus, workload, operatorConfigAtHighestGeneration, true, errs) | ||
return c.updateOperatorStatus(ctx, operatorStatus, workload, operatorConfigAtHighestGeneration, true, removeConditions, errs) | ||
} | ||
|
||
// shouldSync checks ManagementState to determine if we can run this operator, probably set by a cluster administrator. | ||
|
@@ -159,22 +159,30 @@ func (c *Controller) shouldSync(ctx context.Context, operatorSpec *operatorv1.Op | |
} | ||
|
||
// updateOperatorStatus updates the status based on the actual workload and errors that might have occurred during synchronization. | ||
func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *operatorv1.OperatorStatus, workload *appsv1.Deployment, operatorConfigAtHighestGeneration bool, preconditionsReady bool, errs []error) (err error) { | ||
func (c *Controller) updateOperatorStatus(ctx context.Context, previousStatus *operatorv1.OperatorStatus, workload *appsv1.Deployment, operatorConfigAtHighestGeneration, preconditionsReady, removeConditions bool, errs []error) (err error) { | ||
if errs == nil { | ||
errs = []error{} | ||
} | ||
|
||
deploymentAvailableCondition := applyoperatorv1.OperatorCondition(). | ||
WithType(fmt.Sprintf("%sDeployment%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeAvailable)) | ||
typeAvailable := fmt.Sprintf("%sDeployment%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeAvailable) | ||
typeDegraded := fmt.Sprintf("%sDeployment%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeDegraded) | ||
typeProgressing := fmt.Sprintf("%sDeployment%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeProgressing) | ||
typeWorkloadDegraded := fmt.Sprintf("%sWorkload%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeDegraded) | ||
|
||
workloadDegradedCondition := applyoperatorv1.OperatorCondition(). | ||
WithType(fmt.Sprintf("%sWorkloadDegraded", c.conditionsPrefix)) | ||
deploymentAvailableCondition := applyoperatorv1.OperatorCondition().WithType(typeAvailable) | ||
workloadDegradedCondition := applyoperatorv1.OperatorCondition().WithType(typeWorkloadDegraded) | ||
deploymentDegradedCondition := applyoperatorv1.OperatorCondition().WithType(typeDegraded) | ||
deploymentProgressingCondition := applyoperatorv1.OperatorCondition().WithType(typeProgressing) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might make more sense to still consider preconditions even when the workload will be deleted later. Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that the delete would happen during the delegate's sync, we shouldn't normally reach the point of removing the conditions if preconditions are failing. But you are right, we should safe-guard against this -- I'll add a check before removing conditions. |
||
deploymentDegradedCondition := applyoperatorv1.OperatorCondition(). | ||
WithType(fmt.Sprintf("%sDeploymentDegraded", c.conditionsPrefix)) | ||
if preconditionsReady && removeConditions && workload == nil { | ||
jsonPatch := v1helpers.RemoveConditionsJSONPatch(previousStatus, []string{typeAvailable, typeDegraded, typeProgressing, typeWorkloadDegraded}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems we cannot use SSA for removing conditions, but I am not sure if patch is better than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The advantage of the patch here in my opinion is that we're only adding to the patch the specific conditions that we want to remove, so it's more concise -- we won't have to manage the whole status object to perform the update, so maybe it's less prone to mistakes. What would you think @bertinatto? |
||
if jsonPatch.IsEmpty() { | ||
return kerrors.NewAggregate(errs) | ||
} | ||
|
||
deploymentProgressingCondition := applyoperatorv1.OperatorCondition(). | ||
WithType(fmt.Sprintf("%sDeployment%s", c.conditionsPrefix, operatorv1.OperatorStatusTypeProgressing)) | ||
err = c.operatorClient.PatchOperatorStatus(ctx, jsonPatch) | ||
return kerrors.NewAggregate(append(errs, err)) | ||
} | ||
|
||
status := applyoperatorv1.OperatorStatus() | ||
if workload != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be beneficial to add some unit tests for the new deletion behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unit tests would end up using mocks for most of the stuff that the deletion does; but on second thought it might be beneficial to test the operator status, so I'll add some 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to import and use this change in one of the consumers (e.g. cluster-authentication-operator) and show that the CI is passing there.