Skip to content

Add aws_ses_template table #2480

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

Merged
merged 10 commits into from
May 21, 2025
Merged

Add aws_ses_template table #2480

merged 10 commits into from
May 21, 2025

Conversation

misraved
Copy link
Contributor

@misraved misraved commented Apr 30, 2025

Integration test logs

Logs
Add passing integration test logs here

Example query results

Results
select * from aws_ses_template
+------------------+--------------------------+---------------------------------+------------------------------------------+---------------------------+------------------+------------------------------------------------------------------+-----------+-----------+------->
| name             | subject_part             | text_part                       | html_part                                | created_timestamp         | title            | akas                                                             | partition | region    | accoun>
+------------------+--------------------------+---------------------------------+------------------------------------------+---------------------------+------------------+------------------------------------------------------------------+-----------+-----------+------->
| MySimpleTemplate | Updated subject from SES | This is the updated text email. | <h1>This is the updated HTML email.</h1> | 2025-05-20T19:09:49+05:30 | MySimpleTemplate | ["arn:aws:ses:us-east-1:111111111111111:template/MySimpleTemplate"] | aws       | us-east-1 | 111111111111>
+------------------+--------------------------+---------------------------------+------------------------------------------+---------------------------+------------------

@misraved misraved requested review from ParthaI and Copilot April 30, 2025 09:52
@misraved misraved self-assigned this Apr 30, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request adds support for querying AWS SES Templates by introducing a new table definition and corresponding integration tests.

  • Introduces documentation for the aws_ses_template table.
  • Implements the aws_ses_template table in Go with list and get hydrate functions.
  • Updates the plugin to register the new table.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
docs/tables/aws_ses_template.md Adds documentation and usage examples for the aws_ses_template table.
aws/table_aws_ses_template.go Implements the aws_ses_template table with list and get functions using AWS SDK v2 and v1 where applicable.
aws/plugin.go Registers the aws_ses_template table with the plugin.

Copy link
Contributor

@ParthaI ParthaI left a comment

Choose a reason for hiding this comment

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

Hello @misraved, the changes look great. However, I've added a couple of suggestions—could you please take a look?

Copy link
Contributor

@ParthaI ParthaI left a comment

Choose a reason for hiding this comment

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

@misraved, left a few review comments; please take a look. Thanks!

Copy link
Contributor

@ParthaI ParthaI left a comment

Choose a reason for hiding this comment

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

Hi @misraved,
Could you please take a look at the following points:

  • There seems to be a mismatch between the List and Get API responses.
  • The List API returns a property called Name, while the Get API returns a field named TemplateName.
  • When running the query:
    select * from aws_ses_template where name = 'MySimpleTemplate';
    the Get API is triggered. Although it successfully returns the template data, the name column in the result appears as null because the Get API response does not include a Name field—only TemplateName. As a result, the query displays an empty row.
  • Additionally, I’m encountering the following error:
> select * from aws_ses_template where name = 'MySimpleTemplate';
Error: rpc error: code = Internal desc = aws: rpc error: code = Internal desc = hydrate function getSESTemplateARN failed with panic interface conversion: interface {} is *types.Template, not types.TemplateMetadata (SQLSTATE HV000)

+------+--------------+-----------+-----------+-------------------+-------+------+-----------+--------+------------+--------------------+--------+------+
| name | subject_part | text_part | html_part | created_timestamp | title | akas | partition | region | account_id | sp_connection_name | sp_ctx | _ctx |
+------+--------------+-----------+-----------+-------------------+-------+------+-----------+--------+------------+--------------------+--------+------+
+------+--------------+-----------+-----------+-------------------+-------+------+-----------+--------+------------+--------------------+--------+------+

@ParthaI
Copy link
Contributor

ParthaI commented May 21, 2025

Purpose-designed for created_timestamp to always be populated correctly:

  • Remove get config.
  • Use getSESTemplate as a Hyrate call.
  • Add name as an optional key qualifier.
  • Add a check in hydrate call if name quals are provided and stop execution if name value is not matched.

Updated code:

package aws

import (
	"context"

	"github.com/aws/aws-sdk-go-v2/service/ses"
	"github.com/aws/aws-sdk-go-v2/service/ses/types"

	"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"
)

