• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mongodb / mongodb-atlas-cli / 16670272475

01 Aug 2025 08:27AM UTC coverage: 57.953% (-7.1%) from 65.017%
16670272475

Pull #4071

github

fmenezes
lint
Pull Request #4071: chore: remove unit tag from tests

23613 of 40745 relevant lines covered (57.95%)

2.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.78
/internal/cli/clusters/create.go
1
// Copyright 2020 MongoDB Inc
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package clusters
16

17
import (
18
        "context"
19
        "errors"
20
        "fmt"
21
        "os"
22
        "strings"
23
        "time"
24

25
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
26
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
27
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
28
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/file"
29
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
30
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/pointer"
31
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store"
32
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/usage"
33
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/validate"
34
        "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/watchers"
35
        "github.com/spf13/afero"
36
        "github.com/spf13/cobra"
37
        atlasClustersPinned "go.mongodb.org/atlas-sdk/v20240530005/admin"
38
        atlasv2 "go.mongodb.org/atlas-sdk/v20250312005/admin"
39
)
40

41
const (
42
        replicaSet                    = "REPLICASET"
43
        tenant                        = "TENANT"
44
        atlasM0                       = "M0"
45
        atlasM2                       = "M2"
46
        atlasFlex                     = "FLEX"
47
        atlasM5                       = "M5"
48
        zoneName                      = "Zone 1"
49
        invalidAttributeErrorCode     = "INVALID_ATTRIBUTE"
50
        duplicateClusterNameErrorCode = "DUPLICATE_CLUSTER_NAME"
51
        regionName                    = "regionName"
52
        priority                      = 7
53
        readOnlyNode                  = 0
54
)
55

56
//go:generate go tool go.uber.org/mock/mockgen -typed -destination=create_mock_test.go -package=clusters . ClusterCreator
57

58
type ClusterCreator interface {
59
        CreateCluster(v15 *atlasClustersPinned.AdvancedClusterDescription) (*atlasClustersPinned.AdvancedClusterDescription, error)
60
        CreateFlexCluster(string, *atlasv2.FlexClusterDescriptionCreate20241113) (*atlasv2.FlexClusterDescription20241113, error)
61
        CreateClusterLatest(*atlasv2.ClusterDescription20240805) (*atlasv2.ClusterDescription20240805, error)
62
}
63

64
type CreateOpts struct {
65
        cli.ProjectOpts
66
        cli.WatchOpts
67
        name                        string
68
        provider                    string
69
        region                      string
70
        tier                        string
71
        members                     int
72
        shards                      int
73
        clusterType                 string
74
        diskSizeGB                  float64
75
        backup                      bool
76
        biConnector                 bool
77
        enableTerminationProtection bool
78
        isFlexCluster               bool
79
        mdbVersion                  string
80
        filename                    string
81
        tag                         map[string]string
82
        fs                          afero.Fs
83
        store                       ClusterCreator
84
        autoScalingMode             string
85
}
86

87
func (opts *CreateOpts) initStore(ctx context.Context) func() error {
1✔
88
        return func() error {
2✔
89
                var err error
1✔
90
                opts.store, err = store.New(store.AuthenticatedPreset(config.Default()), store.WithContext(ctx))
1✔
91
                return err
1✔
92
        }
1✔
93
}
94

95
const (
96
        createTemplate      = "Cluster '{{.Name}}' is being created.\n"
97
        createWatchTemplate = "Cluster '{{.Name}}' created successfully.\n"
98
)
99

100
var clusterObj *atlasClustersPinned.AdvancedClusterDescription
101
var flexCluster *atlasv2.FlexClusterDescription20241113
102
var clusterObjLatest *atlasv2.ClusterDescription20240805
103

104
func (opts *CreateOpts) Run() error {
1✔
105
        if isIndependentShardScaling(opts.autoScalingMode) {
2✔
106
                return opts.RunDedicatedClusterLatest()
1✔
107
        }
1✔
108

109
        if opts.isFlexCluster {
2✔
110
                return opts.RunFlexCluster()
1✔
111
        }
1✔
112

113
        return opts.RunDedicatedCluster()
1✔
114
}
115

