Skip to content

Commit 682f4b4

Browse files
committed
fix: prevent duplicate set element error in project data source
The GET /workspaces API call is ordered by run.created-at. It's possible that between retrieving the first page, and the next page that a workspace will appear on both pages. This then ultimately causes a 'Duplicate Set Element' error in the TF plan. This fix converts storing the API response as 2 lists to a single map, with the key being the workspace ID ensuring we overwrite any duplicates.
1 parent 8bb7be9 commit 682f4b4

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
## Unreleased
22

33
BUG FIXES:
4+
45
* `r/tfe_notification_configuration`: update url attribute to be sensitive, by @jillirami [#1799](https://github.com/hashicorp/terraform-provider-tfe/pull/1799)
6+
* `d/tfe_project`: fixes: 'duplicate set element' error, as pagination ordering is not guaranteed, by @lewis-catley [#1817](https://github.com/hashicorp/terraform-provider-tfe/pull/1817)
57

68
## v0.68.2
79

internal/provider/data_source_project.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type modelDataSourceTFEProject struct {
3939
EffectiveTags types.Map `tfsdk:"effective_tags"`
4040
}
4141

42-
func modelDataSourceFromTFEProject(p *tfe.Project, workspaceIDs, workspaceNames []string, effectiveTags []*tfe.EffectiveTagBinding) (modelDataSourceTFEProject, diag.Diagnostics) {
42+
func modelDataSourceFromTFEProject(p *tfe.Project, workspaces map[string]string, effectiveTags []*tfe.EffectiveTagBinding) (modelDataSourceTFEProject, diag.Diagnostics) {
4343
m := modelDataSourceTFEProject{
4444
ID: types.StringValue(p.ID),
4545
Name: types.StringValue(p.Name),
@@ -48,9 +48,9 @@ func modelDataSourceFromTFEProject(p *tfe.Project, workspaceIDs, workspaceNames
4848
}
4949

5050
var wids, wnames []attr.Value
51-
for w := range workspaceIDs {
52-
wids = append(wids, types.StringValue(workspaceIDs[w]))
53-
wnames = append(wnames, types.StringValue(workspaceNames[w]))
51+
for workspaceID, workspaceName := range workspaces {
52+
wids = append(wids, types.StringValue(workspaceID))
53+
wnames = append(wnames, types.StringValue(workspaceName))
5454
}
5555
m.WorkspaceIDs = types.SetValueMust(types.StringType, wids)
5656
m.WorkspaceNames = types.SetValueMust(types.StringType, wnames)
@@ -187,8 +187,9 @@ func (d *dataSourceTFEProject) Read(ctx context.Context, req datasource.ReadRequ
187187
ProjectID: proj.ID,
188188
}
189189

190-
var workspaceIDs []string
191-
var workspaceNames []string
190+
// Store GET /workspaces response in a map to ensure uniqueness
191+
// key: workspaceID, value: workspaceName
192+
var workspaces map[string]string
192193
for {
193194
wl, err := d.config.Client.Workspaces.List(ctx, organization, readOptions)
194195
if err != nil {
@@ -197,8 +198,7 @@ func (d *dataSourceTFEProject) Read(ctx context.Context, req datasource.ReadRequ
197198
}
198199

199200
for _, workspace := range wl.Items {
200-
workspaceIDs = append(workspaceIDs, workspace.ID)
201-
workspaceNames = append(workspaceNames, workspace.Name)
201+
workspaces[workspace.ID] = workspace.Name
202202
}
203203

204204
// Exit the loop when we've seen all pages.
@@ -221,7 +221,7 @@ func (d *dataSourceTFEProject) Read(ctx context.Context, req datasource.ReadRequ
221221
effectiveBindings = []*tfe.EffectiveTagBinding{}
222222
}
223223

224-
m, diags := modelDataSourceFromTFEProject(proj, workspaceIDs, workspaceNames, effectiveBindings)
224+
m, diags := modelDataSourceFromTFEProject(proj, workspaces, effectiveBindings)
225225
if diags.HasError() {
226226
resp.Diagnostics.Append(diags...)
227227
return

0 commit comments

Comments
 (0)