Skip to content

Commit 21f6118

Browse files
authored
Merge pull request #1851 from hashicorp/TF-7331-workspace-tags
Preserve workspace tags on first apply
2 parents 2f004e7 + f14bae6 commit 21f6118

File tree

3 files changed

+139
-14
lines changed

3 files changed

+139
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## Unreleased
22

3+
BUG FIXES:
4+
* `r/tfe_workspace_settings`: Prevent unintended clearing of workspace-level tags on the first apply when tags is unset by making tag updates sparse. By @shwetamurali [#1851](https://github.com/hashicorp/terraform-provider-tfe/pull/1851)
5+
36
## v0.69.0
47

58
BREAKING CHANGES:

internal/provider/resource_tfe_workspace_settings.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -513,20 +513,24 @@ func (r *workspaceSettings) updateSettings(ctx context.Context, data *modelWorks
513513
updateOptions.ExecutionMode = tfe.String("remote")
514514
}
515515

516-
tags := data.Tags.Elements()
517-
for key, val := range tags {
518-
if strVal, ok := val.(types.String); ok && !strVal.IsNull() {
519-
updateOptions.TagBindings = append(updateOptions.TagBindings, &tfe.TagBinding{
520-
Key: key,
521-
Value: strVal.ValueString(),
522-
})
523-
}
524-
}
525-
526-
if len(tags) == 0 {
527-
err := r.config.Client.Workspaces.DeleteAllTagBindings(ctx, workspaceID)
528-
if err != nil {
529-
return fmt.Errorf("error removing tag bindings from workspace %s: %w", workspaceID, err)
516+
if !data.Tags.IsNull() && !data.Tags.IsUnknown() {
517+
tags := data.Tags.Elements()
518+
519+
switch {
520+
case len(tags) == 0:
521+
if err := r.config.Client.Workspaces.DeleteAllTagBindings(ctx, workspaceID); err != nil {
522+
return fmt.Errorf("error removing tag bindings from workspace %s: %w", workspaceID, err)
523+
}
524+
default:
525+
for key, val := range tags {
526+
strVal, ok := val.(types.String)
527+
if ok && !strVal.IsNull() && !strVal.IsUnknown() {
528+
updateOptions.TagBindings = append(updateOptions.TagBindings, &tfe.TagBinding{
529+
Key: key,
530+
Value: strVal.ValueString(),
531+
})
532+
}
533+
}
530534
}
531535
}
532536

internal/provider/resource_tfe_workspace_settings_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,3 +594,121 @@ resource "tfe_workspace_settings" "test" {
594594
}
595595
`
596596
}
597+
598+
func TestAccTFEWorkspaceSettings_preservesWorkspaceTagsOnFirstApply(t *testing.T) {
599+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
600+
601+
configStep := fmt.Sprintf(`
602+
resource "tfe_organization" "test" {
603+
name = "tst-tfeprovider-%d"
604+
605+
}
606+
607+
resource "tfe_project" "test" {
608+
organization = tfe_organization.test.name
609+
name = "tfe-provider-test-%d"
610+
tags = { projectTag = "valueA" }
611+
}
612+
613+
resource "tfe_workspace" "test" {
614+
name = "tfe-provider-test-workspace-%d"
615+
organization = tfe_organization.test.name
616+
project_id = tfe_project.test.id
617+
tags = { app = "web" } # workspace-level tag
618+
}
619+
620+
resource "tfe_workspace_settings" "test" {
621+
workspace_id = tfe_workspace.test.id
622+
}
623+
`, rInt, rInt, rInt)
624+
625+
resource.Test(t, resource.TestCase{
626+
PreCheck: func() { testAccPreCheck(t) },
627+
ProtoV6ProviderFactories: testAccMuxedProviders,
628+
Steps: []resource.TestStep{
629+
{
630+
Config: configStep,
631+
Check: resource.ComposeTestCheckFunc(
632+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.%", "2"),
633+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.projectTag", "valueA"),
634+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.app", "web"),
635+
),
636+
},
637+
},
638+
})
639+
}
640+
641+
func TestAccTFEWorkspaceSettings_explicitEmptyClearsWorkspaceTags(t *testing.T) {
642+
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
643+
644+
configStep1 := fmt.Sprintf(`
645+
resource "tfe_organization" "test" {
646+
name = "tst-tfeprovider-%d"
647+
648+
}
649+
650+
resource "tfe_project" "test" {
651+
organization = tfe_organization.test.name
652+
name = "tfe-provider-test-%d"
653+
tags = { projectTag = "valueA" }
654+
}
655+
656+
resource "tfe_workspace" "test" {
657+
name = "tfe-provider-test-workspace-%d"
658+
organization = tfe_organization.test.name
659+
project_id = tfe_project.test.id
660+
tags = { app = "web" } # workspace-level tag
661+
}
662+
663+
resource "tfe_workspace_settings" "test" {
664+
workspace_id = tfe_workspace.test.id
665+
}
666+
`, rInt, rInt, rInt)
667+
668+
configStep2 := fmt.Sprintf(`
669+
resource "tfe_organization" "test" {
670+
name = "tst-tfeprovider-%d"
671+
672+
}
673+
674+
resource "tfe_project" "test" {
675+
organization = tfe_organization.test.name
676+
name = "tfe-provider-test-%d"
677+
tags = { projectTag = "valueA" }
678+
}
679+
680+
resource "tfe_workspace" "test" {
681+
name = "tfe-provider-test-workspace-%d"
682+
organization = tfe_organization.test.name
683+
project_id = tfe_project.test.id
684+
}
685+
686+
resource "tfe_workspace_settings" "test" {
687+
workspace_id = tfe_workspace.test.id
688+
tags = {}
689+
}
690+
`, rInt, rInt, rInt)
691+
692+
resource.Test(t, resource.TestCase{
693+
PreCheck: func() { testAccPreCheck(t) },
694+
ProtoV6ProviderFactories: testAccMuxedProviders,
695+
Steps: []resource.TestStep{
696+
{
697+
Config: configStep1,
698+
Check: resource.ComposeTestCheckFunc(
699+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.%", "2"),
700+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.projectTag", "valueA"),
701+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.app", "web"),
702+
),
703+
},
704+
{
705+
Config: configStep2,
706+
Check: resource.ComposeTestCheckFunc(
707+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.%", "1"),
708+
resource.TestCheckResourceAttr("tfe_workspace_settings.test", "effective_tags.projectTag", "valueA"),
709+
resource.TestCheckNoResourceAttr("tfe_workspace_settings.test", "effective_tags.app"),
710+
),
711+
},
712+
},
713+
})
714+
}

0 commit comments

Comments
 (0)