116
func (opts *CreateOpts) RunFlexCluster() error {
1✔
117
        flexClusterReq, err := opts.newFlexCluster()
1✔
118
        if err != nil {
1✔
119
                return err
×
120
        }
×
121

122
        flexCluster, err = opts.store.CreateFlexCluster(opts.ConfigProjectID(), flexClusterReq)
1✔
123

1✔
124
        apiError, ok := atlasv2.AsError(err)
1✔
125
        code := apiError.GetErrorCode()
1✔
126
        if ok {
1✔
127
                if apiError.GetErrorCode() == invalidAttributeErrorCode && strings.Contains(apiError.GetDetail(), regionName) {
×
128
                        return cli.ErrNoRegionExistsTryCommand
×
129
                }
×
130
                if ok && code == duplicateClusterNameErrorCode {
×
131
                        return cli.ErrNameExists
×
132
                }
×
133
        }
134

135
        return err
1✔
136
}
137

138
func (opts *CreateOpts) newFlexCluster() (*atlasv2.FlexClusterDescriptionCreate20241113, error) {
1✔
139
        cluster := new(atlasv2.FlexClusterDescriptionCreate20241113)
1✔
140
        if opts.filename != "" {
2✔
141
                if err := file.Load(opts.fs, opts.filename, cluster); err != nil {
1✔
142
                        return nil, err
×
143
                }
×
144
        } else {
1✔
145
                cluster = opts.newFlexClusterDescriptionCreate20241113()
1✔
146
        }
1✔
147

148
        if opts.name != "" {
2✔
149
                cluster.Name = opts.name
1✔
150
        }
1✔
151

152
        return cluster, nil
1✔
153
}
154

155
func (opts *CreateOpts) RunDedicatedClusterLatest() error {
1✔
156
        cluster, err := opts.newClusterLatest()
1✔
157
        if err != nil {
1✔
158
                return err
×
159
        }
×
160

161
        clusterObjLatest, err = opts.store.CreateClusterLatest(cluster)
1✔
162
        apiError, ok := atlasv2.AsError(err)
1✔
163
        code := apiError.GetErrorCode()
1✔
164
        if ok {
1✔
165
                if apiError.GetErrorCode() == invalidAttributeErrorCode && strings.Contains(apiError.GetDetail(), regionName) {
×
166
                        return cli.ErrNoRegionExistsTryCommand
×
167
                }
×
168
                if ok && code == duplicateClusterNameErrorCode {
×
169
                        return cli.ErrNameExists
×
170
                }
×
171
        }
172

173
        return err
1✔
174
}
175

176
func (opts *CreateOpts) RunDedicatedCluster() error {
1✔
177
        cluster, err := opts.newCluster()
1✔
178
        if err != nil {
1✔
179
                return err
×
180
        }
×
181

182
        clusterObj, err = opts.store.CreateCluster(cluster)
1✔
183
        apiError, ok := atlasClustersPinned.AsError(err)
1✔
184
        code := apiError.GetErrorCode()
1✔
185
        if ok {
1✔
186
                if apiError.GetErrorCode() == invalidAttributeErrorCode && strings.Contains(apiError.GetDetail(), regionName) {
×
187
                        return cli.ErrNoRegionExistsTryCommand
×
188
                }
×
189
                if ok && code == duplicateClusterNameErrorCode {
×
190
                        return cli.ErrNameExists
×
191
                }
×
192
        }
193

194
        return err
1✔
195
}
196

197
func (opts *CreateOpts) PostRun() error {
1✔
198
        if isIndependentShardScaling(opts.autoScalingMode) {
2✔
199
                return opts.PostRunDedicatedClusterLatest()
1✔
200
        }
1✔
201

202
        if opts.isFlexCluster {
2✔
203
                return opts.PostRunFlexCluster()
1✔
204
        }
1✔
205

206
        return opts.PostRunDedicatedCluster()
1✔
207
}
208

