Skip to content
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

CLOUDP-296898: use errors for termination #2072

Merged
merged 1 commit into from
Jan 27, 2025
Merged
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 @@ -2,6 +2,7 @@ package atlasbackupcompliancepolicy

import (
"context"
"errors"
"fmt"

"go.uber.org/zap"
Expand Down Expand Up @@ -148,7 +149,7 @@ func (r *AtlasBackupCompliancePolicyReconciler) skip(ctx context.Context, log *z
log.Infow(fmt.Sprintf("-> Skipping AtlasBackupCompliancePolicy reconciliation as annotation %s=%s", customresource.ReconciliationPolicyAnnotation, customresource.ReconciliationPolicySkip), "spec", bcp.Spec)
if !bcp.GetDeletionTimestamp().IsZero() {
if err := customresource.ManageFinalizer(ctx, r.Client, bcp, customresource.UnsetFinalizer); err != nil {
result := workflow.Terminate(workflow.Internal, err.Error())
result := workflow.Terminate(workflow.Internal, err)
log.Errorw("Failed to remove finalizer", "terminate", err)

return result.ReconcileResult()
Expand All @@ -166,15 +167,15 @@ func (r *AtlasBackupCompliancePolicyReconciler) invalidate(invalid workflow.Resu

func (r *AtlasBackupCompliancePolicyReconciler) unsupport(ctx *workflow.Context) ctrl.Result {
unsupported := workflow.Terminate(
workflow.AtlasGovUnsupported, "the AtlasBackupCompliancePolicy is not supported by Atlas for government").
workflow.AtlasGovUnsupported, errors.New("the AtlasBackupCompliancePolicy is not supported by Atlas for government")).
WithoutRetry()
ctx.SetConditionFromResult(api.ReadyType, unsupported)
return unsupported.ReconcileResult()
}

func (r *AtlasBackupCompliancePolicyReconciler) terminate(ctx *workflow.Context, errorCondition workflow.ConditionReason, err error) ctrl.Result {
r.Log.Error(err)
terminated := workflow.Terminate(errorCondition, err.Error())
terminated := workflow.Terminate(errorCondition, err)
ctx.SetConditionFromResult(api.ReadyType, terminated)
return terminated.ReconcileResult()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (r *AtlasCustomRoleReconciler) terminate(
err error,
) ctrl.Result {
r.Log.Errorf("resource %T(%s/%s) failed on condition %s: %s", object, object.GetNamespace(), object.GetName(), condition, err)
result := workflow.Terminate(reason, err.Error())
result := workflow.Terminate(reason, err)
ctx.SetConditionFromResult(condition, result)

if !retry {
Expand All @@ -170,7 +170,7 @@ func (r *AtlasCustomRoleReconciler) idle(ctx *workflow.Context) ctrl.Result {
// fail terminates the reconciliation silently(no updates on conditions)
func (r *AtlasCustomRoleReconciler) fail(req ctrl.Request, err error) ctrl.Result {
r.Log.Errorf("Failed to query object %s: %s", req.NamespacedName, err)
return workflow.TerminateSilently().ReconcileResult()
return workflow.TerminateSilently(err).ReconcileResult()
}

// skip prevents the reconciliation to start and successfully return
Expand All @@ -183,8 +183,9 @@ func (r *AtlasCustomRoleReconciler) skip() ctrl.Result {

// notFound terminates the reconciliation silently(no updates on conditions) and without retry
func (r *AtlasCustomRoleReconciler) notFound(req ctrl.Request) ctrl.Result {
r.Log.Infof("Object %s doesn't exist, was it deleted after reconcile request?", req.NamespacedName)
return workflow.TerminateSilently().WithoutRetry().ReconcileResult()
err := fmt.Errorf("object %s doesn't exist, was it deleted after reconcile request?", req.NamespacedName)
r.Log.Infof(err.Error())
return workflow.TerminateSilently(err).WithoutRetry().ReconcileResult()
}

func (r *AtlasCustomRoleReconciler) SetupWithManager(mgr ctrl.Manager, skipNameValidation bool) error {
Expand Down
11 changes: 5 additions & 6 deletions internal/controller/atlascustomrole/custom_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import (
"fmt"
"reflect"

"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/api"
akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/customresource"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow"

"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/customroles"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/project"
)
Expand Down Expand Up @@ -45,12 +44,12 @@ func handleCustomRole(ctx *workflow.Context, k8sClient client.Client, project *p
func (r *roleController) Reconcile() workflow.Result {
if r.project.ID == "" {
return workflow.Terminate(workflow.ProjectCustomRolesReady,
fmt.Sprintf("the referenced AtlasProject resource '%s' doesn't have ID (status.ID is empty)", r.project.Name))
fmt.Errorf("the referenced AtlasProject resource '%s' doesn't have ID (status.ID is empty)", r.project.Name))
}
roleFoundInAtlas := false
roleInAtlas, err := r.service.Get(r.ctx.Context, r.project.ID, r.role.Spec.Role.Name)
if err != nil {
return workflow.Terminate(workflow.ProjectCustomRolesReady, err.Error())
return workflow.Terminate(workflow.ProjectCustomRolesReady, err)
}
roleFoundInAtlas = roleInAtlas != customroles.CustomRole{}

Expand Down Expand Up @@ -113,7 +112,7 @@ func (r *roleController) delete(roleInAtlas customroles.CustomRole) workflow.Res

func (r *roleController) terminate(reason workflow.ConditionReason, err error) workflow.Result {
r.ctx.Log.Error(err)
result := workflow.Terminate(reason, err.Error())
result := workflow.Terminate(reason, err)
r.ctx.SetConditionFromResult(api.ProjectCustomRolesReadyType, result)
return result
}
Expand Down
11 changes: 6 additions & 5 deletions internal/controller/atlascustomrole/custom_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package atlascustomrole

import (
"context"
"errors"
"fmt"
"net/http"
"reflect"
Expand Down Expand Up @@ -177,7 +178,7 @@ func Test_roleController_Reconcile(t *testing.T) {
Status: status.AtlasCustomRoleStatus{},
},
},
want: workflow.Terminate(workflow.AtlasCustomRoleNotCreated, "unable to create role"),
want: workflow.Terminate(workflow.AtlasCustomRoleNotCreated, errors.New("unable to create role")),
},
{
name: "Create custom role with error on Getting roles",
Expand Down Expand Up @@ -225,7 +226,7 @@ func Test_roleController_Reconcile(t *testing.T) {
Status: status.AtlasCustomRoleStatus{},
},
},
want: workflow.Terminate(workflow.ProjectCustomRolesReady, "unable to Get roles"),
want: workflow.Terminate(workflow.ProjectCustomRolesReady, errors.New("unable to Get roles")),
},
{
name: "Update custom role successfully",
Expand Down Expand Up @@ -374,7 +375,7 @@ func Test_roleController_Reconcile(t *testing.T) {
Status: status.AtlasCustomRoleStatus{},
},
},
want: workflow.Terminate(workflow.AtlasCustomRoleNotUpdated, "unable to update custom role"),
want: workflow.Terminate(workflow.AtlasCustomRoleNotUpdated, errors.New("unable to update custom role")),
},
{
name: "Update custom role successfully no update",
Expand Down Expand Up @@ -693,7 +694,7 @@ func Test_roleController_Reconcile(t *testing.T) {
Status: status.AtlasCustomRoleStatus{},
},
},
want: workflow.Terminate(workflow.AtlasCustomRoleNotDeleted, "unable to delete custom role"),
want: workflow.Terminate(workflow.AtlasCustomRoleNotDeleted, errors.New("unable to delete custom role")),
},
}
for _, tt := range tests {
Expand Down Expand Up @@ -929,7 +930,7 @@ func Test_handleCustomRole(t *testing.T) {
},
},
},
want: workflow.Terminate(workflow.ProjectCustomRolesReady, "the referenced AtlasProject resource 'testProject' doesn't have ID (status.ID is empty)"),
want: workflow.Terminate(workflow.ProjectCustomRolesReady, errors.New("the referenced AtlasProject resource 'testProject' doesn't have ID (status.ID is empty)")),
},
{
name: "DO NOT create custom role if external project reference doesn't exist",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ func (r *AtlasDatabaseUserReconciler) Reconcile(ctx context.Context, req ctrl.Re

// notFound terminates the reconciliation silently(no updates on conditions) and without retry
func (r *AtlasDatabaseUserReconciler) notFound(req ctrl.Request) ctrl.Result {
r.Log.Infof("Object %s doesn't exist, was it deleted after reconcile request?", req.NamespacedName)
return workflow.TerminateSilently().WithoutRetry().ReconcileResult()
err := fmt.Errorf("object %s doesn't exist, was it deleted after reconcile request?", req.NamespacedName)
r.Log.Infof(err.Error())
return workflow.TerminateSilently(err).WithoutRetry().ReconcileResult()
}

// fail terminates the reconciliation silently(no updates on conditions)
func (r *AtlasDatabaseUserReconciler) fail(req ctrl.Request, err error) ctrl.Result {
r.Log.Errorf("Failed to query object %s: %s", req.NamespacedName, err)
return workflow.TerminateSilently().ReconcileResult()
return workflow.TerminateSilently(err).ReconcileResult()
}

// skip prevents the reconciliation to start and successfully return
Expand All @@ -132,7 +133,7 @@ func (r *AtlasDatabaseUserReconciler) terminate(
err error,
) ctrl.Result {
r.Log.Errorf("resource %T(%s/%s) failed on condition %s: %s", object, object.GetNamespace(), object.GetName(), condition, err)
result := workflow.Terminate(reason, err.Error())
result := workflow.Terminate(reason, err)
ctx.SetConditionFromResult(condition, result)

if !retry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func TestNotFound(t *testing.T) {
assert.Equal(t, ctrl.Result{}, c.notFound(ctrl.Request{NamespacedName: types.NamespacedName{Name: "object", Namespace: "test"}}))
assert.Equal(t, 1, logs.Len())
assert.Equal(t, zapcore.Level(0), logs.All()[0].Level)
assert.Equal(t, "Object test/object doesn't exist, was it deleted after reconcile request?", logs.All()[0].Message)
assert.Equal(t, "object test/object doesn't exist, was it deleted after reconcile request?", logs.All()[0].Message)
})
}

Expand Down Expand Up @@ -311,7 +311,7 @@ func TestReady(t *testing.T) {
return errors.New("failed to set finalizer")
},
},
expectedResult: workflow.Terminate(workflow.AtlasFinalizerNotSet, "").ReconcileResult(),
expectedResult: workflow.Terminate(workflow.AtlasFinalizerNotSet, errors.New("")).ReconcileResult(),
expectedConditions: []api.Condition{
api.FalseCondition(api.DatabaseUserReadyType).
WithReason(string(workflow.AtlasFinalizerNotSet)).
Expand Down Expand Up @@ -348,7 +348,7 @@ func TestReady(t *testing.T) {
return errors.New("failed to set last applied config")
},
},
expectedResult: workflow.Terminate(workflow.Internal, "").ReconcileResult(),
expectedResult: workflow.Terminate(workflow.Internal, errors.New("")).ReconcileResult(),
expectedConditions: []api.Condition{
api.FalseCondition(api.DatabaseUserReadyType).
WithReason(string(workflow.Internal)).
Expand Down
8 changes: 4 additions & 4 deletions internal/controller/atlasdatafederation/connectionsecrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ func (r *AtlasDataFederationReconciler) ensureConnectionSecrets(ctx *workflow.Co
databaseUsers := akov2.AtlasDatabaseUserList{}
err := r.Client.List(ctx.Context, &databaseUsers, &client.ListOptions{})
if err != nil {
return workflow.Terminate(workflow.Internal, err.Error())
return workflow.Terminate(workflow.Internal, err)
}

atlasDF, err := federationService.Get(ctx.Context, project.ID(), df.Spec.Name)
if err != nil {
return workflow.Terminate(workflow.Internal, err.Error())
return workflow.Terminate(workflow.Internal, err)
}

connectionHosts := atlasDF.Hostnames
Expand Down Expand Up @@ -57,7 +57,7 @@ func (r *AtlasDataFederationReconciler) ensureConnectionSecrets(ctx *workflow.Co

password, err := dbUser.ReadPassword(ctx.Context, r.Client)
if err != nil {
return workflow.Terminate(workflow.DeploymentConnectionSecretsNotCreated, err.Error())
return workflow.Terminate(workflow.DeploymentConnectionSecretsNotCreated, err)
}

var connURLs []string
Expand All @@ -75,7 +75,7 @@ func (r *AtlasDataFederationReconciler) ensureConnectionSecrets(ctx *workflow.Co

secretName, err := connectionsecret.Ensure(ctx.Context, r.Client, dbUser.Namespace, project.Spec.Name, project.ID(), df.Spec.Name, data)
if err != nil {
return workflow.Terminate(workflow.DeploymentConnectionSecretsNotCreated, err.Error())
return workflow.Terminate(workflow.DeploymentConnectionSecretsNotCreated, err)
}
secrets = append(secrets, secretName)
}
Expand Down
8 changes: 4 additions & 4 deletions internal/controller/atlasdatafederation/datafederation.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ func (r *AtlasDataFederationReconciler) ensureDataFederation(ctx *workflow.Conte

akoDataFederation, err := datafederation.NewDataFederation(&dataFederation.Spec, projectID, nil)
if err != nil {
return workflow.Terminate(workflow.Internal, err.Error())
return workflow.Terminate(workflow.Internal, err)
}

atlasDataFederation, err := federationService.Get(ctx.Context, projectID, operatorSpec.Name)
if err != nil {
if !errors.Is(err, datafederation.ErrorNotFound) {
return workflow.Terminate(workflow.Internal, err.Error())
return workflow.Terminate(workflow.Internal, err)
}

err = federationService.Create(ctx.Context, akoDataFederation)
if err != nil {
return workflow.Terminate(workflow.DataFederationNotCreatedInAtlas, err.Error())
return workflow.Terminate(workflow.DataFederationNotCreatedInAtlas, err)
}

return workflow.InProgress(workflow.DataFederationCreating, "Data Federation is being created")
Expand All @@ -37,7 +37,7 @@ func (r *AtlasDataFederationReconciler) ensureDataFederation(ctx *workflow.Conte

err = federationService.Update(ctx.Context, akoDataFederation)
if err != nil {
return workflow.Terminate(workflow.DataFederationNotUpdatedInAtlas, err.Error())
return workflow.Terminate(workflow.DataFederationNotUpdatedInAtlas, err)
}

return workflow.InProgress(workflow.DataFederationUpdating, "Data Federation is being updated")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c
if !dataFederation.GetDeletionTimestamp().IsZero() {
err := customresource.ManageFinalizer(context, r.Client, dataFederation, customresource.UnsetFinalizer)
if err != nil {
result = workflow.Terminate(workflow.Internal, err.Error())
result = workflow.Terminate(workflow.Internal, err)
log.Errorw("failed to remove finalizer", "error", err)
return result.ReconcileResult(), nil
}
Expand All @@ -85,7 +85,7 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c
}

if !r.AtlasProvider.IsResourceSupported(dataFederation) {
result := workflow.Terminate(workflow.AtlasGovUnsupported, "the AtlasDataFederation is not supported by Atlas for government").
result := workflow.Terminate(workflow.AtlasGovUnsupported, errors.New("the AtlasDataFederation is not supported by Atlas for government")).
WithoutRetry()
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
return result.ReconcileResult(), nil
Expand All @@ -99,14 +99,14 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c

endpointService, err := datafederation.NewDatafederationPrivateEndpointService(ctx.Context, r.AtlasProvider, project.ConnectionSecretObjectKey(), log)
if err != nil {
result = workflow.Terminate(workflow.AtlasAPIAccessNotConfigured, err.Error())
result = workflow.Terminate(workflow.AtlasAPIAccessNotConfigured, err)
ctx.SetConditionFromResult(api.DatabaseUserReadyType, result)
return result.ReconcileResult(), nil
}

dataFederationService, err := datafederation.NewAtlasDataFederationService(ctx.Context, r.AtlasProvider, project.ConnectionSecretObjectKey(), log)
if err != nil {
result = workflow.Terminate(workflow.AtlasAPIAccessNotConfigured, err.Error())
result = workflow.Terminate(workflow.AtlasAPIAccessNotConfigured, err)
ctx.SetConditionFromResult(api.DatabaseUserReadyType, result)
return result.ReconcileResult(), nil
}
Expand All @@ -129,12 +129,12 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c
if !customresource.HaveFinalizer(dataFederation, customresource.FinalizerLabel) {
err = r.Client.Get(context, kube.ObjectKeyFromObject(dataFederation), dataFederation)
if err != nil {
result = workflow.Terminate(workflow.Internal, err.Error())
result = workflow.Terminate(workflow.Internal, err)
return result.ReconcileResult(), nil
}
customresource.SetFinalizer(dataFederation, customresource.FinalizerLabel)
if err = r.Client.Update(context, dataFederation); err != nil {
result = workflow.Terminate(workflow.Internal, err.Error())
result = workflow.Terminate(workflow.Internal, err)
log.Errorw("failed to add finalizer", "error", err)
return result.ReconcileResult(), nil
}
Expand All @@ -147,7 +147,7 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c

err = customresource.ApplyLastConfigApplied(context, dataFederation, r.Client)
if err != nil {
result = workflow.Terminate(workflow.Internal, err.Error())
result = workflow.Terminate(workflow.Internal, err)
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
log.Error(result.GetMessage())

Expand All @@ -166,19 +166,19 @@ func (r *AtlasDataFederationReconciler) handleDelete(ctx *workflow.Context, log
} else {
if err := r.deleteConnectionSecrets(ctx.Context, dataFederation); err != nil {
log.Errorf("failed to remove DataFederation connection secrets from Atlas: %s", err)
result := workflow.Terminate(workflow.Internal, err.Error())
result := workflow.Terminate(workflow.Internal, err)
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
return result
}
if err := r.deleteDataFederationFromAtlas(ctx.Context, service, dataFederation, project, log); err != nil {
log.Errorf("failed to remove DataFederation from Atlas: %s", err)
result := workflow.Terminate(workflow.Internal, err.Error())
result := workflow.Terminate(workflow.Internal, err)
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
return result
}
}
if err := customresource.ManageFinalizer(ctx.Context, r.Client, dataFederation, customresource.UnsetFinalizer); err != nil {
result := workflow.Terminate(workflow.AtlasFinalizerNotRemoved, err.Error())
result := workflow.Terminate(workflow.AtlasFinalizerNotRemoved, err)
log.Errorw("failed to remove finalizer", "error", err)
return result
}
Expand Down Expand Up @@ -207,7 +207,7 @@ func (r *AtlasDataFederationReconciler) deleteDataFederationFromAtlas(ctx contex

func (r *AtlasDataFederationReconciler) readProjectResource(ctx context.Context, dataFederation *akov2.AtlasDataFederation, project *akov2.AtlasProject) workflow.Result {
if err := r.Client.Get(ctx, dataFederation.AtlasProjectObjectKey(), project); err != nil {
return workflow.Terminate(workflow.Internal, err.Error())
return workflow.Terminate(workflow.Internal, err)
}
return workflow.OK()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (r *AtlasDataFederationReconciler) ensurePrivateEndpoints(ctx *workflow.Con

func (r *AtlasDataFederationReconciler) privateEndpointsFailed(ctx *workflow.Context, err error) workflow.Result {
ctx.Log.Errorw("getAllDataFederationPEs error", "err", err.Error())
result := workflow.Terminate(workflow.Internal, err.Error())
result := workflow.Terminate(workflow.Internal, err)
ctx.SetConditionFromResult(api.DataFederationPEReadyType, result)
return result
}
Expand Down
Loading
Loading