Skip to content

Commit 5c1bebd

Browse files
fix: project delete function uses correct string representation of id (#1733)
* fix: project delete function uses correct string representation of id * add tests * imrpove mocking to make sure test fail with previous implementation * unify handling non API errors with API errors --------- Co-authored-by: Agustin Bettati <[email protected]>
1 parent f03d37a commit 5c1bebd

File tree

3 files changed

+80
-20
lines changed

3 files changed

+80
-20
lines changed

internal/service/project/resource_project.go

+14-19
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (r *projectRS) Create(ctx context.Context, req resource.CreateRequest, resp
269269

270270
_, _, err := connV2.TeamsApi.AddAllTeamsToProject(ctx, project.GetId(), NewTeamRoleList(ctx, teams)).Execute()
271271
if err != nil {
272-
errd := deleteProject(ctx, r.Client.AtlasV2, project.Id)
272+
errd := deleteProject(ctx, r.Client.AtlasV2, project.GetId())
273273
if errd != nil {
274274
resp.Diagnostics.AddError("error during project deletion when adding teams", fmt.Sprintf(errorProjectDelete, project.GetId(), err.Error()))
275275
return
@@ -290,7 +290,7 @@ func (r *projectRS) Create(ctx context.Context, req resource.CreateRequest, resp
290290
}
291291
_, _, err := connV2.ProjectsApi.SetProjectLimit(ctx, limit.Name.ValueString(), project.GetId(), dataFederationLimit).Execute()
292292
if err != nil {
293-
errd := deleteProject(ctx, r.Client.AtlasV2, project.Id)
293+
errd := deleteProject(ctx, r.Client.AtlasV2, project.GetId())
294294
if errd != nil {
295295
resp.Diagnostics.AddError("error during project deletion when adding limits", fmt.Sprintf(errorProjectDelete, project.GetId(), err.Error()))
296296
return
@@ -304,7 +304,7 @@ func (r *projectRS) Create(ctx context.Context, req resource.CreateRequest, resp
304304
// add settings
305305
projectSettings, _, err := connV2.ProjectsApi.GetProjectSettings(ctx, *project.Id).Execute()
306306
if err != nil {
307-
errd := deleteProject(ctx, r.Client.AtlasV2, project.Id)
307+
errd := deleteProject(ctx, r.Client.AtlasV2, project.GetId())
308308
if errd != nil {
309309
resp.Diagnostics.AddError("error during project deletion when getting project settings", fmt.Sprintf(errorProjectDelete, project.GetId(), err.Error()))
310310
return
@@ -333,7 +333,7 @@ func (r *projectRS) Create(ctx context.Context, req resource.CreateRequest, resp
333333
}
334334

335335
if _, _, err = connV2.ProjectsApi.UpdateProjectSettings(ctx, project.GetId(), projectSettings).Execute(); err != nil {
336-
errd := deleteProject(ctx, r.Client.AtlasV2, project.Id)
336+
errd := deleteProject(ctx, r.Client.AtlasV2, project.GetId())
337337
if errd != nil {
338338
resp.Diagnostics.AddError("error during project deletion when updating project settings", fmt.Sprintf(errorProjectDelete, project.GetId(), err.Error()))
339339
return
@@ -494,7 +494,7 @@ func (r *projectRS) Delete(ctx context.Context, req resource.DeleteRequest, resp
494494
}
495495

496496
projectID := project.ID.ValueString()
497-
err := deleteProject(ctx, r.Client.AtlasV2, &projectID)
497+
err := deleteProject(ctx, r.Client.AtlasV2, projectID)
498498

499499
if err != nil {
500500
resp.Diagnostics.AddError("error when destroying resource", fmt.Sprintf(errorProjectDelete, projectID, err.Error()))
@@ -725,11 +725,11 @@ func UpdateProject(ctx context.Context, client GroupProjectService, projectState
725725
return nil
726726
}
727727

728-
func deleteProject(ctx context.Context, connV2 *admin.APIClient, projectID *string) error {
728+
func deleteProject(ctx context.Context, connV2 *admin.APIClient, projectID string) error {
729729
stateConf := &retry.StateChangeConf{
730730
Pending: []string{projectDependentsStateDeleting, projectDependentsStateRetry},
731731
Target: []string{projectDependentsStateIdle},
732-
Refresh: resourceProjectDependentsDeletingRefreshFunc(ctx, projectID, connV2),
732+
Refresh: ResourceProjectDependentsDeletingRefreshFunc(ctx, projectID, ServiceFromClient(connV2)),
733733
Timeout: 30 * time.Minute,
734734
MinTimeout: 30 * time.Second,
735735
Delay: 0,
@@ -738,10 +738,10 @@ func deleteProject(ctx context.Context, connV2 *admin.APIClient, projectID *stri
738738
_, err := stateConf.WaitForStateContext(ctx)
739739

740740
if err != nil {
741-
tflog.Info(ctx, fmt.Sprintf("[ERROR] could not determine MongoDB project %s dependents status: %s", *projectID, err.Error()))
741+
tflog.Info(ctx, fmt.Sprintf("[ERROR] could not determine MongoDB project %s dependents status: %s", projectID, err.Error()))
742742
}
743743

744-
_, _, err = connV2.ProjectsApi.DeleteProject(ctx, *projectID).Execute()
744+
_, _, err = connV2.ProjectsApi.DeleteProject(ctx, projectID).Execute()
745745

746746
return err
747747
}
@@ -755,18 +755,13 @@ Else consider the aggregate dependents idle.
755755
If we get a defined error response, return that right away
756756
Else retry
757757
*/
758-
func resourceProjectDependentsDeletingRefreshFunc(ctx context.Context, projectID *string, connV2 *admin.APIClient) retry.StateRefreshFunc {
758+
func ResourceProjectDependentsDeletingRefreshFunc(ctx context.Context, projectID string, client GroupProjectService) retry.StateRefreshFunc {
759759
return func() (any, string, error) {
760-
nonNullProjectID := conversion.StringPtrNullIfEmpty(projectID)
761-
clusters, _, err := connV2.ClustersApi.ListClusters(ctx, nonNullProjectID.String()).Execute()
760+
clusters, _, listClustersErr := client.ListClusters(ctx, projectID)
762761
dependents := AtlasProjectDependants{AdvancedClusters: clusters}
763762

764-
if _, ok := admin.AsError(err); ok {
765-
return nil, "", err
766-
}
767-
768-
if err != nil {
769-
return nil, projectDependentsStateRetry, nil
763+
if listClustersErr != nil {
764+
return nil, "", listClustersErr
770765
}
771766

772767
if *dependents.AdvancedClusters.TotalCount == 0 {
@@ -779,7 +774,7 @@ func resourceProjectDependentsDeletingRefreshFunc(ctx context.Context, projectID
779774
}
780775
}
781776

782-
log.Printf("[DEBUG] status for MongoDB project %s dependents: %s", nonNullProjectID, projectDependentsStateDeleting)
777+
log.Printf("[DEBUG] status for MongoDB project %s dependents: %s", projectID, projectDependentsStateDeleting)
783778

784779
return dependents, projectDependentsStateDeleting, nil
785780
}

internal/service/project/resource_project_test.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var (
4242
projectStateNameDiff = project.TfProjectRSModel{
4343
Name: diffName,
4444
}
45-
dummyProjectID = "projectId"
45+
dummyProjectID = "6575af27f93c7a6a4b50b239"
4646
)
4747

4848
func TestGetProjectPropsFromAPI(t *testing.T) {
@@ -418,6 +418,59 @@ func TestUpdateProjectTeams(t *testing.T) {
418418
}
419419
}
420420

421+
func TestResourceProjectDependentsDeletingRefreshFunc(t *testing.T) {
422+
testCases := []struct {
423+
name string
424+
mockResponses ProjectResponse
425+
expectedError bool
426+
}{
427+
{
428+
name: "Error not from the API",
429+
mockResponses: ProjectResponse{
430+
clusterReponse: &admin.PaginatedAdvancedClusterDescription{},
431+
Err: errors.New("Non-API error"),
432+
},
433+
expectedError: true,
434+
},
435+
{
436+
name: "Error from the API",
437+
mockResponses: ProjectResponse{
438+
clusterReponse: &admin.PaginatedAdvancedClusterDescription{},
439+
Err: &admin.GenericOpenAPIError{},
440+
},
441+
expectedError: true,
442+
},
443+
{
444+
name: "Successful API call",
445+
mockResponses: ProjectResponse{
446+
clusterReponse: &admin.PaginatedAdvancedClusterDescription{
447+
TotalCount: conversion.IntPtr(2),
448+
Results: []admin.AdvancedClusterDescription{
449+
{StateName: conversion.StringPtr("IDLE")},
450+
{StateName: conversion.StringPtr("DELETING")},
451+
},
452+
},
453+
Err: nil,
454+
},
455+
expectedError: false,
456+
},
457+
}
458+
459+
for _, tc := range testCases {
460+
t.Run(tc.name, func(t *testing.T) {
461+
testObject := new(MockProjectService)
462+
463+
testObject.On("ListClusters", mock.Anything, dummyProjectID).Return(tc.mockResponses)
464+
465+
_, _, err := project.ResourceProjectDependentsDeletingRefreshFunc(context.Background(), dummyProjectID, testObject)()
466+
467+
if (err != nil) != tc.expectedError {
468+
t.Errorf("Case %s: Received unexpected error: %v", tc.name, err)
469+
}
470+
})
471+
}
472+
}
473+
421474
func TestAccProjectRSProject_basic(t *testing.T) {
422475
var (
423476
group admin.Group
@@ -901,10 +954,17 @@ func (a *MockProjectService) AddAllTeamsToProject(ctx context.Context, groupID s
901954
return response.ProjectTeamResp, response.HTTPResponse, response.Err
902955
}
903956

957+
func (a *MockProjectService) ListClusters(ctx context.Context, groupID string) (*admin.PaginatedAdvancedClusterDescription, *http.Response, error) {
958+
args := a.Called(ctx, groupID)
959+
var response = args.Get(0).(ProjectResponse)
960+
return response.clusterReponse, response.HTTPResponse, response.Err
961+
}
962+
904963
type ProjectResponse struct {
905964
ProjectResp *admin.Group
906965
ProjectTeamResp *admin.PaginatedTeamRole
907966
GroupSettingsResponse *admin.GroupSettings
967+
clusterReponse *admin.PaginatedAdvancedClusterDescription
908968
HTTPResponse *http.Response
909969
Err error
910970
LimitResponse admin.DataFederationLimit

internal/service/project/service_project.go

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type GroupProjectService interface {
1717
RemoveProjectTeam(ctx context.Context, groupID, teamID string) (*http.Response, error)
1818
UpdateTeamRoles(ctx context.Context, groupID, teamID string, teamRole *admin.TeamRole) (*admin.PaginatedTeamRole, *http.Response, error)
1919
AddAllTeamsToProject(ctx context.Context, groupID string, teamRole *[]admin.TeamRole) (*admin.PaginatedTeamRole, *http.Response, error)
20+
ListClusters(ctx context.Context, groupID string) (*admin.PaginatedAdvancedClusterDescription, *http.Response, error)
2021
}
2122

2223
type GroupProjectServiceFromClient struct {
@@ -60,6 +61,10 @@ func (a *GroupProjectServiceFromClient) AddAllTeamsToProject(ctx context.Context
6061
return a.client.TeamsApi.AddAllTeamsToProject(ctx, groupID, teamRole).Execute()
6162
}
6263

64+
func (a *GroupProjectServiceFromClient) ListClusters(ctx context.Context, groupID string) (*admin.PaginatedAdvancedClusterDescription, *http.Response, error) {
65+
return a.client.ClustersApi.ListClusters(ctx, groupID).Execute()
66+
}
67+
6368
func ServiceFromClient(client *admin.APIClient) GroupProjectService {
6469
return &GroupProjectServiceFromClient{
6570
client: client,

0 commit comments

Comments
 (0)