209
func (opts *CreateOpts) PostRunFlexCluster() error {
1✔
210
        if !opts.EnableWatch {
2✔
211
                return opts.Print(flexCluster)
1✔
212
        }
1✔
213
        opts.Template = createWatchTemplate
×
214

×
215
        watcher := watchers.NewWatcherWithDefaultWait(
×
216
                *watchers.ClusterCreated,
×
217
                watchers.NewAtlasFlexClusterStateDescriber(
×
218
                        opts.store.(store.ClusterDescriber),
×
219
                        opts.ConfigProjectID(),
×
220
                        opts.name,
×
221
                ),
×
222
                opts.GetDefaultWait(),
×
223
        )
×
224

×
225
        watcher.Timeout = time.Duration(opts.Timeout)
×
226
        if err := opts.WatchWatcher(watcher); err != nil {
×
227
                return err
×
228
        }
×
229

230
        return opts.Print(flexCluster)
×
231
}
232

233
func (opts *CreateOpts) PostRunDedicatedClusterLatest() error {
1✔
234
        if !opts.EnableWatch {
2✔
235
                return opts.Print(clusterObjLatest)
1✔
236
        }
1✔
237

238
        watcher := watchers.NewWatcherWithDefaultWait(
1✔
239
                *watchers.ClusterCreated,
1✔
240
                watchers.NewAtlasClusterStateDescriber(
1✔
241
                        opts.store.(store.ClusterDescriber),
1✔
242
                        opts.ConfigProjectID(),
1✔
243
                        opts.name,
1✔
244
                ),
1✔
245
                opts.GetDefaultWait(),
1✔
246
        )
1✔
247

1✔
248
        watcher.Timeout = time.Duration(opts.Timeout)
1✔
249
        if err := opts.WatchWatcher(watcher); err != nil {
1✔
250
                return err
×
251
        }
×
252

253
        return opts.Print(clusterObjLatest)
1✔
254
}
255

256
func (opts *CreateOpts) PostRunDedicatedCluster() error {
1✔
257
        if !opts.EnableWatch {
2✔
258
                return opts.Print(clusterObj)
1✔
259
        }
1✔
260

261
        opts.Template = createWatchTemplate
1✔
262

1✔
263
        watcher := watchers.NewWatcherWithDefaultWait(
1✔
264
                *watchers.ClusterCreated,
1✔
265
                watchers.NewAtlasClusterStateDescriber(
1✔
266
                        opts.store.(store.ClusterDescriber),
1✔
267
                        opts.ConfigProjectID(),
1✔
268
                        opts.name,
1✔
269
                ),
1✔
270
                opts.GetDefaultWait(),
1✔
271
        )
1✔
272

1✔
273
        watcher.Timeout = time.Duration(opts.Timeout)
1✔
274
        if err := opts.WatchWatcher(watcher); err != nil {
1✔
275
                return err
×
276
        }
×
277

278
        return opts.Print(clusterObj)
1✔
279
}
280

281
func (opts *CreateOpts) newCluster() (*atlasClustersPinned.AdvancedClusterDescription, error) {
1✔
282
        cluster := new(atlasClustersPinned.AdvancedClusterDescription)
1✔
283
        if opts.filename != "" {
2✔
284
                if err := file.Load(opts.fs, opts.filename, cluster); err != nil {
1✔
285
                        return nil, err
×
286
                }
×
287
                removeReadOnlyAttributes(cluster)
1✔
288
        } else {
1✔
289
                opts.applyOptsAdvancedCluster(cluster)
1✔
290
        }
1✔
291

292
        if opts.name != "" {
2✔
293
                cluster.Name = &opts.name
1✔
294
        }
1✔
295

296
        cluster.GroupId = pointer.Get(opts.ConfigProjectID())
1✔
297
        return cluster, nil
1✔
298
}
299

