diff --git a/e2e/atlas_dbusers_test.go b/e2e/atlas_dbusers_test.go index 6a80bb131f..cf32940231 100644 --- a/e2e/atlas_dbusers_test.go +++ b/e2e/atlas_dbusers_test.go @@ -125,7 +125,7 @@ func TestAtlasDBUsers(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - cmd := exec.Command(cliPath, atlasEntity, dbusersEntity, "delete", username, "--force") + cmd := exec.Command(cliPath, atlasEntity, dbusersEntity, "delete", username, "--force", "--authDB", "admin") cmd.Env = os.Environ() resp, err := cmd.CombinedOutput() diff --git a/internal/cli/atlas_alert_config_delete_test.go b/internal/cli/atlas_alert_config_delete_test.go index 236d1d54d1..c40fc15807 100644 --- a/internal/cli/atlas_alert_config_delete_test.go +++ b/internal/cli/atlas_alert_config_delete_test.go @@ -30,8 +30,9 @@ func TestAtlasAlertConfigsDelete_Run(t *testing.T) { deleteOpts := &atlasAlertConfigDeleteOpts{ globalOpts: newGlobalOpts(), deleteOpts: &deleteOpts{ - confirm: true, - entry: "test", + confirm: true, + entry: "test", + successMessage: "Alert config '%s' deleted\n", }, store: mockStore, } diff --git a/internal/cli/atlas_clusters_delete_test.go b/internal/cli/atlas_clusters_delete_test.go index 58aea91f26..03e8cd7fc0 100644 --- a/internal/cli/atlas_clusters_delete_test.go +++ b/internal/cli/atlas_clusters_delete_test.go @@ -30,8 +30,9 @@ func TestAtlasClustersDelete_Run(t *testing.T) { deleteOpts := &atlasClustersDeleteOpts{ globalOpts: newGlobalOpts(), deleteOpts: &deleteOpts{ - confirm: true, - entry: "test", + confirm: true, + entry: "test", + successMessage: "Cluster '%s' deleted\n", }, store: mockStore, } diff --git a/internal/cli/atlas_dbusers_delete.go b/internal/cli/atlas_dbusers_delete.go index 72d8b71cec..1e21d05ce8 100644 --- a/internal/cli/atlas_dbusers_delete.go +++ b/internal/cli/atlas_dbusers_delete.go @@ -24,7 +24,8 @@ import ( type atlasDBUsersDeleteOpts struct { *globalOpts *deleteOpts - store store.DatabaseUserDeleter + authDB string + store store.DatabaseUserDeleter } func (opts *atlasDBUsersDeleteOpts) init() error { @@ -38,7 +39,7 @@ func (opts *atlasDBUsersDeleteOpts) init() error { } func (opts *atlasDBUsersDeleteOpts) Run() error { - return opts.DeleteFromProject(opts.store.DeleteDatabaseUser, opts.ProjectID()) + return opts.DeleterFromProjectAuthDB(opts.store.DeleteDatabaseUser, opts.authDB, opts.ProjectID()) } // mongocli atlas dbuser(s) delete --force @@ -70,6 +71,7 @@ func AtlasDBUsersDeleteBuilder() *cobra.Command { cmd.Flags().BoolVar(&opts.confirm, flags.Force, false, usage.Force) cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID) + cmd.Flags().StringVar(&opts.authDB, flags.AuthDB, "admin", usage.AuthDB) return cmd } diff --git a/internal/cli/atlas_dbusers_delete_test.go b/internal/cli/atlas_dbusers_delete_test.go index a4e8aa92ef..97b4252566 100644 --- a/internal/cli/atlas_dbusers_delete_test.go +++ b/internal/cli/atlas_dbusers_delete_test.go @@ -30,15 +30,17 @@ func TestAtlasDBUsersDelete_Run(t *testing.T) { deleteOpts := &atlasDBUsersDeleteOpts{ globalOpts: newGlobalOpts(), deleteOpts: &deleteOpts{ - confirm: true, - entry: "test", + confirm: true, + entry: "test", + successMessage: "DB user '%s' deleted\n", }, - store: mockStore, + authDB: "admin", + store: mockStore, } mockStore. EXPECT(). - DeleteDatabaseUser(deleteOpts.projectID, deleteOpts.entry). + DeleteDatabaseUser(deleteOpts.authDB, deleteOpts.projectID, deleteOpts.entry). Return(nil). Times(1) diff --git a/internal/cli/atlas_whitelist_delete_test.go b/internal/cli/atlas_whitelist_delete_test.go index 48f08b7e00..397c9b6818 100644 --- a/internal/cli/atlas_whitelist_delete_test.go +++ b/internal/cli/atlas_whitelist_delete_test.go @@ -30,8 +30,9 @@ func TestAtlasWhitelistDelete_Run(t *testing.T) { deleteOpts := &atlasWhitelistDeleteOpts{ globalOpts: newGlobalOpts(), deleteOpts: &deleteOpts{ - confirm: true, - entry: "test", + confirm: true, + entry: "test", + successMessage: "Project whitelist entry '%s' deleted\n", }, store: mockStore, } diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 9414302c62..ebf94c1a4c 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -65,6 +65,9 @@ type deleteOpts struct { // DeleterFromProject a function to delete from the store. type DeleterFromProject func(projectID string, entry string) error +// DeleterFromProjectAuthDB a function to delete from the store. +type DeleterFromProjectAuthDB func(authDB string, projectID string, entry string) error + // DeleteFromProject deletes a resource from a project, it expects a callback // that should perform the deletion from the store. func (opts *deleteOpts) DeleteFromProject(d DeleterFromProject, projectID string) error { @@ -83,6 +86,24 @@ func (opts *deleteOpts) DeleteFromProject(d DeleterFromProject, projectID string return nil } +// DeleterFromProjectAuthDB deletes a resource from a project, it expects a callback +// that should perform the deletion from the store. +func (opts *deleteOpts) DeleterFromProjectAuthDB(d DeleterFromProjectAuthDB, authDB, projectID string) error { + if !opts.confirm { + fmt.Println(opts.failMessage) + return nil + } + err := d(authDB, projectID, opts.entry) + + if err != nil { + return err + } + + fmt.Printf(opts.successMessage, opts.entry) + + return nil +} + // Deleter a function to delete from the store. type Deleter func(entry string) error diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 3202907dbf..b80ea2999e 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -20,6 +20,7 @@ const ( ProfileShort = "p" // ProfileShort flag to use a profile OrgID = "orgId" // OrgID flag to use an Organization ID ProjectID = "projectId" // ProjectID flag to use a project ID + AuthDB = "authDB" // AuthDB flag Provider = "provider" // Provider flag to set the cloud provider Region = "region" // Region flag RegionShort = "r" // RegionShort flag @@ -31,7 +32,6 @@ const ( Backup = "backup" // Backup flag Username = "username" // Username flag Password = "password" // Password flag - AuthDB = "authDB" // AuthDB flag Email = "email" // Email flag FirstName = "firstName" // FirstName flag LastName = "lastName" // LastName flag diff --git a/internal/mocks/mock_database_users.go b/internal/mocks/mock_database_users.go index 59a59b810e..ce7d169e35 100644 --- a/internal/mocks/mock_database_users.go +++ b/internal/mocks/mock_database_users.go @@ -110,17 +110,17 @@ func (m *MockDatabaseUserDeleter) EXPECT() *MockDatabaseUserDeleterMockRecorder } // DeleteDatabaseUser mocks base method -func (m *MockDatabaseUserDeleter) DeleteDatabaseUser(arg0, arg1 string) error { +func (m *MockDatabaseUserDeleter) DeleteDatabaseUser(arg0, arg1, arg2 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteDatabaseUser", arg0, arg1) + ret := m.ctrl.Call(m, "DeleteDatabaseUser", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // DeleteDatabaseUser indicates an expected call of DeleteDatabaseUser -func (mr *MockDatabaseUserDeleterMockRecorder) DeleteDatabaseUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseUserDeleterMockRecorder) DeleteDatabaseUser(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDatabaseUser", reflect.TypeOf((*MockDatabaseUserDeleter)(nil).DeleteDatabaseUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDatabaseUser", reflect.TypeOf((*MockDatabaseUserDeleter)(nil).DeleteDatabaseUser), arg0, arg1, arg2) } // MockDatabaseUserUpdater is a mock of DatabaseUserUpdater interface @@ -185,18 +185,18 @@ func (m *MockDatabaseUserDescriber) EXPECT() *MockDatabaseUserDescriberMockRecor } // DatabaseUser mocks base method -func (m *MockDatabaseUserDescriber) DatabaseUser(arg0, arg1 string) (*mongodbatlas.DatabaseUser, error) { +func (m *MockDatabaseUserDescriber) DatabaseUser(arg0, arg1, arg2 string) (*mongodbatlas.DatabaseUser, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DatabaseUser", arg0, arg1) + ret := m.ctrl.Call(m, "DatabaseUser", arg0, arg1, arg2) ret0, _ := ret[0].(*mongodbatlas.DatabaseUser) ret1, _ := ret[1].(error) return ret0, ret1 } // DatabaseUser indicates an expected call of DatabaseUser -func (mr *MockDatabaseUserDescriberMockRecorder) DatabaseUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseUserDescriberMockRecorder) DatabaseUser(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DatabaseUser", reflect.TypeOf((*MockDatabaseUserDescriber)(nil).DatabaseUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DatabaseUser", reflect.TypeOf((*MockDatabaseUserDescriber)(nil).DatabaseUser), arg0, arg1, arg2) } // MockDatabaseUserStore is a mock of DatabaseUserStore interface @@ -238,17 +238,17 @@ func (mr *MockDatabaseUserStoreMockRecorder) CreateDatabaseUser(arg0 interface{} } // DeleteDatabaseUser mocks base method -func (m *MockDatabaseUserStore) DeleteDatabaseUser(arg0, arg1 string) error { +func (m *MockDatabaseUserStore) DeleteDatabaseUser(arg0, arg1, arg2 string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteDatabaseUser", arg0, arg1) + ret := m.ctrl.Call(m, "DeleteDatabaseUser", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // DeleteDatabaseUser indicates an expected call of DeleteDatabaseUser -func (mr *MockDatabaseUserStoreMockRecorder) DeleteDatabaseUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseUserStoreMockRecorder) DeleteDatabaseUser(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDatabaseUser", reflect.TypeOf((*MockDatabaseUserStore)(nil).DeleteDatabaseUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDatabaseUser", reflect.TypeOf((*MockDatabaseUserStore)(nil).DeleteDatabaseUser), arg0, arg1, arg2) } // UpdateDatabaseUser mocks base method @@ -267,16 +267,16 @@ func (mr *MockDatabaseUserStoreMockRecorder) UpdateDatabaseUser(arg0 interface{} } // DatabaseUser mocks base method -func (m *MockDatabaseUserStore) DatabaseUser(arg0, arg1 string) (*mongodbatlas.DatabaseUser, error) { +func (m *MockDatabaseUserStore) DatabaseUser(arg0, arg1, arg2 string) (*mongodbatlas.DatabaseUser, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DatabaseUser", arg0, arg1) + ret := m.ctrl.Call(m, "DatabaseUser", arg0, arg1, arg2) ret0, _ := ret[0].(*mongodbatlas.DatabaseUser) ret1, _ := ret[1].(error) return ret0, ret1 } // DatabaseUser indicates an expected call of DatabaseUser -func (mr *MockDatabaseUserStoreMockRecorder) DatabaseUser(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseUserStoreMockRecorder) DatabaseUser(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DatabaseUser", reflect.TypeOf((*MockDatabaseUserStore)(nil).DatabaseUser), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DatabaseUser", reflect.TypeOf((*MockDatabaseUserStore)(nil).DatabaseUser), arg0, arg1, arg2) } diff --git a/internal/store/database_users.go b/internal/store/database_users.go index 9ea96f918d..971a573bb8 100644 --- a/internal/store/database_users.go +++ b/internal/store/database_users.go @@ -31,7 +31,7 @@ type DatabaseUserCreator interface { } type DatabaseUserDeleter interface { - DeleteDatabaseUser(string, string) error + DeleteDatabaseUser(string, string, string) error } type DatabaseUserUpdater interface { @@ -39,7 +39,7 @@ type DatabaseUserUpdater interface { } type DatabaseUserDescriber interface { - DatabaseUser(string, string) (*atlas.DatabaseUser, error) + DatabaseUser(string, string, string) (*atlas.DatabaseUser, error) } type DatabaseUserStore interface { @@ -60,11 +60,10 @@ func (s *Store) CreateDatabaseUser(user *atlas.DatabaseUser) (*atlas.DatabaseUse } } -func (s *Store) DeleteDatabaseUser(groupID, username string) error { - dbName := "admin" +func (s *Store) DeleteDatabaseUser(authDB, groupID, username string) error { switch s.service { case config.CloudService: - _, err := s.client.(*atlas.Client).DatabaseUsers.Delete(context.Background(), dbName, groupID, username) + _, err := s.client.(*atlas.Client).DatabaseUsers.Delete(context.Background(), authDB, groupID, username) return err default: return fmt.Errorf("unsupported service: %s", s.service) @@ -91,11 +90,10 @@ func (s *Store) UpdateDatabaseUser(user *atlas.DatabaseUser) (*atlas.DatabaseUse } } -func (s *Store) DatabaseUser(groupID string, username string) (*atlas.DatabaseUser, error) { - dbName := "admin" +func (s *Store) DatabaseUser(authDB string, groupID string, username string) (*atlas.DatabaseUser, error) { switch s.service { case config.CloudService: - result, _, err := s.client.(*atlas.Client).DatabaseUsers.Get(context.Background(), dbName, groupID, username) + result, _, err := s.client.(*atlas.Client).DatabaseUsers.Get(context.Background(), authDB, groupID, username) return result, err default: return nil, fmt.Errorf("unsupported service: %s", s.service) diff --git a/internal/usage/usage.go b/internal/usage/usage.go index 8e71a98587..a40298457f 100644 --- a/internal/usage/usage.go +++ b/internal/usage/usage.go @@ -23,11 +23,11 @@ const ( DiskSizeGB = "Capacity, in gigabytes, of the host’s root volume." Backup = "If true, uses Atlas Continuous Backups to back up cluster data." MDBVersion = "MongoDB version of the cluster to deploy." + AuthDB = "Authentication database name." Page = "Page number." Limit = "Number of items per page." Username = "Username for authenticating to MongoDB." Password = "User’s password." - AuthDB = "Authentication database name." Roles = "User's roles and the databases or collections on which the roles apply." Comment = "Optional description of the whitelist entry." Force = "Don't ask for confirmation."