Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_cloudfront_distribution: IllegalUpdate test #33578

Merged
merged 10 commits into from
Sep 27, 2023
81 changes: 73 additions & 8 deletions internal/service/cloudfront/continuous_deployment_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,9 @@ func (r *resourceContinuousDeploymentPolicy) Delete(ctx context.Context, req res
return
}

in := &cloudfront.DeleteContinuousDeploymentPolicyInput{
Id: aws.String(state.ID.ValueString()),
IfMatch: aws.String(state.ETag.ValueString()),
}
err := DeleteCDP(ctx, conn, state.ID.ValueString())

_, err := conn.DeleteContinuousDeploymentPolicyWithContext(ctx, in)
if err != nil {
if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchContinuousDeploymentPolicy) {
return
}
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.CloudFront, create.ErrActionDeleting, ResNameContinuousDeploymentPolicy, state.ID.String(), err),
err.Error(),
Expand All @@ -289,6 +282,78 @@ func (r *resourceContinuousDeploymentPolicy) Delete(ctx context.Context, req res
}
}

func DeleteCDP(ctx context.Context, conn *cloudfront.CloudFront, id string) error {
etag, err := cdpETag(ctx, conn, id)
if tfresource.NotFound(err) {
return nil
}

if err != nil {
return err
}

in := &cloudfront.DeleteContinuousDeploymentPolicyInput{
Id: aws.String(id),
IfMatch: etag,
}

_, err = conn.DeleteContinuousDeploymentPolicyWithContext(ctx, in)
if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchContinuousDeploymentPolicy) {
return nil
}

if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodePreconditionFailed, cloudfront.ErrCodeInvalidIfMatchVersion) {
etag, err := cdpETag(ctx, conn, id)
if tfresource.NotFound(err) {
return nil
}

if err != nil {
return err
}

in.SetIfMatch(aws.StringValue(etag))

_, err = conn.DeleteContinuousDeploymentPolicyWithContext(ctx, in)
if tfawserr.ErrCodeEquals(err, cloudfront.ErrCodeNoSuchContinuousDeploymentPolicy) {
return nil
}
}

return err
}

func disableContinuousDeploymentPolicy(ctx context.Context, conn *cloudfront.CloudFront, id string) error {
out, err := FindContinuousDeploymentPolicyByID(ctx, conn, id)
if tfresource.NotFound(err) || out == nil || out.ContinuousDeploymentPolicy == nil || out.ContinuousDeploymentPolicy.ContinuousDeploymentPolicyConfig == nil {
return nil
}

if !aws.BoolValue(out.ContinuousDeploymentPolicy.ContinuousDeploymentPolicyConfig.Enabled) {
return nil
}

out.ContinuousDeploymentPolicy.ContinuousDeploymentPolicyConfig.SetEnabled(false)

in := &cloudfront.UpdateContinuousDeploymentPolicyInput{
Id: out.ContinuousDeploymentPolicy.Id,
IfMatch: out.ETag,
ContinuousDeploymentPolicyConfig: out.ContinuousDeploymentPolicy.ContinuousDeploymentPolicyConfig,
}

_, err = conn.UpdateContinuousDeploymentPolicyWithContext(ctx, in)
return err
}

func cdpETag(ctx context.Context, conn *cloudfront.CloudFront, id string) (*string, error) {
output, err := FindContinuousDeploymentPolicyByID(ctx, conn, id)
if err != nil {
return nil, err
}

return output.ETag, nil
}

func (r *resourceContinuousDeploymentPolicy) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
Expand Down
134 changes: 107 additions & 27 deletions internal/service/cloudfront/continuous_deployment_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/aws/aws-sdk-go/service/cloudfront"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
Expand All @@ -20,6 +21,10 @@ import (
"github.com/hashicorp/terraform-provider-aws/names"
)

const (
defaultDomain = "www.example.com"
)