func tableAwsSESTemplate(_ context.Context) *plugin.Table {
	return &plugin.Table{
		Name:        "aws_ses_template",
		Description: "AWS SES Template",
		List: &plugin.ListConfig{
			Hydrate: listSESTemplates,
			KeyColumns: plugin.KeyColumnSlice{
				{Name: "name", Require: plugin.Optional},
			},
			Tags: map[string]string{"service": "ses", "action": "ListTemplates"},
		},
		HydrateConfig: []plugin.HydrateConfig{
			{
				Func: getSESTemplate,
				Tags: map[string]string{"service": "ses", "action": "GetTemplate"},
			},
		},
		GetMatrixItemFunc: SupportedRegionMatrix(AWS_EMAIL_SERVICE_ID),
		Columns: awsRegionalColumns([]*plugin.Column{
			{
				Name:        "name",
				Description: "The name of the template.",
				Type:        proto.ColumnType_STRING,
				Transform:   transform.FromField("Name", "TemplateName"),
			},
			{
				Name:        "subject_part",
				Description: "The subject line of the email.",
				Type:        proto.ColumnType_STRING,
				Hydrate:     getSESTemplate,
			},
			{
				Name:        "text_part",
				Description: "The email body that will be visible to recipients whose email clients do not display HTML.",
				Type:        proto.ColumnType_STRING,
				Hydrate:     getSESTemplate,
			},
			{
				Name:        "html_part",
				Description: "The HTML body of the email.",
				Type:        proto.ColumnType_STRING,
				Hydrate:     getSESTemplate,
			},
			{
				Name:        "created_timestamp",
				Description: "The time and date the template was created.",
				Type:        proto.ColumnType_TIMESTAMP,
			},
			// Standard columns for all tables
			{
				Name:        "title",
				Description: resourceInterfaceDescription("title"),
				Type:        proto.ColumnType_STRING,
				Transform:   transform.FromField("Name", "TemplateName"),
			},
			{
				Name:        "akas",
				Description: resourceInterfaceDescription("akas"),
				Type:        proto.ColumnType_JSON,
				Hydrate:     getSESTemplateARN,
				Transform:   transform.FromValue().Transform(transform.EnsureStringArray),
			},
		}),
	}
}

//// LIST FUNCTION

func listSESTemplates(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {
	// Create Session
	svc, err := SESClient(ctx, d)
	if err != nil {
		plugin.Logger(ctx).Error("aws_ses_template.listSESTemplates", "connection_error", err)
		return nil, err
	}
	if svc == nil {
		// Unsupported region check
		return nil, nil
	}

	maxItems := int32(1000)
	// Limiting the results
	if d.QueryContext.Limit != nil {
		limit := int32(*d.QueryContext.Limit)
		if limit < maxItems {
			maxItems = limit
		}
	}

	input := &ses.ListTemplatesInput{
		MaxItems: &maxItems,
	}

	// List call
	output, err := svc.ListTemplates(ctx, input)
	if err != nil {
		plugin.Logger(ctx).Error("aws_ses_template.listSESTemplates", "api_error", err)
		return nil, err
	}

	for _, template := range output.TemplatesMetadata {
		d.StreamListItem(ctx, template)

		// Context can be cancelled due to manual cancellation or the limit has been hit
		if d.RowsRemaining(ctx) == 0 {
			return nil, nil
		}
	}

	return nil, nil
}

//// HYDRATE FUNCTIONS

func getSESTemplate(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
	var templateName string
	if h.Item != nil {
		templateName = *h.Item.(types.TemplateMetadata).Name
	}

	// Minimize the api call based on the quals
	if d.EqualsQualString("name") != "" && templateName != d.EqualsQualString("name") {
		plugin.Logger(ctx).Error("DID NOT match stop API call execution", templateName)
		return nil, nil
	}

	// Create Session
	svc, err := SESClient(ctx, d)
	if err != nil {
		plugin.Logger(ctx).Error("aws_ses_template.getSESTemplate", "connection_error", err)
		return nil, err
	}
	if svc == nil {
		// Unsupported region check
		return nil, nil
	}

	// Build the params
	params := &ses.GetTemplateInput{
		TemplateName: &templateName,
	}

	// Get call
	op, err := svc.GetTemplate(ctx, params)
	if err != nil {
		plugin.Logger(ctx).Error("aws_ses_template.getSESTemplate", "api_error", err)
		return nil, err
	}

	return op.Template, nil
}

func getSESTemplateARN(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
	var templateName string
	switch item := h.Item.(type) {
	case types.TemplateMetadata:
		templateName = *item.Name
	case *types.Template:
		templateName = *item.TemplateName
	default:
		return nil, nil
	}
	region := d.EqualsQualString(matrixKeyRegion)

	c, err := getCommonColumns(ctx, d, h)
	if err != nil {
		plugin.Logger(ctx).Error("aws_ses_template.getSESTemplateARN", "api_error", err)
		return nil, err
	}
	commonColumnData := c.(*awsCommonColumnData)
	arn := "arn:" + commonColumnData.Partition + ":ses:" + region + ":" + commonColumnData.AccountId + ":template/" + templateName
	return arn, nil
}

@ParthaI ParthaI requested a review from Copilot May 21, 2025 06:08
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds a new Steampipe table for querying AWS SES Templates, including documentation and implementation for listing and retrieving template details.

  • Introduces detailed markdown documentation with usage examples for the aws_ses_template table.
  • Implements the table and its list/hydrate functions in Go.
  • Updates the plugin registration to include the new table.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
docs/tables/aws_ses_template.md Adds documentation and usage examples for aws_ses_template.
aws/table_aws_ses_template.go Implements the aws_ses_template table and related functions.
aws/plugin.go Registers the new aws_ses_template table.
Comments suppressed due to low confidence (1)

aws/table_aws_ses_template.go:65

  • [nitpick] The 'title' column uses the same transformation as the 'name' column, which could be ambiguous. Consider clarifying its purpose or using a distinct transform if it is intended to offer different information.
    {

@misraved misraved merged commit 7745ce7 into main May 21, 2025
1 check passed
@misraved misraved deleted the add-ses-template-table branch May 21, 2025 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants