diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dba9cf4f0f..85bad7669d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -174,7 +174,7 @@ jobs: go version go get github.com/onsi/ginkgo/ginkgo && \ go get github.com/onsi/gomega/... - ginkgo --focus "${TEST_NAME}" -nodes=3 test/e2e/ + ginkgo --focus "${TEST_NAME}" -v -nodes=3 test/e2e/ - name: Upload operator logs if: ${{ failure() }} diff --git a/pkg/api/v1/atlasdatabaseuser_types.go b/pkg/api/v1/atlasdatabaseuser_types.go index b107d57db2..de12856989 100644 --- a/pkg/api/v1/atlasdatabaseuser_types.go +++ b/pkg/api/v1/atlasdatabaseuser_types.go @@ -220,6 +220,7 @@ func (p *AtlasDatabaseUser) WithName(name string) *AtlasDatabaseUser { p.Name = name return p } + func (p *AtlasDatabaseUser) WithAtlasUserName(name string) *AtlasDatabaseUser { p.Spec.Username = name return p @@ -239,6 +240,7 @@ func (p *AtlasDatabaseUser) WithScope(scopeType ScopeType, name string) *AtlasDa p.Spec.Scopes = append(p.Spec.Scopes, ScopeSpec{Name: name, Type: scopeType}) return p } + func (p *AtlasDatabaseUser) ClearScopes() *AtlasDatabaseUser { p.Spec.Scopes = make([]ScopeSpec, 0) return p diff --git a/pkg/api/v1/project/ipaccesslist.go.go b/pkg/api/v1/project/ipaccesslist.go.go index 905a35548a..acc43c6f6e 100644 --- a/pkg/api/v1/project/ipaccesslist.go.go +++ b/pkg/api/v1/project/ipaccesslist.go.go @@ -48,18 +48,22 @@ func (i IPAccessList) WithComment(comment string) IPAccessList { i.Comment = comment return i } + func (i IPAccessList) WithIP(ip string) IPAccessList { i.IPAddress = ip return i } + func (i IPAccessList) WithCIDR(cidr string) IPAccessList { i.CIDRBlock = cidr return i } + func (i IPAccessList) WithAWSGroup(group string) IPAccessList { i.AwsSecurityGroup = group return i } + func (i IPAccessList) WithDeleteAfterDate(date string) IPAccessList { i.DeleteAfterDate = date return i diff --git a/pkg/api/v1/status/atlasdatabaseuser.go b/pkg/api/v1/status/atlasdatabaseuser.go index 0762c68959..9914eccffc 100644 --- a/pkg/api/v1/status/atlasdatabaseuser.go +++ b/pkg/api/v1/status/atlasdatabaseuser.go @@ -10,6 +10,7 @@ func AtlasDatabaseUserPasswordVersion(passwordVersion string) AtlasDatabaseUserS s.PasswordVersion = passwordVersion } } + func AtlasDatabaseUserNameOption(name string) AtlasDatabaseUserStatusOption { return func(s *AtlasDatabaseUserStatus) { s.UserName = name diff --git a/pkg/api/v1/status/atlasproject.go b/pkg/api/v1/status/atlasproject.go index bb5e350980..924f6d2144 100644 --- a/pkg/api/v1/status/atlasproject.go +++ b/pkg/api/v1/status/atlasproject.go @@ -12,6 +12,7 @@ func AtlasProjectIDOption(id string) AtlasProjectStatusOption { s.ID = id } } + func AtlasProjectExpiredIPAccessOption(lists []project.IPAccessList) AtlasProjectStatusOption { return func(s *AtlasProjectStatus) { s.ExpiredIPAccessList = lists diff --git a/pkg/api/v1/status/status.go b/pkg/api/v1/status/status.go index 83da1886a3..8b6ee0815e 100644 --- a/pkg/api/v1/status/status.go +++ b/pkg/api/v1/status/status.go @@ -38,6 +38,7 @@ type Common struct { func (c Common) GetConditions() []Condition { return c.Conditions } + func (c Common) GetObservedGeneration() int64 { return c.ObservedGeneration } diff --git a/pkg/controller/atlascluster/atlascluster_controller.go b/pkg/controller/atlascluster/atlascluster_controller.go index 6f3ce2189f..db29ff6323 100644 --- a/pkg/controller/atlascluster/atlascluster_controller.go +++ b/pkg/controller/atlascluster/atlascluster_controller.go @@ -58,8 +58,6 @@ type AtlasClusterReconciler struct { // +kubebuilder:rbac:groups=atlas.mongodb.com,namespace=default,resources=atlasclusters/status,verbs=get;update;patch func (r *AtlasClusterReconciler) Reconcile(context context.Context, req ctrl.Request) (ctrl.Result, error) { - // TODO use the context passed - _ = context log := r.Log.With("atlascluster", req.NamespacedName) cluster := &mdbv1.AtlasCluster{} @@ -104,6 +102,11 @@ func (r *AtlasClusterReconciler) Reconcile(context context.Context, req ctrl.Req return result.ReconcileResult(), nil } + if csResult := ensureConnectionSecrets(ctx, r.Client, project, c); !csResult.IsOk() { + ctx.SetConditionFromResult(status.ClusterReadyType, csResult) + return csResult.ReconcileResult(), nil + } + ctx. SetConditionTrue(status.ClusterReadyType). EnsureStatusOption(status.AtlasClusterMongoDBVersionOption(c.MongoDBVersion)). diff --git a/pkg/controller/atlascluster/cluster.go b/pkg/controller/atlascluster/cluster.go index 753d452a86..663ded2142 100644 --- a/pkg/controller/atlascluster/cluster.go +++ b/pkg/controller/atlascluster/cluster.go @@ -9,10 +9,15 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "go.mongodb.org/atlas/mongodbatlas" "go.uber.org/zap" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/status" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/connectionsecret" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/workflow" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/compat" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/stringutil" ) func (r *AtlasClusterReconciler) ensureClusterState(ctx *workflow.Context, project *mdbv1.AtlasProject, cluster *mdbv1.AtlasCluster) (atlasCluster *mongodbatlas.Cluster, _ workflow.Result) { @@ -152,3 +157,50 @@ func ClustersEqual(log *zap.SugaredLogger, clusterAtlas mongodbatlas.Cluster, cl return d == "" } + +func ensureConnectionSecrets(ctx *workflow.Context, k8sClient client.Client, project *mdbv1.AtlasProject, cluster *mongodbatlas.Cluster) workflow.Result { + databaseUsers := mdbv1.AtlasDatabaseUserList{} + err := k8sClient.List(context.TODO(), &databaseUsers, client.InNamespace(project.Namespace)) + if err != nil { + return workflow.Terminate(workflow.Internal, err.Error()) + } + + for _, dbUser := range databaseUsers.Items { + found := false + for _, c := range dbUser.Status.Conditions { + if c.Type == status.ReadyType && c.Status == v1.ConditionTrue { + found = true + break + } + } + + if !found { + ctx.Log.Debugw("AtlasDatabaseUser not ready - not creating connection secret", "user.name", dbUser.Name) + continue + } + + scopes := dbUser.GetScopes(mdbv1.ClusterScopeType) + if len(scopes) != 0 && !stringutil.Contains(scopes, cluster.Name) { + continue + } + + password, err := dbUser.ReadPassword(k8sClient) + if err != nil { + return workflow.Terminate(workflow.ClusterConnectionSecretsNotCreated, err.Error()) + } + + data := connectionsecret.ConnectionData{ + DBUserName: dbUser.Spec.Username, + ConnURL: cluster.ConnectionStrings.Standard, + SrvConnURL: cluster.ConnectionStrings.StandardSrv, + Password: password, + } + + _, err = connectionsecret.Ensure(k8sClient, project.Namespace, project.Spec.Name, project.ID(), cluster.Name, data) + if err != nil { + return workflow.Terminate(workflow.ClusterConnectionSecretsNotCreated, err.Error()) + } + } + + return workflow.OK() +} diff --git a/pkg/controller/atlascluster/cluster_test.go b/pkg/controller/atlascluster/cluster_test.go index 45f73e2630..604532ec9d 100644 --- a/pkg/controller/atlascluster/cluster_test.go +++ b/pkg/controller/atlascluster/cluster_test.go @@ -79,12 +79,15 @@ func TestClusterMatchesSpec(t *testing.T) { t.Run("Clusters match when Atlas adds default ReplicationSpecs", func(t *testing.T) { atlasCluster, err := mdbv1.DefaultAWSCluster("test-ns", "project-name").Spec.Cluster() assert.NoError(t, err) - atlasCluster.ReplicationSpecs = []mongodbatlas.ReplicationSpec{{ - ID: "id", - NumShards: int64ptr(1), - ZoneName: "zone1", - RegionsConfig: map[string]mongodbatlas.RegionsConfig{ - "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}}}, + atlasCluster.ReplicationSpecs = []mongodbatlas.ReplicationSpec{ + { + ID: "id", + NumShards: int64ptr(1), + ZoneName: "zone1", + RegionsConfig: map[string]mongodbatlas.RegionsConfig{ + "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}, + }, + }, } operatorCluster := mdbv1.DefaultAWSCluster("test-ns", "project-name") operatorCluster.Spec.ReplicationSpecs = []mdbv1.ReplicationSpec{{ @@ -101,12 +104,15 @@ func TestClusterMatchesSpec(t *testing.T) { t.Run("Clusters don't match when Atlas adds default ReplicationSpecs and Operator overrides something", func(t *testing.T) { atlasCluster, err := mdbv1.DefaultAWSCluster("test-ns", "project-name").Spec.Cluster() assert.NoError(t, err) - atlasCluster.ReplicationSpecs = []mongodbatlas.ReplicationSpec{{ - ID: "id", - NumShards: int64ptr(1), - ZoneName: "zone1", - RegionsConfig: map[string]mongodbatlas.RegionsConfig{ - "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}}}, + atlasCluster.ReplicationSpecs = []mongodbatlas.ReplicationSpec{ + { + ID: "id", + NumShards: int64ptr(1), + ZoneName: "zone1", + RegionsConfig: map[string]mongodbatlas.RegionsConfig{ + "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}, + }, + }, } operatorCluster := mdbv1.DefaultAWSCluster("test-ns", "project-name") operatorCluster.Spec.ReplicationSpecs = []mdbv1.ReplicationSpec{{ @@ -117,12 +123,15 @@ func TestClusterMatchesSpec(t *testing.T) { merged, err := MergedCluster(*atlasCluster, operatorCluster.Spec) assert.NoError(t, err) - expectedReplicationSpecs := []mongodbatlas.ReplicationSpec{{ - ID: "id", - NumShards: int64ptr(2), - ZoneName: "zone5", - RegionsConfig: map[string]mongodbatlas.RegionsConfig{ - "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}}}, + expectedReplicationSpecs := []mongodbatlas.ReplicationSpec{ + { + ID: "id", + NumShards: int64ptr(2), + ZoneName: "zone5", + RegionsConfig: map[string]mongodbatlas.RegionsConfig{ + "US_EAST": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(3), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}, + }, + }, } assert.Equal(t, expectedReplicationSpecs, merged.ReplicationSpecs) @@ -167,6 +176,7 @@ func TestClusterMatchesSpec(t *testing.T) { assert.False(t, equal) }) } + func int64ptr(i int64) *int64 { return &i } diff --git a/pkg/controller/atlasdatabaseuser/connectionsecrets.go b/pkg/controller/atlasdatabaseuser/connectionsecrets.go index 287d0aa9d4..66acd2944a 100644 --- a/pkg/controller/atlasdatabaseuser/connectionsecrets.go +++ b/pkg/controller/atlasdatabaseuser/connectionsecrets.go @@ -14,8 +14,7 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/stringutil" ) -// createOrUpdateConnectionSecrets -func createOrUpdateConnectionSecrets(ctx *workflow.Context, k8sClient client.Client, project mdbv1.AtlasProject, dbUser mdbv1.AtlasDatabaseUser) workflow.Result { +func CreateOrUpdateConnectionSecrets(ctx *workflow.Context, k8sClient client.Client, project mdbv1.AtlasProject, dbUser mdbv1.AtlasDatabaseUser) workflow.Result { clusters, _, err := ctx.Client.Clusters.List(context.Background(), project.ID(), &mongodbatlas.ListOptions{}) if err != nil { return workflow.Terminate(workflow.DatabaseUserConnectionSecretsNotCreated, err.Error()) diff --git a/pkg/controller/atlasdatabaseuser/databaseuser.go b/pkg/controller/atlasdatabaseuser/databaseuser.go index 999bb29a9f..15fe80a7a1 100644 --- a/pkg/controller/atlasdatabaseuser/databaseuser.go +++ b/pkg/controller/atlasdatabaseuser/databaseuser.go @@ -43,7 +43,7 @@ func (r *AtlasDatabaseUserReconciler) ensureDatabaseUser(ctx *workflow.Context, return result } - if result := createOrUpdateConnectionSecrets(ctx, r.Client, project, dbUser); !result.IsOk() { + if result := CreateOrUpdateConnectionSecrets(ctx, r.Client, project, dbUser); !result.IsOk() { return result } @@ -131,6 +131,7 @@ func performUpdateInAtlas(ctx *workflow.Context, k8sClient client.Client, projec // after the successful update we'll retry reconciliation so that clusters had a chance to start working return retryAfterUpdate } + return workflow.OK() } diff --git a/pkg/controller/workflow/reason.go b/pkg/controller/workflow/reason.go index a55469cb24..79ac888045 100644 --- a/pkg/controller/workflow/reason.go +++ b/pkg/controller/workflow/reason.go @@ -19,10 +19,11 @@ const ( // Atlas Cluster reasons const ( - ClusterNotCreatedInAtlas ConditionReason = "ClusterNotCreatedInAtlas" - ClusterNotUpdatedInAtlas ConditionReason = "ClusterNotUpdatedInAtlas" - ClusterCreating ConditionReason = "ClusterCreating" - ClusterUpdating ConditionReason = "ClusterUpdating" + ClusterNotCreatedInAtlas ConditionReason = "ClusterNotCreatedInAtlas" + ClusterNotUpdatedInAtlas ConditionReason = "ClusterNotUpdatedInAtlas" + ClusterCreating ConditionReason = "ClusterCreating" + ClusterUpdating ConditionReason = "ClusterUpdating" + ClusterConnectionSecretsNotCreated ConditionReason = "ClusterConnectionSecretsNotCreated" ) // Atlas Database User reasons diff --git a/pkg/util/kube/kube_test.go b/pkg/util/kube/kube_test.go index d382020684..9b7cda9b0e 100644 --- a/pkg/util/kube/kube_test.go +++ b/pkg/util/kube/kube_test.go @@ -46,6 +46,7 @@ func TestNormalizeIdentifier(t *testing.T) { } }) } + func TestNormalizeLabelValue(t *testing.T) { t.Run("Valid Label Value", func(t *testing.T) { successCases := []string{ diff --git a/test/app/main.go b/test/app/main.go index ffceb41975..5f537588b7 100644 --- a/test/app/main.go +++ b/test/app/main.go @@ -117,7 +117,6 @@ func getMongoClient() (*mongo.Client, error) { func getMongoCollection(DbName string, CollectionName string) (*mongo.Collection, error) { client, err := getMongoClient() - if err != nil { return nil, err } diff --git a/test/e2e/cli/kube/kubectl.go b/test/e2e/cli/kube/kubectl.go index 05430d8c9d..b10d03d892 100644 --- a/test/e2e/cli/kube/kubectl.go +++ b/test/e2e/cli/kube/kubectl.go @@ -1,12 +1,11 @@ package kube import ( + "encoding/json" "fmt" "os" "strings" - "encoding/json" - . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" diff --git a/test/e2e/configuration_test.go b/test/e2e/configuration_test.go index 0bf1b9c4dc..ea0fbee0d3 100644 --- a/test/e2e/configuration_test.go +++ b/test/e2e/configuration_test.go @@ -27,10 +27,9 @@ type testDataProvider struct { } var _ = Describe("[cluster-ns] Configuration namespaced. Deploy cluster", func() { - var data testDataProvider - var _ = AfterEach(func() { + _ = AfterEach(func() { GinkgoWriter.Write([]byte("===============================================\n")) GinkgoWriter.Write([]byte("Operator namespace: " + data.resources.Namespace + "\n")) GinkgoWriter.Write([]byte("===============================================\n")) @@ -47,7 +46,6 @@ var _ = Describe("[cluster-ns] Configuration namespaced. Deploy cluster", func() } else { Eventually(kube.DeleteNamespace(data.resources.Namespace)).Should(Say("deleted"), "Cant delete namespace after testing") } - }) // TODO remove portGroup (nodePort for the app) diff --git a/test/e2e/operator_type_wide_test.go b/test/e2e/operator_type_wide_test.go index a1e30df2f8..077e9f07ac 100644 --- a/test/e2e/operator_type_wide_test.go +++ b/test/e2e/operator_type_wide_test.go @@ -15,11 +15,10 @@ import ( ) var _ = Describe("[cluster-wide] Users (Norton and Nimnul) can work with one Cluster wide operator", func() { - var NortonSpec, NimnulSpec model.UserInputs commonClusterName := "megacluster" - var _ = BeforeEach(func() { + _ = BeforeEach(func() { By("User Install CRD, cluster wide Operator", func() { Eventually(kube.Apply(ConfigAll)).Should( Say("customresourcedefinition.apiextensions.k8s.io/atlasclusters.atlas.mongodb.com"), @@ -31,7 +30,7 @@ var _ = Describe("[cluster-wide] Users (Norton and Nimnul) can work with one Clu }) }) - var _ = AfterEach(func() { + _ = AfterEach(func() { By("Delete clusters", func() { if CurrentGinkgoTestDescription().Failed { GinkgoWriter.Write([]byte("Resources wasn't clean")) diff --git a/test/e2e/utils/utils.go b/test/e2e/utils/utils.go index 883ec13e82..6124445aa0 100644 --- a/test/e2e/utils/utils.go +++ b/test/e2e/utils/utils.go @@ -2,10 +2,9 @@ package utils import ( "encoding/json" - "os" - "io/ioutil" "log" + "os" "path/filepath" yaml "gopkg.in/yaml.v3" diff --git a/test/int/cluster_test.go b/test/int/cluster_test.go index f5d2e92da3..5bb5d45c06 100644 --- a/test/int/cluster_test.go +++ b/test/int/cluster_test.go @@ -14,6 +14,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/project" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/status" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/atlascluster" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/workflow" @@ -24,7 +25,8 @@ import ( const ( // Set this to true if you are debugging cluster creation. // This may not help much if there was the update though... - ClusterDevMode = false + ClusterDevMode = false + ClusterUpdateTimeout = 3600 ) var _ = Describe("AtlasCluster", func() { @@ -54,7 +56,7 @@ var _ = Describe("AtlasCluster", func() { By(fmt.Sprintf("Creating the Secret %s", kube.ObjectKeyFromObject(&connectionSecret))) Expect(k8sClient.Create(context.Background(), &connectionSecret)).To(Succeed()) - createdProject = mdbv1.DefaultProject(namespace.Name, connectionSecret.Name) + createdProject = mdbv1.DefaultProject(namespace.Name, connectionSecret.Name).WithIPAccessList(project.NewIPAccessList().WithIP("0.0.0.0/0")) if ClusterDevMode { // While developing tests we need to reuse the same project createdProject.Spec.Name = "dev-test atlas-project" @@ -207,7 +209,7 @@ var _ = Describe("AtlasCluster", func() { Expect(k8sClient.Create(context.Background(), expectedCluster)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) doCommonStatusChecks() checkAtlasState() @@ -267,7 +269,8 @@ var _ = Describe("AtlasCluster", func() { RegionsConfig: map[string]mdbv1.RegionsConfig{ "US_EAST_1": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(1), Priority: int64ptr(6), ReadOnlyNodes: int64ptr(0)}, "US_WEST_2": {AnalyticsNodes: int64ptr(0), ElectableNodes: int64ptr(2), Priority: int64ptr(7), ReadOnlyNodes: int64ptr(0)}, - }}} + }, + }} replicationSpecsCheckFunc := func(c *mongodbatlas.Cluster) { cluster, err := createdCluster.Spec.Cluster() @@ -285,7 +288,7 @@ var _ = Describe("AtlasCluster", func() { Expect(k8sClient.Create(context.Background(), createdCluster)).To(Succeed()) Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) doCommonStatusChecks() @@ -302,10 +305,10 @@ var _ = Describe("AtlasCluster", func() { createdCluster.Spec.ProviderSettings.AutoScaling.Compute.MaxInstanceSize = "M30" - performUpdate(80 * time.Minute) + performUpdate(ClusterUpdateTimeout * time.Minute) Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterUpdatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) doCommonStatusChecks() @@ -357,7 +360,7 @@ var _ = Describe("AtlasCluster", func() { Expect(k8sClient.Create(context.Background(), createdCluster)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) doCommonStatusChecks() checkAtlasState() @@ -497,6 +500,53 @@ var _ = Describe("AtlasCluster", func() { }) }) + Describe("Create DBUser before cluster & check secrets", func() { + It("Should Succeed", func() { + By(fmt.Sprintf("Creating password Secret %s", UserPasswordSecret), func() { + passwordSecret := buildPasswordSecret(UserPasswordSecret, DBUserPassword) + Expect(k8sClient.Create(context.Background(), &passwordSecret)).To(Succeed()) + }) + + createdDBUser := mdbv1.DefaultDBUser(namespace.Name, "test-db-user", createdProject.Name).WithPasswordSecret(UserPasswordSecret) + By(fmt.Sprintf("Creating the Database User %s", kube.ObjectKeyFromObject(createdDBUser)), func() { + Expect(k8sClient.Create(context.Background(), createdDBUser)).ToNot(HaveOccurred()) + + Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), + 20, interval).Should(BeTrue()) + + checkUserInAtlas(createdProject.ID(), *createdDBUser) + }) + + createdDBUserFakeScope := mdbv1.DefaultDBUser(namespace.Name, "test-db-user-fake-scope", createdProject.Name). + WithPasswordSecret(UserPasswordSecret). + WithScope(mdbv1.ClusterScopeType, "fake-cluster") + By(fmt.Sprintf("Creating the Database User %s", kube.ObjectKeyFromObject(createdDBUserFakeScope)), func() { + Expect(k8sClient.Create(context.Background(), createdDBUserFakeScope)).ToNot(HaveOccurred()) + + Eventually(testutil.WaitFor(k8sClient, createdDBUserFakeScope, status.FalseCondition(status.DatabaseUserReadyType).WithReason(string(workflow.DatabaseUserInvalidSpec))), + 20, interval).Should(BeTrue()) + }) + checkNumberOfConnectionSecrets(k8sClient, *createdProject, 0) + + createdCluster = mdbv1.DefaultGCPCluster(namespace.Name, createdProject.Name) + By(fmt.Sprintf("Creating the Cluster %s", kube.ObjectKeyFromObject(createdCluster)), func() { + Expect(k8sClient.Create(context.Background(), createdCluster)).ToNot(HaveOccurred()) + + Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), + ClusterUpdateTimeout, interval).Should(BeTrue()) + + doCommonStatusChecks() + checkAtlasState() + }) + + By("Checking connection Secrets", func() { + Expect(tryConnect(createdProject.ID(), *createdCluster, *createdDBUser)).To(Succeed()) + checkNumberOfConnectionSecrets(k8sClient, *createdProject, 1) + validateSecret(k8sClient, *createdProject, *createdCluster, *createdDBUser) + }) + }) + }) + Describe("Create cluster, user, delete cluster and check secrets are removed", func() { It("Should Succeed", func() { createdCluster = mdbv1.DefaultGCPCluster(namespace.Name, createdProject.Name) @@ -504,7 +554,7 @@ var _ = Describe("AtlasCluster", func() { Expect(k8sClient.Create(context.Background(), createdCluster)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdCluster, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) doCommonStatusChecks() checkAtlasState() diff --git a/test/int/dbuser_test.go b/test/int/dbuser_test.go index 13eb592350..915560a2c5 100644 --- a/test/int/dbuser_test.go +++ b/test/int/dbuser_test.go @@ -130,17 +130,6 @@ var _ = Describe("AtlasDatabaseUser", func() { removeControllersAndNamespace() }) - checkUserInAtlas := func(user mdbv1.AtlasDatabaseUser) { - By("Verifying Database User state in Atlas", func() { - atlasDBUser, _, err := atlasClient.DatabaseUsers.Get(context.Background(), user.Spec.DatabaseName, createdProject.ID(), user.Spec.Username) - Expect(err).ToNot(HaveOccurred()) - operatorDBUser, err := user.ToAtlas(k8sClient) - Expect(err).ToNot(HaveOccurred()) - - Expect(*atlasDBUser).To(Equal(normalize(*operatorDBUser, createdProject.ID()))) - }) - } - connSecretname := func(suffix string) string { return kube.NormalizeIdentifier(createdProject.Spec.Name) + suffix } @@ -155,7 +144,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Expect(k8sClient.Create(context.Background(), createdClusterGCP)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdClusterAWS, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) Eventually(testutil.WaitFor(k8sClient, createdClusterGCP, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), 500, interval).Should(BeTrue()) @@ -168,7 +157,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval, validateDatabaseUserUpdatingFunc()).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) Expect(tryConnect(createdProject.ID(), *createdClusterGCP, *createdDBUser)).Should(Succeed()) Expect(tryConnect(createdProject.ID(), *createdClusterAWS, *createdDBUser)).Should(Succeed()) @@ -197,7 +186,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) By("Checking connection Secrets", func() { validateSecret(k8sClient, *createdProject, *createdClusterGCP, *createdDBUser) @@ -244,7 +233,8 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, secondDBUser, status.TrueCondition(status.ReadyType), validateDatabaseUserUpdatingFunc()), DBUserUpdateTimeout, interval).Should(BeTrue()) - checkUserInAtlas(*secondDBUser) + checkUserInAtlas(createdProject.ID(), *secondDBUser) + By("Checking connection Secrets", func() { validateSecret(k8sClient, *createdProject, *createdClusterGCP, *createdDBUser) validateSecret(k8sClient, *createdProject, *createdClusterAWS, *createdDBUser) @@ -282,7 +272,6 @@ var _ = Describe("AtlasDatabaseUser", func() { checkNumberOfConnectionSecrets(k8sClient, *createdProject, 0) }) - }) }) @@ -298,7 +287,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) checkNumberOfConnectionSecrets(k8sClient, *createdProject, 0) }) By("Creating cluster", func() { @@ -315,7 +304,7 @@ var _ = Describe("AtlasDatabaseUser", func() { // DatabaseUser will wait for the cluster to get created. Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) expectedConditionsMatchers := testutil.MatchConditions( status.TrueCondition(status.DatabaseUserReadyType), @@ -323,7 +312,7 @@ var _ = Describe("AtlasDatabaseUser", func() { ) Expect(createdDBUser.Status.Conditions).To(ConsistOf(expectedConditionsMatchers)) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) Expect(tryConnect(createdProject.ID(), *createdClusterAWS, *createdDBUser)).Should(Succeed()) By("Checking connection Secrets", func() { validateSecret(k8sClient, *createdProject, *createdClusterAWS, *createdDBUser) @@ -339,7 +328,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Expect(k8sClient.Create(context.Background(), createdClusterGCP)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdClusterGCP, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) }) createdDBUser = mdbv1.DefaultDBUser(namespace.Name, "test-db-user", createdProject.Name).WithPasswordSecret(UserPasswordSecret) var connSecretInitial corev1.Secret @@ -395,10 +384,10 @@ var _ = Describe("AtlasDatabaseUser", func() { Expect(k8sClient.Create(context.Background(), createdClusterAzure)).ToNot(HaveOccurred()) Eventually(testutil.WaitFor(k8sClient, createdClusterGCP, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) Eventually(testutil.WaitFor(k8sClient, createdClusterAzure, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) }) createdDBUser = mdbv1.DefaultDBUser(namespace.Name, "test-db-user", createdProject.Name).WithPasswordSecret(UserPasswordSecret) @@ -420,7 +409,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval, validateDatabaseUserUpdatingFunc()).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) // Old user has been removed _, _, err := atlasClient.DatabaseUsers.Get(context.Background(), createdDBUser.Spec.DatabaseName, createdProject.ID(), oldName) Expect(err).To(HaveOccurred()) @@ -456,7 +445,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Expect(k8sClient.Create(context.Background(), createdClusterGCP)).To(Succeed()) Eventually(testutil.WaitFor(k8sClient, createdClusterGCP, status.TrueCondition(status.ReadyType), validateClusterCreatingFunc()), - 1800, interval).Should(BeTrue()) + ClusterUpdateTimeout, interval).Should(BeTrue()) }) By("Creating the expired Database User - no user created in Atlas", func() { @@ -484,7 +473,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval, validateDatabaseUserUpdatingFunc()).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) checkNumberOfConnectionSecrets(k8sClient, *createdProject, 1) Expect(tryConnect(createdProject.ID(), *createdClusterGCP, *createdDBUser)).Should(Succeed()) }) @@ -496,7 +485,7 @@ var _ = Describe("AtlasDatabaseUser", func() { Eventually(testutil.WaitFor(k8sClient, createdDBUser, status.TrueCondition(status.ReadyType)), DBUserUpdateTimeout, interval, validateDatabaseUserUpdatingFunc()).Should(BeTrue()) - checkUserInAtlas(*createdDBUser) + checkUserInAtlas(createdProject.ID(), *createdDBUser) }) By("Emulating expiration of the User - connection secret must be removed", func() { before := time.Now().Add(time.Minute * -5).Format("2006-01-02T15:04:05") @@ -694,6 +683,17 @@ func checkSecretsDontExist(namespace string, secretNames []string) func() bool { } } +func checkUserInAtlas(projectID string, user mdbv1.AtlasDatabaseUser) { + By("Verifying Database User state in Atlas", func() { + atlasDBUser, _, err := atlasClient.DatabaseUsers.Get(context.Background(), user.Spec.DatabaseName, projectID, user.Spec.Username) + Expect(err).ToNot(HaveOccurred()) + operatorDBUser, err := user.ToAtlas(k8sClient) + Expect(err).ToNot(HaveOccurred()) + + Expect(*atlasDBUser).To(Equal(normalize(*operatorDBUser, projectID))) + }) +} + func validateDatabaseUserUpdatingFunc() func(a mdbv1.AtlasCustomResource) { return func(a mdbv1.AtlasCustomResource) { d := a.(*mdbv1.AtlasDatabaseUser)