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 000000000..a3f4c5b4b --- /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 000000000..b97449297 --- /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 a594bf425..946b74b2f 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 23c8444ec..a9a314b67 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), - } - - resp, err := conn.DescribeDestinations(params) + destination, exists, err := lookupCloudWatchLogDestination(conn, destination_name, nil) if err != nil { - return fmt.Errorf("Error reading Destinations with name prefix %s: %#v", destination_name, err) + return 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 - } + if !exists { + d.SetId("") + 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 000000000..e612c4407 --- /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 000000000..005b8808f --- /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}" +} +`) +}