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

r/cloudwatchlogs_subscription_filter - add plan time validations #23760

Merged
merged 3 commits into from
Mar 21, 2022
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
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