Skip to content

Commit 217fe8d

Browse files
authored
fix: read ws before creating tfe_workspace_settings (#1795)
* fix: read ws before create settings During create, the default boolean values coming from the model can easily overwrite the values that were set on the tfe_workspace. The solution is to read the workspace before creating the settings resource so that the state is set correctly. * chore: prep for 0.68.2 release * fix underscores in variable names
1 parent e4f3261 commit 217fe8d

File tree

6 files changed

+104
-8
lines changed

6 files changed

+104
-8
lines changed

CHANGELOG.md

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

3+
## v0.68.2
4+
5+
BUG FIXES:
6+
7+
* `r/tfe_workspace_settings`: during create, true boolean values set on tfe_workspace can be overwritten if omitted from tfe_workspace_settings config. [#1795](https://github.com/hashicorp/terraform-provider-tfe/pull/1795)
8+
39
## v0.68.1
410

511
BUG FIXES:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Declare the provider in your configuration and `terraform init` will automatical
2828
terraform {
2929
required_providers {
3030
tfe = {
31-
version = "~> 0.68.1"
31+
version = "~> 0.68.2"
3232
}
3333
}
3434
}

internal/provider/resource_tfe_workspace_settings.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
2323
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
2424
"github.com/hashicorp/terraform-plugin-framework/types"
25+
"github.com/hashicorp/terraform-plugin-log/tflog"
2526
)
2627

2728
// tfe_workspace_settings resource
@@ -621,10 +622,52 @@ func (r *workspaceSettings) addAndRemoveRemoteStateConsumers(workspaceID string,
621622
}
622623

623624
func (r *workspaceSettings) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
624-
var data modelWorkspaceSettings
625-
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
625+
var workspaceID string
626+
resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("workspace_id"), &workspaceID)...)
627+
if resp.Diagnostics.HasError() {
628+
return
629+
}
626630

627-
if err := r.updateSettings(ctx, &data, &resp.State); err != nil {
631+
// Start by reading the current settings of the workspace so we don't overwrite them with defaults
632+
model, err := r.readSettings(ctx, workspaceID)
633+
if err != nil {
634+
resp.Diagnostics.AddError("Error reading workspace", fmt.Sprintf("Could not read workspace %s: %s", workspaceID, err.Error()))
635+
}
636+
637+
planned := modelWorkspaceSettings{}
638+
resp.Diagnostics.Append(req.Config.Get(ctx, &planned)...)
639+
640+
var autoApply types.Bool
641+
var assessmentsEnabled types.Bool
642+
var globalRemoteState types.Bool
643+
644+
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("auto_apply"), &autoApply)...)
645+
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("assessments_enabled"), &assessmentsEnabled)...)
646+
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("global_remote_state"), &globalRemoteState)...)
647+
648+
if resp.Diagnostics.HasError() {
649+
return
650+
}
651+
652+
// Prefer the read value if there is no config value
653+
if autoApply.IsNull() {
654+
tflog.Debug(ctx, fmt.Sprintf("auto_apply is not set in config, overwrite with the read value %v", model.AutoApply.ValueBool()))
655+
planned.AutoApply = model.AutoApply
656+
}
657+
if assessmentsEnabled.IsNull() {
658+
tflog.Debug(ctx, fmt.Sprintf("assessments_enabled is not set in config, overwrite with the read value %v", model.AssessmentsEnabled.ValueBool()))
659+
planned.AssessmentsEnabled = model.AssessmentsEnabled
660+
}
661+
if globalRemoteState.IsNull() {
662+
tflog.Debug(ctx, fmt.Sprintf("global_remote_state is not set in config, overwrite with the read value %v", model.GlobalRemoteState.ValueBool()))
663+
planned.GlobalRemoteState = model.GlobalRemoteState
664+
}
665+
666+
if resp.Diagnostics.HasError() {
667+
return
668+
}
669+
670+
if err := r.updateSettings(ctx, &planned, &resp.State); err != nil {
628671
resp.Diagnostics.AddError("Error updating workspace", err.Error())
629672
}
630673
}

internal/provider/resource_tfe_workspace_settings_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,39 @@ func TestAccTFEWorkspaceSettings_stateSharing(t *testing.T) {
126126
})
127127
}
128128

129+
func TestAccTFEWorkspaceSettings_overlappingBooleans(t *testing.T) {
130+
tfeClient, err := getClientUsingEnv()
131+
if err != nil {
132+
t.Fatal(err)
133+
}
134+
135+
org, cleanupOrg := createBusinessOrganization(t, tfeClient)
136+
t.Cleanup(cleanupOrg)
137+
138+
resource.Test(t, resource.TestCase{
139+
PreCheck: func() { testAccPreCheck(t) },
140+
ProtoV5ProviderFactories: testAccMuxedProviders,
141+
Steps: []resource.TestStep{
142+
// Start with local execution
143+
{
144+
Config: testAccTFEWorkspaceSettingsOverlappingBooleans(org.Name),
145+
Check: resource.ComposeTestCheckFunc(
146+
resource.TestCheckResourceAttrSet(
147+
"tfe_workspace.name", "id"),
148+
resource.TestCheckResourceAttr(
149+
"tfe_workspace.name", "auto_apply", "true"),
150+
resource.TestCheckResourceAttr(
151+
"tfe_workspace.name", "assessments_enabled", "false"),
152+
resource.TestCheckResourceAttr(
153+
"tfe_workspace_settings.self", "auto_apply", "true"),
154+
resource.TestCheckResourceAttr(
155+
"tfe_workspace_settings.self", "assessments_enabled", "false"),
156+
),
157+
},
158+
},
159+
})
160+
}
161+
129162
func TestAccTFEWorkspaceSettings_basicOptions(t *testing.T) {
130163
tfeClient, err := getClientUsingEnv()
131164
if err != nil {
@@ -391,6 +424,20 @@ func testAccCheckTFEWorkspaceSettingsDestroy(s *terraform.State) error {
391424
return nil
392425
}
393426

427+
func testAccTFEWorkspaceSettingsOverlappingBooleans(orgName string) string {
428+
return fmt.Sprintf(`
429+
resource "tfe_workspace_settings" "self" {
430+
workspace_id = tfe_workspace.name.id
431+
}
432+
433+
resource "tfe_workspace" "name" {
434+
organization = "%s"
435+
name="permanent_auto_apply_drift"
436+
auto_apply = true
437+
}
438+
`, orgName)
439+
}
440+
394441
func testAccTFEWorkspaceSettingsUnknownIDRemoteState(orgName string) string {
395442
return fmt.Sprintf(`
396443
resource "tfe_workspace" "foobar1" {

version/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.68.1
1+
0.68.2

website/docs/index.html.markdown

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ automatically installed by `terraform init` in the future:
7474
terraform {
7575
required_providers {
7676
tfe = {
77-
version = "~> 0.68.1"
77+
version = "~> 0.68.2"
7878
}
7979
}
8080
}
@@ -87,7 +87,7 @@ The above snippet using `required_providers` is for Terraform 0.13+; if you are
8787

8888
```hcl
8989
provider "tfe" {
90-
version = "~> 0.68.1"
90+
version = "~> 0.68.2"
9191
...
9292
}
9393
```
@@ -100,7 +100,7 @@ For more information on provider installation and constraining provider versions
100100
provider "tfe" {
101101
hostname = var.hostname # Optional, defaults to HCP Terraform `app.terraform.io`
102102
token = var.token
103-
version = "~> 0.68.1"
103+
version = "~> 0.68.2"
104104
}
105105
106106
# Create an organization

0 commit comments

Comments
 (0)