Skip to content

Commit

Permalink
Merge pull request #1737 from hashicorp/b-update-WriteOnly
Browse files Browse the repository at this point in the history
Correctly update write-only properties.
  • Loading branch information
ewbankkit committed May 22, 2024
2 parents a260e57 + 97d57b6 commit e715448
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ FEATURES:
* **New Resource:** `awscc_inspectorv2_cis_scan_configuration`
* **New Resource:** `awscc_qbusiness_data_source`

BUG FIXES:

* Fix `ValidationException: [REPLACE Operation] noSuchPath in source` errors on resource Update ([#1737](https://github.com/hashicorp/terraform-provider-awscc/issues/1737))

## 0.77.0 (May 16, 2024)

FEATURES:
Expand Down
16 changes: 14 additions & 2 deletions internal/acctest/testcases.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,25 @@ func (td TestData) ResourceTest(t *testing.T, steps []resource.TestStep) {
})
}

func (td TestData) ResourceTestNoProviderFactories(t *testing.T, steps []resource.TestStep) {
td.runAcceptanceTestNoProviderFactories(t, resource.TestCase{
PreCheck: func() { PreCheck(t) },
CheckDestroy: td.CheckDestroy(),
Steps: steps,
})
}

func (td TestData) runAcceptanceTest(t *testing.T, testCase resource.TestCase) {
testCase.ProtoV6ProviderFactories = td.providerFactories()
testCase.ProtoV6ProviderFactories = td.ProviderFactories()

resource.ParallelTest(t, testCase)
}

func (td TestData) runAcceptanceTestNoProviderFactories(t *testing.T, testCase resource.TestCase) {
resource.ParallelTest(t, testCase)
}

func (td TestData) providerFactories() map[string]func() (tfprotov6.ProviderServer, error) {
func (td TestData) ProviderFactories() map[string]func() (tfprotov6.ProviderServer, error) {
return map[string]func() (tfprotov6.ProviderServer, error){
"awscc": providerserver.NewProtocol6WithError(td.provider),
}
Expand Down
89 changes: 89 additions & 0 deletions internal/aws/ec2/launch_template_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package ec2_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-provider-awscc/internal/acctest"
)

func TestAccAWSEC2LaunchTemplate_update(t *testing.T) {
td := acctest.NewTestData(t, "AWS::EC2::LaunchTemplate", "awscc_ec2_launch_template", "test")
resourceName := td.ResourceName
rName := td.RandomName()
testExternalProviders := map[string]resource.ExternalProvider{
"aws": {
Source: "hashicorp/aws",
VersionConstraint: "~> 5.50",
},
}

td.ResourceTestNoProviderFactories(t, []resource.TestStep{
{
ProtoV6ProviderFactories: td.ProviderFactories(),
ExternalProviders: testExternalProviders,
Config: testAccAWSEC2LaunchTemplateInstanceTypeConfig(&td, rName, "t2.large"),
Check: resource.ComposeTestCheckFunc(
td.CheckExistsInAWS(),
resource.TestCheckResourceAttr(resourceName, "launch_template_data.instance_type", "t2.large"),
),
},
{
ProtoV6ProviderFactories: td.ProviderFactories(),
ExternalProviders: testExternalProviders,
ResourceName: td.ResourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"launch_template_data"},
},
{
ProtoV6ProviderFactories: td.ProviderFactories(),
ExternalProviders: testExternalProviders,
Config: testAccAWSEC2LaunchTemplateInstanceTypeConfig(&td, rName, "t3.large"),
Check: resource.ComposeTestCheckFunc(
td.CheckExistsInAWS(),
resource.TestCheckResourceAttr(resourceName, "launch_template_data.instance_type", "t3.large"),
),
},
})
}

func testAccAWSEC2LaunchTemplateInstanceTypeConfig(td *acctest.TestData, rName string, instanceType string) string {
return fmt.Sprintf(`
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-gp2"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
}
resource %[1]q %[2]q {
launch_template_data = {
image_id = data.aws_ami.amazon_linux.id
instance_type = %[4]q
}
launch_template_name = %[3]q
}
`, td.TerraformResourceType, td.ResourceLabel, rName, instanceType)
}
52 changes: 52 additions & 0 deletions internal/aws/iam/user_resource_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions internal/aws/secretsmanager/secret_resource_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion internal/generic/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
ccdiag "github.com/hashicorp/terraform-provider-awscc/internal/errs/diag"
tfcloudcontrol "github.com/hashicorp/terraform-provider-awscc/internal/service/cloudcontrol"
Expand Down Expand Up @@ -522,8 +523,37 @@ func (r *genericResource) Update(ctx context.Context, request resource.UpdateReq
return
}

// Clear any write-only values.
// This forces patch document generation to always add values.
currentStateRaw := currentState.Raw
if len(r.writeOnlyAttributePaths) > 0 {
currentStateRaw, err = tftypes.Transform(currentStateRaw, func(tfPath *tftypes.AttributePath, val tftypes.Value) (tftypes.Value, error) {
if len(tfPath.Steps()) < 1 {
return val, nil
}

path, diags := attributePath(ctx, tfPath, currentState.Schema)
if diags.HasError() {
return val, ccdiag.DiagnosticsError(diags)
}

for _, woPath := range r.writeOnlyAttributePaths {
if woPath.Equal(path) {
return tftypes.NewValue(val.Type(), nil), nil
}
}

return val, nil
})
if err != nil {
response.Diagnostics.Append(DesiredStateErrorDiag("Prior State", err))

return
}
}

translator := toCloudControl{tfToCfNameMap: r.tfToCfNameMap}
currentDesiredState, err := translator.AsString(ctx, currentState.Schema, currentState.Raw)
currentDesiredState, err := translator.AsString(ctx, currentState.Schema, currentStateRaw)

if err != nil {
response.Diagnostics.Append(DesiredStateErrorDiag("Prior State", err))
Expand Down

0 comments on commit e715448

Please sign in to comment.