Skip to content
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 aws/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
"aws_bedrock_custom_model": tableAwsBedrockCustomModel(ctx),
"aws_bedrock_foundation_model": tableAwsBedrockFoundationModel(ctx),
"aws_bedrock_imported_model": tableAwsBedrockImportedModel(ctx),
"aws_bedrock_guardrail": tableAwsBedrockGuardrail(ctx),
"aws_cloudcontrol_resource": tableAwsCloudControlResource(ctx),
"aws_cloudformation_stack_resource": tableAwsCloudFormationStackResource(ctx),
"aws_cloudformation_stack_set": tableAwsCloudFormationStackSet(ctx),
Expand Down
181 changes: 181 additions & 0 deletions aws/table_aws_bedrock_guardrail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package aws

import (
"context"
"time"

"github.com/aws/aws-sdk-go-v2/service/bedrock"
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
)

// unified row used for both List and Get paths
type bedrockGuardrailRow struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the custom struct necessary here?

Arn string `json:"Arn"`
GuardrailId string `json:"GuardrailId"`
Name string `json:"Name"`
Description string `json:"Description"`
Status string `json:"Status"`
Version string `json:"Version"`
CreatedAt time.Time `json:"CreatedAt"`
UpdatedAt time.Time `json:"UpdatedAt"`
}

func tableAwsBedrockGuardrail(_ context.Context) *plugin.Table {
return &plugin.Table{
Name: "aws_bedrock_guardrail",
Description: "Amazon Bedrock Guardrail.",
List: &plugin.ListConfig{
Hydrate: listBedrockGuardrails,
Tags: map[string]string{"service": "bedrock", "action": "ListGuardrails"},
},
Get: &plugin.GetConfig{
// allow lookup by ID or ARN (both map to GuardrailIdentifier)
KeyColumns: plugin.AnyColumn([]string{"guardrail_id", "arn"}),
Hydrate: getBedrockGuardrail,
Tags: map[string]string{"service": "bedrock", "action": "GetGuardrail"},
IgnoreConfig: &plugin.IgnoreConfig{
ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}),
},
},
GetMatrixItemFunc: SupportedRegionMatrix(AWS_BEDROCK_SERVICE_ID),
Columns: awsRegionalColumns([]*plugin.Column{
// identifiers
{Name: "arn", Type: proto.ColumnType_STRING, Description: "ARN of the guardrail.", Transform: transform.FromField("Arn")},
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please confirm whether we should include an explicit transform here (Transform: transform.FromField("Arn")), or if the plugin-level default (DefaultTransform: transform.FromCamel()) already covers this case?

Also, please review the other columns and let me know if any of them require an explicit transform.

{Name: "guardrail_id", Type: proto.ColumnType_STRING, Description: "ID of the guardrail.", Transform: transform.FromField("GuardrailId")},
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{Name: "guardrail_id", Type: proto.ColumnType_STRING, Description: "ID of the guardrail.", Transform: transform.FromField("GuardrailId")},
{Name: "id", Type: proto.ColumnType_STRING, Description: "The unique identifier of the guardrail."},


// metadata
{Name: "name", Type: proto.ColumnType_STRING, Description: "Name of the guardrail.", Transform: transform.FromField("Name")},
{Name: "description", Type: proto.ColumnType_STRING, Description: "Description of the guardrail.", Transform: transform.FromField("Description")},

// status / version
{Name: "status", Type: proto.ColumnType_STRING, Description: "Status of the guardrail.", Transform: transform.FromField("Status")},
{Name: "version", Type: proto.ColumnType_STRING, Description: "Version (DRAFT or a number).", Transform: transform.FromField("Version")},

// timestamps
{Name: "created_at", Type: proto.ColumnType_TIMESTAMP, Transform: transform.FromField("CreatedAt")},
{Name: "updated_at", Type: proto.ColumnType_TIMESTAMP, Transform: transform.FromField("UpdatedAt")},

// steampipe standard
{Name: "title", Type: proto.ColumnType_STRING, Transform: transform.FromField("Name")},
{Name: "akas", Type: proto.ColumnType_JSON, Transform: transform.FromField("Arn").Transform(transform.EnsureStringArray)},
Comment on lines +57 to +62
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add the missing description.

}),
}
}

// LIST: map GuardrailSummary -> bedrockGuardrailRow (ensures Arn/Id are set)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// LIST: map GuardrailSummary -> bedrockGuardrailRow (ensures Arn/Id are set)
//// LIST FUNCTION

