diff --git a/aws/resource_aws_cloudwatch_event_target.go b/aws/resource_aws_cloudwatch_event_target.go index be45a0fd083..4cf192c740d 100644 --- a/aws/resource_aws_cloudwatch_event_target.go +++ b/aws/resource_aws_cloudwatch_event_target.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" events "github.com/aws/aws-sdk-go/service/cloudwatchevents" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) @@ -44,8 +43,9 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { }, "arn": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, }, "input": { @@ -63,8 +63,9 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { }, "role_arn": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, }, "run_command_targets": { @@ -99,9 +100,10 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { ValidateFunc: validation.StringLenBetween(1, 255), }, "launch_type": { - Type: schema.TypeString, - Optional: true, - Default: "EC2", + Type: schema.TypeString, + Optional: true, + Default: events.LaunchTypeEc2, + ValidateFunc: validation.StringInSlice(events.LaunchType_Values(), true), }, "network_configuration": { Type: schema.TypeList, @@ -113,13 +115,11 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, "subnets": { Type: schema.TypeSet, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, "assign_public_ip": { Type: schema.TypeBool, @@ -143,7 +143,7 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource { "task_definition_arn": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringLenBetween(1, 1600), + ValidateFunc: validateArn, }, }, }, @@ -276,22 +276,20 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface d.SetId("") return nil } - if awsErr, ok := err.(awserr.Error); ok { - // This should never happen, but it's useful - // for recovering from https://github.com/hashicorp/terraform/issues/5389 - if awsErr.Code() == "ValidationException" { - log.Printf("[WARN] Removing CloudWatch Event Target %q because it never existed.", d.Id()) - d.SetId("") - return nil - } - - if awsErr.Code() == "ResourceNotFoundException" { - log.Printf("[WARN] CloudWatch Event Target (%q) not found. Removing it from state.", d.Id()) - d.SetId("") - return nil - } + // This should never happen, but it's useful + // for recovering from https://github.com/hashicorp/terraform/issues/5389 + if isAWSErr(err, "ValidationException", "") { + log.Printf("[WARN] Removing CloudWatch Event Target %q because it never existed.", d.Id()) + d.SetId("") + return nil + } + if isAWSErr(err, events.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] CloudWatch Event Target (%q) not found. Removing it from state.", d.Id()) + d.SetId("") + return nil } + return err } log.Printf("[DEBUG] Found Event Target: %s", t) @@ -354,7 +352,7 @@ func findEventTargetById(id, rule string, nextToken *string, conn *events.CloudW } for _, t := range out.Targets { - if *t.Id == id { + if aws.StringValue(t.Id) == id { return t, nil } } @@ -582,7 +580,7 @@ func flattenAwsCloudWatchEventTargetRunParameters(runCommand *events.RunCommandP for _, x := range runCommand.RunCommandTargets { config := make(map[string]interface{}) - config["key"] = *x.Key + config["key"] = aws.StringValue(x.Key) config["values"] = flattenStringList(x.Values) result = append(result, config) @@ -593,17 +591,17 @@ func flattenAwsCloudWatchEventTargetRunParameters(runCommand *events.RunCommandP func flattenAwsCloudWatchEventTargetEcsParameters(ecsParameters *events.EcsParameters) []map[string]interface{} { config := make(map[string]interface{}) if ecsParameters.Group != nil { - config["group"] = *ecsParameters.Group + config["group"] = aws.StringValue(ecsParameters.Group) } if ecsParameters.LaunchType != nil { - config["launch_type"] = *ecsParameters.LaunchType + config["launch_type"] = aws.StringValue(ecsParameters.LaunchType) } config["network_configuration"] = flattenAwsCloudWatchEventTargetEcsParametersNetworkConfiguration(ecsParameters.NetworkConfiguration) if ecsParameters.PlatformVersion != nil { - config["platform_version"] = *ecsParameters.PlatformVersion + config["platform_version"] = aws.StringValue(ecsParameters.PlatformVersion) } - config["task_count"] = *ecsParameters.TaskCount - config["task_definition_arn"] = *ecsParameters.TaskDefinitionArn + config["task_count"] = aws.Int64Value(ecsParameters.TaskCount) + config["task_definition_arn"] = aws.StringValue(ecsParameters.TaskDefinitionArn) result := []map[string]interface{}{config} return result } @@ -613,11 +611,11 @@ func flattenAwsCloudWatchEventTargetEcsParametersNetworkConfiguration(nc *events } result := make(map[string]interface{}) - result["security_groups"] = schema.NewSet(schema.HashString, flattenStringList(nc.AwsvpcConfiguration.SecurityGroups)) - result["subnets"] = schema.NewSet(schema.HashString, flattenStringList(nc.AwsvpcConfiguration.Subnets)) + result["security_groups"] = flattenStringSet(nc.AwsvpcConfiguration.SecurityGroups) + result["subnets"] = flattenStringSet(nc.AwsvpcConfiguration.Subnets) if nc.AwsvpcConfiguration.AssignPublicIp != nil { - result["assign_public_ip"] = *nc.AwsvpcConfiguration.AssignPublicIp == events.AssignPublicIpEnabled + result["assign_public_ip"] = aws.StringValue(nc.AwsvpcConfiguration.AssignPublicIp) == events.AssignPublicIpEnabled } return []interface{}{result} @@ -639,14 +637,14 @@ func flattenAwsCloudWatchEventTargetBatchParameters(batchParameters *events.Batc func flattenAwsCloudWatchEventTargetKinesisParameters(kinesisParameters *events.KinesisParameters) []map[string]interface{} { config := make(map[string]interface{}) - config["partition_key_path"] = *kinesisParameters.PartitionKeyPath + config["partition_key_path"] = aws.StringValue(kinesisParameters.PartitionKeyPath) result := []map[string]interface{}{config} return result } func flattenAwsCloudWatchEventTargetSqsParameters(sqsParameters *events.SqsParameters) []map[string]interface{} { config := make(map[string]interface{}) - config["message_group_id"] = *sqsParameters.MessageGroupId + config["message_group_id"] = aws.StringValue(sqsParameters.MessageGroupId) result := []map[string]interface{}{config} return result } @@ -655,9 +653,9 @@ func flattenAwsCloudWatchInputTransformer(inputTransformer *events.InputTransfor config := make(map[string]interface{}) inputPathsMap := make(map[string]string) for k, v := range inputTransformer.InputPathsMap { - inputPathsMap[k] = *v + inputPathsMap[k] = aws.StringValue(v) } - config["input_template"] = *inputTransformer.InputTemplate + config["input_template"] = aws.StringValue(inputTransformer.InputTemplate) config["input_paths"] = inputPathsMap result := []map[string]interface{}{config} diff --git a/aws/resource_aws_cloudwatch_event_target_test.go b/aws/resource_aws_cloudwatch_event_target_test.go index 067cec25dc9..3fa2ba9aafe 100644 --- a/aws/resource_aws_cloudwatch_event_target_test.go +++ b/aws/resource_aws_cloudwatch_event_target_test.go @@ -92,13 +92,12 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) { resourceName := "aws_cloudwatch_event_target.test" var target events.Target - rName1 := acctest.RandString(5) - rName2 := acctest.RandString(5) - ruleName := fmt.Sprintf("tf-acc-cw-event-rule-basic-%s", rName1) - snsTopicName1 := fmt.Sprintf("tf-acc-%s", rName1) - snsTopicName2 := fmt.Sprintf("tf-acc-%s", rName2) - targetID1 := fmt.Sprintf("tf-acc-cw-target-%s", rName1) - targetID2 := fmt.Sprintf("tf-acc-cw-target-%s", rName2) + topicResourceName := "aws_sns_topic.test" + ruleName := acctest.RandomWithPrefix("tf-acc-cw-event-rule-basic") + snsTopicName1 := acctest.RandomWithPrefix("tf-acc-topic") + snsTopicName2 := acctest.RandomWithPrefix("tf-acc-topic-second") + targetID1 := acctest.RandomWithPrefix("tf-acc-cw-target") + targetID2 := acctest.RandomWithPrefix("tf-acc-cw-target-second") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -111,7 +110,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) { testAccCheckCloudWatchEventTargetExists(resourceName, &target), resource.TestCheckResourceAttr(resourceName, "rule", ruleName), resource.TestCheckResourceAttr(resourceName, "target_id", targetID1), - resource.TestCheckResourceAttrPair(resourceName, "arn", "aws_sns_topic.test", "arn"), + resource.TestCheckResourceAttrPair(resourceName, "arn", topicResourceName, "arn"), ), }, { @@ -120,7 +119,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) { testAccCheckCloudWatchEventTargetExists(resourceName, &target), resource.TestCheckResourceAttr(resourceName, "rule", ruleName), resource.TestCheckResourceAttr(resourceName, "target_id", targetID2), - resource.TestCheckResourceAttrPair(resourceName, "arn", "aws_sns_topic.test", "arn"), + resource.TestCheckResourceAttrPair(resourceName, "arn", topicResourceName, "arn"), ), }, { @@ -137,9 +136,9 @@ func TestAccAWSCloudWatchEventTarget_missingTargetId(t *testing.T) { resourceName := "aws_cloudwatch_event_target.test" var target events.Target - rName := acctest.RandString(5) - ruleName := fmt.Sprintf("tf-acc-cw-event-rule-missing-target-id-%s", rName) - snsTopicName := fmt.Sprintf("tf-acc-%s", rName) + topicResourceName := "aws_sns_topic.test" + ruleName := acctest.RandomWithPrefix("tf-acc-cw-event-rule-missing-target-id") + snsTopicName := acctest.RandomWithPrefix("tf-acc") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -151,7 +150,7 @@ func TestAccAWSCloudWatchEventTarget_missingTargetId(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckCloudWatchEventTargetExists(resourceName, &target), resource.TestCheckResourceAttr(resourceName, "rule", ruleName), - resource.TestCheckResourceAttrPair(resourceName, "arn", "aws_sns_topic.test", "arn"), + resource.TestCheckResourceAttrPair(resourceName, "arn", topicResourceName, "arn"), ), }, { @@ -167,10 +166,10 @@ func TestAccAWSCloudWatchEventTarget_missingTargetId(t *testing.T) { func TestAccAWSCloudWatchEventTarget_full(t *testing.T) { resourceName := "aws_cloudwatch_event_target.test" var target events.Target - rName := acctest.RandString(5) - ruleName := fmt.Sprintf("tf-acc-cw-event-rule-full-%s", rName) + streamResourceName := "aws_kinesis_stream.test" + ruleName := acctest.RandomWithPrefix("tf-acc-cw-event-rule-full") ssmDocumentName := acctest.RandomWithPrefix("tf_ssm_Document") - targetID := fmt.Sprintf("tf-acc-cw-target-full-%s", rName) + targetID := acctest.RandomWithPrefix("tf-acc-cw-target-full") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -183,7 +182,7 @@ func TestAccAWSCloudWatchEventTarget_full(t *testing.T) { testAccCheckCloudWatchEventTargetExists(resourceName, &target), resource.TestCheckResourceAttr(resourceName, "rule", ruleName), resource.TestCheckResourceAttr(resourceName, "target_id", targetID), - resource.TestCheckResourceAttrPair(resourceName, "arn", "aws_kinesis_stream.test", "arn"), + resource.TestCheckResourceAttrPair(resourceName, "arn", streamResourceName, "arn"), resource.TestCheckResourceAttr(resourceName, "input", "{ \"source\": [\"aws.cloudtrail\"] }\n"), resource.TestCheckResourceAttr(resourceName, "input_path", ""), ), @@ -200,6 +199,7 @@ func TestAccAWSCloudWatchEventTarget_full(t *testing.T) { func TestAccAWSCloudWatchEventTarget_ssmDocument(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_ssm_Document") resource.ParallelTest(t, resource.TestCase{ @@ -210,13 +210,13 @@ func TestAccAWSCloudWatchEventTarget_ssmDocument(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigSsmDocument(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -225,6 +225,7 @@ func TestAccAWSCloudWatchEventTarget_ssmDocument(t *testing.T) { func TestAccAWSCloudWatchEventTarget_ecs(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_ecs_target") resource.ParallelTest(t, resource.TestCase{ @@ -235,13 +236,13 @@ func TestAccAWSCloudWatchEventTarget_ecs(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigEcs(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -250,6 +251,7 @@ func TestAccAWSCloudWatchEventTarget_ecs(t *testing.T) { func TestAccAWSCloudWatchEventTarget_ecsWithBlankTaskCount(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_ecs_target") resource.ParallelTest(t, resource.TestCase{ @@ -260,14 +262,14 @@ func TestAccAWSCloudWatchEventTarget_ecsWithBlankTaskCount(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigEcsWithBlankTaskCount(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), - resource.TestCheckResourceAttr("aws_cloudwatch_event_target.test", "ecs_target.0.task_count", "1"), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), + resource.TestCheckResourceAttr(resourceName, "ecs_target.0.task_count", "1"), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -276,6 +278,7 @@ func TestAccAWSCloudWatchEventTarget_ecsWithBlankTaskCount(t *testing.T) { func TestAccAWSCloudWatchEventTarget_batch(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_batch_target") resource.ParallelTest(t, resource.TestCase{ @@ -286,13 +289,13 @@ func TestAccAWSCloudWatchEventTarget_batch(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigBatch(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -301,6 +304,7 @@ func TestAccAWSCloudWatchEventTarget_batch(t *testing.T) { func TestAccAWSCloudWatchEventTarget_kinesis(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_kinesis_target") resource.ParallelTest(t, resource.TestCase{ @@ -311,13 +315,13 @@ func TestAccAWSCloudWatchEventTarget_kinesis(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigKinesis(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -326,6 +330,7 @@ func TestAccAWSCloudWatchEventTarget_kinesis(t *testing.T) { func TestAccAWSCloudWatchEventTarget_sqs(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_sqs_target") resource.ParallelTest(t, resource.TestCase{ @@ -336,13 +341,13 @@ func TestAccAWSCloudWatchEventTarget_sqs(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigSqs(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, @@ -351,6 +356,7 @@ func TestAccAWSCloudWatchEventTarget_sqs(t *testing.T) { func TestAccAWSCloudWatchEventTarget_input_transformer(t *testing.T) { var target events.Target + resourceName := "aws_cloudwatch_event_target.test" rName := acctest.RandomWithPrefix("tf_input_transformer") resource.ParallelTest(t, resource.TestCase{ @@ -361,19 +367,44 @@ func TestAccAWSCloudWatchEventTarget_input_transformer(t *testing.T) { { Config: testAccAWSCloudWatchEventTargetConfigInputTransformer(rName), Check: resource.ComposeTestCheckFunc( - testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target), + testAccCheckCloudWatchEventTargetExists(resourceName, &target), ), }, { - ResourceName: "aws_cloudwatch_event_target.test", + ResourceName: resourceName, ImportState: true, - ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc("aws_cloudwatch_event_target.test"), + ImportStateIdFunc: testAccAWSCloudWatchEventTargetImportStateIdFunc(resourceName), ImportStateVerify: true, }, }, }) } +func TestAccAWSCloudWatchEventTarget_disappears(t *testing.T) { + resourceName := "aws_cloudwatch_event_target.test" + + var target events.Target + ruleName := acctest.RandomWithPrefix("tf-acc-cw-event-rule-basic") + snsTopicName1 := acctest.RandomWithPrefix("tf-acc-topic") + targetID1 := acctest.RandomWithPrefix("tf-acc-cw-target") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCloudWatchEventTargetConfig(ruleName, snsTopicName1, targetID1), + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudWatchEventTargetExists(resourceName, &target), + testAccCheckResourceDisappears(testAccProvider, resourceAwsCloudWatchEventTarget(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckCloudWatchEventTargetExists(n string, rule *events.Target) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -466,10 +497,10 @@ func testAccAWSCloudWatchEventTargetConfig_full(ruleName, targetName, rName stri resource "aws_cloudwatch_event_rule" "test" { name = "%s" schedule_expression = "rate(1 hour)" - role_arn = aws_iam_role.role.arn + role_arn = aws_iam_role.test.arn } -resource "aws_iam_role" "role" { +resource "aws_iam_role" "test" { name = "%s" assume_role_policy = <