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

Fixed aws_cloudwatch_log_group table for the error key column is not globally unique Closes #1975 #1976

Merged
merged 2 commits into from
Jan 22, 2024
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
2 changes: 1 addition & 1 deletion aws-test/tests/aws_cloudwatch_log_group/test-get-query.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
select name
from aws.aws_cloudwatch_log_group
where name = '{{ resourceName }}'
where name = '{{ resourceName }}' and region = '{{ output.region_name.value }}'
28 changes: 21 additions & 7 deletions aws/table_aws_cloudwatch_log_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@ func tableAwsCloudwatchLogGroup(_ context.Context) *plugin.Table {
Name: "aws_cloudwatch_log_group",
Description: "AWS CloudWatch Log Group",
Get: &plugin.GetConfig{
KeyColumns: plugin.SingleColumn("name"),
// Log groups with the same name can exist in different regions for an account, we should filter the results by region in such cases to resolve the error: "Error: get call returned 2 results - the key column is not globally unique".
KeyColumns: plugin.AllColumns([]string{"name", "region"}),
Hydrate: getCloudwatchLogGroup,
Tags: map[string]string{"service": "logs", "action": "DescribeLogGroups"},
},
List: &plugin.ListConfig{
Hydrate: listCloudwatchLogGroups,
Tags: map[string]string{"service": "logs", "action": "DescribeLogGroups"},
KeyColumns: plugin.KeyColumnSlice{
{
Name: "name",
Require: plugin.Optional,
},
},
},
HydrateConfig: []plugin.HydrateConfig{
{
Expand Down Expand Up @@ -127,6 +134,8 @@ func listCloudwatchLogGroups(ctx context.Context, d *plugin.QueryData, _ *plugin
return nil, err
}

name := d.EqualsQualString("name")

maxItems := int32(50)

// Reduce the basic request limit down if the user has only requested a small number
Expand All @@ -145,6 +154,10 @@ func listCloudwatchLogGroups(ctx context.Context, d *plugin.QueryData, _ *plugin
Limit: &maxItems,
}

if name != "" {
input.LogGroupNamePrefix = aws.String(name)
}

paginator := cloudwatchlogs.NewDescribeLogGroupsPaginator(svc, input, func(o *cloudwatchlogs.DescribeLogGroupsPaginatorOptions) {
o.Limit = maxItems
o.StopOnDuplicateToken = true
Expand Down Expand Up @@ -176,19 +189,20 @@ func listCloudwatchLogGroups(ctx context.Context, d *plugin.QueryData, _ *plugin
//// HYDRATE FUNCTIONS

func getCloudwatchLogGroup(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {
name := d.EqualsQualString("name")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ParthaI shouldn't we be adding an additional check for the region column as well?

If a user does not pass in the region along with the name, then we should return nil.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@misraved, in accordance with our design, we utilize the SupportedRegionMatrix.

Here's how it works:

  • If a user queries without specifying the region but includes the name, we will perform a list API call. This approach ensures that there will be no errors such as 'key column is not globally unique'.
  • Conversely, if the region value is specified along with the name, a Get API call will be executed, but only for the specified region.

Note: We can have multiple LogGroups with same name but in different region. Therefore, our approach ensures that users receive actual results rather than an empty row in such cases.


// check if name is empty
if strings.TrimSpace(name) == "" {
return nil, nil
}

// Get client
svc, err := CloudWatchLogsClient(ctx, d)
if err != nil {
plugin.Logger(ctx).Error("aws_cloudwatch_log_group.getCloudwatchLogGroup", "client_error", err)
return nil, err
}

// check if name is empty
name := d.EqualsQuals["name"].GetStringValue()
if strings.TrimSpace(name) == "" {
return nil, nil
}

params := &cloudwatchlogs.DescribeLogGroupsInput{
LogGroupNamePrefix: aws.String(name),
}
Expand Down