Skip to content

Commit 676b7f9

Browse files
roothorps-urbaniak
andauthored
CLOUDP-295843: Add Deprecation Warning for Shared & Serverless (#2067)
* emit events for deprecated deployments * emit deprecation message in status when ready * fix unit tests * refactor per review * update deprecation messages * Add deprecation warning to Serverless CRD field * make manifests * fix nil panic in deprecated --------- Co-authored-by: Sergiusz Urbaniak <[email protected]>
1 parent 85a1f2a commit 676b7f9

File tree

10 files changed

+274
-11
lines changed

10 files changed

+274
-11
lines changed

api/v1/atlasdeployment_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type AtlasDeploymentSpec struct {
6262
BackupScheduleRef common.ResourceRefNamespaced `json:"backupRef"`
6363

6464
// Configuration for the serverless deployment API. https://www.mongodb.com/docs/atlas/reference/api/serverless-instances/
65+
// DEPRECATED FIELD: Serverless instances are deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details.
6566
// +optional
6667
ServerlessSpec *ServerlessSpec `json:"serverlessSpec,omitempty"`
6768

config/crd/bases/atlas.mongodb.com_atlasdeployments.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,9 @@ spec:
737737
- name
738738
type: object
739739
serverlessSpec:
740-
description: Configuration for the serverless deployment API. https://www.mongodb.com/docs/atlas/reference/api/serverless-instances/
740+
description: |-
741+
Configuration for the serverless deployment API. https://www.mongodb.com/docs/atlas/reference/api/serverless-instances/
742+
DEPRECATED FIELD: Serverless instances are deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details.
741743
properties:
742744
backupOptions:
743745
description: Serverless Backup Options

internal/controller/atlasdeployment/advanced_deployment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func (r *AtlasDeploymentReconciler) handleAdvancedDeployment(ctx *workflow.Conte
110110
return r.terminate(ctx, workflow.Internal, err)
111111
}
112112

113-
return r.ready(ctx, akoCluster.GetCustomResource(), atlasCluster)
113+
return r.ready(ctx, akoCluster, atlasCluster)
114114
case status.StateCREATING:
115115
return r.inProgress(ctx, akoCluster.GetCustomResource(), atlasCluster, workflow.DeploymentCreating, "deployment is provisioning")
116116
case status.StateUPDATING, status.StateREPAIRING:

internal/controller/atlasdeployment/atlasdeployment_controller.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"time"
2424

2525
"go.uber.org/zap"
26+
"go.uber.org/zap/zapcore"
2627
corev1 "k8s.io/api/core/v1"
2728
k8serrors "k8s.io/apimachinery/pkg/api/errors"
2829
"k8s.io/apimachinery/pkg/fields"
@@ -164,7 +165,14 @@ func (r *AtlasDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Requ
164165
workflowCtx.SetConditionTrue(api.ValidationSucceeded)
165166

166167
deploymentInAKO := deployment.NewDeployment(atlasProject.ID, atlasDeployment)
168+
169+
if ok, deprecationMsg := deploymentInAKO.Deprecated(); ok {
170+
// emit Log and event
171+
r.Log.Log(zapcore.WarnLevel, deprecationMsg)
172+
r.EventRecorder.Event(deploymentInAKO.GetCustomResource(), corev1.EventTypeWarning, "DeprecationWarning", deprecationMsg)
173+
}
167174
deploymentInAtlas, err := deploymentService.GetDeployment(workflowCtx.Context, atlasProject.ID, atlasDeployment)
175+
168176
if err != nil {
169177
return r.terminate(workflowCtx, workflow.Internal, err)
170178
}
@@ -343,19 +351,21 @@ func (r *AtlasDeploymentReconciler) inProgress(ctx *workflow.Context, atlasDeplo
343351
return result.ReconcileResult(), nil
344352
}
345353

346-
func (r *AtlasDeploymentReconciler) ready(ctx *workflow.Context, atlasDeployment *akov2.AtlasDeployment, deploymentInAtlas deployment.Deployment) (ctrl.Result, error) {
347-
if err := customresource.ManageFinalizer(ctx.Context, r.Client, atlasDeployment, customresource.SetFinalizer); err != nil {
354+
func (r *AtlasDeploymentReconciler) ready(ctx *workflow.Context, deploymentInAKO, deploymentInAtlas deployment.Deployment) (ctrl.Result, error) {
355+
if err := customresource.ManageFinalizer(ctx.Context, r.Client, deploymentInAKO.GetCustomResource(), customresource.SetFinalizer); err != nil {
348356
return r.terminate(ctx, workflow.AtlasFinalizerNotSet, err)
349357
}
350358

359+
_, deprecationMsg := deploymentInAKO.Deprecated()
360+
351361
ctx.SetConditionTrue(api.DeploymentReadyType).
352-
SetConditionTrue(api.ReadyType).
362+
SetConditionTrueMsg(api.ReadyType, deprecationMsg).
353363
EnsureStatusOption(status.AtlasDeploymentStateNameOption(deploymentInAtlas.GetState())).
354364
EnsureStatusOption(status.AtlasDeploymentReplicaSet(deploymentInAtlas.GetReplicaSet())).
355365
EnsureStatusOption(status.AtlasDeploymentMongoDBVersionOption(deploymentInAtlas.GetMongoDBVersion())).
356366
EnsureStatusOption(status.AtlasDeploymentConnectionStringsOption(deploymentInAtlas.GetConnection()))
357367

358-
if atlasDeployment.Spec.ExternalProjectRef != nil {
368+
if deploymentInAKO.GetCustomResource().Spec.ExternalProjectRef != nil {
359369
return workflow.Requeue(r.independentSyncPeriod).ReconcileResult(), nil
360370
}
361371

internal/controller/atlasdeployment/atlasdeployment_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ func TestChangeDeploymentType(t *testing.T) {
14171417
Log: logger.Sugar(),
14181418
},
14191419
AtlasProvider: tt.atlasProvider,
1420-
EventRecorder: record.NewFakeRecorder(1),
1420+
EventRecorder: record.NewFakeRecorder(10),
14211421
}
14221422
result, err := r.Reconcile(
14231423
ctx,

internal/controller/atlasdeployment/flex_deployment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (r *AtlasDeploymentReconciler) handleFlexInstance(ctx *workflow.Context, pr
5252
return r.terminate(ctx, workflow.Internal, err)
5353
}
5454

55-
return r.ready(ctx, akoFlex.GetCustomResource(), atlasFlex)
55+
return r.ready(ctx, akoFlex, atlasFlex)
5656

5757
case status.StateCREATING:
5858
return r.inProgress(ctx, akoFlex.GetCustomResource(), atlasFlex, workflow.DeploymentCreating, "deployment is provisioning")

internal/controller/atlasdeployment/serverless_deployment.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ func (r *AtlasDeploymentReconciler) handleServerlessInstance(ctx *workflow.Conte
6262
return r.terminate(ctx, workflow.Internal, err)
6363
}
6464

65-
return r.ready(ctx, akoServerless.GetCustomResource(), atlasServerless)
66-
65+
return r.ready(ctx, akoServerless, atlasServerless)
6766
case status.StateCREATING:
6867
return r.inProgress(ctx, akoServerless.GetCustomResource(), atlasServerless, workflow.DeploymentCreating, "deployment is provisioning")
6968
case status.StateUPDATING, status.StateREPAIRING:

internal/controller/atlasdeployment/serverless_deployment_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,8 @@ func TestHandleServerlessInstance(t *testing.T) {
716716
expectedResult: ctrl.Result{},
717717
expectedConditions: []api.Condition{
718718
api.TrueCondition(api.DeploymentReadyType),
719-
api.TrueCondition(api.ReadyType),
719+
api.TrueCondition(api.ReadyType).
720+
WithMessageRegexp("WARNING: Serverless is deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details."),
720721
},
721722
},
722723
"serverless instance has an unknown state": {

internal/translation/deployment/conversion.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Deployment interface {
2727
GetReplicaSet() []status.ReplicaSet
2828
IsServerless() bool
2929
IsFlex() bool
30+
Deprecated() (bool, string)
3031
}
3132

3233
type Cluster struct {
@@ -84,6 +85,37 @@ func (c *Cluster) IsTenant() bool {
8485
return c.isTenant
8586
}
8687

88+
func (c *Cluster) Deprecated() (bool, string) {
89+
for _, replicationSpec := range c.ReplicationSpecs {
90+
if replicationSpec == nil {
91+
continue
92+
}
93+
94+
for _, regionConfig := range replicationSpec.RegionConfigs {
95+
if regionConfig == nil {
96+
continue
97+
}
98+
99+
if deprecatedSpecs(regionConfig.ElectableSpecs) ||
100+
deprecatedSpecs(regionConfig.ReadOnlySpecs) ||
101+
deprecatedSpecs(regionConfig.AnalyticsSpecs) {
102+
return true, "WARNING: M2 and M5 instance sizes are deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details."
103+
}
104+
}
105+
}
106+
return false, ""
107+
}
108+
109+
func deprecatedSpecs(specs *akov2.Specs) bool {
110+
if specs == nil {
111+
return false
112+
}
113+
if specs.InstanceSize == "M2" || specs.InstanceSize == "M5" {
114+
return true
115+
}
116+
return false
117+
}
118+
87119
type Serverless struct {
88120
*akov2.ServerlessSpec
89121
ProjectID string
@@ -130,6 +162,10 @@ func (s *Serverless) IsFlex() bool {
130162
return false
131163
}
132164

165+
func (s *Serverless) Deprecated() (bool, string) {
166+
return true, "WARNING: Serverless is deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details."
167+
}
168+
133169
type Flex struct {
134170
*akov2.FlexSpec
135171
ProjectID string
@@ -176,6 +212,10 @@ func (f *Flex) IsFlex() bool {
176212
return true
177213
}
178214

215+
func (f *Flex) Deprecated() (bool, string) {
216+
return false, ""
217+
}
218+
179219
type Connection struct {
180220
Name string
181221
ConnURL string

internal/translation/deployment/conversion_test.go

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,3 +779,213 @@ func TestRoundtrip_CustomZone(t *testing.T) {
779779
}
780780
}
781781
}
782+
783+
func TestDeprecated(t *testing.T) {
784+
for _, tc := range []struct {
785+
name string
786+
deployment *akov2.AtlasDeployment
787+
wantDeprecated bool
788+
wantMsg string
789+
}{
790+
{
791+
name: "nil replication specs",
792+
deployment: &akov2.AtlasDeployment{
793+
Spec: akov2.AtlasDeploymentSpec{
794+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
795+
ReplicationSpecs: nil,
796+
},
797+
},
798+
},
799+
},
800+
{
801+
name: "nil replication spec entries",
802+
deployment: &akov2.AtlasDeployment{
803+
Spec: akov2.AtlasDeploymentSpec{
804+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
805+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
806+
nil, nil, nil,
807+
},
808+
},
809+
},
810+
},
811+
},
812+
{
813+
name: "nil region configs",
814+
deployment: &akov2.AtlasDeployment{
815+
Spec: akov2.AtlasDeploymentSpec{
816+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
817+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
818+
{
819+
RegionConfigs: nil,
820+
},
821+
},
822+
},
823+
},
824+
},
825+
},
826+
{
827+
name: "nil region config entries",
828+
deployment: &akov2.AtlasDeployment{
829+
Spec: akov2.AtlasDeploymentSpec{
830+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
831+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
832+
{
833+
RegionConfigs: []*akov2.AdvancedRegionConfig{
834+
nil, nil, nil,
835+
},
836+
},
837+
},
838+
},
839+
},
840+
},
841+
},
842+
{
843+
name: "nil regionconfig specs",
844+
deployment: &akov2.AtlasDeployment{
845+
Spec: akov2.AtlasDeploymentSpec{
846+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
847+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
848+
{
849+
RegionConfigs: []*akov2.AdvancedRegionConfig{
850+
{
851+
AnalyticsSpecs: nil,
852+
ElectableSpecs: nil,
853+
ReadOnlySpecs: nil,
854+
},
855+
},
856+
},
857+
},
858+
},
859+
},
860+
},
861+
},
862+
{
863+
name: "empty regionconfig specs",
864+
deployment: &akov2.AtlasDeployment{
865+
Spec: akov2.AtlasDeploymentSpec{
866+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
867+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
868+
{
869+
RegionConfigs: []*akov2.AdvancedRegionConfig{
870+
{
871+
AnalyticsSpecs: &akov2.Specs{},
872+
ElectableSpecs: &akov2.Specs{},
873+
ReadOnlySpecs: &akov2.Specs{},
874+
},
875+
},
876+
},
877+
},
878+
},
879+
},
880+
},
881+
},
882+
{
883+
name: "non deprecated M10 instance",
884+
deployment: &akov2.AtlasDeployment{
885+
Spec: akov2.AtlasDeploymentSpec{
886+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
887+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
888+
{
889+
RegionConfigs: []*akov2.AdvancedRegionConfig{
890+
{
891+
AnalyticsSpecs: &akov2.Specs{
892+
InstanceSize: "M10",
893+
NodeCount: pointer.MakePtr(1),
894+
},
895+
ElectableSpecs: &akov2.Specs{
896+
InstanceSize: "M10",
897+
NodeCount: pointer.MakePtr(1),
898+
},
899+
ReadOnlySpecs: &akov2.Specs{
900+
InstanceSize: "M10",
901+
NodeCount: pointer.MakePtr(1),
902+
},
903+
},
904+
},
905+
},
906+
},
907+
},
908+
},
909+
},
910+
},
911+
{
912+
name: "deprecated M2 instance",
913+
deployment: &akov2.AtlasDeployment{
914+
Spec: akov2.AtlasDeploymentSpec{
915+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
916+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
917+
{
918+
RegionConfigs: []*akov2.AdvancedRegionConfig{
919+
{
920+
AnalyticsSpecs: &akov2.Specs{
921+
InstanceSize: "M2",
922+
NodeCount: pointer.MakePtr(1),
923+
},
924+
ElectableSpecs: &akov2.Specs{
925+
InstanceSize: "M2",
926+
NodeCount: pointer.MakePtr(1),
927+
},
928+
ReadOnlySpecs: &akov2.Specs{
929+
InstanceSize: "M2",
930+
NodeCount: pointer.MakePtr(1),
931+
},
932+
},
933+
},
934+
},
935+
},
936+
},
937+
},
938+
},
939+
wantDeprecated: true,
940+
wantMsg: "WARNING: M2 and M5 instance sizes are deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details.",
941+
},
942+
{
943+
name: "deprecated M2 instance",
944+
deployment: &akov2.AtlasDeployment{
945+
Spec: akov2.AtlasDeploymentSpec{
946+
DeploymentSpec: &akov2.AdvancedDeploymentSpec{
947+
ReplicationSpecs: []*akov2.AdvancedReplicationSpec{
948+
{
949+
RegionConfigs: []*akov2.AdvancedRegionConfig{
950+
{
951+
AnalyticsSpecs: &akov2.Specs{
952+
InstanceSize: "M5",
953+
NodeCount: pointer.MakePtr(1),
954+
},
955+
ElectableSpecs: &akov2.Specs{
956+
InstanceSize: "M5",
957+
NodeCount: pointer.MakePtr(1),
958+
},
959+
ReadOnlySpecs: &akov2.Specs{
960+
InstanceSize: "M5",
961+
NodeCount: pointer.MakePtr(1),
962+
},
963+
},
964+
},
965+
},
966+
},
967+
},
968+
},
969+
},
970+
wantDeprecated: true,
971+
wantMsg: "WARNING: M2 and M5 instance sizes are deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details.",
972+
},
973+
{
974+
name: "empty serverless instance",
975+
deployment: &akov2.AtlasDeployment{
976+
Spec: akov2.AtlasDeploymentSpec{
977+
ServerlessSpec: &akov2.ServerlessSpec{},
978+
},
979+
},
980+
wantDeprecated: true,
981+
wantMsg: "WARNING: Serverless is deprecated. See https://dochub.mongodb.org/core/atlas-flex-migration for details.",
982+
},
983+
} {
984+
t.Run(tc.name, func(t *testing.T) {
985+
d := NewDeployment("123", tc.deployment)
986+
gotDeprecated, gotMsg := d.Deprecated()
987+
require.Equal(t, tc.wantDeprecated, gotDeprecated)
988+
require.Equal(t, tc.wantMsg, gotMsg)
989+
})
990+
}
991+
}

0 commit comments

Comments
 (0)