300
func (opts *CreateOpts) newClusterLatest() (*atlasv2.ClusterDescription20240805, error) {
1✔
301
        cluster := new(atlasv2.ClusterDescription20240805)
1✔
302
        if opts.filename != "" {
2✔
303
                if err := file.Load(opts.fs, opts.filename, cluster); err != nil {
1✔
304
                        return nil, err
×
305
                }
×
306

307
                removeReadOnlyAttributesLatest(cluster)
1✔
308
                cluster.GroupId = pointer.Get(opts.ConfigProjectID())
1✔
309
                if opts.name != "" {
2✔
310
                        cluster.Name = &opts.name
1✔
311
                }
1✔
312

313
                return cluster, nil
1✔
314
        }
315

316
        opts.applyOptsClusterLatest(cluster)
1✔
317

1✔
318
        return cluster, nil
1✔
319
}
320

321
func (opts *CreateOpts) applyOptsAdvancedCluster(out *atlasClustersPinned.AdvancedClusterDescription) {
1✔
322
        replicationSpec := opts.newAdvanceReplicationSpec()
1✔
323
        if opts.backup {
2✔
324
                out.BackupEnabled = &opts.backup
1✔
325
                out.PitEnabled = &opts.backup
1✔
326
        }
1✔
327
        if opts.biConnector {
1✔
328
                out.BiConnector = &atlasClustersPinned.BiConnector{Enabled: &opts.biConnector}
×
329
        }
×
330
        out.TerminationProtectionEnabled = &opts.enableTerminationProtection
1✔
331
        out.ClusterType = &opts.clusterType
1✔
332

1✔
333
        if !opts.isTenant() {
2✔
334
                out.DiskSizeGB = &opts.diskSizeGB
1✔
335

1✔
336
                // If no MongoDB version is specified, the backend uses the default MongoDB version
1✔
337
                if opts.mdbVersion != "" {
2✔
338
                        out.MongoDBMajorVersion = &opts.mdbVersion
1✔
339
                }
1✔
340
        }
341

342
        out.ReplicationSpecs = &[]atlasClustersPinned.ReplicationSpec{replicationSpec}
1✔
343

1✔
344
        addTags(out, opts.tag)
1✔
345
}
346

347
func (opts *CreateOpts) applyOptsClusterLatest(out *atlasv2.ClusterDescription20240805) {
1✔
348
        out.GroupId = pointer.Get(opts.ConfigProjectID())
1✔
349
        out.ClusterType = &opts.clusterType
1✔
350
        out.TerminationProtectionEnabled = &opts.enableTerminationProtection
1✔
351
        out.ReplicationSpecs = opts.newAdvanceReplicationSpecsLatest()
1✔
352

1✔
353
        if opts.name != "" {
2✔
354
                out.Name = &opts.name
1✔
355
        }
1✔
356

357
        if opts.backup {
1✔
358
                out.BackupEnabled = &opts.backup
×
359
                out.PitEnabled = &opts.backup
×
360
        }
×
361

362
        if opts.biConnector {
1✔
363
                out.BiConnector = &atlasv2.BiConnector{Enabled: &opts.biConnector}
×
364
        }
×
365

366
        if len(opts.tag) > 0 {
1✔
367
                out.Tags = newResourceTags(opts.tag)
×
368
        }
×
369
}
370

371
func (opts *CreateOpts) newFlexClusterDescriptionCreate20241113() *atlasv2.FlexClusterDescriptionCreate20241113 {
1✔
372
        return &atlasv2.FlexClusterDescriptionCreate20241113{
1✔
373
                Name: opts.name,
1✔
374
                ProviderSettings: atlasv2.FlexProviderSettingsCreate20241113{
1✔
375
                        BackingProviderName: opts.provider,
1✔
376
                        ProviderName:        pointer.Get(opts.tier),
1✔
377
                        RegionName:          opts.region,
1✔
378
                },
1✔
379
                TerminationProtectionEnabled: &opts.enableTerminationProtection,
1✔
380
                Tags:                         newResourceTags(opts.tag),
1✔
381
        }
1✔
382
}
1✔
383

384
func (opts *CreateOpts) isTenant() bool {
1✔
385
        return opts.tier == atlasM0 || opts.tier == atlasM2 || opts.tier == atlasM5
1✔
386
}
1✔
387

388
func (opts *CreateOpts) providerName() string {
1✔
389
        if opts.isTenant() {
2✔
390
                return tenant
1✔
391
        }
1✔
392
        return opts.provider
1✔
393
}
394