func TestAccCloudFrontContinuousDeploymentPolicy_basic(t *testing.T) {
ctx := acctest.Context(t)
var policy cloudfront.GetContinuousDeploymentPolicyOutput
Expand All @@ -39,7 +44,7 @@ func TestAccCloudFrontContinuousDeploymentPolicy_basic(t *testing.T) {
CheckDestroy: testAccCheckContinuousDeploymentPolicyDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccContinuousDeploymentPolicyConfig_init(),
Config: testAccContinuousDeploymentPolicyConfig_init(defaultDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionExists(ctx, stagingDistributionResourceName, &stagingDistribution),
testAccCheckDistributionExists(ctx, productionDistributionResourceName, &productionDistribution),
Expand Down Expand Up @@ -93,7 +98,7 @@ func TestAccCloudFrontContinuousDeploymentPolicy_disappears(t *testing.T) {
CheckDestroy: testAccCheckContinuousDeploymentPolicyDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccContinuousDeploymentPolicyConfig_init(),
Config: testAccContinuousDeploymentPolicyConfig_init(defaultDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionExists(ctx, stagingDistributionResourceName, &stagingDistribution),
testAccCheckDistributionExists(ctx, productionDistributionResourceName, &productionDistribution),
Expand Down Expand Up @@ -125,15 +130,15 @@ func TestAccCloudFrontContinuousDeploymentPolicy_trafficConfig(t *testing.T) {
CheckDestroy: testAccCheckContinuousDeploymentPolicyDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccContinuousDeploymentPolicyConfig_init(),
Config: testAccContinuousDeploymentPolicyConfig_init(defaultDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionExists(ctx, stagingDistributionResourceName, &stagingDistribution),
testAccCheckDistributionExists(ctx, productionDistributionResourceName, &productionDistribution),
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
),
},
{
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(false, "0.01", 300, 600),
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(false, "0.01", 300, 600, defaultDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "enabled", "false"),
Expand All @@ -153,7 +158,7 @@ func TestAccCloudFrontContinuousDeploymentPolicy_trafficConfig(t *testing.T) {
ImportStateVerify: true,
},
{
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(true, "0.02", 600, 1200),
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(true, "0.02", 600, 1200, defaultDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
Expand Down Expand Up @@ -202,6 +207,81 @@ func TestAccCloudFrontContinuousDeploymentPolicy_trafficConfig(t *testing.T) {
})
}

// https://github.com/hashicorp/terraform-provider-aws/issues/33338
func TestAccCloudFrontContinuousDeploymentPolicy_domainChange(t *testing.T) {
ctx := acctest.Context(t)
var policy cloudfront.GetContinuousDeploymentPolicyOutput
var stagingDistribution cloudfront.Distribution
var productionDistribution cloudfront.Distribution
resourceName := "aws_cloudfront_continuous_deployment_policy.test"
stagingDistributionResourceName := "aws_cloudfront_distribution.staging"
productionDistributionResourceName := "aws_cloudfront_distribution.test"
domain1 := fmt.Sprintf("%s.example.com", sdkacctest.RandomWithPrefix(acctest.ResourcePrefix))
domain2 := fmt.Sprintf("%s.example.com", sdkacctest.RandomWithPrefix(acctest.ResourcePrefix))

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, cloudfront.EndpointsID)
},
ErrorCheck: acctest.ErrorCheck(t, cloudfront.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckContinuousDeploymentPolicyDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccContinuousDeploymentPolicyConfig_init(domain1),
Check: resource.ComposeTestCheckFunc(
testAccCheckDistributionExists(ctx, stagingDistributionResourceName, &stagingDistribution),
testAccCheckDistributionExists(ctx, productionDistributionResourceName, &productionDistribution),
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
),
},
{
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(true, "0.01", 300, 600, domain1),
Check: resource.ComposeTestCheckFunc(
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "traffic_config.*", map[string]string{
"type": "SingleWeight",
"single_weight_config.#": "1",
"single_weight_config.0.weight": "0.01",
"single_weight_config.0.session_stickiness_config.#": "1",
"single_weight_config.0.session_stickiness_config.0.idle_ttl": "300",
"single_weight_config.0.session_stickiness_config.0.maximum_ttl": "600",
}),
resource.TestCheckTypeSetElemNestedAttrs(stagingDistributionResourceName, "origin.*", map[string]string{
"domain_name": domain1,
}),
resource.TestCheckTypeSetElemNestedAttrs(productionDistributionResourceName, "origin.*", map[string]string{
"domain_name": domain1,
}),
),
},
{
Config: testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(true, "0.01", 300, 600, domain2),
Check: resource.ComposeTestCheckFunc(
testAccCheckContinuousDeploymentPolicyExists(ctx, resourceName, &policy),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "traffic_config.*", map[string]string{
"type": "SingleWeight",
"single_weight_config.#": "1",
"single_weight_config.0.weight": "0.01",
"single_weight_config.0.session_stickiness_config.#": "1",
"single_weight_config.0.session_stickiness_config.0.idle_ttl": "300",
"single_weight_config.0.session_stickiness_config.0.maximum_ttl": "600",
}),
resource.TestCheckTypeSetElemNestedAttrs(stagingDistributionResourceName, "origin.*", map[string]string{
"domain_name": domain2,
}),
resource.TestCheckTypeSetElemNestedAttrs(productionDistributionResourceName, "origin.*", map[string]string{
"domain_name": domain2,
}),
),
},
},
})
}

func testAccCheckContinuousDeploymentPolicyDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).CloudFrontConn(ctx)
Expand Down Expand Up @@ -249,8 +329,8 @@ func testAccCheckContinuousDeploymentPolicyExists(ctx context.Context, name stri
}
}

