From b22ce9dd341fed04ed6d6f8acc7cf900d38dd7f0 Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Mon, 25 Jan 2021 17:33:58 +0000 Subject: [PATCH 1/8] fix linter --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 379b0e82f0..b2729887fd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,28 @@ # MongoDB Atlas Operator Welcome to MongoDB Atlas Operator - the Operator allowing to manage Atlas Clusters from Kubernetes. +> Current Status: *pre-alpha*. We are currently working on the initial set of features that will give users the opportunity to +provision Atlas projects, clusters and database users using Kubernetes Specifications and bind connection information +into the applications deployed to Kubernetes. + +## Installation / Upgrade + +### Using Kubernetes config files + +``` +kubectl apply -f +``` + +## Create Atlas Cluster + +In order to work with Atlas you'll need to provide the authentication information that would allow the Atlas Operator +communicate with Atlas API. You need to create the secret first: + +``` +kubectl create secret generic my-atlas-key \ + --from-literal="orgId=" \ + --from-literal="publicApiKey=" \ + --from-literal="privateApiKey=" \ + -n +``` + From 9929dec2a58cc382e534d6e4fb9800ec332f8f0c Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Fri, 5 Feb 2021 16:33:39 +0000 Subject: [PATCH 2/8] wip --- .../atlasproject/atlasproject_controller.go | 7 +++- pkg/controller/atlasproject/ipaccess_list.go | 40 +++++++++++++++++++ pkg/controller/workflow/reason.go | 3 +- pkg/util/timeutil/timeutil.go | 7 ++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 pkg/controller/atlasproject/ipaccess_list.go create mode 100644 pkg/util/timeutil/timeutil.go diff --git a/pkg/controller/atlasproject/atlasproject_controller.go b/pkg/controller/atlasproject/atlasproject_controller.go index 880d316ba1..c07f18ed79 100644 --- a/pkg/controller/atlasproject/atlasproject_controller.go +++ b/pkg/controller/atlasproject/atlasproject_controller.go @@ -82,9 +82,12 @@ func (r *AtlasProjectReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error // Updating the status with "projectReady = true" and "IPAccessListReady = false" (not as separate updates!) ctx.SetConditionTrue(status.ProjectReadyType) - statushandler.Update(ctx.SetConditionFalse(status.IPAccessListReadyType), r.Client, project) - // TODO projectAccessList + if result = r.ensureIPAccessList(ctx, connection, project); !result.IsOk() { + ctx.SetConditionFromResult(status.IPAccessListReadyType, result) + return result.ReconcileResult(), nil + } + ctx.SetConditionTrue(status.IPAccessListReadyType) ctx.SetConditionTrue(status.ReadyType) return ctrl.Result{}, nil } diff --git a/pkg/controller/atlasproject/ipaccess_list.go b/pkg/controller/atlasproject/ipaccess_list.go new file mode 100644 index 0000000000..da108dfcd4 --- /dev/null +++ b/pkg/controller/atlasproject/ipaccess_list.go @@ -0,0 +1,40 @@ +package atlasproject + +import ( + "fmt" + "time" + + mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/atlas" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/workflow" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/timeutil" +) + +func (r *AtlasProjectReconciler) ensureIPAccessList(ctx *workflow.Context, connection atlas.Connection, project *mdbv1.AtlasProject) workflow.Result { + active, expired, result := filterActiveIPAccessLists(project) + if !result.IsOk() { + return result + } + fmt.Println(active, expired, ctx, connection) + return workflow.OK() +} + +func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAccessList, []mdbv1.ProjectIPAccessList, workflow.Result) { + active := make([]mdbv1.ProjectIPAccessList, 0) + expired := make([]mdbv1.ProjectIPAccessList, 0) + for _, list := range project.Spec.ProjectIPAccessList { + if list.DeleteAfterDate != "" { + iso8601, err := timeutil.ParseISO8601(list.DeleteAfterDate) + if err != nil { + return active, expired, workflow.Terminate(workflow.ProjectIPAccessBadFormatted, err.Error()) + } + if iso8601.Before(time.Now()) { + expired = append(expired, list) + continue + } + } + // Either 'deleteAfterDate' field is not specified or it's higher than the current time + active = append(active, list) + } + return active, expired, workflow.OK() +} diff --git a/pkg/controller/workflow/reason.go b/pkg/controller/workflow/reason.go index 17d6c65675..1f16f11d17 100644 --- a/pkg/controller/workflow/reason.go +++ b/pkg/controller/workflow/reason.go @@ -12,7 +12,8 @@ const ( // Atlas Project reasons const ( - ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" + ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" + ProjectIPAccessBadFormatted ConditionReason = "ProjectIpAccessListBadFormatted" ) // Atlas Cluster reasons diff --git a/pkg/util/timeutil/timeutil.go b/pkg/util/timeutil/timeutil.go new file mode 100644 index 0000000000..8eb35388b8 --- /dev/null +++ b/pkg/util/timeutil/timeutil.go @@ -0,0 +1,7 @@ +package timeutil + +import "time" + +func ParseISO8601(dateTime string) (time.Time, error) { + return time.Parse(dateTime, "2006-01-02T15:04:05-0700") +} From a4d3a20e85009adb2f604c4b63acb907d4449a6a Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Fri, 5 Feb 2021 20:15:30 +0000 Subject: [PATCH 3/8] wip --- pkg/api/v1/atlascluster_types.go | 16 +--- pkg/api/v1/atlasproject_types.go | 15 ++++ .../atlasproject/atlasproject_controller.go | 2 +- pkg/controller/atlasproject/ipaccess_list.go | 89 ++++++++++++++++++- pkg/controller/workflow/reason.go | 5 +- test/int/project_test.go | 13 +++ 6 files changed, 122 insertions(+), 18 deletions(-) diff --git a/pkg/api/v1/atlascluster_types.go b/pkg/api/v1/atlascluster_types.go index d1534ae6f0..e9e5254db7 100644 --- a/pkg/api/v1/atlascluster_types.go +++ b/pkg/api/v1/atlascluster_types.go @@ -17,13 +17,12 @@ limitations under the License. package v1 import ( - "encoding/json" - "go.mongodb.org/atlas/mongodbatlas" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/status" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/compat" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/kube" ) @@ -238,17 +237,8 @@ var _ = RegionsConfig(mongodbatlas.RegionsConfig{}) // Cluster converts the Spec to native Atlas client format. func (spec *AtlasClusterSpec) Cluster() (*mongodbatlas.Cluster, error) { result := mongodbatlas.Cluster{} - b, err := json.Marshal(spec) - if err != nil { - return nil, err - } - - err = json.Unmarshal(b, &result) - if err != nil { - return nil, err - } - - return &result, nil + err := compat.JSONCopy(result, spec) + return &result, err } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/api/v1/atlasproject_types.go b/pkg/api/v1/atlasproject_types.go index eff9266bac..19e2bbcb69 100644 --- a/pkg/api/v1/atlasproject_types.go +++ b/pkg/api/v1/atlasproject_types.go @@ -17,10 +17,12 @@ limitations under the License. package v1 import ( + "go.mongodb.org/atlas/mongodbatlas" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1/status" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/compat" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/kube" ) @@ -96,6 +98,19 @@ type ProjectIPAccessList struct { IPAddress string `json:"ipAddress,omitempty"` } +// ToAtlas converts the ProjectIPAccessList to native Atlas client format. +func (i *ProjectIPAccessList) ToAtlas() (mongodbatlas.ProjectIPAccessList, error) { + result := mongodbatlas.ProjectIPAccessList{} + err := compat.JSONCopy(result, i) + return result, err +} + +// Identifier returns the "id" of the ProjectIPAccessList. Note, that it's an error to specify more than one of these +// fields - the business layer must validate this beforehand +func (i ProjectIPAccessList) Identifier() interface{} { + return i.CIDRBlock + i.AwsSecurityGroup + i.IPAddress +} + func (p *AtlasProject) ConnectionSecretObjectKey() *client.ObjectKey { if p.Spec.ConnectionSecret != nil { key := kube.ObjectKey(p.Namespace, p.Spec.ConnectionSecret.Name) diff --git a/pkg/controller/atlasproject/atlasproject_controller.go b/pkg/controller/atlasproject/atlasproject_controller.go index c07f18ed79..b3882bd9f6 100644 --- a/pkg/controller/atlasproject/atlasproject_controller.go +++ b/pkg/controller/atlasproject/atlasproject_controller.go @@ -83,7 +83,7 @@ func (r *AtlasProjectReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error // Updating the status with "projectReady = true" and "IPAccessListReady = false" (not as separate updates!) ctx.SetConditionTrue(status.ProjectReadyType) - if result = r.ensureIPAccessList(ctx, connection, project); !result.IsOk() { + if result = r.ensureIPAccessList(ctx, connection, projectID, project); !result.IsOk() { ctx.SetConditionFromResult(status.IPAccessListReadyType, result) return result.ReconcileResult(), nil } diff --git a/pkg/controller/atlasproject/ipaccess_list.go b/pkg/controller/atlasproject/ipaccess_list.go index da108dfcd4..44f4f1331a 100644 --- a/pkg/controller/atlasproject/ipaccess_list.go +++ b/pkg/controller/atlasproject/ipaccess_list.go @@ -1,24 +1,104 @@ package atlasproject import ( + "context" + "errors" "fmt" "time" + "go.mongodb.org/atlas/mongodbatlas" + "go.uber.org/zap" + mdbv1 "github.com/mongodb/mongodb-atlas-kubernetes/pkg/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/atlas" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/controller/workflow" + "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/set" "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/timeutil" ) -func (r *AtlasProjectReconciler) ensureIPAccessList(ctx *workflow.Context, connection atlas.Connection, project *mdbv1.AtlasProject) workflow.Result { +type atlasProjectIPAccessList mongodbatlas.ProjectIPAccessList + +func (i atlasProjectIPAccessList) Identifier() interface{} { + return i.CIDRBlock + i.AwsSecurityGroup + i.IPAddress +} + +func (r *AtlasProjectReconciler) ensureIPAccessList(ctx *workflow.Context, connection atlas.Connection, projectID string, project *mdbv1.AtlasProject) workflow.Result { + if err := validateIPAccessLists(project.Spec.ProjectIPAccessList); err != nil { + return workflow.Terminate(workflow.ProjectIPAccessInvalid, err.Error()) + } active, expired, result := filterActiveIPAccessLists(project) if !result.IsOk() { return result } + client, err := atlas.Client(r.AtlasDomain, connection, ctx.Log) + if err != nil { + return workflow.Terminate(workflow.Internal, err.Error()) + } + if result := createOrDeleteInAtlas(client, projectID, active, ctx.Log); !result.IsOk() { + return result + } fmt.Println(active, expired, ctx, connection) return workflow.OK() } +func validateIPAccessLists(ipAccessList []mdbv1.ProjectIPAccessList) error { + for _, list := range ipAccessList { + if list.DeleteAfterDate != "" { + _, err := timeutil.ParseISO8601(list.DeleteAfterDate) + if err != nil { + return err + } + } + // Go doesn't support XOR, but uses '!=' instead: https://stackoverflow.com/a/23025720/614239 + onlyOneSpecified := isNotEmpty(list.AwsSecurityGroup) != isNotEmpty(list.CIDRBlock) != isNotEmpty(list.IPAddress) + if !onlyOneSpecified { + return errors.New("only one of the 'awsSecurityGroup', 'cidrBlock' or 'ipAddress' is required be specified") + } + } + return nil +} + +func createOrDeleteInAtlas(client *mongodbatlas.Client, projectID string, ipAccessLists []mdbv1.ProjectIPAccessList, log *zap.SugaredLogger) workflow.Result { + atlasAccessLists, _, err := client.ProjectIPAccessList.List(context.Background(), projectID, &mongodbatlas.ListOptions{}) + if err != nil { + return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) + } + atlasAccess := make([]atlasProjectIPAccessList, len(atlasAccessLists.Results)) + for i, r := range atlasAccessLists.Results { + atlasAccess[i] = atlasProjectIPAccessList(r) + } + + operatorAccessLists := make([]*mongodbatlas.ProjectIPAccessList, len(ipAccessLists)) + for i, list := range ipAccessLists { + atlasFormat, err := list.ToAtlas() + if err != nil { + return workflow.Terminate(workflow.Internal, err.Error()) + } + operatorAccessLists[i] = &atlasFormat + } + + difference := set.Difference(atlasAccess, operatorAccessLists) + + if err := deleteIPAccessFromAtlas(client, projectID, difference, log); err != nil { + return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) + } + + if _, _, err := client.ProjectIPAccessList.Create(context.Background(), projectID, operatorAccessLists); err != nil { + return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) + } + return workflow.OK() +} + +func deleteIPAccessFromAtlas(client *mongodbatlas.Client, projectID string, listsToRemove []set.Identifiable, log *zap.SugaredLogger) error { + for _, l := range listsToRemove { + if _, err := client.ProjectIPAccessList.Delete(context.Background(), projectID, l.Identifier().(string)); err != nil { + return err + } + log.Debugw("Removed IPAccessList from Atlas as it's not specified in current AtlasProject", "id", l.Identifier()) + } + return nil +} + func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAccessList, []mdbv1.ProjectIPAccessList, workflow.Result) { active := make([]mdbv1.ProjectIPAccessList, 0) expired := make([]mdbv1.ProjectIPAccessList, 0) @@ -26,7 +106,8 @@ func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAc if list.DeleteAfterDate != "" { iso8601, err := timeutil.ParseISO8601(list.DeleteAfterDate) if err != nil { - return active, expired, workflow.Terminate(workflow.ProjectIPAccessBadFormatted, err.Error()) + // Bad formatting done by user + return active, expired, workflow.Terminate(workflow.ProjectIPAccessInvalid, err.Error()) } if iso8601.Before(time.Now()) { expired = append(expired, list) @@ -38,3 +119,7 @@ func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAc } return active, expired, workflow.OK() } + +func isNotEmpty(s string) bool { + return s != "" +} diff --git a/pkg/controller/workflow/reason.go b/pkg/controller/workflow/reason.go index 1f16f11d17..93b2bec4c7 100644 --- a/pkg/controller/workflow/reason.go +++ b/pkg/controller/workflow/reason.go @@ -12,8 +12,9 @@ const ( // Atlas Project reasons const ( - ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" - ProjectIPAccessBadFormatted ConditionReason = "ProjectIpAccessListBadFormatted" + ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" + ProjectIPAccessInvalid ConditionReason = "ProjectIpAccessListInvalid" + ProjectIPNotCreatedInAtlas ConditionReason = "ProjectIpAccessListNotCreatedInAtlas" ) // Atlas Cluster reasons diff --git a/test/int/project_test.go b/test/int/project_test.go index 5559b96829..7793473453 100644 --- a/test/int/project_test.go +++ b/test/int/project_test.go @@ -134,6 +134,19 @@ var _ = Describe("AtlasProject", func() { Expect(atlasProject.Name).To(Equal(expectedProject.Spec.Name)) }) }) + + FDescribe("Creating the project IP access list", func() { + It("Should Succeed", func() { + expectedProject := testAtlasProject(namespace.Name, namespace.Name, connectionSecret.Name) + expectedProject.Spec.ProjectIPAccessList = []mdbv1.ProjectIPAccessList{{Comment: "bla", IPAddress: "192.0.2.15"}} + createdProject.ObjectMeta = expectedProject.ObjectMeta + Expect(k8sClient.Create(context.Background(), expectedProject)).ToNot(HaveOccurred()) + + Eventually(testutil.WaitFor(k8sClient, createdProject, status.TrueCondition(status.ReadyType)), + 20, interval).Should(BeTrue()) + }) + }) + }) // TODO builders From 12ad0f02d129023364b503e783c59a921548eccb Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Fri, 5 Feb 2021 20:43:31 +0000 Subject: [PATCH 4/8] merged main --- pkg/api/v1/atlasproject_types.go | 4 +- pkg/controller/atlasproject/ipaccess_list.go | 54 +++++++++++--------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/pkg/api/v1/atlasproject_types.go b/pkg/api/v1/atlasproject_types.go index 19e2bbcb69..e30d244303 100644 --- a/pkg/api/v1/atlasproject_types.go +++ b/pkg/api/v1/atlasproject_types.go @@ -99,8 +99,8 @@ type ProjectIPAccessList struct { } // ToAtlas converts the ProjectIPAccessList to native Atlas client format. -func (i *ProjectIPAccessList) ToAtlas() (mongodbatlas.ProjectIPAccessList, error) { - result := mongodbatlas.ProjectIPAccessList{} +func (i ProjectIPAccessList) ToAtlas() (*mongodbatlas.ProjectIPAccessList, error) { + result := &mongodbatlas.ProjectIPAccessList{} err := compat.JSONCopy(result, i) return result, err } diff --git a/pkg/controller/atlasproject/ipaccess_list.go b/pkg/controller/atlasproject/ipaccess_list.go index 44f4f1331a..4cd8efbc52 100644 --- a/pkg/controller/atlasproject/ipaccess_list.go +++ b/pkg/controller/atlasproject/ipaccess_list.go @@ -3,7 +3,6 @@ package atlasproject import ( "context" "errors" - "fmt" "time" "go.mongodb.org/atlas/mongodbatlas" @@ -16,6 +15,8 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/pkg/util/timeutil" ) +// atlasProjectIPAccessList is a synonym of Atlas object as we need to implement 'Identifier' (and we cannot modify +// their object) type atlasProjectIPAccessList mongodbatlas.ProjectIPAccessList func (i atlasProjectIPAccessList) Identifier() interface{} { @@ -26,10 +27,8 @@ func (r *AtlasProjectReconciler) ensureIPAccessList(ctx *workflow.Context, conne if err := validateIPAccessLists(project.Spec.ProjectIPAccessList); err != nil { return workflow.Terminate(workflow.ProjectIPAccessInvalid, err.Error()) } - active, expired, result := filterActiveIPAccessLists(project) - if !result.IsOk() { - return result - } + active, _ := filterActiveIPAccessLists(project) + client, err := atlas.Client(r.AtlasDomain, connection, ctx.Log) if err != nil { return workflow.Terminate(workflow.Internal, err.Error()) @@ -37,7 +36,7 @@ func (r *AtlasProjectReconciler) ensureIPAccessList(ctx *workflow.Context, conne if result := createOrDeleteInAtlas(client, projectID, active, ctx.Log); !result.IsOk() { return result } - fmt.Println(active, expired, ctx, connection) + // TODO update status - add the expired project IP access list there return workflow.OK() } @@ -58,29 +57,37 @@ func validateIPAccessLists(ipAccessList []mdbv1.ProjectIPAccessList) error { return nil } -func createOrDeleteInAtlas(client *mongodbatlas.Client, projectID string, ipAccessLists []mdbv1.ProjectIPAccessList, log *zap.SugaredLogger) workflow.Result { - atlasAccessLists, _, err := client.ProjectIPAccessList.List(context.Background(), projectID, &mongodbatlas.ListOptions{}) +func createOrDeleteInAtlas(client *mongodbatlas.Client, projectID string, operatorIPAccessLists []mdbv1.ProjectIPAccessList, log *zap.SugaredLogger) workflow.Result { + atlasAccess, _, err := client.ProjectIPAccessList.List(context.Background(), projectID, &mongodbatlas.ListOptions{}) if err != nil { return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) } - atlasAccess := make([]atlasProjectIPAccessList, len(atlasAccessLists.Results)) - for i, r := range atlasAccessLists.Results { - atlasAccess[i] = atlasProjectIPAccessList(r) + // Making a new slice with synonyms as Atlas IP Access list to enable usage of 'Identifiable' + atlasAccessLists := make([]atlasProjectIPAccessList, len(atlasAccess.Results)) + for i, r := range atlasAccess.Results { + atlasAccessLists[i] = atlasProjectIPAccessList(r) + } + + difference := set.Difference(atlasAccessLists, operatorIPAccessLists) + + if err := deleteIPAccessFromAtlas(client, projectID, difference, log); err != nil { + return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) + } + + if result := createIPAccessListsInAtlas(client, projectID, operatorIPAccessLists); !result.IsOk() { + return result } + return workflow.OK() +} +func createIPAccessListsInAtlas(client *mongodbatlas.Client, projectID string, ipAccessLists []mdbv1.ProjectIPAccessList) workflow.Result { operatorAccessLists := make([]*mongodbatlas.ProjectIPAccessList, len(ipAccessLists)) for i, list := range ipAccessLists { atlasFormat, err := list.ToAtlas() if err != nil { return workflow.Terminate(workflow.Internal, err.Error()) } - operatorAccessLists[i] = &atlasFormat - } - - difference := set.Difference(atlasAccess, operatorAccessLists) - - if err := deleteIPAccessFromAtlas(client, projectID, difference, log); err != nil { - return workflow.Terminate(workflow.ProjectIPNotCreatedInAtlas, err.Error()) + operatorAccessLists[i] = atlasFormat } if _, _, err := client.ProjectIPAccessList.Create(context.Background(), projectID, operatorAccessLists); err != nil { @@ -99,16 +106,13 @@ func deleteIPAccessFromAtlas(client *mongodbatlas.Client, projectID string, list return nil } -func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAccessList, []mdbv1.ProjectIPAccessList, workflow.Result) { +func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAccessList, []mdbv1.ProjectIPAccessList) { active := make([]mdbv1.ProjectIPAccessList, 0) expired := make([]mdbv1.ProjectIPAccessList, 0) for _, list := range project.Spec.ProjectIPAccessList { if list.DeleteAfterDate != "" { - iso8601, err := timeutil.ParseISO8601(list.DeleteAfterDate) - if err != nil { - // Bad formatting done by user - return active, expired, workflow.Terminate(workflow.ProjectIPAccessInvalid, err.Error()) - } + // We are ignoring the error as it will never happen due to validation check before + iso8601, _ := timeutil.ParseISO8601(list.DeleteAfterDate) if iso8601.Before(time.Now()) { expired = append(expired, list) continue @@ -117,7 +121,7 @@ func filterActiveIPAccessLists(project *mdbv1.AtlasProject) ([]mdbv1.ProjectIPAc // Either 'deleteAfterDate' field is not specified or it's higher than the current time active = append(active, list) } - return active, expired, workflow.OK() + return active, expired } func isNotEmpty(s string) bool { From 7469406e98bf4d73a85254eb1d7ee7f01e095143 Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Fri, 5 Feb 2021 20:47:31 +0000 Subject: [PATCH 5/8] remove F --- test/int/project_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/int/project_test.go b/test/int/project_test.go index e690285d36..548e313a6c 100644 --- a/test/int/project_test.go +++ b/test/int/project_test.go @@ -182,7 +182,7 @@ var _ = Describe("AtlasProject", func() { }) }) - FDescribe("Creating the project IP access list", func() { + Describe("Creating the project IP access list", func() { It("Should Succeed", func() { expectedProject := testAtlasProject(namespace.Name, "test-project", namespace.Name, connectionSecret.Name) expectedProject.Spec.ProjectIPAccessList = []mdbv1.ProjectIPAccessList{{Comment: "bla", IPAddress: "192.0.2.15"}} From 2a8cedc24eea8d7896c25d0dba74128be261269f Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Mon, 8 Feb 2021 11:48:34 +0000 Subject: [PATCH 6/8] fix tests --- pkg/api/v1/atlascluster_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/api/v1/atlascluster_types.go b/pkg/api/v1/atlascluster_types.go index 59d84c3bfc..418e2cafb1 100644 --- a/pkg/api/v1/atlascluster_types.go +++ b/pkg/api/v1/atlascluster_types.go @@ -239,9 +239,9 @@ var _ = RegionsConfig(mongodbatlas.RegionsConfig{}) // Cluster converts the Spec to native Atlas client format. func (spec *AtlasClusterSpec) Cluster() (*mongodbatlas.Cluster, error) { - result := mongodbatlas.Cluster{} + result := &mongodbatlas.Cluster{} err := compat.JSONCopy(result, spec) - return &result, err + return result, err } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object From ca378a9826b9899c59cad797cd32137b7cad2fae Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Mon, 8 Feb 2021 12:44:34 +0000 Subject: [PATCH 7/8] fix test --- test/int/project_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/int/project_test.go b/test/int/project_test.go index 548e313a6c..50f627c60d 100644 --- a/test/int/project_test.go +++ b/test/int/project_test.go @@ -65,7 +65,7 @@ var _ = Describe("AtlasProject", func() { Expect(createdProject.Status.ID).NotTo(BeNil()) expectedConditionsMatchers := testutil.MatchConditions( status.TrueCondition(status.ProjectReadyType), - status.FalseCondition(status.IPAccessListReadyType), + status.TrueCondition(status.IPAccessListReadyType), status.TrueCondition(status.ReadyType), ) Expect(createdProject.Status.Conditions).To(ConsistOf(expectedConditionsMatchers)) From 38e5ff7af75829ec2604f8a567002bc281156ad8 Mon Sep 17 00:00:00 2001 From: antonlisovenko Date: Mon, 8 Feb 2021 15:36:41 +0000 Subject: [PATCH 8/8] reasons formatting --- pkg/controller/workflow/reason.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controller/workflow/reason.go b/pkg/controller/workflow/reason.go index 93b2bec4c7..096a01398b 100644 --- a/pkg/controller/workflow/reason.go +++ b/pkg/controller/workflow/reason.go @@ -13,8 +13,8 @@ const ( // Atlas Project reasons const ( ProjectNotCreatedInAtlas ConditionReason = "ProjectNotCreatedInAtlas" - ProjectIPAccessInvalid ConditionReason = "ProjectIpAccessListInvalid" - ProjectIPNotCreatedInAtlas ConditionReason = "ProjectIpAccessListNotCreatedInAtlas" + ProjectIPAccessInvalid ConditionReason = "ProjectIPAccessListInvalid" + ProjectIPNotCreatedInAtlas ConditionReason = "ProjectIPAccessListNotCreatedInAtlas" ) // Atlas Cluster reasons