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

provider/aws: cloudwatch_logs_subscription_filter resource #5996

Merged
merged 1 commit into from
Apr 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ func Provider() terraform.ResourceProvider {
"aws_cloudwatch_event_target": resourceAwsCloudWatchEventTarget(),
"aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(),
"aws_cloudwatch_log_metric_filter": resourceAwsCloudWatchLogMetricFilter(),
"aws_cloudwatch_log_subscription_filter": resourceAwsCloudwatchLogSubscriptionFilter(),
"aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(),
"aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(),
"aws_codedeploy_app": resourceAwsCodeDeployApp(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package aws

import (
"bytes"
"fmt"
"log"
"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/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsCloudwatchLogSubscriptionFilter() *schema.Resource {
return &schema.Resource{
Create: resourceAwsCloudwatchLogSubscriptionFilterCreate,
Read: resourceAwsCloudwatchLogSubscriptionFilterRead,
Update: resourceAwsCloudwatchLogSubscriptionFilterUpdate,
Delete: resourceAwsCloudwatchLogSubscriptionFilterDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"destination_arn": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"filter_pattern": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"log_group_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"role_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}

func resourceAwsCloudwatchLogSubscriptionFilterCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatchlogsconn
params := getAwsCloudWatchLogsSubscriptionFilterInput(d)
log.Printf("[DEBUG] Creating SubscriptionFilter %#v", params)

return resource.Retry(30*time.Second, func() *resource.RetryError {
_, err := conn.PutSubscriptionFilter(&params)

if err == nil {
d.SetId(cloudwatchLogsSubscriptionFilterId(d.Get("log_group_name").(string)))
log.Printf("[DEBUG] Cloudwatch logs subscription %q created", d.Id())
}

awsErr, ok := err.(awserr.Error)
if !ok {
return resource.RetryableError(err)
}

if awsErr.Code() == "InvalidParameterException" {
log.Printf("[DEBUG] Caught message: %q, code: %q: Retrying", awsErr.Message(), awsErr.Code())
resource.NonRetryableError(err)
}

return resource.NonRetryableError(err)
})
}

func resourceAwsCloudwatchLogSubscriptionFilterUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatchlogsconn

params := getAwsCloudWatchLogsSubscriptionFilterInput(d)

log.Printf("[DEBUG] Update SubscriptionFilter %#v", params)
_, err := conn.PutSubscriptionFilter(&params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok {
return fmt.Errorf("[WARN] Error updating SubscriptionFilter (%s) for LogGroup (%s), message: \"%s\", code: \"%s\"",
d.Get("name").(string), d.Get("log_group_name").(string), awsErr.Message(), awsErr.Code())
}
return err
}

d.SetId(cloudwatchLogsSubscriptionFilterId(d.Get("log_group_name").(string)))
return resourceAwsCloudwatchLogSubscriptionFilterRead(d, meta)
}

func getAwsCloudWatchLogsSubscriptionFilterInput(d *schema.ResourceData) cloudwatchlogs.PutSubscriptionFilterInput {
name := d.Get("name").(string)
destination_arn := d.Get("destination_arn").(string)
filter_pattern := d.Get("filter_pattern").(string)
log_group_name := d.Get("log_group_name").(string)

params := cloudwatchlogs.PutSubscriptionFilterInput{
FilterName: aws.String(name),
DestinationArn: aws.String(destination_arn),
FilterPattern: aws.String(filter_pattern),
LogGroupName: aws.String(log_group_name),
}

if _, ok := d.GetOk("role_arn"); ok {
params.RoleArn = aws.String(d.Get("role_arn").(string))
}

return params
}

func resourceAwsCloudwatchLogSubscriptionFilterRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatchlogsconn

log_group_name := d.Get("log_group_name").(string)
name := d.Get("name").(string) // "name" is a required field in the schema

req := &cloudwatchlogs.DescribeSubscriptionFiltersInput{
LogGroupName: aws.String(log_group_name),
FilterNamePrefix: aws.String(name),
}

resp, err := conn.DescribeSubscriptionFilters(req)
if err != nil {
return fmt.Errorf("Error reading SubscriptionFilters for log group %s with name prefix %s: %#v", log_group_name, d.Get("name").(string), err)
}

for _, subscriptionFilter := range resp.SubscriptionFilters {
if *subscriptionFilter.LogGroupName == log_group_name {
d.SetId(cloudwatchLogsSubscriptionFilterId(log_group_name))
return nil // OK, matching subscription filter found
}
}

return fmt.Errorf("Subscription filter for log group %s with name prefix %s not found!", log_group_name, d.Get("name").(string))
}

func resourceAwsCloudwatchLogSubscriptionFilterDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudwatchlogsconn
log.Printf("[INFO] Deleting CloudWatch Log Group Subscription: %s", d.Id())
log_group_name := d.Get("log_group_name").(string)
name := d.Get("name").(string)

params := &cloudwatchlogs.DeleteSubscriptionFilterInput{
FilterName: aws.String(name), // Required
LogGroupName: aws.String(log_group_name), // Required
}
_, err := conn.DeleteSubscriptionFilter(params)
if err != nil {
return fmt.Errorf(
"Error deleting Subscription Filter from log group: %s with name filter name %s", log_group_name, name)
}
d.SetId("")
return nil
}

func cloudwatchLogsSubscriptionFilterId(log_group_name string) string {
var buf bytes.Buffer

buf.WriteString(fmt.Sprintf("%s-", log_group_name)) // only one filter allowed per log_group_name at the moment

return fmt.Sprintf("cwlsf-%d", hashcode.String(buf.String()))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSCloudwatchLogSubscriptionFilter_basic(t *testing.T) {
var conf lambda.GetFunctionOutput

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudwatchLogSubscriptionFilterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSCloudwatchLogSubscriptionFilterConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsCloudwatchLogSubscriptionFilterExists("aws_cloudwatch_log_subscription_filter.test_lambdafunction_logfilter", &conf),
testAccCheckAWSCloudwatchLogSubscriptionFilterAttributes(&conf),
),
},
},
})
}

func testAccCheckCloudwatchLogSubscriptionFilterDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).lambdaconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_cloudwatch_log_subscription_filter" {
continue
}

_, err := conn.GetFunction(&lambda.GetFunctionInput{
FunctionName: aws.String(rs.Primary.ID),
})

if err == nil {
return fmt.Errorf("Lambda Function still exists")
}

}

return nil

}

func testAccCheckAwsCloudwatchLogSubscriptionFilterExists(n string, function *lambda.GetFunctionOutput) resource.TestCheckFunc {
// Wait for IAM role
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Lambda function not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("Lambda function ID not set")
}

conn := testAccProvider.Meta().(*AWSClient).lambdaconn

params := &lambda.GetFunctionInput{
FunctionName: aws.String("example_lambda_name"),
}

getFunction, err := conn.GetFunction(params)
if err != nil {
return err
}

*function = *getFunction

return nil
}
}

func testAccCheckAWSCloudwatchLogSubscriptionFilterAttributes(function *lambda.GetFunctionOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {
c := function.Configuration
const expectedName = "example_lambda_name"
if *c.FunctionName != expectedName {
return fmt.Errorf("Expected function name %s, got %s", expectedName, *c.FunctionName)
}

if *c.FunctionArn == "" {
return fmt.Errorf("Could not read Lambda Function's ARN")
}

return nil
}
}

const testAccAWSCloudwatchLogSubscriptionFilterConfig = `
resource "aws_cloudwatch_log_subscription_filter" "test_lambdafunction_logfilter" {
name = "test_lambdafunction_logfilter"
log_group_name = "example_lambda_name"
filter_pattern = "logtype test"
destination_arn = "${aws_lambda_function.test_lambdafunction.arn}"
}
resource "aws_lambda_function" "test_lambdafunction" {
filename = "test-fixtures/lambdatest.zip"
function_name = "example_lambda_name"
role = "${aws_iam_role.iam_for_lambda.arn}"
handler = "exports.handler"
}
resource "aws_cloudwatch_log_group" "logs" {
name = "example_lambda_name"
retention_in_days = 1
}
resource "aws_lambda_permission" "allow_cloudwatch_logs" {
statement_id = "AllowExecutionFromCloudWatchLogs"
action = "lambda:*"
function_name = "${aws_lambda_function.test_lambdafunction.arn}"
principal = "logs.eu-west-1.amazonaws.com"
}
resource "aws_iam_role" "iam_for_lambda" {
name = "test_lambdafuntion_iam_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "test_lambdafunction_iam_policy" {
name = "test_lambdafunction_iam_policy"
role = "${aws_iam_role.iam_for_lambda.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1441111030000",
"Effect": "Allow",
"Action": [
"dynamodb:*"
],
"Resource": [
"*"
]
}
]
}
EOF
}
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
layout: "aws"
page_title: "AWS: aws_cloudwatch_log_subscription_filter"
sidebar_current: "docs-aws-resource-cloudwatch-log-subscription-filter"
description: |-
Provides a CloudWatch Logs subscription filter.
---

# aws\_cloudwatch\_logs\_subscription\_filter

Provides a CloudWatch Logs subscription filter resource.

## Example Usage

```
resource "aws_cloudwatch_log_subscription_filter" "test_lambdafunction_logfilter" {
name = "test_lambdafunction_logfilter"
role_arn = "${aws_iam_role.iam_for_lambda.arn}"
log_group_name = "/aws/lambda/example_lambda_name"
filter_pattern = "logtype test"
destination_arn = "${aws_kinesis_stream.test_logstream.arn}"
}
```

## Argument Reference

The following arguments are supported:

* `name` - (Required) A name for the subscription filter
* `destination_arn` - (Required) The ARN of the destination to deliver matching log events to. Currently only Kinesis stream / a logical destination
* `filter_pattern` - (Required) A valid CloudWatch Logs filter pattern for subscribing to a filtered stream of log events.
* `log_group_name` - (Required) The name of the log group to associate the subscription filter with
* `role_arn` - (Optional) The ARN of an IAM role that grants Amazon CloudWatch Logs permissions to deliver ingested log events to the destination stream

## Attributes Reference

The following attributes are exported:

* `arn` - The Amazon Resource Name (ARN) specifying the log subscription filter.
4 changes: 4 additions & 0 deletions website/source/layouts/aws.erb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@
<a href="/docs/providers/aws/r/cloudwatch_log_group.html">aws_cloudwatch_log_group</a>
</li>

<li<%= sidebar_current("docs-aws-resource-cloudwatch-log-subscription-filter") %>>
<a href="/docs/providers/aws/r/cloudwatch_log_subscription_filter.html">aws_cloudwatch_log_subscription_filter</a>
</li>

<li<%= sidebar_current("docs-aws-resource-cloudwatch-log-metric-filter") %>>
<a href="/docs/providers/aws/r/cloudwatch_log_metric_filter.html">aws_cloudwatch_log_metric_filter</a>
</li>
Expand Down