@@ -16,6 +16,7 @@ package clusters
1616
1717import (
1818 "context"
19+ "errors"
1920 "fmt"
2021
2122 "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
@@ -27,10 +28,15 @@ import (
2728 "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/usage"
2829 "github.com/spf13/afero"
2930 "github.com/spf13/cobra"
31+ atlasv2 "go.mongodb.org/atlas-sdk/v20241113002/admin"
3032 atlas "go.mongodb.org/atlas/mongodbatlas"
3133)
3234
33- const upgradeTemplate = "Upgrading cluster '{{.Name}}'.\n "
35+ const (
36+ upgradeTemplate = "Upgrading cluster '{{.Name}}'.\n "
37+ replicaSetNodeCount = 3
38+ replicaSetPriority = 7
39+ )
3440
3541type UpgradeOpts struct {
3642 cli.ProjectOpts
@@ -42,6 +48,7 @@ type UpgradeOpts struct {
4248 filename string
4349 enableTerminationProtection bool
4450 disableTerminationProtection bool
51+ isFlexCluster bool
4552 tag map [string ]string
4653 fs afero.Fs
4754 store store.AtlasSharedClusterGetterUpgrader
@@ -56,6 +63,28 @@ func (opts *UpgradeOpts) initStore(ctx context.Context) func() error {
5663}
5764
5865func (opts * UpgradeOpts ) Run () error {
66+ if opts .isFlexCluster {
67+ return opts .RunFlexCluster ()
68+ }
69+
70+ return opts .RunSharedCluster ()
71+ }
72+
73+ func (opts * UpgradeOpts ) RunFlexCluster () error {
74+ cluster , err := opts .atlasTenantClusterUpgradeRequest20240805 ()
75+ if err != nil {
76+ return err
77+ }
78+
79+ r , err := opts .store .UpgradeFlexCluster (opts .ConfigProjectID (), cluster )
80+ if err != nil {
81+ return err
82+ }
83+
84+ return opts .Print (r )
85+ }
86+
87+ func (opts * UpgradeOpts ) RunSharedCluster () error {
5988 cluster , err := opts .cluster ()
6089 if err != nil {
6190 return err
@@ -72,18 +101,125 @@ func (opts *UpgradeOpts) Run() error {
72101 return opts .Print (r )
73102}
74103
104+ func (opts * UpgradeOpts ) atlasTenantClusterUpgradeRequest20240805 () (* atlasv2.AtlasTenantClusterUpgradeRequest20240805 , error ) {
105+ var cluster * atlasv2.AtlasTenantClusterUpgradeRequest20240805
106+ if opts .filename != "" {
107+ err := file .Load (opts .fs , opts .filename , & cluster )
108+ if err != nil {
109+ return nil , err
110+ }
111+
112+ cluster .Name = opts .name
113+
114+ return cluster , nil
115+ }
116+
117+ flexClusterDescription , err := opts .store .FlexCluster (opts .ConfigProjectID (), opts .name )
118+ if err != nil {
119+ return nil , err
120+ }
121+
122+ return opts .newAtlasTenantClusterUpgradeRequestFromFlexClusterDescription (flexClusterDescription ), nil
123+ }
124+
125+ func (opts * UpgradeOpts ) newAtlasTenantClusterUpgradeRequestFromFlexClusterDescription (flexCluster * atlasv2.FlexClusterDescription20241113 ) * atlasv2.AtlasTenantClusterUpgradeRequest20240805 {
126+ mdbVersion := flexCluster .MongoDBVersion
127+ if opts .mdbVersion != "" {
128+ mdbVersion = & opts .mdbVersion
129+ }
130+
131+ terminationProtectionEnabled := flexCluster .GetTerminationProtectionEnabled ()
132+ if opts .disableTerminationProtection {
133+ terminationProtectionEnabled = false
134+ }
135+
136+ if opts .enableTerminationProtection {
137+ terminationProtectionEnabled = true
138+ }
139+
140+ var tags []atlasv2.ResourceTag
141+ if flexCluster .Tags != nil {
142+ tags = flexCluster .GetTags ()
143+ }
144+
145+ if len (opts .tag ) > 0 {
146+ newTags := newResourceTags (opts .tag )
147+ tags = append (tags , * newTags ... )
148+ }
149+
150+ backupEnabled := false
151+ if settings , ok := flexCluster .GetBackupSettingsOk (); ok {
152+ backupEnabled = settings .GetEnabled ()
153+ }
154+
155+ flexGroupID , _ := flexCluster .GetGroupIdOk ()
156+ versionRelease , _ := flexCluster .GetVersionReleaseSystemOk ()
157+ flexClusterType , _ := flexCluster .GetClusterTypeOk ()
158+
159+ return & atlasv2.AtlasTenantClusterUpgradeRequest20240805 {
160+ BackupEnabled : & backupEnabled ,
161+ ClusterType : flexClusterType ,
162+ GroupId : flexGroupID ,
163+ MongoDBVersion : mdbVersion ,
164+ Name : flexCluster .GetName (),
165+ Tags : & tags ,
166+ TerminationProtectionEnabled : & terminationProtectionEnabled ,
167+ VersionReleaseSystem : versionRelease ,
168+ ReplicationSpecs : opts .newReplicationSpecFromOpts (flexCluster ),
169+ }
170+ }
171+
172+ func (opts * UpgradeOpts ) newReplicationSpecFromOpts (flexCluster * atlasv2.FlexClusterDescription20241113 ) * []atlasv2.ReplicationSpec20240805 {
173+ if opts .tier == "" {
174+ return nil
175+ }
176+
177+ diskSizeGb := 0.0
178+ backingProviderName := ""
179+ regionN := ""
180+ if settings , ok := flexCluster .GetProviderSettingsOk (); ok {
181+ diskSizeGb = settings .GetDiskSizeGB ()
182+ backingProviderName = settings .GetBackingProviderName ()
183+ regionN = settings .GetRegionName ()
184+ }
185+
186+ if opts .diskSizeGB != 0 {
187+ diskSizeGb = opts .diskSizeGB
188+ }
189+
190+ replicaSetCount := replicaSetNodeCount
191+ priority := replicaSetPriority
192+
193+ replicaSpec := atlasv2.ReplicationSpec20240805 {
194+ RegionConfigs : & []atlasv2.CloudRegionConfig20240805 {
195+ {
196+ ElectableSpecs : & atlasv2.HardwareSpec20240805 {
197+ InstanceSize : & opts .tier ,
198+ DiskSizeGB : & diskSizeGb ,
199+ NodeCount : & replicaSetCount ,
200+ },
201+ ProviderName : & backingProviderName ,
202+ RegionName : & regionN ,
203+ Priority : & priority ,
204+ },
205+ },
206+ }
207+
208+ return & []atlasv2.ReplicationSpec20240805 {replicaSpec }
209+ }
210+
75211func (opts * UpgradeOpts ) cluster () (* atlas.Cluster , error ) {
76212 var cluster * atlas.Cluster
77213 if opts .filename != "" {
78214 err := file .Load (opts .fs , opts .filename , & cluster )
79215 if err != nil {
80216 return nil , err
81217 }
82- if opts .name == "" {
83- opts .name = cluster .Name
84- }
218+ cluster .Name = opts .name
219+
85220 return cluster , nil
86221 }
222+
87223 return opts .store .AtlasSharedCluster (opts .ProjectID , opts .name )
88224}
89225
@@ -129,6 +265,26 @@ func isTenant(instanceSizeName string) bool {
129265 instanceSizeName == atlasM5
130266}
131267
268+ // newIsFlexCluster sets the opts.isFlexCluster that indicates if the cluster to create is
269+ // a FlexCluster. The function calls the AtlasSharedAPI to get the cluster, and it sets the opts.isFlexCluster = true
270+ // in the event of a cannotUseFlexWithClusterApisErrorCode.
271+ func (opts * UpgradeOpts ) newIsFlexCluster () error {
272+ _ , err := opts .store .AtlasSharedCluster (opts .ConfigProjectID (), opts .name )
273+ var errorResponse * atlas.ErrorResponse
274+ ok := errors .As (err , & errorResponse )
275+ if ! ok {
276+ opts .isFlexCluster = false
277+ return err
278+ }
279+
280+ if errorResponse .ErrorCode != cannotUseFlexWithClusterApisErrorCode {
281+ return err
282+ }
283+
284+ opts .isFlexCluster = true
285+ return nil
286+ }
287+
132288// UpgradeBuilder builds a cobra.Command that can run as:
133289// atlas cluster(s) upgrade [clusterName] --projectId projectId [--tier M#] [--diskSizeGB N] [--mdbVersion] [--tag key=value].
134290func UpgradeBuilder () * cobra.Command {
@@ -152,6 +308,7 @@ func UpgradeBuilder() *cobra.Command {
152308 opts .ValidateProjectID ,
153309 opts .initStore (cmd .Context ()),
154310 opts .InitOutput (cmd .OutOrStdout (), upgradeTemplate ),
311+ opts .newIsFlexCluster ,
155312 )
156313 },
157314 RunE : func (_ * cobra.Command , _ []string ) error {
0 commit comments