Skip to content

Commit f3c1934

Browse files
authored
CLOUDP-57841: Delete dbusers C/OM (#57)
1 parent 737e9e6 commit f3c1934

17 files changed

+407
-85
lines changed

internal/cli/atlas_alert_config_delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (opts *atlasAlertConfigDeleteOpts) init() error {
3838
}
3939

4040
func (opts *atlasAlertConfigDeleteOpts) Run() error {
41-
return opts.DeleteFromProject(opts.store.DeleteAlertConfiguration, opts.ProjectID())
41+
return opts.Delete(opts.store.DeleteAlertConfiguration, opts.ProjectID())
4242
}
4343

4444
// mongocli atlas alerts config(s) delete id --projectId projectId [--confirm]

internal/cli/atlas_clusters_delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (opts *atlasClustersDeleteOpts) init() error {
3838
}
3939

4040
func (opts *atlasClustersDeleteOpts) Run() error {
41-
return opts.DeleteFromProject(opts.store.DeleteCluster, opts.ProjectID())
41+
return opts.Delete(opts.store.DeleteCluster, opts.ProjectID())
4242
}
4343

4444
// mongocli atlas cluster(s) delete name --projectId projectId [--confirm]

internal/cli/atlas_dbusers_create.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type atlasDBUsersCreateOpts struct {
3131
*globalOpts
3232
username string
3333
password string
34+
authDB string
3435
roles []string
3536
store store.DatabaseUserCreator
3637
}
@@ -58,7 +59,7 @@ func (opts *atlasDBUsersCreateOpts) Run() error {
5859

5960
func (opts *atlasDBUsersCreateOpts) newDatabaseUser() *atlas.DatabaseUser {
6061
return &atlas.DatabaseUser{
61-
DatabaseName: convert.AdminDB,
62+
DatabaseName: opts.authDB,
6263
Roles: convert.BuildAtlasRoles(opts.roles),
6364
GroupID: opts.ProjectID(),
6465
Username: opts.username,
@@ -105,6 +106,7 @@ func AtlasDBUsersCreateBuilder() *cobra.Command {
105106
cmd.Flags().StringVar(&opts.username, flags.Username, "", usage.Username)
106107
cmd.Flags().StringVar(&opts.password, flags.Password, "", usage.Password)
107108
cmd.Flags().StringSliceVar(&opts.roles, flags.Role, []string{}, usage.Roles)
109+
cmd.Flags().StringVar(&opts.authDB, flags.AuthDB, convert.AdminDB, usage.AuthDB)
108110

109111
cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID)
110112

internal/cli/atlas_dbusers_delete.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package cli
1616

1717
import (
18+
"github.com/mongodb/mongocli/internal/convert"
1819
"github.com/mongodb/mongocli/internal/flags"
1920
"github.com/mongodb/mongocli/internal/store"
2021
"github.com/mongodb/mongocli/internal/usage"
@@ -39,7 +40,7 @@ func (opts *atlasDBUsersDeleteOpts) init() error {
3940
}
4041

4142
func (opts *atlasDBUsersDeleteOpts) Run() error {
42-
return opts.DeleterFromProjectAuthDB(opts.store.DeleteDatabaseUser, opts.authDB, opts.ProjectID())
43+
return opts.Delete(opts.store.DeleteDatabaseUser, opts.authDB, opts.ProjectID())
4344
}
4445

4546
// mongocli atlas dbuser(s) delete <username> --force
@@ -69,9 +70,9 @@ func AtlasDBUsersDeleteBuilder() *cobra.Command {
6970
}
7071

7172
cmd.Flags().BoolVar(&opts.confirm, flags.Force, false, usage.Force)
73+
cmd.Flags().StringVar(&opts.authDB, flags.AuthDB, convert.AdminDB, usage.AuthDB)
7274

7375
cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID)
74-
cmd.Flags().StringVar(&opts.authDB, flags.AuthDB, "admin", usage.AuthDB)
7576

7677
return cmd
7778
}

internal/cli/atlas_whitelist_delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (opts *atlasWhitelistDeleteOpts) init() error {
3838
}
3939

4040
func (opts *atlasWhitelistDeleteOpts) Run() error {
41-
return opts.DeleteFromProject(opts.store.DeleteProjectIPWhitelist, opts.ProjectID())
41+
return opts.Delete(opts.store.DeleteProjectIPWhitelist, opts.ProjectID())
4242
}
4343

4444
// mongocli atlas whitelist delete <entry> --force

internal/cli/cli.go

Lines changed: 33 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package cli
1616

1717
import (
18+
"errors"
1819
"fmt"
1920

2021
"github.com/AlecAivazis/survey/v2"
@@ -24,7 +25,7 @@ import (
2425

2526
const (
2627
fallbackSuccessMessage = "'%s' deleted\n"
27-
fallbackFailMessage = "'%s' not deleted\n"
28+
fallbackFailMessage = "entry not deleted"
2829
)
2930

3031
type globalOpts struct {
@@ -58,7 +59,7 @@ func (opts *globalOpts) OrgID() string {
5859
}
5960

6061
// deleteOpts options required when deleting a resource.
61-
// A command can embed this structure and then safely rely on the methods Confirm, DeleteFromProject or Delete
62+
// A command can compose this struct and then safely rely on the methods Confirm, or Delete
6263
// to manage the interactions with the user
6364
type deleteOpts struct {
6465
entry string
@@ -67,83 +68,31 @@ type deleteOpts struct {
6768
failMessage string
6869
}
6970

70-
// DeleterFromProject a function to delete from the store.
71-
type DeleterFromProject func(projectID string, entry string) error
72-
73-
// DeleterFromProjectAuthDB a function to delete from the store.
74-
type DeleterFromProjectAuthDB func(authDB string, projectID string, entry string) error
75-
76-
// DeleteFromProject deletes a resource from a project, it expects a callback
71+
// Delete deletes a resource not associated to a project, it expects a callback
7772
// that should perform the deletion from the store.
78-
func (opts *deleteOpts) DeleteFromProject(d DeleterFromProject, projectID string) error {
73+
func (opts *deleteOpts) Delete(d interface{}, a ...string) error {
7974
if !opts.confirm {
80-
opts.printFailMessage()
75+
fmt.Println(opts.FailMessage())
8176
return nil
8277
}
83-
err := d(projectID, opts.entry)
84-
85-
if err != nil {
86-
return err
87-
}
88-
89-
opts.printSuccessMessage()
90-
91-
return nil
92-
}
9378

94-
// DeleterFromProjectAuthDB deletes a resource from a project, it expects a callback
95-
// that should perform the deletion from the store.
96-
func (opts *deleteOpts) DeleterFromProjectAuthDB(d DeleterFromProjectAuthDB, authDB, projectID string) error {
97-
if !opts.confirm {
98-
opts.printFailMessage()
99-
return nil
79+
var err error
80+
switch f := d.(type) {
81+
case func(string) error:
82+
err = f(opts.entry)
83+
case func(string, string) error:
84+
err = f(a[0], opts.entry)
85+
case func(string, string, string) error:
86+
err = f(a[0], a[1], opts.entry)
87+
default:
88+
return errors.New("invalid")
10089
}
101-
err := d(authDB, projectID, opts.entry)
10290

10391
if err != nil {
10492
return err
10593
}
10694

107-
opts.printSuccessMessage()
108-
109-
return nil
110-
}
111-
112-
// printSuccessMessage prints a success message
113-
func (opts *deleteOpts) printSuccessMessage() {
114-
if opts.successMessage != "" {
115-
fmt.Printf(opts.successMessage, opts.entry)
116-
} else {
117-
fmt.Printf(fallbackSuccessMessage, opts.entry)
118-
}
119-
}
120-
121-
// printFailMessage prints a fail message
122-
func (opts *deleteOpts) printFailMessage() {
123-
if opts.successMessage != "" {
124-
fmt.Printf(opts.failMessage, opts.entry)
125-
} else {
126-
fmt.Printf(fallbackFailMessage, opts.entry)
127-
}
128-
}
129-
130-
// Deleter a function to delete from the store.
131-
type Deleter func(entry string) error
132-
133-
// Delete deletes a resource not associated to a project, it expects a callback
134-
//// that should perform the deletion from the store.
135-
func (opts *deleteOpts) Delete(d Deleter) error {
136-
if !opts.confirm {
137-
opts.printFailMessage()
138-
return nil
139-
}
140-
err := d(opts.entry)
141-
142-
if err != nil {
143-
return err
144-
}
145-
146-
opts.printSuccessMessage()
95+
fmt.Printf(opts.SuccessMessage(), opts.entry)
14796

14897
return nil
14998
}
@@ -157,3 +106,19 @@ func (opts *deleteOpts) Confirm() error {
157106
prompt := prompts.NewDeleteConfirm(opts.entry)
158107
return survey.AskOne(prompt, &opts.confirm)
159108
}
109+
110+
// SuccessMessage gets the set success message or the default value
111+
func (opts *deleteOpts) SuccessMessage() string {
112+
if opts.successMessage != "" {
113+
return opts.successMessage
114+
}
115+
return fallbackSuccessMessage
116+
}
117+
118+
// FailMessage gets the set fail message or the default value
119+
func (opts *deleteOpts) FailMessage() string {
120+
if opts.failMessage != "" {
121+
return opts.failMessage
122+
}
123+
return fallbackFailMessage
124+
}

internal/cli/ops_manager_dbusers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ A user’s roles apply to all the clusters in the project.`,
3131

3232
cmd.AddCommand(OpsManagerDBUsersCreateBuilder())
3333
cmd.AddCommand(OpsManagerDBUsersListBuilder())
34+
cmd.AddCommand(OpsManagerDBUsersDeleteBuilder())
3435

3536
return cmd
3637
}

internal/cli/ops_manager_dbusers_create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (opts *opsManagerDBUsersCreateOpts) Run() error {
5757
return err
5858
}
5959

60-
current.Auth.Users = append(current.Auth.Users, opts.newDBUser())
60+
convert.AddUser(current, opts.newDBUser())
6161

6262
if err = opts.store.UpdateAutomationConfig(opts.ProjectID(), current); err != nil {
6363
return err
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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 cli
16+
17+
import (
18+
"fmt"
19+
20+
"github.com/mongodb/mongocli/internal/config"
21+
"github.com/mongodb/mongocli/internal/convert"
22+
"github.com/mongodb/mongocli/internal/flags"
23+
"github.com/mongodb/mongocli/internal/messages"
24+
"github.com/mongodb/mongocli/internal/store"
25+
"github.com/mongodb/mongocli/internal/usage"
26+
"github.com/spf13/cobra"
27+
)
28+
29+
type opsManagerDBUsersDeleteOpts struct {
30+
*globalOpts
31+
*deleteOpts
32+
authDB string
33+
store store.AutomationPatcher
34+
}
35+
36+
func (opts *opsManagerDBUsersDeleteOpts) init() error {
37+
if opts.ProjectID() == "" {
38+
return errMissingProjectID
39+
}
40+
41+
var err error
42+
opts.store, err = store.New()
43+
return err
44+
}
45+
46+
func (opts *opsManagerDBUsersDeleteOpts) Run() error {
47+
current, err := opts.store.GetAutomationConfig(opts.ProjectID())
48+
49+
if err != nil {
50+
return err
51+
}
52+
53+
convert.RemoveUser(current, opts.entry, opts.authDB)
54+
55+
if err = opts.store.UpdateAutomationConfig(opts.ProjectID(), current); err != nil {
56+
return err
57+
}
58+
59+
fmt.Print(messages.DeploymentStatus(config.OpsManagerURL(), opts.ProjectID()))
60+
61+
return nil
62+
}
63+
64+
// mongocli atlas dbuser(s) delete <username> [--projectId projectId]
65+
func OpsManagerDBUsersDeleteBuilder() *cobra.Command {
66+
opts := &opsManagerDBUsersDeleteOpts{
67+
globalOpts: newGlobalOpts(),
68+
deleteOpts: &deleteOpts{
69+
successMessage: "DB user '%s' deleted\n",
70+
failMessage: "DB user not deleted",
71+
},
72+
}
73+
cmd := &cobra.Command{
74+
Use: "delete [username]",
75+
Short: "Delete a database user for a project.",
76+
Aliases: []string{"rm"},
77+
Args: cobra.ExactArgs(1),
78+
PreRunE: func(cmd *cobra.Command, args []string) error {
79+
if err := opts.init(); err != nil {
80+
return err
81+
}
82+
opts.entry = args[0]
83+
return opts.Confirm()
84+
},
85+
RunE: func(cmd *cobra.Command, args []string) error {
86+
return opts.Run()
87+
},
88+
}
89+
90+
cmd.Flags().StringVar(&opts.authDB, flags.AuthDB, convert.AdminDB, usage.AuthDB)
91+
92+
cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID)
93+
94+
return cmd
95+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 cli
16+
17+
import (
18+
"testing"
19+
20+
"github.com/golang/mock/gomock"
21+
"github.com/mongodb/mongocli/internal/fixtures"
22+
"github.com/mongodb/mongocli/internal/mocks"
23+
)
24+
25+
func TestOpsManagerDBUserDelete_Run(t *testing.T) {
26+
ctrl := gomock.NewController(t)
27+
mockStore := mocks.NewMockAutomationPatcher(ctrl)
28+
29+
defer ctrl.Finish()
30+
31+
expected := fixtures.AutomationConfig()
32+
33+
createOpts := &opsManagerDBUsersDeleteOpts{
34+
globalOpts: newGlobalOpts(),
35+
deleteOpts: &deleteOpts{
36+
confirm: true,
37+
entry: "test",
38+
successMessage: "DB user '%s' deleted\n",
39+
},
40+
authDB: "admin",
41+
store: mockStore,
42+
}
43+
44+
mockStore.
45+
EXPECT().
46+
GetAutomationConfig(createOpts.projectID).
47+
Return(expected, nil).
48+
Times(1)
49+
50+
mockStore.
51+
EXPECT().
52+
UpdateAutomationConfig(createOpts.projectID, expected).
53+
Return(nil).
54+
Times(1)
55+
56+
err := createOpts.Run()
57+
if err != nil {
58+
t.Fatalf("Run() unexpected error: %v", err)
59+
}
60+
}

0 commit comments

Comments
 (0)