func testAccContinuousDeploymentPolicyConfigBase_staging() string {
return `
func testAccContinuousDeploymentPolicyConfigBase_staging(domain string) string {
return fmt.Sprintf(`
resource "aws_cloudfront_distribution" "staging" {
enabled = true
retain_on_delete = false
Expand All @@ -272,7 +352,7 @@ resource "aws_cloudfront_distribution" "staging" {
}

origin {
domain_name = "www.example.com"
domain_name = %[1]q
origin_id = "test"

custom_origin_config {
Expand All @@ -293,15 +373,15 @@ resource "aws_cloudfront_distribution" "staging" {
cloudfront_default_certificate = true
}
}
`
`, domain)
}

// The initial production distribution must be created _without_ the continuous
// deployment policy attached. Example error:
//
// InvalidArgument: Continuous deployment policy is not supported during distribution creation.
func testAccContinuousDeploymentPolicyConfigBase_productionInit() string {
return `
func testAccContinuousDeploymentPolicyConfigBase_productionInit(domain string) string {
return fmt.Sprintf(`
resource "aws_cloudfront_distribution" "test" {
enabled = true
retain_on_delete = false
Expand All @@ -322,7 +402,7 @@ resource "aws_cloudfront_distribution" "test" {
}

origin {
domain_name = "www.example.com"
domain_name = %[1]q
origin_id = "test"

custom_origin_config {
Expand All @@ -343,11 +423,11 @@ resource "aws_cloudfront_distribution" "test" {
cloudfront_default_certificate = true
}
}
`
`, domain)
}

func testAccContinuousDeploymentPolicyConfigBase_production() string {
return `
func testAccContinuousDeploymentPolicyConfigBase_production(domain string) string {
return fmt.Sprintf(`
resource "aws_cloudfront_distribution" "test" {
enabled = true
retain_on_delete = false
Expand All @@ -370,7 +450,7 @@ resource "aws_cloudfront_distribution" "test" {
}

origin {
domain_name = "www.example.com"
domain_name = %[1]q
origin_id = "test"

custom_origin_config {
Expand All @@ -391,7 +471,7 @@ resource "aws_cloudfront_distribution" "test" {
cloudfront_default_certificate = true
}
}
`
`, domain)
}

// testAccContinuousDeploymentPolicyConfig_init initializes the staging and production
Expand All @@ -405,10 +485,10 @@ resource "aws_cloudfront_distribution" "test" {
//
// ContinuousDeploymentPolicyInUse: The specified continuous deployment policy is
// currently associated with a distribution.
func testAccContinuousDeploymentPolicyConfig_init() string {
func testAccContinuousDeploymentPolicyConfig_init(domain string) string {
return acctest.ConfigCompose(
testAccContinuousDeploymentPolicyConfigBase_staging(),
testAccContinuousDeploymentPolicyConfigBase_productionInit(),
testAccContinuousDeploymentPolicyConfigBase_staging(domain),
testAccContinuousDeploymentPolicyConfigBase_productionInit(domain),
`
resource "aws_cloudfront_continuous_deployment_policy" "test" {
enabled = false
Expand All @@ -430,8 +510,8 @@ resource "aws_cloudfront_continuous_deployment_policy" "test" {

func testAccContinuousDeploymentPolicyConfig_basic() string {
return acctest.ConfigCompose(
testAccContinuousDeploymentPolicyConfigBase_staging(),
testAccContinuousDeploymentPolicyConfigBase_production(),
testAccContinuousDeploymentPolicyConfigBase_staging(defaultDomain),
testAccContinuousDeploymentPolicyConfigBase_production(defaultDomain),
`
resource "aws_cloudfront_continuous_deployment_policy" "test" {
enabled = false
Expand All @@ -451,10 +531,10 @@ resource "aws_cloudfront_continuous_deployment_policy" "test" {
`)
}

func testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(enabled bool, weight string, idleTTL, maxTTL int) string {
func testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleWeight(enabled bool, weight string, idleTTL, maxTTL int, domain string) string {
return acctest.ConfigCompose(
testAccContinuousDeploymentPolicyConfigBase_staging(),
testAccContinuousDeploymentPolicyConfigBase_production(),
testAccContinuousDeploymentPolicyConfigBase_staging(domain),
testAccContinuousDeploymentPolicyConfigBase_production(domain),
fmt.Sprintf(`
resource "aws_cloudfront_continuous_deployment_policy" "test" {
enabled = %[1]t
Expand All @@ -480,8 +560,8 @@ resource "aws_cloudfront_continuous_deployment_policy" "test" {

func testAccContinuousDeploymentPolicyConfig_TrafficConfig_singleHeader(enabled bool, header, value string) string {
return acctest.ConfigCompose(
testAccContinuousDeploymentPolicyConfigBase_staging(),
testAccContinuousDeploymentPolicyConfigBase_production(),
testAccContinuousDeploymentPolicyConfigBase_staging(defaultDomain),
testAccContinuousDeploymentPolicyConfigBase_production(defaultDomain),
fmt.Sprintf(`
resource "aws_cloudfront_continuous_deployment_policy" "test" {
enabled = %[1]t
Expand Down
Loading
Loading