From da744b1c030998d84b79f55fe14123fecad5fc97 Mon Sep 17 00:00:00 2001 From: Patrick Decat Date: Tue, 26 Nov 2024 05:46:30 +0100 Subject: [PATCH] Add tags column to aws_backup_plan table (#2336) --- aws/backup_tags.go | 50 +++++++++++++++++++++++++ aws/table_aws_backup_plan.go | 26 +++++++++++++ aws/table_aws_backup_recovery_point.go | 52 +++----------------------- aws/table_aws_backup_vault.go | 33 +--------------- 4 files changed, 82 insertions(+), 79 deletions(-) create mode 100644 aws/backup_tags.go diff --git a/aws/backup_tags.go b/aws/backup_tags.go new file mode 100644 index 000000000..a888e881a --- /dev/null +++ b/aws/backup_tags.go @@ -0,0 +1,50 @@ +package aws + +import ( + "context" + "errors" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/backup" + "github.com/aws/smithy-go" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin" +) + +func getAwsBackupResourceTags(ctx context.Context, d *plugin.QueryData, arn string) (interface{}, error) { + // Create Session + svc, err := BackupClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("backup_tags.getAwsBackupResourceTags", "connection_error", err) + return nil, err + } + if svc == nil { + // Unsupported region, return no data + return nil, nil + } + + params := &backup.ListTagsInput{ + ResourceArn: aws.String(arn), + } + + op, err := svc.ListTags(ctx, params) + plugin.Logger(ctx).Debug("backup_tags.getAwsBackupResourceTags", "ListTagsOutput", op) + if err != nil { + var ae smithy.APIError + if errors.As(err, &ae) { + plugin.Logger(ctx).Debug("backup_tags.getAwsBackupResourceTags", "smithy.APIError", ae) + if ae.ErrorCode() == "ResourceNotFoundException" { + return &backup.ListTagsOutput{ + Tags: map[string]string{}, + }, nil + } + } + plugin.Logger(ctx).Error("backup_tags.getAwsBackupResourceTags", "api_error", err) + return nil, err + } + + if op.Tags == nil { + op.Tags = map[string]string{} + } + + return op, nil +} diff --git a/aws/table_aws_backup_plan.go b/aws/table_aws_backup_plan.go index 588586c76..73af6e153 100644 --- a/aws/table_aws_backup_plan.go +++ b/aws/table_aws_backup_plan.go @@ -37,6 +37,10 @@ func tableAwsBackupPlan(_ context.Context) *plugin.Table { Func: getAwsBackupPlan, Tags: map[string]string{"service": "backup", "action": "GetBackupPlan"}, }, + { + Func: getAwsBackupPlanTags, + Tags: map[string]string{"service": "backup", "action": "ListTags"}, + }, }, GetMatrixItemFunc: SupportedRegionMatrix(backupv1.EndpointsID), Columns: awsRegionalColumns([]*plugin.Column{ @@ -101,6 +105,12 @@ func tableAwsBackupPlan(_ context.Context) *plugin.Table { Type: proto.ColumnType_STRING, Transform: transform.FromField("BackupPlanName", "BackupPlan.BackupPlanName"), }, + { + Name: "tags", + Description: resourceInterfaceDescription("tags"), + Type: proto.ColumnType_JSON, + Hydrate: getAwsBackupPlanTags, + }, { Name: "akas", Description: resourceInterfaceDescription("akas"), @@ -213,3 +223,19 @@ func getAwsBackupPlan(ctx context.Context, d *plugin.QueryData, h *plugin.Hydrat return op, nil } + +func getAwsBackupPlanTags(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + arn := backupPlanArn(h.Item) + + return getAwsBackupResourceTags(ctx, d, arn) +} + +func backupPlanArn(item interface{}) string { + switch item := item.(type) { + case types.BackupPlansListMember: + return *item.BackupPlanArn + case backup.GetBackupPlanOutput: + return *item.BackupPlanArn + } + return "" +} diff --git a/aws/table_aws_backup_recovery_point.go b/aws/table_aws_backup_recovery_point.go index 677f749c4..c22ff65dd 100644 --- a/aws/table_aws_backup_recovery_point.go +++ b/aws/table_aws_backup_recovery_point.go @@ -2,15 +2,12 @@ package aws import ( "context" - "errors" - "regexp" "strings" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/service/backup" "github.com/aws/aws-sdk-go-v2/service/backup/types" - "github.com/aws/smithy-go" backupv1 "github.com/aws/aws-sdk-go/service/backup" @@ -57,6 +54,10 @@ func tableAwsBackupRecoveryPoint(_ context.Context) *plugin.Table { Func: getAwsBackupRecoveryPoint, Tags: map[string]string{"service": "backup", "action": "DescribeRecoveryPoint"}, }, + { + Func: getAwsBackupRecoveryPointTags, + Tags: map[string]string{"service": "backup", "action": "ListTags"}, + }, }, GetMatrixItemFunc: SupportedRegionMatrix(backupv1.EndpointsID), Columns: awsRegionalColumns([]*plugin.Column{ @@ -327,50 +328,7 @@ func getAwsBackupRecoveryPoint(ctx context.Context, d *plugin.QueryData, h *plug func getAwsBackupRecoveryPointTags(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { arn := recoveryPointArn(h.Item) - // Define the regex pattern for the recovery point ARN - pattern := `arn:aws:backup:[a-z0-9\-]+:[0-9]{12}:recovery-point:.*` - - // Create a regular expression object - re := regexp.MustCompile(pattern) - - // Only return the tags associated with the resovery point - if !re.MatchString(arn) { - return nil, nil - } - - // Create Session - svc, err := BackupClient(ctx, d) - if err != nil { - plugin.Logger(ctx).Error("aws_backup_recovery_point.getAwsBackupRecoveryPointTags", "connection_error", err) - return nil, err - } - if svc == nil { - // Unsupported region, return no data - return nil, nil - } - - params := &backup.ListTagsInput{ - ResourceArn: aws.String(arn), - } - - op, err := svc.ListTags(ctx, params) - if err != nil { - - var ae smithy.APIError - if errors.As(err, &ae) { - if ae.ErrorCode() == "ResourceNotFoundException" { - return &backup.GetBackupVaultNotificationsOutput{}, nil - } - } - plugin.Logger(ctx).Error("aws_backup_recovery_point.getAwsBackupRecoveryPointTags", "api_error", err) - return nil, err - } - - if op.Tags == nil { - return nil, nil - } - - return op, nil + return getAwsBackupResourceTags(ctx, d, arn) } func recoveryPointArn(item interface{}) string { diff --git a/aws/table_aws_backup_vault.go b/aws/table_aws_backup_vault.go index 6b7e03eec..aa1c1ee4e 100644 --- a/aws/table_aws_backup_vault.go +++ b/aws/table_aws_backup_vault.go @@ -259,10 +259,6 @@ func getAwsBackupVaultNotification(ctx context.Context, d *plugin.QueryData, h * plugin.Logger(ctx).Error("aws_backup_vault.getAwsBackupVaultNotification", "connection_error", err) return nil, err } - if svc == nil { - // Unsupported region, return no data - return nil, nil - } if svc == nil { // Unsupported region, return no data @@ -294,36 +290,9 @@ func getAwsBackupVaultNotification(ctx context.Context, d *plugin.QueryData, h * } func getAwsBackupVaultTags(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { - // Create Session - svc, err := BackupClient(ctx, d) - if err != nil { - plugin.Logger(ctx).Error("aws_backup_vault.getAwsBackupVaultTags", "connection_error", err) - return nil, err - } - if svc == nil { - // Unsupported region, return no data - return nil, nil - } - arn := vaultArn(h.Item) - params := &backup.ListTagsInput{ - ResourceArn: aws.String(arn), - } - - op, err := svc.ListTags(ctx, params) - if err != nil { - - var ae smithy.APIError - if errors.As(err, &ae) { - if ae.ErrorCode() == "ResourceNotFoundException" { - return &backup.ListTagsOutput{}, nil - } - } - plugin.Logger(ctx).Error("aws_backup_vault.getAwsBackupVaultTags", "api_error", err) - return nil, err - } - return op, nil + return getAwsBackupResourceTags(ctx, d, arn) } func getAwsBackupVaultAccessPolicy(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {