From 7a55fe4bcc2f1fb0ada387f1f49070d767a1e7a3 Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Tue, 14 Feb 2017 14:41:26 +0000 Subject: [PATCH 1/8] First stab at fixing hashicorp/terraform#9930 Add the following resources: * `aws_cloudwatch_log_destination` * `aws_cloudwatch_log_destination_policy` --- builtin/providers/aws/provider.go | 2 + ...resource_aws_cloudwatch_log_destination.go | 111 ++++++++++++++++++ ...e_aws_cloudwatch_log_destination_policy.go | 87 ++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_log_destination.go create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 308d01a279..b5ca1bc0d2 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -232,6 +232,8 @@ func Provider() terraform.ResourceProvider { "aws_cloudtrail": resourceAwsCloudTrail(), "aws_cloudwatch_event_rule": resourceAwsCloudWatchEventRule(), "aws_cloudwatch_event_target": resourceAwsCloudWatchEventTarget(), + "aws_cloudwatch_log_destination": resourceAwsCloudWatchLogDestination(), + "aws_cloudwatch_log_destination_policy": resourceAwsCloudWatchLogDestinationPolicy(), "aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(), "aws_cloudwatch_log_metric_filter": resourceAwsCloudWatchLogMetricFilter(), "aws_cloudwatch_log_stream": resourceAwsCloudWatchLogStream(), diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go new file mode 100644 index 0000000000..f959919f67 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -0,0 +1,111 @@ +package aws + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" +) + +func resourceAwsCloudWatchLogDestination() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCloudWatchLogDestinationPut, + Update: resourceAwsCloudWatchLogDestinationPut, + + Read: resourceAwsCloudWatchLogDestinationRead, + Delete: resourceAwsCloudWatchLogDestinationDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "role_arn": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "target_arn": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchlogsconn + + name := d.Get("name").(string) + role_arn := d.Get("role_arn").(string) + target_arn := d.Get("target_arn").(string) + + params := &cloudwatchlogs.PutDestinationInput{ + DestinationName: aws.String(name), + RoleArn: aws.String(role_arn), + TargetArn: aws.String(target_arn), + } + + resp, err := conn.PutDestination(params) + + if err != nil { + return fmt.Errorf("Error creating Destination with name %s: %#v", name, err) + } + + d.SetId(*resp.Destination.Arn) + d.Set("arn", *resp.Destination.Arn) + return resourceAwsCloudWatchLogDestinationRead(d, meta) +} + +func resourceAwsCloudWatchLogDestinationRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchlogsconn + + name := d.Get("name").(string) + + params := &cloudwatchlogs.DescribeDestinationsInput{ + DestinationNamePrefix: aws.String(name), + } + + resp, err := conn.DescribeDestinations(params) + if err != nil { + return fmt.Errorf("Error reading Destinations with name prefix %s: %#v", name, err) + } + + for _, destination := range resp.Destinations { + if *destination.DestinationName == name { + d.SetId(*destination.Arn) + d.Set("arn", *destination.Arn) + d.Set("role_arn", *destination.RoleArn) + d.Set("target_arn", *destination.TargetArn) + return nil + } + } + + d.SetId("") + return nil +} + +func resourceAwsCloudWatchLogDestinationDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchlogsconn + + name := d.Get("name").(string) + + params := &cloudwatchlogs.DeleteDestinationInput{ + DestinationName: aws.String(name), + } + _, err := conn.DeleteDestination(params) + if err != nil { + return fmt.Errorf("Error deleting Destination with name %s", name) + } + d.SetId("") + return nil +} diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go new file mode 100644 index 0000000000..f5f06d1fbb --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go @@ -0,0 +1,87 @@ +package aws + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" +) + +func resourceAwsCloudWatchLogDestinationPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsCloudWatchLogDestinationPolicyPut, + Update: resourceAwsCloudWatchLogDestinationPolicyPut, + + Read: resourceAwsCloudWatchLogDestinationPolicyRead, + Delete: resourceAwsCloudWatchLogDestinationPolicyDelete, + + Schema: map[string]*schema.Schema{ + "destination_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "access_policy": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func resourceAwsCloudWatchLogDestinationPolicyPut(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchlogsconn + + destination_name := d.Get("destination_name").(string) + access_policy := d.Get("access_policy").(string) + + params := &cloudwatchlogs.PutDestinationPolicyInput{ + DestinationName: aws.String(destination_name), + AccessPolicy: aws.String(access_policy), + } + + _, err := conn.PutDestinationPolicy(params) + + if err != nil { + return fmt.Errorf("Error creating DestinationPolicy with destination_name %s: %#v", destination_name, err) + } + + d.SetId(destination_name) + return resourceAwsCloudWatchLogDestinationPolicyRead(d, meta) +} + +func resourceAwsCloudWatchLogDestinationPolicyRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).cloudwatchlogsconn + + destination_name := d.Get("destination_name").(string) + + params := &cloudwatchlogs.DescribeDestinationsInput{ + DestinationNamePrefix: aws.String(destination_name), + } + + resp, err := conn.DescribeDestinations(params) + if err != nil { + return fmt.Errorf("Error reading Destinations with name prefix %s: %#v", destination_name, err) + } + + for _, destination := range resp.Destinations { + if *destination.DestinationName == destination_name { + if destination.AccessPolicy != nil { + d.Set("access_policy", *destination.AccessPolicy) + } + d.SetId(destination_name) + return nil + } + } + + d.SetId("") + return nil +} + +func resourceAwsCloudWatchLogDestinationPolicyDelete(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} From a08fbcbadb0f55852eff7d07a02e9e3cd9ff15ea Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Tue, 14 Feb 2017 16:16:22 +0000 Subject: [PATCH 2/8] Add documentation --- .../cloudwatch_log_destination.html.markdown | 35 ++++++++++++ ...watch_log_destination_policy.html.markdown | 55 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown create mode 100644 website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown diff --git a/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown b/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown new file mode 100644 index 0000000000..86ed2437fa --- /dev/null +++ b/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "aws" +page_title: "AWS: aws_cloudwatch_log_destination" +sidebar_current: "docs-aws-resource-cloudwatch-log-destination" +description: |- + Provides a CloudWatch Logs destination. +--- + +# aws\_cloudwatch\_log\_destination + +Provides a CloudWatch Logs destination resource. + +## Example Usage + +``` +resource "aws_cloudwatch_log_destination" "test_destination" { + name = "test_destination" + role_arn = "${aws_iam_role.iam_for_cloudwatch.arn}" + target_arn = "${aws_kinesis_stream.kinesis_for_cloudwatch.arn}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) A name for the log destination +* `role_arn` - (Required) The ARN of an IAM role that grants Amazon CloudWatch Logs permissions to put data into the target +* `target_arn` - (Required) The ARN of the target Amazon Kinesis stream or Amazon Lambda resource for the destination + +## Attributes Reference + +The following attributes are exported: + +* `arn` - The Amazon Resource Name (ARN) specifying the log destination. diff --git a/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown b/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown new file mode 100644 index 0000000000..ccb248a52c --- /dev/null +++ b/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "aws" +page_title: "AWS: aws_cloudwatch_log_destination_policy" +sidebar_current: "docs-aws-resource-cloudwatch-log-destination-policy" +description: |- + Provides a CloudWatch Logs destination policy. +--- + +# aws\_cloudwatch\_log\_destination\_policy + +Provides a CloudWatch Logs destination policy resource. + +## Example Usage + +``` +resource "aws_cloudwatch_log_destination" "test_destination" { + name = "test_destination" + role_arn = "${aws_iam_role.iam_for_cloudwatch.arn}" + target_arn = "${aws_kinesis_stream.kinesis_for_cloudwatch.arn}" +} + +data "aws_iam_policy_document" "test_destination_policy" { + statement { + effect = "Allow" + + principals = { + type = "AWS" + + identifiers = [ + "123456789012", + ] + } + + actions = [ + "logs:PutSubscriptionFilter", + ] + + resources = [ + "${aws_cloudwatch_log_destination.test_destination.arn}", + ] + } +} + +resource "aws_cloudwatch_log_destination_policy" "test_destination_policy" { + destination_name = "${aws_cloudwatch_log_destination.test_destination.name}" + access_policy = "${data.aws_iam_policy_document.test_destination_policy.json}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `destination_name` - (Required) A name for the subscription filter +* `access_policy` - (Required) The policy document. This is a JSON formatted string. From 3939a7220d244105115ef9eee4e4fef930a0e72a Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Tue, 14 Feb 2017 18:09:48 +0000 Subject: [PATCH 3/8] Add import functionality --- .../aws/resource_aws_cloudwatch_log_destination.go | 7 +++++++ .../aws/resource_aws_cloudwatch_log_destination_policy.go | 7 +++++++ .../aws/r/cloudwatch_log_destination.html.markdown | 8 ++++++++ .../aws/r/cloudwatch_log_destination_policy.html.markdown | 8 ++++++++ 4 files changed, 30 insertions(+) diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go index f959919f67..2cbe7d4712 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -17,6 +17,13 @@ func resourceAwsCloudWatchLogDestination() *schema.Resource { Read: resourceAwsCloudWatchLogDestinationRead, Delete: resourceAwsCloudWatchLogDestinationDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + d.Set("name", d.Id()) + return []*schema.ResourceData{d}, nil + }, + }, + Schema: map[string]*schema.Schema{ "name": &schema.Schema{ Type: schema.TypeString, diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go index f5f06d1fbb..23c8444ec5 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go @@ -17,6 +17,13 @@ func resourceAwsCloudWatchLogDestinationPolicy() *schema.Resource { Read: resourceAwsCloudWatchLogDestinationPolicyRead, Delete: resourceAwsCloudWatchLogDestinationPolicyDelete, + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + d.Set("destination_name", d.Id()) + return []*schema.ResourceData{d}, nil + }, + }, + Schema: map[string]*schema.Schema{ "destination_name": &schema.Schema{ Type: schema.TypeString, diff --git a/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown b/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown index 86ed2437fa..d1b1e92384 100644 --- a/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown +++ b/website/source/docs/providers/aws/r/cloudwatch_log_destination.html.markdown @@ -33,3 +33,11 @@ The following arguments are supported: The following attributes are exported: * `arn` - The Amazon Resource Name (ARN) specifying the log destination. + +## Import + +CloudWatch Logs destinations can be imported using the `name`, e.g. + +``` +$ terraform import aws_cloudwatch_log_destination.test_destination test_destination +``` diff --git a/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown b/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown index ccb248a52c..452e254dd1 100644 --- a/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown +++ b/website/source/docs/providers/aws/r/cloudwatch_log_destination_policy.html.markdown @@ -53,3 +53,11 @@ The following arguments are supported: * `destination_name` - (Required) A name for the subscription filter * `access_policy` - (Required) The policy document. This is a JSON formatted string. + +## Import + +CloudWatch Logs destination policies can be imported using the `destination_name`, e.g. + +``` +$ terraform import aws_cloudwatch_log_destination_policy.test_destination_policy test_destination +``` From e4b4d2b5637ce31f6218287c2cfa5a490b404d9b Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Wed, 15 Feb 2017 09:39:37 +0000 Subject: [PATCH 4/8] Improve error reporting at creation Code borrowed from nearby subscription filter resource. --- ...resource_aws_cloudwatch_log_destination.go | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go index 2cbe7d4712..3a6dd844de 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -2,11 +2,13 @@ package aws import ( "fmt" - - "github.com/hashicorp/terraform/helper/schema" + "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" ) func resourceAwsCloudWatchLogDestination() *schema.Resource { @@ -62,15 +64,25 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa TargetArn: aws.String(target_arn), } - resp, err := conn.PutDestination(params) + return resource.Retry(30*time.Second, func() *resource.RetryError { + resp, err := conn.PutDestination(params) - if err != nil { - return fmt.Errorf("Error creating Destination with name %s: %#v", name, err) - } + if err == nil { + d.SetId(*resp.Destination.Arn) + d.Set("arn", *resp.Destination.Arn) + } + + awsErr, ok := err.(awserr.Error) + if !ok { + return resource.RetryableError(err) + } + + if awsErr.Code() == "InvalidParameterException" { + return resource.NonRetryableError(err) + } - d.SetId(*resp.Destination.Arn) - d.Set("arn", *resp.Destination.Arn) - return resourceAwsCloudWatchLogDestinationRead(d, meta) + return resource.NonRetryableError(err) + }) } func resourceAwsCloudWatchLogDestinationRead(d *schema.ResourceData, meta interface{}) error { From 93b2ac36dc787d9330f2f3ddab88beba9396998d Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Wed, 15 Feb 2017 11:35:39 +0000 Subject: [PATCH 5/8] Handle specific exceptions at creation If we get `InvalidParameterException` with the message "Could not deliver test message to specified" then retry as this is often down to some sort of internal delay in Amazons API. Also increase the timeout from 30 seconds to 3 minutes as it has been observed to take that long sometimes for the creation to succeed. This applies to both log destinations and subscription filters. --- .../aws/resource_aws_cloudwatch_log_destination.go | 6 +++++- .../aws/resource_aws_cloudwatch_log_subscription_filter.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go index 3a6dd844de..a594bf425b 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -64,7 +65,7 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa TargetArn: aws.String(target_arn), } - return resource.Retry(30*time.Second, func() *resource.RetryError { + return resource.Retry(3*time.Minute, func() *resource.RetryError { resp, err := conn.PutDestination(params) if err == nil { @@ -78,6 +79,9 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa } if awsErr.Code() == "InvalidParameterException" { + if strings.Contains(awsErr.Message(), "Could not deliver test message to specified") { + return resource.RetryableError(err) + } return resource.NonRetryableError(err) } diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_subscription_filter.go b/builtin/providers/aws/resource_aws_cloudwatch_log_subscription_filter.go index 479a78dbaf..4d17859d55 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_subscription_filter.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_subscription_filter.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "log" + "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -56,7 +57,7 @@ func resourceAwsCloudwatchLogSubscriptionFilterCreate(d *schema.ResourceData, me params := getAwsCloudWatchLogsSubscriptionFilterInput(d) log.Printf("[DEBUG] Creating SubscriptionFilter %#v", params) - return resource.Retry(30*time.Second, func() *resource.RetryError { + return resource.Retry(3*time.Minute, func() *resource.RetryError { _, err := conn.PutSubscriptionFilter(¶ms) if err == nil { @@ -71,6 +72,9 @@ func resourceAwsCloudwatchLogSubscriptionFilterCreate(d *schema.ResourceData, me if awsErr.Code() == "InvalidParameterException" { log.Printf("[DEBUG] Caught message: %q, code: %q: Retrying", awsErr.Message(), awsErr.Code()) + if strings.Contains(awsErr.Message(), "Could not deliver test message to specified") { + return resource.RetryableError(err) + } resource.NonRetryableError(err) } From de2542ef6b55b9831f2d0fb5fd54c41e3782f7e0 Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Wed, 15 Feb 2017 14:59:28 +0000 Subject: [PATCH 6/8] Add acceptance tests Refactor the `DescribeDestinations` call so it can be used by the tests as well as the normal code. --- ..._cloudwatch_log_destination_policy_test.go | 28 +++ ...ort_aws_cloudwatch_log_destination_test.go | 28 +++ ...resource_aws_cloudwatch_log_destination.go | 53 ++++-- ...e_aws_cloudwatch_log_destination_policy.go | 27 ++- ..._cloudwatch_log_destination_policy_test.go | 161 ++++++++++++++++++ ...rce_aws_cloudwatch_log_destination_test.go | 161 ++++++++++++++++++ 6 files changed, 424 insertions(+), 34 deletions(-) create mode 100644 builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go create mode 100644 builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go create mode 100644 builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go diff --git a/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go b/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go new file mode 100644 index 0000000000..a3f4c5b4b5 --- /dev/null +++ b/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go @@ -0,0 +1,28 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSCloudwatchLogDestinationPolicy_importBasic(t *testing.T) { + resourceName := "aws_cloudwatch_log_destination_policy.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudwatchLogDestinationPolicyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSCloudwatchLogDestinationPolicyConfig(), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go b/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go new file mode 100644 index 0000000000..b974492972 --- /dev/null +++ b/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go @@ -0,0 +1,28 @@ +package aws + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAWSCloudwatchLogDestination_importBasic(t *testing.T) { + resourceName := "aws_cloudwatch_log_destination.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudwatchLogDestinationDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSCloudwatchLogDestinationConfig(), + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go index a594bf425b..946b74b2ff 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -69,7 +69,7 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa resp, err := conn.PutDestination(params) if err == nil { - d.SetId(*resp.Destination.Arn) + d.SetId(name) d.Set("arn", *resp.Destination.Arn) } @@ -91,29 +91,22 @@ func resourceAwsCloudWatchLogDestinationPut(d *schema.ResourceData, meta interfa func resourceAwsCloudWatchLogDestinationRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).cloudwatchlogsconn - name := d.Get("name").(string) - - params := &cloudwatchlogs.DescribeDestinationsInput{ - DestinationNamePrefix: aws.String(name), - } - - resp, err := conn.DescribeDestinations(params) + destination, exists, err := lookupCloudWatchLogDestination(conn, name, nil) if err != nil { - return fmt.Errorf("Error reading Destinations with name prefix %s: %#v", name, err) + return err } - for _, destination := range resp.Destinations { - if *destination.DestinationName == name { - d.SetId(*destination.Arn) - d.Set("arn", *destination.Arn) - d.Set("role_arn", *destination.RoleArn) - d.Set("target_arn", *destination.TargetArn) - return nil - } + if !exists { + d.SetId("") + return nil } - d.SetId("") + d.SetId(name) + d.Set("arn", destination.Arn) + d.Set("role_arn", destination.RoleArn) + d.Set("target_arn", destination.TargetArn) + return nil } @@ -132,3 +125,27 @@ func resourceAwsCloudWatchLogDestinationDelete(d *schema.ResourceData, meta inte d.SetId("") return nil } + +func lookupCloudWatchLogDestination(conn *cloudwatchlogs.CloudWatchLogs, + name string, nextToken *string) (*cloudwatchlogs.Destination, bool, error) { + input := &cloudwatchlogs.DescribeDestinationsInput{ + DestinationNamePrefix: aws.String(name), + NextToken: nextToken, + } + resp, err := conn.DescribeDestinations(input) + if err != nil { + return nil, true, err + } + + for _, destination := range resp.Destinations { + if *destination.DestinationName == name { + return destination, true, nil + } + } + + if resp.NextToken != nil { + return lookupCloudWatchLogDestination(conn, name, resp.NextToken) + } + + return nil, false, nil +} diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go index 23c8444ec5..a9a314b67b 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go @@ -62,29 +62,24 @@ func resourceAwsCloudWatchLogDestinationPolicyPut(d *schema.ResourceData, meta i func resourceAwsCloudWatchLogDestinationPolicyRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).cloudwatchlogsconn - destination_name := d.Get("destination_name").(string) - - params := &cloudwatchlogs.DescribeDestinationsInput{ - DestinationNamePrefix: aws.String(destination_name), + destination, exists, err := lookupCloudWatchLogDestination(conn, destination_name, nil) + if err != nil { + return err } - resp, err := conn.DescribeDestinations(params) - if err != nil { - return fmt.Errorf("Error reading Destinations with name prefix %s: %#v", destination_name, err) + if !exists { + d.SetId("") + return nil } - for _, destination := range resp.Destinations { - if *destination.DestinationName == destination_name { - if destination.AccessPolicy != nil { - d.Set("access_policy", *destination.AccessPolicy) - } - d.SetId(destination_name) - return nil - } + if destination.AccessPolicy != nil { + d.SetId(destination_name) + d.Set("access_policy", *destination.AccessPolicy) + } else { + d.SetId("") } - d.SetId("") return nil } diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go new file mode 100644 index 0000000000..e612c44070 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go @@ -0,0 +1,161 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSCloudwatchLogDestinationPolicy_basic(t *testing.T) { + var destination cloudwatchlogs.Destination + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudwatchLogDestinationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCloudwatchLogDestinationPolicyConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCloudwatchLogDestinationPolicyExists("aws_cloudwatch_log_destination_policy.test", &destination), + ), + }, + }, + }) +} + +func testAccCheckAWSCloudwatchLogDestinationPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).cloudwatchlogsconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cloudwatch_log_destination_policy" { + continue + } + _, exists, err := lookupCloudWatchLogDestination(conn, rs.Primary.ID, nil) + if err != nil { + return nil + } + + if exists { + return fmt.Errorf("Bad: Destination Policy still exists: %q", rs.Primary.ID) + } + } + + return nil + +} + +func testAccCheckAWSCloudwatchLogDestinationPolicyExists(n string, d *cloudwatchlogs.Destination) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).cloudwatchlogsconn + destination, exists, err := lookupCloudWatchLogDestination(conn, rs.Primary.ID, nil) + if err != nil { + return err + } + if !exists || destination.AccessPolicy == nil { + return fmt.Errorf("Bad: Destination Policy %q does not exist", rs.Primary.ID) + } + + *d = *destination + + return nil + } +} + +func testAccAWSCloudwatchLogDestinationPolicyConfig() string { + return fmt.Sprintf(` +resource "aws_kinesis_stream" "test" { + name = "RootAccess" + shard_count = 1 +} + +data "aws_region" "current" { + current = true +} + +data "aws_iam_policy_document" "role" { + statement { + effect = "Allow" + principals = { + type = "Service" + identifiers = [ + "logs.${data.aws_region.current.name}.amazonaws.com" + ] + } + actions = [ + "sts:AssumeRole", + ] + } +} + +resource "aws_iam_role" "test" { + name = "CWLtoKinesisRole" + assume_role_policy = "${data.aws_iam_policy_document.role.json}" +} + +data "aws_iam_policy_document" "policy" { + statement { + effect = "Allow" + actions = [ + "kinesis:PutRecord", + ] + resources = [ + "${aws_kinesis_stream.test.arn}" + ] + } + statement { + effect = "Allow" + actions = [ + "iam:PassRole" + ] + resources = [ + "${aws_iam_role.test.arn}" + ] + } +} + +resource "aws_iam_role_policy" "test" { + name = "Permissions-Policy-For-CWL" + role = "${aws_iam_role.test.id}" + policy = "${data.aws_iam_policy_document.policy.json}" +} + +resource "aws_cloudwatch_log_destination" "test" { + name = "testDestination" + target_arn = "${aws_kinesis_stream.test.arn}" + role_arn = "${aws_iam_role.test.arn}" + depends_on = ["aws_iam_role_policy.test"] +} + +data "aws_iam_policy_document" "access" { + statement { + effect = "Allow" + principals = { + type = "AWS" + identifiers = [ + "000000000000" + ] + } + actions = [ + "logs:PutSubscriptionFilter" + ] + resources = [ + "${aws_cloudwatch_log_destination.test.arn}" + ] + } +} + +resource "aws_cloudwatch_log_destination_policy" "test" { + destination_name = "${aws_cloudwatch_log_destination.test.name}" + access_policy = "${data.aws_iam_policy_document.access.json}" +} +`) +} diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go new file mode 100644 index 0000000000..005b8808f2 --- /dev/null +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go @@ -0,0 +1,161 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSCloudwatchLogDestination_basic(t *testing.T) { + var destination cloudwatchlogs.Destination + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCloudwatchLogDestinationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCloudwatchLogDestinationConfig(), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCloudwatchLogDestinationExists("aws_cloudwatch_log_destination.test", &destination), + ), + }, + }, + }) +} + +func testAccCheckAWSCloudwatchLogDestinationDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).cloudwatchlogsconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_cloudwatch_log_destination" { + continue + } + _, exists, err := lookupCloudWatchLogDestination(conn, rs.Primary.ID, nil) + if err != nil { + return nil + } + + if exists { + return fmt.Errorf("Bad: Destination still exists: %q", rs.Primary.ID) + } + } + + return nil + +} + +func testAccCheckAWSCloudwatchLogDestinationExists(n string, d *cloudwatchlogs.Destination) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + conn := testAccProvider.Meta().(*AWSClient).cloudwatchlogsconn + destination, exists, err := lookupCloudWatchLogDestination(conn, rs.Primary.ID, nil) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("Bad: Destination %q does not exist", rs.Primary.ID) + } + + *d = *destination + + return nil + } +} + +func testAccAWSCloudwatchLogDestinationConfig() string { + return fmt.Sprintf(` +resource "aws_kinesis_stream" "test" { + name = "RootAccess" + shard_count = 1 +} + +data "aws_region" "current" { + current = true +} + +data "aws_iam_policy_document" "role" { + statement { + effect = "Allow" + principals = { + type = "Service" + identifiers = [ + "logs.${data.aws_region.current.name}.amazonaws.com" + ] + } + actions = [ + "sts:AssumeRole", + ] + } +} + +resource "aws_iam_role" "test" { + name = "CWLtoKinesisRole" + assume_role_policy = "${data.aws_iam_policy_document.role.json}" +} + +data "aws_iam_policy_document" "policy" { + statement { + effect = "Allow" + actions = [ + "kinesis:PutRecord", + ] + resources = [ + "${aws_kinesis_stream.test.arn}" + ] + } + statement { + effect = "Allow" + actions = [ + "iam:PassRole" + ] + resources = [ + "${aws_iam_role.test.arn}" + ] + } +} + +resource "aws_iam_role_policy" "test" { + name = "Permissions-Policy-For-CWL" + role = "${aws_iam_role.test.id}" + policy = "${data.aws_iam_policy_document.policy.json}" +} + +resource "aws_cloudwatch_log_destination" "test" { + name = "testDestination" + target_arn = "${aws_kinesis_stream.test.arn}" + role_arn = "${aws_iam_role.test.arn}" + depends_on = ["aws_iam_role_policy.test"] +} + +data "aws_iam_policy_document" "access" { + statement { + effect = "Allow" + principals = { + type = "AWS" + identifiers = [ + "000000000000" + ] + } + actions = [ + "logs:PutSubscriptionFilter" + ] + resources = [ + "${aws_cloudwatch_log_destination.test.arn}" + ] + } +} + +resource "aws_cloudwatch_log_destination_policy" "test" { + destination_name = "${aws_cloudwatch_log_destination.test.name}" + access_policy = "${data.aws_iam_policy_document.access.json}" +} +`) +} From 4678fa412101683a44d845db4eb6d1443c6737fb Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Thu, 16 Feb 2017 22:14:24 +0000 Subject: [PATCH 7/8] Add missing resource types to the sidebar --- website/source/layouts/aws.erb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index cb3bb07e63..19662fefc8 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -231,6 +231,14 @@ aws_cloudwatch_event_target + > + aws_cloudwatch_log_destination + + + > + aws_cloudwatch_log_destination_policy + + > aws_cloudwatch_log_group From e141df0cd0a2dad3de606808876f92ed7d5b1623 Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Sat, 18 Feb 2017 18:53:32 +0000 Subject: [PATCH 8/8] Seed test value names and tidy up whitespace --- ...ws_cloudwatch_log_destination_policy_test.go | 5 ++++- ...mport_aws_cloudwatch_log_destination_test.go | 5 ++++- .../resource_aws_cloudwatch_log_destination.go | 1 - ...rce_aws_cloudwatch_log_destination_policy.go | 1 - ...ws_cloudwatch_log_destination_policy_test.go | 17 ++++++++++------- ...ource_aws_cloudwatch_log_destination_test.go | 17 ++++++++++------- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go b/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go index a3f4c5b4b5..f7c4a7f35e 100644 --- a/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go +++ b/builtin/providers/aws/import_aws_cloudwatch_log_destination_policy_test.go @@ -3,19 +3,22 @@ package aws import ( "testing" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" ) func TestAccAWSCloudwatchLogDestinationPolicy_importBasic(t *testing.T) { resourceName := "aws_cloudwatch_log_destination_policy.test" + rstring := acctest.RandString(5) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSCloudwatchLogDestinationPolicyDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccAWSCloudwatchLogDestinationPolicyConfig(), + Config: testAccAWSCloudwatchLogDestinationPolicyConfig(rstring), }, resource.TestStep{ diff --git a/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go b/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go index b974492972..b0c1d25356 100644 --- a/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go +++ b/builtin/providers/aws/import_aws_cloudwatch_log_destination_test.go @@ -3,19 +3,22 @@ package aws import ( "testing" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" ) func TestAccAWSCloudwatchLogDestination_importBasic(t *testing.T) { resourceName := "aws_cloudwatch_log_destination.test" + rstring := acctest.RandString(5) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSCloudwatchLogDestinationDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccAWSCloudwatchLogDestinationConfig(), + Config: testAccAWSCloudwatchLogDestinationConfig(rstring), }, resource.TestStep{ diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go index 946b74b2ff..172630648e 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination.go @@ -16,7 +16,6 @@ func resourceAwsCloudWatchLogDestination() *schema.Resource { return &schema.Resource{ Create: resourceAwsCloudWatchLogDestinationPut, Update: resourceAwsCloudWatchLogDestinationPut, - Read: resourceAwsCloudWatchLogDestinationRead, Delete: resourceAwsCloudWatchLogDestinationDelete, diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go index a9a314b67b..704dacf452 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy.go @@ -13,7 +13,6 @@ func resourceAwsCloudWatchLogDestinationPolicy() *schema.Resource { return &schema.Resource{ Create: resourceAwsCloudWatchLogDestinationPolicyPut, Update: resourceAwsCloudWatchLogDestinationPolicyPut, - Read: resourceAwsCloudWatchLogDestinationPolicyRead, Delete: resourceAwsCloudWatchLogDestinationPolicyDelete, diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go index e612c44070..c1ba60fc1c 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_policy_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" ) @@ -12,13 +13,15 @@ import ( func TestAccAWSCloudwatchLogDestinationPolicy_basic(t *testing.T) { var destination cloudwatchlogs.Destination + rstring := acctest.RandString(5) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSCloudwatchLogDestinationPolicyDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCloudwatchLogDestinationPolicyConfig(), + Config: testAccAWSCloudwatchLogDestinationPolicyConfig(rstring), Check: resource.ComposeTestCheckFunc( testAccCheckAWSCloudwatchLogDestinationPolicyExists("aws_cloudwatch_log_destination_policy.test", &destination), ), @@ -70,10 +73,10 @@ func testAccCheckAWSCloudwatchLogDestinationPolicyExists(n string, d *cloudwatch } } -func testAccAWSCloudwatchLogDestinationPolicyConfig() string { +func testAccAWSCloudwatchLogDestinationPolicyConfig(rstring string) string { return fmt.Sprintf(` resource "aws_kinesis_stream" "test" { - name = "RootAccess" + name = "RootAccess_%s" shard_count = 1 } @@ -97,7 +100,7 @@ data "aws_iam_policy_document" "role" { } resource "aws_iam_role" "test" { - name = "CWLtoKinesisRole" + name = "CWLtoKinesisRole_%s" assume_role_policy = "${data.aws_iam_policy_document.role.json}" } @@ -123,13 +126,13 @@ data "aws_iam_policy_document" "policy" { } resource "aws_iam_role_policy" "test" { - name = "Permissions-Policy-For-CWL" + name = "Permissions-Policy-For-CWL_%s" role = "${aws_iam_role.test.id}" policy = "${data.aws_iam_policy_document.policy.json}" } resource "aws_cloudwatch_log_destination" "test" { - name = "testDestination" + name = "testDestination_%s" target_arn = "${aws_kinesis_stream.test.arn}" role_arn = "${aws_iam_role.test.arn}" depends_on = ["aws_iam_role_policy.test"] @@ -157,5 +160,5 @@ resource "aws_cloudwatch_log_destination_policy" "test" { destination_name = "${aws_cloudwatch_log_destination.test.name}" access_policy = "${data.aws_iam_policy_document.access.json}" } -`) +`, rstring, rstring, rstring, rstring) } diff --git a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go index 005b8808f2..2996122feb 100644 --- a/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go +++ b/builtin/providers/aws/resource_aws_cloudwatch_log_destination_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" ) @@ -12,13 +13,15 @@ import ( func TestAccAWSCloudwatchLogDestination_basic(t *testing.T) { var destination cloudwatchlogs.Destination + rstring := acctest.RandString(5) + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSCloudwatchLogDestinationDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCloudwatchLogDestinationConfig(), + Config: testAccAWSCloudwatchLogDestinationConfig(rstring), Check: resource.ComposeTestCheckFunc( testAccCheckAWSCloudwatchLogDestinationExists("aws_cloudwatch_log_destination.test", &destination), ), @@ -70,10 +73,10 @@ func testAccCheckAWSCloudwatchLogDestinationExists(n string, d *cloudwatchlogs.D } } -func testAccAWSCloudwatchLogDestinationConfig() string { +func testAccAWSCloudwatchLogDestinationConfig(rstring string) string { return fmt.Sprintf(` resource "aws_kinesis_stream" "test" { - name = "RootAccess" + name = "RootAccess_%s" shard_count = 1 } @@ -97,7 +100,7 @@ data "aws_iam_policy_document" "role" { } resource "aws_iam_role" "test" { - name = "CWLtoKinesisRole" + name = "CWLtoKinesisRole_%s" assume_role_policy = "${data.aws_iam_policy_document.role.json}" } @@ -123,13 +126,13 @@ data "aws_iam_policy_document" "policy" { } resource "aws_iam_role_policy" "test" { - name = "Permissions-Policy-For-CWL" + name = "Permissions-Policy-For-CWL_%s" role = "${aws_iam_role.test.id}" policy = "${data.aws_iam_policy_document.policy.json}" } resource "aws_cloudwatch_log_destination" "test" { - name = "testDestination" + name = "testDestination_%s" target_arn = "${aws_kinesis_stream.test.arn}" role_arn = "${aws_iam_role.test.arn}" depends_on = ["aws_iam_role_policy.test"] @@ -157,5 +160,5 @@ resource "aws_cloudwatch_log_destination_policy" "test" { destination_name = "${aws_cloudwatch_log_destination.test.name}" access_policy = "${data.aws_iam_policy_document.access.json}" } -`) +`, rstring, rstring, rstring, rstring) }