Skip to content

Commit

Permalink
CLOUDP-238465: remove ownership detection (#1607)
Browse files Browse the repository at this point in the history
* controller/atlasdeployment: remove ownership detection

* controller/atlasproject: remove ownership detection

* controller/atlasproject/auditing: remove ownership detection

* controller/atlasproject/cloud_provider_integration: remove ownership detection

* controller/atlasproject/custom_roles: remove ownership detection

* controller/atlasproject/encryption_at_rest: remove ownership detection

* controller/atlasproject/integrations: remove ownership detection

* controller/atlasproject/ipaccess_list: remove ownership detection

* controller/atlasproject/maintenancewindow: remove ownership detection

* controller/atlasproject/network_peering: remove ownership detection

* controller/atlasproject/project_settings: remove ownership detection

* controller/atlasfederatedauth/atlasfederated_auth_controller: remove ownership detection

* controller/atlasproject/team_reconciler: remove ownership detection

* controller/atlasproject/teams: remove ownership detection

* controller/atlasdatabaseuser/atlasdatabaseuser_controller: remove ownership detection

* controller/atlasdatafederation/datafederation_controller: remove ownership detection
  • Loading branch information
s-urbaniak authored May 30, 2024
1 parent c3e159d commit 81988e5
Show file tree
Hide file tree
Showing 28 changed files with 29 additions and 5,247 deletions.
47 changes: 0 additions & 47 deletions pkg/controller/atlasdatabaseuser/atlasdatabaseuser_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,27 +133,6 @@ func (r *AtlasDatabaseUserReconciler) Reconcile(ctx context.Context, req ctrl.Re
workflowCtx.OrgID = orgID
workflowCtx.Client = atlasClient

// Setting protection flag to static false because ownership detection is disabled.
owner, err := customresource.IsOwner(databaseUser, false, customresource.IsResourceManagedByOperator, managedByAtlas(ctx, atlasClient, project.ID(), log))
if err != nil {
result = workflow.Terminate(workflow.Internal, fmt.Sprintf("enable to resolve ownership for deletion protection: %s", err))
workflowCtx.SetConditionFromResult(api.DatabaseUserReadyType, result)
log.Error(result.GetMessage())

return result.ReconcileResult(), nil
}

if !owner {
result = workflow.Terminate(
workflow.AtlasDeletionProtection,
"unable to reconcile database user: it already exists in Atlas, it was not previously managed by the operator, and the deletion protection is enabled.",
)
workflowCtx.SetConditionFromResult(api.DatabaseUserReadyType, result)
log.Error(result.GetMessage())

return result.ReconcileResult(), nil
}

deletionRequest, result := r.handleDeletion(ctx, databaseUser, project, atlasClient, log)
if deletionRequest {
return result.ReconcileResult(), nil
Expand Down Expand Up @@ -281,29 +260,3 @@ func (r *AtlasDatabaseUserReconciler) SetupWithManager(mgr ctrl.Manager) error {
Watches(&corev1.Secret{}, watch.NewSecretHandler(&r.DeprecatedResourceWatcher)).
Complete(r)
}

func managedByAtlas(ctx context.Context, atlasClient *mongodbatlas.Client, projectID string, log *zap.SugaredLogger) customresource.AtlasChecker {
return func(resource api.AtlasCustomResource) (bool, error) {
dbUser, ok := resource.(*akov2.AtlasDatabaseUser)
if !ok {
return false, errors.New("failed to match resource type as AtlasDatabaseUser")
}

atlasDBUser, _, err := atlasClient.DatabaseUsers.Get(ctx, dbUser.Spec.DatabaseName, projectID, dbUser.Spec.Username)
if err != nil {
var apiError *mongodbatlas.ErrorResponse
if errors.As(err, &apiError) && apiError.ErrorCode == atlas.UsernameNotFound {
return false, nil
}

return false, err
}

isSame, err := userMatchesSpec(log, atlasDBUser, dbUser.Spec)
if err != nil {
return true, err
}

return !isSame, nil
}
}
14 changes: 0 additions & 14 deletions pkg/controller/atlasdatafederation/datafederation.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,3 @@ func getMergedSpec(atlasSpec, operatorSpec akov2.DataFederationSpec) (akov2.Data

return mergedSpec, nil
}

func dataFederationMatchesSpec(log *zap.SugaredLogger, atlasSpec *mongodbatlas.DataFederationInstance, operatorSpec *akov2.AtlasDataFederation) (bool, error) {
newAtlasSpec, err := DataFederationFromAtlas(atlasSpec)
if err != nil {
return false, err
}

equal, diff := dataFederationEqual(*newAtlasSpec, operatorSpec.Spec, log)
if !equal {
log.Debugf("DataFederation differs from spec: %s", diff)
}

return equal, nil
}
45 changes: 0 additions & 45 deletions pkg/controller/atlasdatafederation/datafederation_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,27 +104,6 @@ func (r *AtlasDataFederationReconciler) Reconcile(context context.Context, req c
ctx.OrgID = orgID
ctx.Client = atlasClient

// Setting protection flag to static false because ownership detection is disabled.
owner, err := customresource.IsOwner(dataFederation, false, customresource.IsResourceManagedByOperator, managedByAtlas(context, atlasClient, project.ID(), log))
if err != nil {
result = workflow.Terminate(workflow.Internal, fmt.Sprintf("unable to resolve ownership for deletion protection: %s", err))
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
log.Error(result.GetMessage())

return result.ReconcileResult(), nil
}

if !owner {
result = workflow.Terminate(
workflow.AtlasDeletionProtection,
"unable to reconcile DataFederation: it already exists in Atlas, it was not previously managed by the operator, and the deletion protection is enabled.",
)
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
log.Error(result.GetMessage())

return result.ReconcileResult(), nil
}

if result = r.ensureDataFederation(ctx, project, dataFederation); !result.IsOk() {
ctx.SetConditionFromResult(api.DataFederationReadyType, result)
return result.ReconcileResult(), nil
Expand Down Expand Up @@ -261,27 +240,3 @@ func (r *AtlasDataFederationReconciler) Delete(ctx context.Context, e event.Dele

return nil
}

func managedByAtlas(ctx context.Context, atlasClient *mongodbatlas.Client, projectID string, log *zap.SugaredLogger) customresource.AtlasChecker {
return func(resource api.AtlasCustomResource) (bool, error) {
dataFederation, ok := resource.(*akov2.AtlasDataFederation)
if !ok {
return false, errors.New("failed to match resource type as AtlasDataFederation")
}

atlasDataFederation, _, err := atlasClient.DataFederation.Get(ctx, projectID, dataFederation.Spec.Name)
if err != nil {
var apiError *mongodbatlas.ErrorResponse
if errors.As(err, &apiError) && (apiError.ErrorCode == atlas.DataFederationTenantNotFound || apiError.ErrorCode == atlas.ResourceNotFound) {
return false, nil
}
return false, err
}

isSame, err := dataFederationMatchesSpec(log, atlasDataFederation, dataFederation)
if err != nil {
return true, nil
}
return !isSame, nil
}
}
150 changes: 0 additions & 150 deletions pkg/controller/atlasdeployment/atlasdeployment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/compat"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/kube"
akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1"
"github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/provider"
Expand Down Expand Up @@ -169,10 +165,6 @@ func (r *AtlasDeploymentReconciler) Reconcile(context context.Context, req ctrl.
// convertedDeployment is always a separate copy, to avoid changes on it to go back to k8s
convertedDeployment := deployment.DeepCopy()

if result := r.checkDeploymentIsManaged(workflowCtx, log, project, convertedDeployment); !result.IsOk() {
return result.ReconcileResult(), nil
}

deletionRequest, result := r.handleDeletion(workflowCtx, log, prevResult, project, deployment)
if deletionRequest {
return result.ReconcileResult(), nil
Expand Down Expand Up @@ -234,42 +226,6 @@ func (r *AtlasDeploymentReconciler) verifyNonTenantCase(deployment *akov2.AtlasD
modifyProviderSettings(pSettings, deploymentType)
}

func (r *AtlasDeploymentReconciler) checkDeploymentIsManaged(
workflowCtx *workflow.Context,
log *zap.SugaredLogger,
project *akov2.AtlasProject,
deployment *akov2.AtlasDeployment,
) workflow.Result {
// Setting protection flag to static false because ownership detection is disabled.
owner, err := customresource.IsOwner(
deployment,
false,
customresource.IsResourceManagedByOperator,
managedByAtlas(workflowCtx, project.ID(), log),
)

if err != nil {
result := workflow.Terminate(workflow.Internal, fmt.Sprintf("unable to resolve ownership for deletion protection: %s", err))
workflowCtx.SetConditionFromResult(api.DeploymentReadyType, result)
log.Error(result.GetMessage())

return result
}

if !owner {
result := workflow.Terminate(
workflow.AtlasDeletionProtection,
"unable to reconcile Deployment due to deletion protection being enabled. see https://dochub.mongodb.org/core/ako-deletion-protection for further information",
)
workflowCtx.SetConditionFromResult(api.DeploymentReadyType, result)
log.Error(result.GetMessage())

return result
}

return workflow.OK()
}

func (r *AtlasDeploymentReconciler) handleDeletion(
workflowCtx *workflow.Context,
log *zap.SugaredLogger,
Expand Down Expand Up @@ -709,112 +665,6 @@ func (r *AtlasDeploymentReconciler) removeDeletionFinalizer(context context.Cont

type deploymentHandlerFunc func(workflowCtx *workflow.Context, project *akov2.AtlasProject, deployment *akov2.AtlasDeployment, req reconcile.Request) (workflow.Result, error)

type atlasClusterType int

const (
Unset atlasClusterType = iota
Advanced
Serverless
)

type atlasTypedCluster struct {
clusterType atlasClusterType
serverless *mongodbatlas.Cluster
advanced *mongodbatlas.AdvancedCluster
}

func managedByAtlas(workflowCtx *workflow.Context, projectID string, log *zap.SugaredLogger) customresource.AtlasChecker {
return func(resource api.AtlasCustomResource) (bool, error) {
deployment, ok := resource.(*akov2.AtlasDeployment)
if !ok {
return false, errors.New("failed to match resource type as AtlasDeployment")
}

typedAtlasCluster, err := findTypedAtlasCluster(workflowCtx, projectID, deployment.GetDeploymentName())
if typedAtlasCluster == nil || err != nil {
return false, err
}

isSame, err := deploymentMatchesSpec(log, typedAtlasCluster, deployment)
if err != nil {
return true, err
}

return !isSame, nil
}
}

func findTypedAtlasCluster(workflowCtx *workflow.Context, projectID, deploymentName string) (*atlasTypedCluster, error) {
advancedCluster, _, err := workflowCtx.Client.AdvancedClusters.Get(workflowCtx.Context, projectID, deploymentName)
if err == nil {
return &atlasTypedCluster{clusterType: Advanced, advanced: advancedCluster}, nil
}
var apiError *mongodbatlas.ErrorResponse
if errors.As(err, &apiError) &&
apiError.ErrorCode != atlas.ClusterNotFound &&
apiError.ErrorCode != atlas.ServerlessInstanceFromClusterAPI {
return nil, err
}
// if not found, maybe it is a serverless instead
serverless, _, err := workflowCtx.Client.ServerlessInstances.Get(workflowCtx.Context, projectID, deploymentName)
if err == nil {
return &atlasTypedCluster{clusterType: Serverless, serverless: serverless}, nil
}
if errors.As(err, &apiError) && apiError.ErrorCode == atlas.ServerlessInstanceNotFound {
return nil, nil
}
return nil, err
}

func deploymentMatchesSpec(log *zap.SugaredLogger, atlasSpec *atlasTypedCluster, deployment *akov2.AtlasDeployment) (bool, error) {
if deployment.IsServerless() {
if atlasSpec.clusterType != Serverless {
return false, nil
}
return serverlessDeploymentMatchesSpec(log, atlasSpec.serverless, deployment.Spec.ServerlessSpec)
}
if atlasSpec.clusterType != Advanced {
return false, nil
}
return advancedDeploymentMatchesSpec(log, atlasSpec.advanced, deployment.Spec.DeploymentSpec)
}

func serverlessDeploymentMatchesSpec(log *zap.SugaredLogger, atlasSpec *mongodbatlas.Cluster, operatorSpec *akov2.ServerlessSpec) (bool, error) {
clusterMerged := mongodbatlas.Cluster{}
if err := compat.JSONCopy(&clusterMerged, atlasSpec); err != nil {
return false, err
}

if err := compat.JSONCopy(&clusterMerged, operatorSpec); err != nil {
return false, err
}

d := cmp.Diff(atlasSpec, &clusterMerged, cmpopts.EquateEmpty())
if d != "" {
log.Debugf("Serverless deployment differs from spec: %s", d)
}

return d == "", nil
}

func advancedDeploymentMatchesSpec(log *zap.SugaredLogger, atlasSpec *mongodbatlas.AdvancedCluster, operatorSpec *akov2.AdvancedDeploymentSpec) (bool, error) {
clusterMerged := mongodbatlas.AdvancedCluster{}
if err := compat.JSONCopy(&clusterMerged, atlasSpec); err != nil {
return false, err
}

if err := compat.JSONCopy(&clusterMerged, operatorSpec); err != nil {
return false, err
}

d := cmp.Diff(atlasSpec, &clusterMerged, cmpopts.EquateEmpty())
if d != "" {
log.Debugf("Advanced deployment differs from spec: %s", d)
}

return d == "", nil
}

// Parse through tags and verify that all keys are unique. Return error otherwise.
func uniqueKey(deploymentSpec *akov2.AtlasDeploymentSpec) error {
store := make(map[string]string)
Expand Down
Loading

0 comments on commit 81988e5

Please sign in to comment.