diff --git a/internal/service/project/data_source_project.go b/internal/service/project/data_source_project.go index 94b7dce8ab..d788dc99d9 100644 --- a/internal/service/project/data_source_project.go +++ b/internal/service/project/data_source_project.go @@ -208,9 +208,13 @@ func (d *projectDS) Read(ctx context.Context, req datasource.ReadRequest, resp * return } - projectState = NewTFProjectDataSourceModel(ctx, project, *projectProps) + newProjectState, diags := NewTFProjectDataSourceModel(ctx, project, *projectProps) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } - resp.Diagnostics.Append(resp.State.Set(ctx, &projectState)...) + resp.Diagnostics.Append(resp.State.Set(ctx, &newProjectState)...) if resp.Diagnostics.HasError() { return } diff --git a/internal/service/project/data_source_projects.go b/internal/service/project/data_source_projects.go index d2fc5e9c56..78c7766b5b 100644 --- a/internal/service/project/data_source_projects.go +++ b/internal/service/project/data_source_projects.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" @@ -185,9 +186,9 @@ func (d *ProjectsDS) Read(ctx context.Context, req datasource.ReadRequest, resp return } - err = populateProjectsDataSourceModel(ctx, connV2, &stateModel, projectsRes) - if err != nil { - resp.Diagnostics.AddError("error in monogbatlas_projects data source", err.Error()) + diags := populateProjectsDataSourceModel(ctx, connV2, &stateModel, projectsRes) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { return } @@ -197,19 +198,23 @@ func (d *ProjectsDS) Read(ctx context.Context, req datasource.ReadRequest, resp } } -func populateProjectsDataSourceModel(ctx context.Context, connV2 *admin.APIClient, stateModel *tfProjectsDSModel, projectsRes *admin.PaginatedAtlasGroup) error { +func populateProjectsDataSourceModel(ctx context.Context, connV2 *admin.APIClient, stateModel *tfProjectsDSModel, projectsRes *admin.PaginatedAtlasGroup) diag.Diagnostics { + diagnostics := []diag.Diagnostic{} input := projectsRes.GetResults() results := make([]*TFProjectDSModel, 0, len(input)) for i := range input { project := input[i] projectProps, err := GetProjectPropsFromAPI(ctx, ServiceFromClient(connV2), project.GetId()) if err == nil { // if the project is still valid, e.g. could have just been deleted - projectModel := NewTFProjectDataSourceModel(ctx, &project, *projectProps) - results = append(results, &projectModel) + projectModel, diags := NewTFProjectDataSourceModel(ctx, &project, *projectProps) + diagnostics = append(diagnostics, diags...) + if projectModel != nil { + results = append(results, projectModel) + } } } stateModel.Results = results stateModel.TotalCount = types.Int64Value(int64(projectsRes.GetTotalCount())) stateModel.ID = types.StringValue(id.UniqueId()) - return nil + return diagnostics } diff --git a/internal/service/project/model_project.go b/internal/service/project/model_project.go index 9fbb08d28a..fdd53c1a72 100644 --- a/internal/service/project/model_project.go +++ b/internal/service/project/model_project.go @@ -3,15 +3,19 @@ package project import ( "context" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" "go.mongodb.org/atlas-sdk/v20231115004/admin" ) -func NewTFProjectDataSourceModel(ctx context.Context, project *admin.Group, projectProps AdditionalProperties) TFProjectDSModel { - ipAddressesModel := NewTFIPAddressesModel(ctx, projectProps.IPAddresses) +func NewTFProjectDataSourceModel(ctx context.Context, project *admin.Group, projectProps AdditionalProperties) (*TFProjectDSModel, diag.Diagnostics) { + ipAddressesModel, diags := NewTFIPAddressesModel(ctx, projectProps.IPAddresses) + if diags.HasError() { + return nil, diags + } projectSettings := projectProps.Settings - return TFProjectDSModel{ + return &TFProjectDSModel{ ID: types.StringValue(project.GetId()), ProjectID: types.StringValue(project.GetId()), Name: types.StringValue(project.Name), @@ -27,7 +31,7 @@ func NewTFProjectDataSourceModel(ctx context.Context, project *admin.Group, proj Teams: NewTFTeamsDataSourceModel(ctx, projectProps.Teams), Limits: NewTFLimitsDataSourceModel(ctx, projectProps.Limits), IPAddresses: ipAddressesModel, - } + }, nil } func NewTFTeamsDataSourceModel(ctx context.Context, atlasTeams *admin.PaginatedTeamRole) []*TFTeamDSModel { @@ -62,7 +66,7 @@ func NewTFLimitsDataSourceModel(ctx context.Context, dataFederationLimits []admi return limits } -func NewTFIPAddressesModel(ctx context.Context, ipAddresses *admin.GroupIPAddresses) types.Object { +func NewTFIPAddressesModel(ctx context.Context, ipAddresses *admin.GroupIPAddresses) (types.Object, diag.Diagnostics) { clusterIPs := []TFClusterIPsModel{} if ipAddresses != nil && ipAddresses.Services != nil { clusterIPAddresses := ipAddresses.Services.GetClusters() @@ -77,16 +81,19 @@ func NewTFIPAddressesModel(ctx context.Context, ipAddresses *admin.GroupIPAddres } } } - obj, _ := types.ObjectValueFrom(ctx, IPAddressesObjectType.AttrTypes, TFIPAddressesModel{ + obj, diags := types.ObjectValueFrom(ctx, IPAddressesObjectType.AttrTypes, TFIPAddressesModel{ Services: TFServicesModel{ Clusters: clusterIPs, }, }) - return obj + return obj, diags } -func NewTFProjectResourceModel(ctx context.Context, projectRes *admin.Group, projectProps AdditionalProperties) *TFProjectRSModel { - ipAddressesModel := NewTFIPAddressesModel(ctx, projectProps.IPAddresses) +func NewTFProjectResourceModel(ctx context.Context, projectRes *admin.Group, projectProps AdditionalProperties) (*TFProjectRSModel, diag.Diagnostics) { + ipAddressesModel, diags := NewTFIPAddressesModel(ctx, projectProps.IPAddresses) + if diags.HasError() { + return nil, diags + } projectPlan := TFProjectRSModel{ ID: types.StringValue(projectRes.GetId()), Name: types.StringValue(projectRes.Name), @@ -109,7 +116,7 @@ func NewTFProjectResourceModel(ctx context.Context, projectRes *admin.Group, pro projectPlan.IsSchemaAdvisorEnabled = types.BoolValue(*projectSettings.IsSchemaAdvisorEnabled) } - return &projectPlan + return &projectPlan, nil } func newTFLimitsResourceModel(ctx context.Context, dataFederationLimits []admin.DataFederationLimit) types.Set { diff --git a/internal/service/project/model_project_test.go b/internal/service/project/model_project_test.go index abd727d7eb..c1f55d44cf 100644 --- a/internal/service/project/model_project_test.go +++ b/internal/service/project/model_project_test.go @@ -234,7 +234,10 @@ func TestProjectDataSourceSDKToDataSourceTFModel(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - resultModel := project.NewTFProjectDataSourceModel(context.Background(), tc.project, tc.projectProps) + resultModel, diags := project.NewTFProjectDataSourceModel(context.Background(), tc.project, tc.projectProps) + if diags.HasError() { + t.Errorf("unexpected errors found: %s", diags.Errors()[0].Summary()) + } if !assert.Equal(t, tc.expectedTFModel, resultModel) { t.Errorf("created terraform model did not match expected output") } @@ -283,7 +286,10 @@ func TestProjectDataSourceSDKToResourceTFModel(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - resultModel := project.NewTFProjectResourceModel(context.Background(), tc.project, tc.projectProps) + resultModel, diags := project.NewTFProjectResourceModel(context.Background(), tc.project, tc.projectProps) + if diags.HasError() { + t.Errorf("unexpected errors found: %s", diags.Errors()[0].Summary()) + } if !assert.Equal(t, tc.expectedTFModel, *resultModel) { t.Errorf("created terraform model did not match expected output") } @@ -424,7 +430,10 @@ func TestIPAddressesModelToTF(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - resultModel := project.NewTFIPAddressesModel(context.Background(), tc.sdkModel) + resultModel, diags := project.NewTFIPAddressesModel(context.Background(), tc.sdkModel) + if diags.HasError() { + t.Errorf("unexpected errors found: %s", diags.Errors()[0].Summary()) + } if !assert.Equal(t, tc.expectedResult, resultModel) { t.Errorf("created terraform model did not match expected output") } diff --git a/internal/service/project/resource_project.go b/internal/service/project/resource_project.go index b5f02f4c8b..d0a5a3a70a 100644 --- a/internal/service/project/resource_project.go +++ b/internal/service/project/resource_project.go @@ -409,7 +409,11 @@ func (r *projectRS) Create(ctx context.Context, req resource.CreateRequest, resp filteredLimits := FilterUserDefinedLimits(projectProps.Limits, limits) projectProps.Limits = filteredLimits - projectPlanNew := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + projectPlanNew, diags := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } updatePlanFromConfig(projectPlanNew, &projectPlan) // set state to fully populated data @@ -457,7 +461,11 @@ func (r *projectRS) Read(ctx context.Context, req resource.ReadRequest, resp *re filteredLimits := FilterUserDefinedLimits(projectProps.Limits, limits) projectProps.Limits = filteredLimits - projectStateNew := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + projectStateNew, diags := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } updatePlanFromConfig(projectStateNew, &projectState) // save read data into Terraform state @@ -530,7 +538,11 @@ func (r *projectRS) Update(ctx context.Context, req resource.UpdateRequest, resp filteredLimits := FilterUserDefinedLimits(projectProps.Limits, planLimits) projectProps.Limits = filteredLimits - projectPlanNew := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + projectPlanNew, diags := NewTFProjectResourceModel(ctx, projectRes, *projectProps) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } updatePlanFromConfig(projectPlanNew, &projectPlan) // save updated data into Terraform state