Skip to content

Commit

Permalink
Merge pull request #23760 from DrFaust92/cw-logs-filter-valid
Browse files Browse the repository at this point in the history
r/cloudwatchlogs_subscription_filter - add plan time validations
  • Loading branch information
ewbankkit authored Mar 21, 2022
2 parents c52b3aa + 40205fb commit 8658924
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 89 deletions.
3 changes: 3 additions & 0 deletions .changelog/23760.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_cloudwatch_log_subscription_filter: Add plan time validations for `name`, `destination_arn`, `filter_pattern`, `role_arn`, `distribution`.
```
34 changes: 34 additions & 0 deletions internal/service/cloudwatchlogs/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func FindQueryDefinition(ctx context.Context, conn *cloudwatchlogs.CloudWatchLogs, name, queryDefinitionID string) (*cloudwatchlogs.QueryDefinition, error) {
Expand All @@ -31,3 +34,34 @@ func FindQueryDefinition(ctx context.Context, conn *cloudwatchlogs.CloudWatchLog

return result, err
}

func FindSubscriptionFilter(conn *cloudwatchlogs.CloudWatchLogs, logGroupName, name string) (*cloudwatchlogs.SubscriptionFilter, error) {
input := &cloudwatchlogs.DescribeSubscriptionFiltersInput{
LogGroupName: aws.String(logGroupName),
FilterNamePrefix: aws.String(name),
}

output, err := conn.DescribeSubscriptionFilters(input)
if tfawserr.ErrCodeEquals(err, cloudwatchlogs.ErrCodeResourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil {
return nil, tfresource.NewEmptyResultError(input)
}

filters := output.SubscriptionFilters

if len(filters) == 0 || filters[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

return filters[0], nil
}
89 changes: 39 additions & 50 deletions internal/service/cloudwatchlogs/subscription_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import (
"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/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/create"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceSubscriptionFilter() *schema.Resource {
Expand All @@ -30,34 +31,39 @@ func ResourceSubscriptionFilter() *schema.Resource {

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 512),
},
"destination_arn": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: verify.ValidARN,
},
"filter_pattern": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
Type: schema.TypeString,
Required: true,
ForceNew: false,
ValidateFunc: validation.StringLenBetween(0, 1024),
},
"log_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"role_arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: verify.ValidARN,
},
"distribution": {
Type: schema.TypeString,
Optional: true,
Default: cloudwatchlogs.DistributionByLogStream,
Type: schema.TypeString,
Optional: true,
Default: cloudwatchlogs.DistributionByLogStream,
ValidateFunc: validation.StringInSlice(cloudwatchlogs.Distribution_Values(), false),
},
},
}
Expand Down Expand Up @@ -131,16 +137,11 @@ func resourceSubscriptionFilterUpdate(d *schema.ResourceData, meta interface{})
}

func getSubscriptionFilterInput(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),
FilterName: aws.String(d.Get("name").(string)),
DestinationArn: aws.String(d.Get("destination_arn").(string)),
FilterPattern: aws.String(d.Get("filter_pattern").(string)),
LogGroupName: aws.String(d.Get("log_group_name").(string)),
}

if _, ok := d.GetOk("role_arn"); ok {
Expand All @@ -160,35 +161,24 @@ func resourceSubscriptionFilterRead(d *schema.ResourceData, meta interface{}) er
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),
subscriptionFilter, err := FindSubscriptionFilter(conn, log_group_name, name)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] Cloudwatch Logs Subscription Filter (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

resp, err := conn.DescribeSubscriptionFilters(req)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" {
log.Printf("[WARN] SubscriptionFilters (%q) Not Found", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("Error reading SubscriptionFilters for log group %s with name prefix %s: %#v", log_group_name, d.Get("name").(string), err)
return fmt.Errorf("error reading Cloudwatch Logs Subscription Filter (%s): %w", d.Id(), err)
}

for _, subscriptionFilter := range resp.SubscriptionFilters {
if aws.StringValue(subscriptionFilter.LogGroupName) == log_group_name {
d.SetId(cloudwatchLogsSubscriptionFilterId(log_group_name))
d.Set("destination_arn", subscriptionFilter.DestinationArn)
d.Set("distribution", subscriptionFilter.Distribution)
d.Set("filter_pattern", subscriptionFilter.FilterPattern)
d.Set("log_group_name", subscriptionFilter.LogGroupName)
d.Set("role_arn", subscriptionFilter.RoleArn)
return nil // OK, matching subscription filter found
}
}
d.Set("destination_arn", subscriptionFilter.DestinationArn)
d.Set("distribution", subscriptionFilter.Distribution)
d.Set("filter_pattern", subscriptionFilter.FilterPattern)
d.Set("log_group_name", subscriptionFilter.LogGroupName)
d.Set("role_arn", subscriptionFilter.RoleArn)

log.Printf("[DEBUG] Subscription Filter%q Not Found", name)
d.SetId("")
return nil
}

Expand All @@ -207,8 +197,7 @@ func resourceSubscriptionFilterDelete(d *schema.ResourceData, meta interface{})
if tfawserr.ErrMessageContains(err, cloudwatchlogs.ErrCodeResourceNotFoundException, "The specified log group does not exist") {
return nil
}
return fmt.Errorf(
"Error deleting Subscription Filter from log group: %s with name filter name %s: %+v", log_group_name, name, err)
return fmt.Errorf("error deleting Subscription Filter from log group: %s with name filter name %s: %w", log_group_name, name, err)
}

return nil
Expand Down
53 changes: 14 additions & 39 deletions internal/service/cloudwatchlogs/subscription_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfcloudwatchlogs "github.com/hashicorp/terraform-provider-aws/internal/service/cloudwatchlogs"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func TestAccCloudWatchLogsSubscriptionFilter_basic(t *testing.T) {
Expand Down Expand Up @@ -64,7 +65,7 @@ func TestAccCloudWatchLogsSubscriptionFilter_disappears(t *testing.T) {
Config: testAccSubscriptionFilterDestinationARNLambdaConfig(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckSubscriptionFilterExists(resourceName, &filter),
testAccCheckCloudwatchLogSubscriptionFilterDisappears(&filter),
acctest.CheckResourceDisappears(acctest.Provider, tfcloudwatchlogs.ResourceSubscriptionFilter(), resourceName),
),
ExpectNonEmptyPlan: true,
},
Expand All @@ -91,7 +92,7 @@ func TestAccCloudWatchLogsSubscriptionFilter_Disappears_logGroup(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckSubscriptionFilterExists(resourceName, &filter),
testAccCheckCloudWatchLogGroupExists(logGroupResourceName, &logGroup),
testAccCheckCloudWatchLogGroupDisappears(&logGroup),
acctest.CheckResourceDisappears(acctest.Provider, tfcloudwatchlogs.ResourceGroup(), logGroupResourceName),
),
ExpectNonEmptyPlan: true,
},
Expand Down Expand Up @@ -233,21 +234,6 @@ func TestAccCloudWatchLogsSubscriptionFilter_roleARN(t *testing.T) {
})
}

func testAccCheckCloudwatchLogSubscriptionFilterDisappears(filter *cloudwatchlogs.SubscriptionFilter) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).CloudWatchLogsConn

input := &cloudwatchlogs.DeleteSubscriptionFilterInput{
FilterName: filter.FilterName,
LogGroupName: filter.LogGroupName,
}

_, err := conn.DeleteSubscriptionFilter(input)

return err
}
}

func testAccCheckCloudwatchLogSubscriptionFilterDestroy(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).CloudWatchLogsConn

Expand All @@ -259,16 +245,18 @@ func testAccCheckCloudwatchLogSubscriptionFilterDestroy(s *terraform.State) erro
logGroupName := rs.Primary.Attributes["log_group_name"]
filterName := rs.Primary.Attributes["name"]

input := cloudwatchlogs.DescribeSubscriptionFiltersInput{
LogGroupName: aws.String(logGroupName),
FilterNamePrefix: aws.String(filterName),
_, err := tfcloudwatchlogs.FindSubscriptionFilter(conn, logGroupName, filterName)

if tfresource.NotFound(err) {
continue
}

_, err := conn.DescribeSubscriptionFilters(&input)
if err == nil {
return fmt.Errorf("SubscriptionFilter still exists")
if err != nil {
return err
}

return fmt.Errorf("Subscription Filter still exists")

}

return nil
Expand All @@ -291,26 +279,13 @@ func testAccCheckSubscriptionFilterExists(n string, filter *cloudwatchlogs.Subsc
logGroupName := rs.Primary.Attributes["log_group_name"]
filterName := rs.Primary.Attributes["name"]

input := cloudwatchlogs.DescribeSubscriptionFiltersInput{
LogGroupName: aws.String(logGroupName),
FilterNamePrefix: aws.String(filterName),
}
sub, err := tfcloudwatchlogs.FindSubscriptionFilter(conn, logGroupName, filterName)

resp, err := conn.DescribeSubscriptionFilters(&input)
if err != nil {
return err
}

for _, sf := range resp.SubscriptionFilters {
if aws.StringValue(sf.FilterName) == filterName {
*filter = *sf
break
}
}

if filter == nil {
return fmt.Errorf("SubscriptionFilter not found")
}
*filter = *sub

return nil
}
Expand Down

0 comments on commit 8658924

Please sign in to comment.