Skip to content

Commit 1cc527f

Browse files
committed
CLOUDP-330561: Moves unauth error check to common errors (#4043)
1 parent 224eacb commit 1cc527f

File tree

20 files changed

+236
-69
lines changed

20 files changed

+236
-69
lines changed

cmd/atlas/atlas.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"strings"
2222

2323
"github.com/AlecAivazis/survey/v2/core"
24+
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2425
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/root"
2526
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2627
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/telemetry"
@@ -36,6 +37,8 @@ func execute(rootCmd *cobra.Command) {
3637
3738
To learn more, see our documentation: https://www.mongodb.com/docs/atlas/cli/stable/connect-atlas-cli/`
3839
if cmd, err := rootCmd.ExecuteContextC(ctx); err != nil {
40+
err := commonerrors.Check(err)
41+
rootCmd.PrintErrln(rootCmd.ErrPrefix(), err)
3942
if !telemetry.StartedTrackingCommand() {
4043
telemetry.StartTrackingCommand(cmd, os.Args[1:])
4144
}

internal/cli/auth/login.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/AlecAivazis/survey/v2"
2424
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
25+
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2526
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2627
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2728
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -397,7 +398,7 @@ func (opts *LoginOpts) LoginPreRun(ctx context.Context) func() error {
397398
// clean up any expired or invalid tokens
398399
opts.config.Set(config.AccessTokenField, "")
399400

400-
if !errors.Is(err, cli.ErrInvalidRefreshToken) {
401+
if !commonerrors.IsInvalidRefreshToken(err) {
401402
return err
402403
}
403404
}

internal/cli/backup/restores/start.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,15 @@ func (opts *StartOpts) Run() error {
7373
if opts.isFlexCluster {
7474
r, err := opts.store.CreateRestoreFlexClusterJobs(opts.ConfigProjectID(), opts.clusterName, opts.newFlexBackupRestoreJobCreate())
7575
if err != nil {
76-
return commonerrors.Check(err)
76+
return err
7777
}
7878
return opts.Print(r)
7979
}
8080

8181
request := opts.newCloudProviderSnapshotRestoreJob()
8282
restoreJob, err := opts.store.CreateRestoreJobs(opts.ConfigProjectID(), opts.clusterName, request)
8383
if err != nil {
84-
return commonerrors.Check(err)
84+
return err
8585
}
8686

8787
return opts.Print(restoreJob)

internal/cli/backup/snapshots/create.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020

2121
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
22-
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2322
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2423
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2524
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -59,7 +58,7 @@ func (opts *CreateOpts) Run() error {
5958

6059
r, err := opts.store.CreateSnapshot(opts.ConfigProjectID(), opts.clusterName, createRequest)
6160
if err != nil {
62-
return commonerrors.Check(err)
61+
return err
6362
}
6463
return opts.Print(r)
6564
}

internal/cli/clusters/advancedsettings/update.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"context"
1919

2020
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
21-
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2221
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2322
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2423
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -67,7 +66,7 @@ func (opts *UpdateOpts) initStore(ctx context.Context) func() error {
6766
func (opts *UpdateOpts) Run() error {
6867
r, err := opts.store.UpdateAtlasClusterConfigurationOptions(opts.ConfigProjectID(), opts.name, opts.newProcessArgs())
6968
if err != nil {
70-
return commonerrors.Check(err)
69+
return err
7170
}
7271

7372
return opts.Print(r)

internal/cli/clusters/describe.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020

2121
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
22-
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2322
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2423
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2524
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -83,12 +82,12 @@ func (opts *DescribeOpts) RunFlexCluster(err error) error {
8382
}
8483

8584
if *apiError.ErrorCode != cannotUseFlexWithClusterApisErrorCode {
86-
return commonerrors.Check(err)
85+
return err
8786
}
8887

8988
r, err := opts.store.FlexCluster(opts.ConfigProjectID(), opts.name)
9089
if err != nil {
91-
return commonerrors.Check(err)
90+
return err
9291
}
9392

9493
return opts.Print(r)

internal/cli/clusters/pause.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020

2121
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
22-
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2322
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2423
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2524
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -60,14 +59,14 @@ func (opts *PauseOpts) Run() error {
6059
if isIndependentShardScaling(opts.autoScalingMode) {
6160
r, err := opts.store.PauseClusterLatest(opts.ConfigProjectID(), opts.name)
6261
if err != nil {
63-
return commonerrors.Check(err)
62+
return err
6463
}
6564
return opts.Print(r)
6665
}
6766

6867
r, err := opts.store.PauseCluster(opts.ConfigProjectID(), opts.name)
6968
if err != nil {
70-
return commonerrors.Check(err)
69+
return err
7170
}
7271
return opts.Print(r)
7372
}

internal/cli/clusters/start.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"fmt"
2020

2121
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
22-
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/commonerrors"
2322
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
2423
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
2524
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/flag"
@@ -60,14 +59,14 @@ func (opts *StartOpts) Run() error {
6059
if isIndependentShardScaling(opts.autoScalingMode) {
6160
r, err := opts.store.StartClusterLatest(opts.ConfigProjectID(), opts.name)
6261
if err != nil {
63-
return commonerrors.Check(err)
62+
return err
6463
}
6564
return opts.Print(r)
6665
}
6766

6867
r, err := opts.store.StartCluster(opts.ConfigProjectID(), opts.name)
6968
if err != nil {
70-
return commonerrors.Check(err)
69+
return err
7170
}
7271
return opts.Print(r)
7372
}

internal/cli/clusters/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func (opts *UpdateOpts) RunDedicatedClusterWideScaling() error {
211211

212212
r, err := opts.store.UpdateCluster(opts.ConfigProjectID(), opts.name, cluster)
213213
if err != nil {
214-
return commonerrors.Check(err)
214+
return err
215215
}
216216

217217
return opts.Print(r)

internal/cli/commonerrors/errors.go

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,128 @@ package commonerrors
1616

1717
import (
1818
"errors"
19+
"net/http"
1920

20-
"go.mongodb.org/atlas-sdk/v20250312005/admin"
21+
atlasClustersPinned "go.mongodb.org/atlas-sdk/v20240530005/admin"
22+
atlasv2 "go.mongodb.org/atlas-sdk/v20250312005/admin"
23+
atlas "go.mongodb.org/atlas/mongodbatlas"
2124
)
2225

2326
var (
2427
errClusterUnsupported = errors.New("atlas supports this command only for M10+ clusters. You can upgrade your cluster by running the 'atlas cluster upgrade' command")
2528
errOutsideVPN = errors.New("forbidden action outside access allow list, if you are a MongoDB employee double check your VPN connection")
2629
errAsymmetricShardUnsupported = errors.New("trying to run a cluster wide scaling command on an independent shard scaling cluster. Use --autoScalingMode 'independentShardScaling' instead")
30+
ErrUnauthorized = errors.New(`this action requires authentication
31+
32+
To log in using your Atlas username and password, run: atlas auth login
33+
To set credentials using API keys, run: atlas config init`)
34+
ErrInvalidRefreshToken = errors.New(`session expired
35+
36+
Please note that your session expires periodically.
37+
If you use Atlas CLI for automation, see https://www.mongodb.com/docs/atlas/cli/stable/atlas-cli-automate/ for best practices.
38+
To login, run: atlas auth login`)
2739
)
2840

2941
const (
30-
asymmetricShardUnsupportedErrorCode = "ASYMMETRIC_SHARD_UNSUPPORTED"
42+
unknownErrorCode = "UNKNOWN_ERROR"
43+
asymmetricShardUnsupportedErrorCode = "ASYMMETRIC_SHARD_UNSUPPORTED"
44+
tenantClusterUpdateUnsupportedErrorCode = "TENANT_CLUSTER_UPDATE_UNSUPPORTED"
45+
globalUserOutsideSubnetErrorCode = "GLOBAL_USER_OUTSIDE_SUBNET"
46+
unauthorizedErrorCode = "UNAUTHORIZED"
47+
invalidRefreshTokenErrorCode = "INVALID_REFRESH_TOKEN"
3148
)
3249

50+
// Check checks the error and returns a more user-friendly error message if applicable.
3351
func Check(err error) error {
3452
if err == nil {
3553
return nil
3654
}
3755

38-
apiError, ok := admin.AsError(err)
39-
if ok {
40-
switch apiError.GetErrorCode() {
41-
case "TENANT_CLUSTER_UPDATE_UNSUPPORTED":
42-
return errClusterUnsupported
43-
case "GLOBAL_USER_OUTSIDE_SUBNET":
44-
return errOutsideVPN
45-
case asymmetricShardUnsupportedErrorCode:
46-
return errAsymmetricShardUnsupported
47-
}
56+
apiErrorCode := getErrorCode(err)
57+
58+
switch apiErrorCode {
59+
case unauthorizedErrorCode:
60+
return ErrUnauthorized
61+
case invalidRefreshTokenErrorCode:
62+
return ErrInvalidRefreshToken
63+
case tenantClusterUpdateUnsupportedErrorCode:
64+
return errClusterUnsupported
65+
case globalUserOutsideSubnetErrorCode:
66+
return errOutsideVPN
67+
case asymmetricShardUnsupportedErrorCode:
68+
return errAsymmetricShardUnsupported
4869
}
70+
71+
apiError := getError(err) // some `Unauthorized` errors do not have an error code, so we check the HTTP status code
72+
73+
if apiError == http.StatusUnauthorized {
74+
return ErrUnauthorized
75+
}
76+
4977
return err
5078
}
5179

80+
// getErrorCode extracts the error code from the error if it is an Atlas error.
81+
// This function checks for v2 SDK, the pinned clusters SDK and the old SDK errors.
82+
// If the error is not any of these Atlas errors, it returns "UNKNOWN_ERROR".
83+
func getErrorCode(err error) string {
84+
if err == nil {
85+
return unknownErrorCode
86+
}
87+
88+
var atlasErr *atlas.ErrorResponse
89+
if errors.As(err, &atlasErr) {
90+
return atlasErr.ErrorCode
91+
}
92+
if sdkError, ok := atlasv2.AsError(err); ok {
93+
return sdkError.ErrorCode
94+
}
95+
if sdkPinnedError, ok := atlasClustersPinned.AsError(err); ok {
96+
return sdkPinnedError.GetErrorCode()
97+
}
98+
99+
return unknownErrorCode
100+
}
101+
102+
// getError extracts the HTTP error code from the error if it is an Atlas error.
103+
// This function checks for v2 SDK, the pinned clusters SDK and the old SDK errors.
104+
// If the error is not any of these Atlas errors, it returns 0.
105+
func getError(err error) int {
106+
if err == nil {
107+
return 0
108+
}
109+
110+
var atlasErr *atlas.ErrorResponse
111+
if errors.As(err, &atlasErr) {
112+
return atlasErr.HTTPCode
113+
}
114+
if apiError, ok := atlasv2.AsError(err); ok {
115+
return apiError.GetError()
116+
}
117+
if apiPinnedError, ok := atlasClustersPinned.AsError(err); ok {
118+
return apiPinnedError.GetError()
119+
}
120+
121+
return 0
122+
}
123+
52124
func IsAsymmetricShardUnsupported(err error) bool {
53-
apiError, ok := admin.AsError(err)
125+
apiError, ok := atlasv2.AsError(err)
54126
if !ok {
55127
return false
56128
}
57129
return apiError.GetErrorCode() == asymmetricShardUnsupportedErrorCode
58130
}
59131

60132
func IsCannotUseFlexWithClusterApis(err error) bool {
61-
apiError, ok := admin.AsError(err)
133+
apiError, ok := atlasv2.AsError(err)
62134
if !ok {
63135
return false
64136
}
65137
return apiError.GetErrorCode() == "CANNOT_USE_FLEX_CLUSTER_IN_CLUSTER_API"
66138
}
139+
140+
func IsInvalidRefreshToken(err error) bool {
141+
errCode := getErrorCode(err)
142+
return errCode == invalidRefreshTokenErrorCode
143+
}

0 commit comments

Comments
 (0)