395
func (opts *CreateOpts) newAdvanceReplicationSpec() atlasClustersPinned.ReplicationSpec {
1✔
396
        return atlasClustersPinned.ReplicationSpec{
1✔
397
                NumShards:     &opts.shards,
1✔
398
                ZoneName:      pointer.Get(zoneName),
1✔
399
                RegionConfigs: &[]atlasClustersPinned.CloudRegionConfig{opts.newAdvancedRegionConfig()},
1✔
400
        }
1✔
401
}
1✔
402

403
func (opts *CreateOpts) newAdvanceReplicationSpecsLatest() *[]atlasv2.ReplicationSpec20240805 {
1✔
404
        replicationSpecs := make([]atlasv2.ReplicationSpec20240805, opts.shards)
1✔
405
        for i := range opts.shards {
2✔
406
                replicationSpecs[i] = atlasv2.ReplicationSpec20240805{
1✔
407
                        ZoneName: pointer.Get(zoneName),
1✔
408
                        RegionConfigs: &[]atlasv2.CloudRegionConfig20240805{
1✔
409
                                opts.newAdvanceRegionConfigLatest(),
1✔
410
                        },
1✔
411
                }
1✔
412
        }
1✔
413
        return &replicationSpecs
1✔
414
}
415

416
func (opts *CreateOpts) newAdvancedRegionConfig() atlasClustersPinned.CloudRegionConfig {
1✔
417
        providerName := opts.providerName()
1✔
418

1✔
419
        regionConfig := atlasClustersPinned.CloudRegionConfig{
1✔
420
                Priority:     pointer.Get(priority),
1✔
421
                RegionName:   &opts.region,
1✔
422
                ProviderName: &providerName,
1✔
423
                ElectableSpecs: &atlasClustersPinned.HardwareSpec{
1✔
424
                        InstanceSize: &opts.tier,
1✔
425
                },
1✔
426
        }
1✔
427

1✔
428
        if providerName == tenant {
2✔
429
                regionConfig.BackingProviderName = &opts.provider
1✔
430
        } else {
2✔
431
                regionConfig.ElectableSpecs.NodeCount = &opts.members
1✔
432
        }
1✔
433

434
        readOnlySpec := &atlasClustersPinned.DedicatedHardwareSpec{
1✔
435
                InstanceSize: &opts.tier,
1✔
436
                NodeCount:    pointer.Get(readOnlyNode),
1✔
437
        }
1✔
438
        regionConfig.ReadOnlySpecs = readOnlySpec
1✔
439

1✔
440
        return regionConfig
1✔
441
}
442

443
func (opts *CreateOpts) newAdvanceRegionConfigLatest() atlasv2.CloudRegionConfig20240805 {
1✔
444
        providerName := opts.providerName()
1✔
445
        regionConfig := atlasv2.CloudRegionConfig20240805{
1✔
446
                ProviderName: pointer.Get(providerName),
1✔
447
                Priority:     pointer.Get(priority),
1✔
448
                RegionName:   pointer.Get(opts.region),
1✔
449
                ElectableSpecs: &atlasv2.HardwareSpec20240805{
1✔
450
                        InstanceSize: pointer.Get(opts.tier),
1✔
451
                },
1✔
452
                ReadOnlySpecs: &atlasv2.DedicatedHardwareSpec20240805{
1✔
453
                        InstanceSize: pointer.Get(opts.tier),
1✔
454
                        NodeCount:    pointer.Get(readOnlyNode),
1✔
455
                },
1✔
456
        }
1✔
457

1✔
458
        if providerName == tenant {
1✔
459
                regionConfig.BackingProviderName = &opts.provider
×
460
        } else {
1✔
461
                regionConfig.ElectableSpecs.NodeCount = pointer.Get(opts.members)
1✔
462
                regionConfig.ElectableSpecs.DiskSizeGB = &opts.diskSizeGB
1✔
463
        }
1✔
464

465
        return regionConfig
1✔
466
}
467

468
// newIsFlexCluster sets the opts.isFlexCluster that indicates if the cluster to create is
469
// a FlexCluster. When opts.filename is not provided, a FlexCluster has the opts.tier==FLEX.
470
// When opts.filename is provided, the function loads the file and check that the field replicationSpecs
471
// (available only for Dedicated Cluster) is present.
472
func (opts *CreateOpts) newIsFlexCluster() error {
1✔
473
        if opts.filename == "" {
2✔
474
                opts.isFlexCluster = opts.tier == atlasFlex
1✔
475
                return nil
1✔
476
        }
1✔
477

478
        var m map[string]any
1✔
479
        if err := file.Load(opts.fs, opts.filename, &m); err != nil {
1✔
480
                opts.isFlexCluster = false
×
481
                return fmt.Errorf("%w: %w", errFailedToLoadClusterFileMessage, err)
×
482
        }
×
483

484
        _, ok := m["replicationSpecs"]
1✔
485
        opts.isFlexCluster = !ok
1✔
486
        return nil
1✔
487
}
488

489
func (opts *CreateOpts) validateTier() error {
1✔
490
        opts.tier = strings.ToUpper(opts.tier)
1✔
491
        if opts.tier == atlasM2 || opts.tier == atlasM5 {
1✔
492
                _, _ = fmt.Fprintf(os.Stderr, deprecateMessageSharedTier, opts.tier)
×
493
        }
×
494
        return nil
1✔
495
}
496

497
func (opts *CreateOpts) validateAutoScalingMode() error {
1✔
498
        if opts.isFlexCluster && !isClusterWideScaling(opts.autoScalingMode) {
1✔
499
                return fmt.Errorf("flex is incompatible with %s auto scaling mode, set a --tier value different from FLEX, e.g. M10", opts.autoScalingMode)
×
500
        }
×
501

502
        err := validate.AutoScalingMode(opts.autoScalingMode)()
1✔
503
        if err != nil {
1✔
504
                return err
×
505
        }
×
506

507
        if opts.isFlexCluster {
2✔
508
                return nil
1✔
509
        }
1✔
510

511
        if opts.filename != "" {
2✔
512
                opts.autoScalingMode = detectAutoScalingModeFromFile(opts.fs, opts.filename)
1✔
513
        }
1✔
514

515
        return nil
1✔
516
}
517

