Merge pull request #14463 from ewbankkit/issue-5653
Nothing to update in cloudformation should not result in errors
This commit is contained in:
commit
a53c8825a8
|
@ -398,9 +398,17 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Updating CloudFormation stack: %s", input)
|
log.Printf("[DEBUG] Updating CloudFormation stack: %s", input)
|
||||||
stack, err := conn.UpdateStack(input)
|
_, err := conn.UpdateStack(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
awsErr, ok := err.(awserr.Error)
|
||||||
|
// ValidationError: No updates are to be performed.
|
||||||
|
if !ok ||
|
||||||
|
awsErr.Code() != "ValidationError" ||
|
||||||
|
awsErr.Message() != "No updates are to be performed." {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Current CloudFormation stack has no updates")
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUpdatedTime, err := getLastCfEventTimestamp(d.Id(), conn)
|
lastUpdatedTime, err := getLastCfEventTimestamp(d.Id(), conn)
|
||||||
|
@ -416,6 +424,7 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var lastStatus string
|
var lastStatus string
|
||||||
|
var stackId string
|
||||||
wait := resource.StateChangeConf{
|
wait := resource.StateChangeConf{
|
||||||
Pending: []string{
|
Pending: []string{
|
||||||
"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
|
"UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
|
||||||
|
@ -424,6 +433,7 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
"UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
|
"UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
|
||||||
},
|
},
|
||||||
Target: []string{
|
Target: []string{
|
||||||
|
"CREATE_COMPLETE", // If no stack update was performed
|
||||||
"UPDATE_COMPLETE",
|
"UPDATE_COMPLETE",
|
||||||
"UPDATE_ROLLBACK_COMPLETE",
|
"UPDATE_ROLLBACK_COMPLETE",
|
||||||
"UPDATE_ROLLBACK_FAILED",
|
"UPDATE_ROLLBACK_FAILED",
|
||||||
|
@ -439,6 +449,8 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stackId = aws.StringValue(resp.Stacks[0].StackId)
|
||||||
|
|
||||||
status := *resp.Stacks[0].StackStatus
|
status := *resp.Stacks[0].StackStatus
|
||||||
lastStatus = status
|
lastStatus = status
|
||||||
log.Printf("[DEBUG] Current CloudFormation stack status: %q", status)
|
log.Printf("[DEBUG] Current CloudFormation stack status: %q", status)
|
||||||
|
@ -453,7 +465,7 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastStatus == "UPDATE_ROLLBACK_COMPLETE" || lastStatus == "UPDATE_ROLLBACK_FAILED" {
|
if lastStatus == "UPDATE_ROLLBACK_COMPLETE" || lastStatus == "UPDATE_ROLLBACK_FAILED" {
|
||||||
reasons, err := getCloudFormationRollbackReasons(*stack.StackId, lastUpdatedTime, conn)
|
reasons, err := getCloudFormationRollbackReasons(stackId, lastUpdatedTime, conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed getting details about rollback: %q", err.Error())
|
return fmt.Errorf("Failed getting details about rollback: %q", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -461,7 +473,7 @@ func resourceAwsCloudFormationStackUpdate(d *schema.ResourceData, meta interface
|
||||||
return fmt.Errorf("%s: %q", lastStatus, reasons)
|
return fmt.Errorf("%s: %q", lastStatus, reasons)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] CloudFormation stack %q has been updated", *stack.StackId)
|
log.Printf("[DEBUG] CloudFormation stack %q has been updated", stackId)
|
||||||
|
|
||||||
return resourceAwsCloudFormationStackRead(d, meta)
|
return resourceAwsCloudFormationStackRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,8 @@ func TestAccAWSCloudFormation_withParams(t *testing.T) {
|
||||||
// Regression for https://github.com/hashicorp/terraform/issues/4534
|
// Regression for https://github.com/hashicorp/terraform/issues/4534
|
||||||
func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) {
|
func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) {
|
||||||
var stack cloudformation.Stack
|
var stack cloudformation.Stack
|
||||||
|
cfRandInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
||||||
|
cfBucketName := fmt.Sprintf("tf-stack-with-url-and-params-%d", cfRandInt)
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -150,13 +152,13 @@ func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) {
|
||||||
CheckDestroy: testAccCheckAWSCloudFormationDestroy,
|
CheckDestroy: testAccCheckAWSCloudFormationDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
{
|
{
|
||||||
Config: testAccAWSCloudFormationConfig_templateUrl_withParams,
|
Config: testAccAWSCloudFormationConfig_templateUrl_withParams(cfBucketName, "tf-cf-stack.json", "11.0.0.0/16"),
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config: testAccAWSCloudFormationConfig_templateUrl_withParams_modified,
|
Config: testAccAWSCloudFormationConfig_templateUrl_withParams(cfBucketName, "tf-cf-stack.json", "13.0.0.0/16"),
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
||||||
),
|
),
|
||||||
|
@ -167,6 +169,8 @@ func TestAccAWSCloudFormation_withUrl_withParams(t *testing.T) {
|
||||||
|
|
||||||
func TestAccAWSCloudFormation_withUrl_withParams_withYaml(t *testing.T) {
|
func TestAccAWSCloudFormation_withUrl_withParams_withYaml(t *testing.T) {
|
||||||
var stack cloudformation.Stack
|
var stack cloudformation.Stack
|
||||||
|
cfRandInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
||||||
|
cfBucketName := fmt.Sprintf("tf-stack-with-url-and-params-%d", cfRandInt)
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
@ -174,7 +178,7 @@ func TestAccAWSCloudFormation_withUrl_withParams_withYaml(t *testing.T) {
|
||||||
CheckDestroy: testAccCheckAWSCloudFormationDestroy,
|
CheckDestroy: testAccCheckAWSCloudFormationDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
{
|
{
|
||||||
Config: testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml,
|
Config: testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml(cfBucketName, "tf-cf-stack.yaml", "13.0.0.0/16"),
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params-and-yaml", &stack),
|
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params-and-yaml", &stack),
|
||||||
),
|
),
|
||||||
|
@ -183,6 +187,33 @@ func TestAccAWSCloudFormation_withUrl_withParams_withYaml(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for https://github.com/hashicorp/terraform/issues/5653
|
||||||
|
func TestAccAWSCloudFormation_withUrl_withParams_noUpdate(t *testing.T) {
|
||||||
|
var stack cloudformation.Stack
|
||||||
|
cfRandInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
||||||
|
cfBucketName := fmt.Sprintf("tf-stack-with-url-and-params-%d", cfRandInt)
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckAWSCloudFormationDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccAWSCloudFormationConfig_templateUrl_withParams(cfBucketName, "tf-cf-stack-1.json", "11.0.0.0/16"),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccAWSCloudFormationConfig_templateUrl_withParams(cfBucketName, "tf-cf-stack-2.json", "11.0.0.0/16"),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckCloudFormationStackExists("aws_cloudformation_stack.with-url-and-params", &stack),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc {
|
func testAccCheckCloudFormationStackExists(n string, stack *cloudformation.Stack) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
@ -490,7 +521,8 @@ var testAccAWSCloudFormationConfig_withParams_modified = fmt.Sprintf(
|
||||||
tpl_testAccAWSCloudFormationConfig_withParams,
|
tpl_testAccAWSCloudFormationConfig_withParams,
|
||||||
"12.0.0.0/16")
|
"12.0.0.0/16")
|
||||||
|
|
||||||
var tpl_testAccAWSCloudFormationConfig_templateUrl_withParams = `
|
func testAccAWSCloudFormationConfig_templateUrl_withParams(bucketName, bucketKey, vpcCidr string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
resource "aws_s3_bucket" "b" {
|
resource "aws_s3_bucket" "b" {
|
||||||
bucket = "%s"
|
bucket = "%s"
|
||||||
acl = "public-read"
|
acl = "public-read"
|
||||||
|
@ -519,7 +551,7 @@ POLICY
|
||||||
|
|
||||||
resource "aws_s3_bucket_object" "object" {
|
resource "aws_s3_bucket_object" "object" {
|
||||||
bucket = "${aws_s3_bucket.b.id}"
|
bucket = "${aws_s3_bucket.b.id}"
|
||||||
key = "tf-cf-stack.json"
|
key = "%s"
|
||||||
source = "test-fixtures/cloudformation-template.json"
|
source = "test-fixtures/cloudformation-template.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,9 +564,11 @@ resource "aws_cloudformation_stack" "with-url-and-params" {
|
||||||
on_failure = "DELETE"
|
on_failure = "DELETE"
|
||||||
timeout_in_minutes = 1
|
timeout_in_minutes = 1
|
||||||
}
|
}
|
||||||
`
|
`, bucketName, bucketName, bucketKey, vpcCidr)
|
||||||
|
}
|
||||||
|
|
||||||
var tpl_testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml = `
|
func testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml(bucketName, bucketKey, vpcCidr string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
resource "aws_s3_bucket" "b" {
|
resource "aws_s3_bucket" "b" {
|
||||||
bucket = "%s"
|
bucket = "%s"
|
||||||
acl = "public-read"
|
acl = "public-read"
|
||||||
|
@ -563,7 +597,7 @@ POLICY
|
||||||
|
|
||||||
resource "aws_s3_bucket_object" "object" {
|
resource "aws_s3_bucket_object" "object" {
|
||||||
bucket = "${aws_s3_bucket.b.id}"
|
bucket = "${aws_s3_bucket.b.id}"
|
||||||
key = "tf-cf-stack.yaml"
|
key = "%s"
|
||||||
source = "test-fixtures/cloudformation-template.yaml"
|
source = "test-fixtures/cloudformation-template.yaml"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,17 +610,5 @@ resource "aws_cloudformation_stack" "with-url-and-params-and-yaml" {
|
||||||
on_failure = "DELETE"
|
on_failure = "DELETE"
|
||||||
timeout_in_minutes = 1
|
timeout_in_minutes = 1
|
||||||
}
|
}
|
||||||
`
|
`, bucketName, bucketName, bucketKey, vpcCidr)
|
||||||
|
}
|
||||||
var cfRandInt = rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
|
||||||
var cfBucketName = "tf-stack-with-url-and-params-" + fmt.Sprintf("%d", cfRandInt)
|
|
||||||
|
|
||||||
var testAccAWSCloudFormationConfig_templateUrl_withParams = fmt.Sprintf(
|
|
||||||
tpl_testAccAWSCloudFormationConfig_templateUrl_withParams,
|
|
||||||
cfBucketName, cfBucketName, "11.0.0.0/16")
|
|
||||||
var testAccAWSCloudFormationConfig_templateUrl_withParams_modified = fmt.Sprintf(
|
|
||||||
tpl_testAccAWSCloudFormationConfig_templateUrl_withParams,
|
|
||||||
cfBucketName, cfBucketName, "13.0.0.0/16")
|
|
||||||
var testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml = fmt.Sprintf(
|
|
||||||
tpl_testAccAWSCloudFormationConfig_templateUrl_withParams_withYaml,
|
|
||||||
cfBucketName, cfBucketName, "13.0.0.0/16")
|
|
||||||
|
|
Loading…
Reference in New Issue