func listBedrockGuardrails(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {
svc, err := BedrockClient(ctx, d)
if svc == nil {
return nil, nil
}
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.listBedrockGuardrails", "connection_error", err)
return nil, err
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.listBedrockGuardrails", "connection_error", err)
return nil, err
}
if svc == nil {
return nil, err
}
Comment on lines +70 to +82
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please remove the duplicated code block?


p := bedrock.NewListGuardrailsPaginator(svc, &bedrock.ListGuardrailsInput{})
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you set the input parameter MaxResults to 1000 by default, and also honor a user-specified limit in the query parameters? For reference, see https://github.com/turbot/steampipe-plugin-aws/blob/main/aws/table_aws_appsync_api.go#L117-L135.

for p.HasMorePages() {
out, err := p.NextPage(ctx)
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.listBedrockGuardrails", "api_error", err)
return nil, err
}
for _, s := range out.Guardrails {
row := bedrockGuardrailRow{
Arn: str(s.Arn),
GuardrailId: str(s.Id),
Name: str(s.Name),
Description: str(s.Description),
Status: string(s.Status),
Version: str(s.Version),
CreatedAt: t(s.CreatedAt),
UpdatedAt: t(s.UpdatedAt),
}
Comment on lines +92 to +101
Copy link
Contributor

Choose a reason for hiding this comment

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

I don’t think we need a custom struct—let’s stream the API response as-is. The Get API response includes more detail than the List response, so we should expose all top-level properties as table columns. For fields that are only available via Get, add per-column Hydrate functions. For reference, see the aws_bedrock_agent table.

d.StreamListItem(ctx, row)
if d.RowsRemaining(ctx) == 0 {
return nil, nil
}
}
}
return nil, nil
}

// GET: map GetGuardrailOutput -> bedrockGuardrailRow (ensures Arn/Id are set)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// GET: map GetGuardrailOutput -> bedrockGuardrailRow (ensures Arn/Id are set)
//// HYDRATE FUNCTIONS

func getBedrockGuardrail(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {

Check failure on line 112 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name getBedrockGuardrail, expected (

Check failure on line 112 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name getBedrockGuardrail, expected (
id := d.EqualsQualString("guardrail_id")
if id == "" {
id = d.EqualsQualString("arn")
}
if id == "" {
return nil, nil
}

svc, err := BedrockClient(ctx, d)
if svc == nil {
return nil, nil
}
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.getBedrockGuardrail", "connection_error", err)
return nil, err
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.getBedrockGuardrail", "connection_error", err)
return nil, err
}
if svc == nil {
return nil, nil
}
Comment on lines +122 to +134
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please remove the duplicated code block?


out, err := svc.GetGuardrail(ctx, &bedrock.GetGuardrailInput{
GuardrailIdentifier: &id, // accepts ID or ARN
})
if err != nil {
plugin.Logger(ctx).Error("aws_bedrock_guardrail.getBedrockGuardrail", "api_error", err)
return nil, err
}

row := bedrockGuardrailRow{
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is required anymore.

Arn: str(out.GuardrailArn),
GuardrailId: str(out.GuardrailId),
Name: str(out.Name),
Description: str(out.Description),
Status: string(out.Status),
Version: str(out.Version),
CreatedAt: t(out.CreatedAt),
UpdatedAt: t(out.UpdatedAt),
}
return row, nil
}

// small ptr helpers (avoid extra deps)
func str(p *string) string {

Check failure on line 158 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name str, expected (

Check failure on line 158 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name str, expected (
if p == nil {
return ""
}
return *p
}
func t(p *time.Time) time.Time {

Check failure on line 164 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name t, expected (

Check failure on line 164 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected name t, expected (
if p == nil {
return time.Time{}
}
return *p
}
Arn: aws.ToString(out.GuardrailArn),
GuardrailId: aws.ToString(out.GuardrailId),

Check failure on line 171 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected :, expected := or = or comma (typecheck)

Check failure on line 171 in aws/table_aws_bedrock_guardrail.go

View workflow job for this annotation

GitHub Actions / golangci_lint_workflow / lint

syntax error: unexpected :, expected := or = or comma) (typecheck)
Name: aws.ToString(out.Name),
Description: aws.ToString(out.Description),
Status: string(out.Status),
Version: aws.ToString(out.Version),
CreatedAt: aws.ToTime(out.CreatedAt),
UpdatedAt: aws.ToTime(out.UpdatedAt),
}
return row, nil
}

Loading