diff --git a/config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml b/config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml index 4c41cf4f28..5674baff37 100644 --- a/config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml +++ b/config/crd/bases/atlas.mongodb.com_atlasdatabaseusers.yaml @@ -66,18 +66,6 @@ spec: - USER - ROLE type: string - connectionSecret: - description: A reference to an object in the same namespace as the - referent - properties: - name: - description: |- - Name of the resource being referred to - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object databaseName: default: admin description: DatabaseName is a Database against which Atlas authenticates diff --git a/internal/translation/dbuser/conversion.go b/internal/translation/dbuser/conversion.go index 4df4a1591e..b79608e701 100644 --- a/internal/translation/dbuser/conversion.go +++ b/internal/translation/dbuser/conversion.go @@ -68,7 +68,6 @@ func (u *User) clearedSpecClone() *akov2.AtlasDatabaseUserSpec { clone.Project.Name = "" clone.Project.Namespace = "" clone.PasswordSecret = nil - clone.ConnectionSecret = nil return &clone } diff --git a/internal/translation/dbuser/conversion_test.go b/internal/translation/dbuser/conversion_test.go index 40eee7ad70..9012a60796 100644 --- a/internal/translation/dbuser/conversion_test.go +++ b/internal/translation/dbuser/conversion_test.go @@ -9,7 +9,6 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/timeutil" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/dbuser" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/common" ) @@ -394,7 +393,6 @@ func TestDiffSpecs(t *testing.T) { spec.Project.Name = "some-project" spec.Project.Namespace = "some-namespace" spec.PasswordSecret = &common.ResourceRef{Name: "some-secret-ref"} - spec.ConnectionSecret = &api.LocalObjectReference{Name: "some-local-secret-ref"} return spec }(), }, @@ -410,7 +408,6 @@ func TestDiffSpecs(t *testing.T) { spec.Project.Name = "another-project" spec.Project.Namespace = "another-namespace" spec.PasswordSecret = &common.ResourceRef{Name: "another-secret-ref"} - spec.ConnectionSecret = &api.LocalObjectReference{Name: "another-local-secret-ref"} return spec }(), }, diff --git a/pkg/api/credentials.go b/pkg/api/credentials.go deleted file mode 100644 index 763d98c62a..0000000000 --- a/pkg/api/credentials.go +++ /dev/null @@ -1,28 +0,0 @@ -package api - -type LocalRef string - -// +k8s:deepcopy-gen=false - -// CredentialsProvider gives access to custom local credentials -type CredentialsProvider interface { - Credentials() *LocalObjectReference -} - -// +k8s:deepcopy-gen=false - -// ResourceWithCredentials is to be implemented by all CRDs using custom local credentials -type ResourceWithCredentials interface { - CredentialsProvider - GetName() string - GetNamespace() string -} - -// LocalCredentialHolder is to be embedded by Specs of CRDs using custom local credentials -type LocalCredentialHolder struct { - ConnectionSecret *LocalObjectReference `json:"connectionSecret,omitempty"` -} - -func (ch *LocalCredentialHolder) Credentials() *LocalObjectReference { - return ch.ConnectionSecret -} diff --git a/pkg/api/localref.go b/pkg/api/localref.go deleted file mode 100644 index 69af4ffd19..0000000000 --- a/pkg/api/localref.go +++ /dev/null @@ -1,8 +0,0 @@ -package api - -// LocalObjectReference is a reference to an object in the same namespace as the referent -type LocalObjectReference struct { - // Name of the resource being referred to - // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - Name string `json:"name"` -} diff --git a/pkg/api/v1/atlasdatabaseuser_types.go b/pkg/api/v1/atlasdatabaseuser_types.go index ba431bda50..ac763bfe31 100644 --- a/pkg/api/v1/atlasdatabaseuser_types.go +++ b/pkg/api/v1/atlasdatabaseuser_types.go @@ -52,8 +52,6 @@ const ( // AtlasDatabaseUserSpec defines the desired state of Database User in Atlas type AtlasDatabaseUserSpec struct { - api.LocalCredentialHolder `json:",inline"` - // Project is a reference to AtlasProject resource the user belongs to Project common.ResourceRefNamespaced `json:"projectRef"` @@ -298,10 +296,6 @@ func (p *AtlasDatabaseUser) WithDeleteAfterDate(date string) *AtlasDatabaseUser return p } -func (p *AtlasDatabaseUser) Credentials() *api.LocalObjectReference { - return p.Spec.Credentials() -} - func DefaultDBUser(namespace, username, projectName string) *AtlasDatabaseUser { return NewDBUser(namespace, username, username, projectName).WithRole("clusterMonitor", "admin", "") } diff --git a/pkg/api/v1/zz_generated.deepcopy.go b/pkg/api/v1/zz_generated.deepcopy.go index fdd4c48b46..0b916fe3f6 100644 --- a/pkg/api/v1/zz_generated.deepcopy.go +++ b/pkg/api/v1/zz_generated.deepcopy.go @@ -677,7 +677,6 @@ func (in *AtlasDatabaseUserList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AtlasDatabaseUserSpec) DeepCopyInto(out *AtlasDatabaseUserSpec) { *out = *in - in.LocalCredentialHolder.DeepCopyInto(&out.LocalCredentialHolder) out.Project = in.Project if in.Labels != nil { in, out := &in.Labels, &out.Labels diff --git a/pkg/api/zz_generated.deepcopy.go b/pkg/api/zz_generated.deepcopy.go index 3e2216c836..6311a7c2ef 100644 --- a/pkg/api/zz_generated.deepcopy.go +++ b/pkg/api/zz_generated.deepcopy.go @@ -49,38 +49,3 @@ func (in *Condition) DeepCopy() *Condition { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LocalCredentialHolder) DeepCopyInto(out *LocalCredentialHolder) { - *out = *in - if in.ConnectionSecret != nil { - in, out := &in.ConnectionSecret, &out.ConnectionSecret - *out = new(LocalObjectReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalCredentialHolder. -func (in *LocalCredentialHolder) DeepCopy() *LocalCredentialHolder { - if in == nil { - return nil - } - out := new(LocalCredentialHolder) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. -func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { - if in == nil { - return nil - } - out := new(LocalObjectReference) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/controller/atlasdatabaseuser/databaseuser.go b/pkg/controller/atlasdatabaseuser/databaseuser.go index 0da3ced362..7c46436931 100644 --- a/pkg/controller/atlasdatabaseuser/databaseuser.go +++ b/pkg/controller/atlasdatabaseuser/databaseuser.go @@ -48,11 +48,7 @@ func (r *AtlasDatabaseUserReconciler) handleDatabaseUser(ctx *workflow.Context, return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.Internal, true, err) } - credentialsSecret, err := customresource.ComputeSecret(atlasProject, atlasDatabaseUser) - if err != nil { - return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.AtlasAPIAccessNotConfigured, true, err) - } - sdkClient, _, err := r.AtlasProvider.SdkClient(ctx.Context, credentialsSecret, r.Log) + sdkClient, _, err := r.AtlasProvider.SdkClient(ctx.Context, atlasProject.ConnectionSecretObjectKey(), r.Log) if err != nil { return r.terminate(ctx, atlasDatabaseUser, api.DatabaseUserReadyType, workflow.AtlasAPIAccessNotConfigured, true, err) } diff --git a/pkg/controller/atlasproject/atlasproject_controller_test.go b/pkg/controller/atlasproject/atlasproject_controller_test.go index e16d971138..6c2588173b 100644 --- a/pkg/controller/atlasproject/atlasproject_controller_test.go +++ b/pkg/controller/atlasproject/atlasproject_controller_test.go @@ -36,7 +36,7 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/indexer" ) -func TestReconcile(t *testing.T) { +func TestRenconcile(t *testing.T) { tests := map[string]struct { atlasClientMocker func() *mongodbatlas.Client atlasSDKMocker func() *admin.APIClient diff --git a/pkg/controller/customresource/customresource.go b/pkg/controller/customresource/customresource.go index c3253464de..cd6f9a5842 100644 --- a/pkg/controller/customresource/customresource.go +++ b/pkg/controller/customresource/customresource.go @@ -4,12 +4,13 @@ import ( "context" "fmt" - "github.com/Masterminds/semver" "go.uber.org/zap" apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/Masterminds/semver" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/controller/workflow" @@ -138,20 +139,3 @@ func SetAnnotation(resource api.AtlasCustomResource, key, value string) { annot[key] = value resource.SetAnnotations(annot) } - -func ComputeSecret(project *akov2.AtlasProject, resource api.ResourceWithCredentials) (*client.ObjectKey, error) { - if resource == nil { - return nil, fmt.Errorf("resource cannot be nil") - } - creds := resource.Credentials() - if creds != nil && creds.Name != "" { - return &client.ObjectKey{ - Namespace: resource.GetNamespace(), - Name: creds.Name, - }, nil - } - if project == nil { - return nil, fmt.Errorf("project cannot be nil") - } - return project.ConnectionSecretObjectKey(), nil -} diff --git a/pkg/controller/customresource/customresource_test.go b/pkg/controller/customresource/customresource_test.go index c5ec3ea8e0..2d3140ec7f 100644 --- a/pkg/controller/customresource/customresource_test.go +++ b/pkg/controller/customresource/customresource_test.go @@ -6,14 +6,11 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/common" "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/status" "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/version" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" ) func TestResourceShouldBeLeftInAtlas(t *testing.T) { @@ -230,102 +227,3 @@ func TestResourceVersionIsValid(t *testing.T) { }) } } - -func TestComputeSecret(t *testing.T) { - for _, tt := range []struct { - name string - project *akov2.AtlasProject - resource api.ResourceWithCredentials - wantRef *types.NamespacedName - wantErrorMsg string - }{ - { - name: "nil inputs fails with resource cannot be nil", - wantErrorMsg: "resource cannot be nil", - }, - - { - name: "nil project ignored if resource is set", - resource: &akov2.AtlasDatabaseUser{ - ObjectMeta: metav1.ObjectMeta{Namespace: "local"}, - Spec: akov2.AtlasDatabaseUserSpec{ - LocalCredentialHolder: api.LocalCredentialHolder{ - ConnectionSecret: &api.LocalObjectReference{Name: "local-secret"}, - }, - }, - }, - wantRef: &client.ObjectKey{ - Name: "local-secret", - Namespace: "local", - }, - }, - - { - name: "nil resource and empty project fails", - project: &akov2.AtlasProject{}, - wantErrorMsg: "resource cannot be nil", - }, - - { - name: "when both are set empty it renders nil", - project: &akov2.AtlasProject{}, - resource: &akov2.AtlasDatabaseUser{}, - }, - - { - name: "empty resource and proper project get creds from project", - project: &akov2.AtlasProject{ - Spec: akov2.AtlasProjectSpec{ - Name: "", - RegionUsageRestrictions: "", - ConnectionSecret: &common.ResourceRefNamespaced{ - Name: "project-secret", - Namespace: "some-namespace", - }, - }, - }, - resource: &akov2.AtlasDatabaseUser{}, - wantRef: &client.ObjectKey{ - Name: "project-secret", - Namespace: "some-namespace", - }, - }, - - { - name: "when both are properly set the resource wins", - project: &akov2.AtlasProject{ - Spec: akov2.AtlasProjectSpec{ - Name: "", - RegionUsageRestrictions: "", - ConnectionSecret: &common.ResourceRefNamespaced{ - Name: "project-secret", - Namespace: "some-namespace", - }, - }, - }, - resource: &akov2.AtlasDatabaseUser{ - ObjectMeta: metav1.ObjectMeta{Namespace: "local"}, - Spec: akov2.AtlasDatabaseUserSpec{ - LocalCredentialHolder: api.LocalCredentialHolder{ - ConnectionSecret: &api.LocalObjectReference{Name: "local-secret"}, - }, - }, - }, - wantRef: &client.ObjectKey{ - Name: "local-secret", - Namespace: "local", - }, - }, - } { - t.Run(tt.name, func(t *testing.T) { - result, err := ComputeSecret(tt.project, tt.resource) - if tt.wantErrorMsg != "" { - assert.Nil(t, result, nil) - assert.ErrorContains(t, err, tt.wantErrorMsg) - } else { - assert.Equal(t, result, tt.wantRef) - assert.NoError(t, err) - } - }) - } -} diff --git a/pkg/operator/builder.go b/pkg/operator/builder.go index 6cdf9f18bc..e74d2a1375 100644 --- a/pkg/operator/builder.go +++ b/pkg/operator/builder.go @@ -262,14 +262,14 @@ func (b *Builder) Build(ctx context.Context) (manager.Manager, error) { return nil, fmt.Errorf("unable to create controller AtlasFederatedAuth: %w", err) } - streamsInstanceReconciler := atlasstream.NewAtlasStreamsInstanceReconciler( + streamsInstanceReconiler := atlasstream.NewAtlasStreamsInstanceReconciler( mgr, b.predicates, b.atlasProvider, b.deletionProtection, b.logger, ) - if err = streamsInstanceReconciler.SetupWithManager(mgr, b.skipNameValidation); err != nil { + if err = streamsInstanceReconiler.SetupWithManager(mgr, b.skipNameValidation); err != nil { return nil, fmt.Errorf("unable to create controller AtlasStreamsInstance: %w", err) } diff --git a/test/e2e/db_users_test.go b/test/e2e/db_users_test.go index dfb50be298..a1af3b056d 100644 --- a/test/e2e/db_users_test.go +++ b/test/e2e/db_users_test.go @@ -2,7 +2,6 @@ package e2e import ( "context" - "fmt" "strings" "time" @@ -24,15 +23,10 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/data" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/k8s" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/model" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/utils" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/resources" ) -const ( - localSecretName = "local-secret" -) - -var _ = Describe("Operator watch all namespace should create connection secrets for database users in any namespace", Label("users", "users-ns"), func() { +var _ = Describe("Operator watch all namespace should create connection secrets for database users in any namespace", Label("users"), func() { var testData *model.TestDataProvider secondNamespace := "second-namespace" @@ -82,17 +76,14 @@ var _ = Describe("Operator watch all namespace should create connection secrets data.WithSecretRef("dbuser-secret-u2"), data.WithReadWriteRole(), data.WithNamespace(secondNamespace), - // user 2 access Atlas a local secret - data.WithCredentials(localSecretName), ), ) testData.Resources.Namespace = config.DefaultOperatorNS }) By("Running operator watching global namespace", func() { - Expect(k8s.CreateNamespace(testData.Context, testData.K8SClient, config.DefaultOperatorNS)).NotTo(HaveOccurred()) + k8s.CreateNamespace(testData.Context, testData.K8SClient, config.DefaultOperatorNS) k8s.CreateDefaultSecret(testData.Context, testData.K8SClient, config.DefaultOperatorGlobalKey, config.DefaultOperatorNS) - Expect(k8s.CreateNamespace(testData.Context, testData.K8SClient, secondNamespace)).NotTo(HaveOccurred()) - k8s.CreateDefaultSecret(testData.Context, testData.K8SClient, localSecretName, secondNamespace) + k8s.CreateNamespace(testData.Context, testData.K8SClient, secondNamespace) mgr, err := k8s.BuildManager(&k8s.Config{ GlobalAPISecret: client.ObjectKey{ @@ -164,96 +155,6 @@ var _ = Describe("Operator watch all namespace should create connection secrets }) }) -var _ = Describe("Operator fails if local credentials is mentioned but unavailable", Label("users", "users-no-creds"), func() { - var testData *model.TestDataProvider - namespace := utils.RandomName("namespace") - - _ = AfterEach(func() { - actions.DeleteTestDataUsers(testData) - actions.DeleteTestDataProject(testData) - actions.AfterEachFinalCleanup([]model.TestDataProvider{*testData}) - Expect(k8s.DeleteNamespace(testData.Context, testData.K8SClient, namespace)).Should(Succeed()) - }) - - It("Operator run on global namespace to test bogus local credential", func() { - By("Setting up test data", func() { - project := data.DefaultProject() - project.Namespace = namespace - - testData = model.DataProvider( - "dbusers-operator-global", - model.NewEmptyAtlasKeyType().UseDefaultFullAccess(), - 30008, - []func(*model.TestDataProvider){}, - ).WithProject(project). - WithUsers( - data.BasicUser( - "reader1", - "reader1", - data.WithSecretRef("dbuser-secret-u1"), - data.WithReadWriteRole(), - data.WithNamespace(namespace), - data.WithLabels([]common.LabelSpec{ - {Key: "type", Value: "e2e-test"}, - {Key: "context", Value: "cloud"}, - }), - // user 2 access Atlas a local secret - data.WithCredentials(localSecretName), - ), - ) - testData.Resources.Namespace = namespace - }) - By("Running operator watching global namespace missing credentials", func() { - Expect(k8s.CreateNamespace(testData.Context, testData.K8SClient, namespace)).NotTo(HaveOccurred()) - k8s.CreateDefaultSecret(testData.Context, testData.K8SClient, config.DefaultOperatorGlobalKey, namespace) - - mgr, err := k8s.BuildManager(&k8s.Config{ - GlobalAPISecret: client.ObjectKey{ - Namespace: namespace, - Name: config.DefaultOperatorGlobalKey, - }, - WatchedNamespaces: map[string]bool{ - namespace: true, - }, - FeatureFlags: featureflags.NewFeatureFlags(func() []string { return []string{} }), - }) - Expect(err).NotTo(HaveOccurred()) - - go func(ctx context.Context) context.Context { - err := mgr.Start(ctx) - Expect(err).NotTo(HaveOccurred()) - return ctx - }(testData.Context) - }) - By("Creating project", func() { - deploy.CreateProject(testData) - }) - By("Creating user with missing credentials", func() { - user := testData.Users[0] - if user.Spec.PasswordSecret != nil { - secret := utils.UserSecretPassword() - Expect(k8s.CreateUserSecret(testData.Context, testData.K8SClient, secret, - user.Spec.PasswordSecret.Name, user.Namespace)).Should(Succeed(), - "Create user secret failed") - } - err := testData.K8SClient.Create(testData.Context, user) - Expect(err).ShouldNot(HaveOccurred(), fmt.Sprintf("User was not created: %v", user)) - Eventually(func(g Gomega) { - g.Expect(testData.K8SClient.Get(testData.Context, types.NamespacedName{Name: user.GetName(), Namespace: user.GetNamespace()}, user)) - g.Expect(user.Status.Conditions).ShouldNot(BeEmpty()) - for _, condition := range user.Status.Conditions { - if condition.Type == api.ReadyType { - g.Expect(condition.Status).ShouldNot(Equal(corev1.ConditionTrue), "User should NOT be ready") - } - if condition.Type == api.DatabaseUserReadyType { - g.Expect(condition.Message).Should(ContainSubstring(`Secret "local-secret" not found`)) - } - } - }).WithTimeout(2*time.Minute).WithPolling(20*time.Second).Should(Succeed(), "User did not fail as expected") - }) - }) -}) - func countConnectionSecrets(k8sClient client.Client, projectName string) int { secretList := corev1.SecretList{} Expect(k8sClient.List(context.Background(), &secretList)).To(Succeed()) diff --git a/test/helper/e2e/data/user.go b/test/helper/e2e/data/user.go index 27c9d848bb..6da2116950 100644 --- a/test/helper/e2e/data/user.go +++ b/test/helper/e2e/data/user.go @@ -3,7 +3,6 @@ package data import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/v2/pkg/api/v1/common" ) @@ -105,9 +104,3 @@ func WithLabels(labels []common.LabelSpec) func(user *akov2.AtlasDatabaseUser) { user.Spec.Labels = labels } } - -func WithCredentials(secretName string) func(user *akov2.AtlasDatabaseUser) { - return func(user *akov2.AtlasDatabaseUser) { - user.Spec.ConnectionSecret = &api.LocalObjectReference{Name: secretName} - } -}