518
// CreateBuilder builds a cobra.Command that can run as:
519
// create <name> --projectId projectId --provider AWS|GCP|AZURE --region regionName [--members N] [--tier M#] [--diskSizeGB N] [--backup] [--mdbVersion] [--tag key=value].
520
func CreateBuilder() *cobra.Command {
1✔
521
        opts := &CreateOpts{
1✔
522
                fs: afero.NewOsFs(),
1✔
523
        }
1✔
524

1✔
525
        cmd := &cobra.Command{
1✔
526
                Use:   "create [name]",
1✔
527
                Short: "Create a cluster for your project.",
1✔
528
                Long: `To get started quickly, specify a name for your cluster, a cloud provider, and a region to deploy a three-member replica set with the latest MongoDB server version.
1✔
529
For full control of your deployment, or to create multi-cloud clusters, provide a JSON configuration file with the --file flag.
1✔
530

1✔
531
Deprecation note: the M2 and M5 tiers are now deprecated; when selecting M2 or M5, a FLEX tier will be created instead. For the migration guide, visit: https://dochub.mongodb.org/core/flex-migration.\n
1✔
532

1✔
533
` + fmt.Sprintf(usage.RequiredRole, "Project Owner"),
1✔
534
                Example: `  # Deploy a free cluster named myCluster for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
535
  atlas cluster create myCluster --projectId 5e2211c17a3e5a48f5497de3 --provider AWS --region US_EAST_1 --tier M0
1✔
536

1✔
537
  # Deploy a Flex cluster named myFlexCluster for the project with the ID 5e2211c17a3e5a48f5497de3 and tag "env=dev":
1✔
538
  atlas cluster create myFlexCluster --projectId 5e2211c17a3e5a48f5497de3 --provider AWS --region US_EAST_1 --tier FLEX --tag env=dev
1✔
539

1✔
540
  # Deploy a free cluster named myCluster for the project with the ID 5e2211c17a3e5a48f5497de3 and tag "env=dev":
1✔
541
  atlas cluster create myCluster --projectId 5e2211c17a3e5a48f5497de3 --provider AWS --region US_EAST_1 --tier M0 --tag env=dev
1✔
542

1✔
543
  # Deploy a three-member replica set named myRS in AWS for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
544
  atlas cluster create myRS --projectId 5e2211c17a3e5a48f5497de3 --provider AWS --region US_EAST_1 --members 3 --tier M10 --mdbVersion 5.0 --diskSizeGB 10
1✔
545

1✔
546
  # Deploy a three-member replica set named myRS in AZURE for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
547
  atlas cluster create myRS --projectId 5e2211c17a3e5a48f5497de3 --provider AZURE --region US_EAST_2 --members 3 --tier M10  --mdbVersion 5.0 --diskSizeGB 10
1✔
548
  
1✔
549
  # Deploy a three-member replica set named myRS in GCP for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
550
  atlas cluster create myRS --projectId 5e2211c17a3e5a48f5497de3 --provider GCP --region EASTERN_US --members 3 --tier M10  --mdbVersion 5.0 --diskSizeGB 10
1✔
551

1✔
552
  # Deploy a cluster or a multi-cloud cluster from a JSON configuration file named myfile.json for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
553
  atlas cluster create --projectId <projectId> --file myfile.json
1✔
554
  
1✔
555
  # Deploy a three-member sharded cluster with independent shard scaling mode named myRS in GCP for the project with the ID 5e2211c17a3e5a48f5497de3:
1✔
556
  atlas cluster create myRS --projectId 5e2211c17a3e5a48f5497de3 --provider GCP --region EASTERN_US --members 3 --tier M10  --mdbVersion 5.0 --diskSizeGB 10 --autoScalingMode independentShardScaling
1✔
557
  `,
1✔
558
                Args: require.MaximumNArgs(1),
1✔
559
                PreRunE: func(cmd *cobra.Command, args []string) error {
2✔
560
                        if opts.filename == "" {
2✔
561
                                _ = cmd.MarkFlagRequired(flag.Provider)
1✔
562
                                _ = cmd.MarkFlagRequired(flag.Region)
1✔
563
                                if len(args) == 0 {
1✔
564
                                        return errors.New("cluster name missing")
×
565
                                }
×
566
                        }
567

568
                        if len(args) != 0 {
2✔
569
                                opts.name = args[0]
1✔
570
                        }
1✔
571

572
                        opts.tier = strings.ToUpper(opts.tier)
1✔
573
                        opts.region = strings.ToUpper(opts.region)
1✔
574
                        return opts.PreRunE(
1✔
575
                                opts.validateTier,
1✔
576
                                opts.newIsFlexCluster,
1✔
577
                                opts.validateAutoScalingMode,
1✔
578
                                opts.ValidateProjectID,
1✔
579
                                opts.initStore(cmd.Context()),
1✔
580
                                opts.InitOutput(cmd.OutOrStdout(), createTemplate),
1✔
581
                        )
1✔
582
                },
583
                RunE: func(_ *cobra.Command, _ []string) error {
1✔
584
                        return opts.Run()
1✔
585
                },
1✔
586
                PostRunE: func(_ *cobra.Command, _ []string) error {
1✔
587
                        return opts.PostRun()
1✔
588
                },
1✔
589
                Annotations: map[string]string{
590
                        "nameDesc": "Name of the cluster. The cluster name cannot be changed after the cluster is created. Cluster name can contain ASCII letters, numbers, and hyphens. You must specify the cluster name argument if you don't use the --file option.",
591
                        "output":   createTemplate,
592
                },
593
        }
594

595
        const (
1✔
596
                defaultMembersSize = 3
1✔
597
                defaultDiskSize    = 2
1✔
598
                defaultShardSize   = 1
1✔
599
        )
1✔
600
        cmd.Flags().StringVar(&opts.provider, flag.Provider, "", usage.CreateProvider)
1✔
601
        cmd.Flags().StringVarP(&opts.region, flag.Region, flag.RegionShort, "", usage.CreateRegion)
1✔
602
        cmd.Flags().IntVarP(&opts.members, flag.Members, flag.MembersShort, defaultMembersSize, usage.Members)
1✔
603
        cmd.Flags().StringVar(&opts.tier, flag.Tier, atlasFlex, usage.Tier)
1✔
604
        cmd.Flags().Float64Var(&opts.diskSizeGB, flag.DiskSizeGB, defaultDiskSize, usage.DiskSizeGB)
1✔
605
        cmd.Flags().StringVar(&opts.mdbVersion, flag.MDBVersion, "", usage.MDBVersionCreate)
1✔
606
        cmd.Flags().BoolVar(&opts.backup, flag.Backup, false, usage.Backup)
1✔
607
        cmd.Flags().BoolVar(&opts.biConnector, flag.BIConnector, false, usage.BIConnector)
1✔
608
        cmd.Flags().StringVarP(&opts.filename, flag.File, flag.FileShort, "", usage.ClusterFilename)
1✔
609
        cmd.Flags().StringVar(&opts.clusterType, flag.TypeFlag, replicaSet, usage.ClusterTypes)
1✔
610
        cmd.Flags().IntVarP(&opts.shards, flag.Shards, flag.ShardsShort, defaultShardSize, usage.Shards)
1✔
611
        cmd.Flags().BoolVar(&opts.enableTerminationProtection, flag.EnableTerminationProtection, false, usage.EnableTerminationProtection)
1✔
612
        cmd.Flags().StringToStringVar(&opts.tag, flag.Tag, nil, usage.Tag)
1✔
613
        cmd.Flags().StringVar(&opts.autoScalingMode, flag.AutoScalingMode, clusterWideScalingFlag, usage.AutoScalingMode)
1✔
614

1✔
615
        cmd.Flags().BoolVarP(&opts.EnableWatch, flag.EnableWatch, flag.EnableWatchShort, false, usage.EnableWatch)
1✔
616
        cmd.Flags().Int64Var(&opts.Timeout, flag.WatchTimeout, 0, usage.WatchTimeout)
1✔
617

1✔
618
        opts.AddProjectOptsFlags(cmd)
1✔
619
        opts.AddOutputOptFlags(cmd)
1✔
620

1✔
621
        _ = cmd.MarkFlagFilename(flag.File)
1✔
622

1✔
623
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Tier)
1✔
624
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Provider)
1✔
625
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Members)
1✔
626
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Region)
1✔
627
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.DiskSizeGB)
1✔
628
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.MDBVersion)
1✔
629
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.BIConnector)
1✔
630
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.TypeFlag)
1✔
631
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Shards)
1✔
632
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.Tag)
1✔
633
        cmd.MarkFlagsMutuallyExclusive(flag.File, flag.AutoScalingMode)
1✔
634

1✔
635
        _ = cmd.RegisterFlagCompletionFunc(flag.TypeFlag, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
1✔
636
                return []string{"REPLICASET", "SHARDED", "GEOSHARDED"}, cobra.ShellCompDirectiveDefault
×
637
        })
×
638

639
        _ = cmd.RegisterFlagCompletionFunc(flag.Provider, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
1✔
640
                return []string{"AWS", "AZURE", "GCP"}, cobra.ShellCompDirectiveDefault
×
641
        })
×
642

643
        _ = cmd.RegisterFlagCompletionFunc(flag.AutoScalingMode, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
1✔
644
                return []string{clusterWideScalingFlag, independentShardScalingFlag}, cobra.ShellCompDirectiveDefault
×
645
        })
×
646

647
        autocomplete := &autoCompleteOpts{}
1✔
648
        _ = cmd.RegisterFlagCompletionFunc(flag.Tier, autocomplete.autocompleteTier())
1✔
649
        _ = cmd.RegisterFlagCompletionFunc(flag.Region, autocomplete.autocompleteRegion())
1✔
650

1✔
651
        return cmd
1✔
652
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc