From 66c95e137001378919a42b33bfc18e946651b412 Mon Sep 17 00:00:00 2001 From: ParthaI <47887552+ParthaI@users.noreply.github.com> Date: Tue, 20 Aug 2024 18:36:26 +0530 Subject: [PATCH] Add table aws_timestreamwrite_database and aws_timestreamwrite_table Closes #2263 #2262 (#2269) --- .../dependencies.txt | 0 .../test-get-expected.json | 6 + .../test-get-query.sql | 3 + .../test-list-call-expected.json | 6 + .../test-list-call-query.sql | 3 + .../test-turbot-expected.json | 6 + .../test-turbot-query.sql | 3 + .../variables.json | 1 + .../aws_timestreamwrite_database/variables.tf | 102 +++++++++ .../dependencies.txt | 0 .../test-get-expected.json | 7 + .../test-get-query.sql | 3 + .../test-list-call-expected.json | 6 + .../test-list-call-query.sql | 3 + .../test-turbot-expected.json | 6 + .../test-turbot-query.sql | 3 + .../aws_timestreamwrite_table/variables.json | 1 + .../aws_timestreamwrite_table/variables.tf | 116 ++++++++++ aws/plugin.go | 2 + aws/service.go | 13 ++ aws/table_aws_timestreamwrite_database.go | 170 +++++++++++++++ aws/table_aws_timestreamwrite_table.go | 198 ++++++++++++++++++ docs/tables/aws_timestreamwrite_database.md | 137 ++++++++++++ docs/tables/aws_timestreamwrite_table.md | 164 +++++++++++++++ go.mod | 3 +- go.sum | 6 +- 26 files changed, 965 insertions(+), 3 deletions(-) create mode 100644 aws-test/tests/aws_timestreamwrite_database/dependencies.txt create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-get-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-get-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-list-call-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-list-call-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-turbot-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_database/test-turbot-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_database/variables.json create mode 100644 aws-test/tests/aws_timestreamwrite_database/variables.tf create mode 100644 aws-test/tests/aws_timestreamwrite_table/dependencies.txt create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-get-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-get-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-list-call-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-list-call-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-turbot-expected.json create mode 100644 aws-test/tests/aws_timestreamwrite_table/test-turbot-query.sql create mode 100644 aws-test/tests/aws_timestreamwrite_table/variables.json create mode 100644 aws-test/tests/aws_timestreamwrite_table/variables.tf create mode 100644 aws/table_aws_timestreamwrite_database.go create mode 100644 aws/table_aws_timestreamwrite_table.go create mode 100644 docs/tables/aws_timestreamwrite_database.md create mode 100644 docs/tables/aws_timestreamwrite_table.md diff --git a/aws-test/tests/aws_timestreamwrite_database/dependencies.txt b/aws-test/tests/aws_timestreamwrite_database/dependencies.txt new file mode 100644 index 000000000..e69de29bb diff --git a/aws-test/tests/aws_timestreamwrite_database/test-get-expected.json b/aws-test/tests/aws_timestreamwrite_database/test-get-expected.json new file mode 100644 index 000000000..cf8a1b65f --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-get-expected.json @@ -0,0 +1,6 @@ +[ + { + "arn": "{{ output.resource_aka.value }}", + "database_name": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_database/test-get-query.sql b/aws-test/tests/aws_timestreamwrite_database/test-get-query.sql new file mode 100644 index 000000000..9ee60d40a --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-get-query.sql @@ -0,0 +1,3 @@ +select arn, database_name +from aws.aws_timestreamwrite_database +where database_name = '{{ resourceName }}'; diff --git a/aws-test/tests/aws_timestreamwrite_database/test-list-call-expected.json b/aws-test/tests/aws_timestreamwrite_database/test-list-call-expected.json new file mode 100644 index 000000000..cf8a1b65f --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-list-call-expected.json @@ -0,0 +1,6 @@ +[ + { + "arn": "{{ output.resource_aka.value }}", + "database_name": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_database/test-list-call-query.sql b/aws-test/tests/aws_timestreamwrite_database/test-list-call-query.sql new file mode 100644 index 000000000..b438115e6 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-list-call-query.sql @@ -0,0 +1,3 @@ +select arn, database_name +from aws.aws_timestreamwrite_database +where akas::text = '["{{ output.resource_aka.value }}"]'; diff --git a/aws-test/tests/aws_timestreamwrite_database/test-turbot-expected.json b/aws-test/tests/aws_timestreamwrite_database/test-turbot-expected.json new file mode 100644 index 000000000..eb472ba02 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-turbot-expected.json @@ -0,0 +1,6 @@ +[ + { + "akas": ["{{ output.resource_aka.value }}"], + "title": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_database/test-turbot-query.sql b/aws-test/tests/aws_timestreamwrite_database/test-turbot-query.sql new file mode 100644 index 000000000..a9207b9cb --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/test-turbot-query.sql @@ -0,0 +1,3 @@ +select akas, title +from aws.aws_timestreamwrite_database +where akas::text = '["{{ output.resource_aka.value }}"]'; diff --git a/aws-test/tests/aws_timestreamwrite_database/variables.json b/aws-test/tests/aws_timestreamwrite_database/variables.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/variables.json @@ -0,0 +1 @@ +{} diff --git a/aws-test/tests/aws_timestreamwrite_database/variables.tf b/aws-test/tests/aws_timestreamwrite_database/variables.tf new file mode 100644 index 000000000..6ec9795c0 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_database/variables.tf @@ -0,0 +1,102 @@ + +variable "resource_name" { + type = string + default = "turbot-test-20200125-create-update" + description = "Name of the resource used throughout the test." +} + +variable "aws_profile" { + type = string + default = "default" + description = "AWS credentials profile used for the test. Default is to use the default profile." +} + +variable "aws_region" { + type = string + default = "us-east-1" + description = "AWS region used for the test. Does not work with default region in config, so must be defined here." +} + +variable "aws_region_alternate" { + type = string + default = "us-east-2" + description = "Alternate AWS region used for tests that require two regions (e.g. DynamoDB global tables)." +} + +provider "aws" { + profile = var.aws_profile + region = var.aws_region +} + +provider "aws" { + alias = "alternate" + profile = var.aws_profile + region = var.aws_region_alternate +} + +data "aws_partition" "current" {} +data "aws_caller_identity" "current" {} +data "aws_region" "primary" {} +data "aws_region" "alternate" { + provider = aws.alternate +} + +data "null_data_source" "resource" { + inputs = { + scope = "arn:${data.aws_partition.current.partition}:::${data.aws_caller_identity.current.account_id}" + } +} + +resource "aws_kms_key" "named_test_resource" { + description = "An example symmetric encryption KMS key" + enable_key_rotation = true + deletion_window_in_days = 20 +} + +resource "aws_kms_key_policy" "named_test_resource" { + key_id = aws_kms_key.named_test_resource.id + policy = jsonencode({ + Version = "2012-10-17" + Id = "key-default-1" + Statement = [ + { + Sid = "Enable IAM User Permissions" + Effect = "Allow" + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + }, + Action = "kms:*" + Resource = "*" + } + ] + }) +} + +resource "aws_timestreamwrite_database" "named_test_resource" { + database_name = var.resource_name + kms_key_id = aws_kms_key.named_test_resource.arn + + tags = { + Name = var.resource_name + } +} + +output "resource_aka" { + value = aws_timestreamwrite_database.named_test_resource.arn +} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +output "region_name" { + value = data.aws_region.primary.name +} + +output "aws_partition" { + value = data.aws_partition.current.partition +} + +output "resource_name" { + value = var.resource_name +} diff --git a/aws-test/tests/aws_timestreamwrite_table/dependencies.txt b/aws-test/tests/aws_timestreamwrite_table/dependencies.txt new file mode 100644 index 000000000..e69de29bb diff --git a/aws-test/tests/aws_timestreamwrite_table/test-get-expected.json b/aws-test/tests/aws_timestreamwrite_table/test-get-expected.json new file mode 100644 index 000000000..5ed6c7032 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-get-expected.json @@ -0,0 +1,7 @@ +[ + { + "arn": "{{ output.resource_aka.value }}", + "database_name": "{{ resourceName }}", + "table_name": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_table/test-get-query.sql b/aws-test/tests/aws_timestreamwrite_table/test-get-query.sql new file mode 100644 index 000000000..ccd5990e8 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-get-query.sql @@ -0,0 +1,3 @@ +select table_name, arn, database_name +from aws.aws_timestreamwrite_table +where table_name = '{{ resourceName }}' and database_name = '{{ resourceName }}'; diff --git a/aws-test/tests/aws_timestreamwrite_table/test-list-call-expected.json b/aws-test/tests/aws_timestreamwrite_table/test-list-call-expected.json new file mode 100644 index 000000000..577d416cf --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-list-call-expected.json @@ -0,0 +1,6 @@ +[ + { + "arn": "{{ output.resource_aka.value }}", + "table_name": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_table/test-list-call-query.sql b/aws-test/tests/aws_timestreamwrite_table/test-list-call-query.sql new file mode 100644 index 000000000..2d49d8519 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-list-call-query.sql @@ -0,0 +1,3 @@ +select arn, table_name +from aws.aws_timestreamwrite_table +where akas::text = '["{{ output.resource_aka.value }}"]'; diff --git a/aws-test/tests/aws_timestreamwrite_table/test-turbot-expected.json b/aws-test/tests/aws_timestreamwrite_table/test-turbot-expected.json new file mode 100644 index 000000000..eb472ba02 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-turbot-expected.json @@ -0,0 +1,6 @@ +[ + { + "akas": ["{{ output.resource_aka.value }}"], + "title": "{{ resourceName }}" + } +] diff --git a/aws-test/tests/aws_timestreamwrite_table/test-turbot-query.sql b/aws-test/tests/aws_timestreamwrite_table/test-turbot-query.sql new file mode 100644 index 000000000..2812f1d0a --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/test-turbot-query.sql @@ -0,0 +1,3 @@ +select akas, title +from aws.aws_timestreamwrite_table +where akas::text = '["{{ output.resource_aka.value }}"]'; diff --git a/aws-test/tests/aws_timestreamwrite_table/variables.json b/aws-test/tests/aws_timestreamwrite_table/variables.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/variables.json @@ -0,0 +1 @@ +{} diff --git a/aws-test/tests/aws_timestreamwrite_table/variables.tf b/aws-test/tests/aws_timestreamwrite_table/variables.tf new file mode 100644 index 000000000..916e618f6 --- /dev/null +++ b/aws-test/tests/aws_timestreamwrite_table/variables.tf @@ -0,0 +1,116 @@ + +variable "resource_name" { + type = string + default = "turbot-test-20200125-create-update" + description = "Name of the resource used throughout the test." +} + +variable "aws_profile" { + type = string + default = "default" + description = "AWS credentials profile used for the test. Default is to use the default profile." +} + +variable "aws_region" { + type = string + default = "us-east-1" + description = "AWS region used for the test. Does not work with default region in config, so must be defined here." +} + +variable "aws_region_alternate" { + type = string + default = "us-east-2" + description = "Alternate AWS region used for tests that require two regions (e.g. DynamoDB global tables)." +} + +provider "aws" { + profile = var.aws_profile + region = var.aws_region +} + +provider "aws" { + alias = "alternate" + profile = var.aws_profile + region = var.aws_region_alternate +} + +data "aws_partition" "current" {} +data "aws_caller_identity" "current" {} +data "aws_region" "primary" {} +data "aws_region" "alternate" { + provider = aws.alternate +} + +data "null_data_source" "resource" { + inputs = { + scope = "arn:${data.aws_partition.current.partition}:::${data.aws_caller_identity.current.account_id}" + } +} + +resource "aws_kms_key" "named_test_resource" { + description = "An example symmetric encryption KMS key" + enable_key_rotation = true + deletion_window_in_days = 20 +} + +resource "aws_kms_key_policy" "named_test_resource" { + key_id = aws_kms_key.named_test_resource.id + policy = jsonencode({ + Version = "2012-10-17" + Id = "key-default-1" + Statement = [ + { + Sid = "Enable IAM User Permissions" + Effect = "Allow" + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + }, + Action = "kms:*" + Resource = "*" + } + ] + }) +} + +resource "aws_timestreamwrite_database" "named_test_resource" { + database_name = var.resource_name + kms_key_id = aws_kms_key.named_test_resource.arn + + tags = { + Name = var.resource_name + } +} + +resource "aws_timestreamwrite_table" "named_test_resource" { + database_name = aws_timestreamwrite_database.named_test_resource.database_name + table_name = var.resource_name + + retention_properties { + magnetic_store_retention_period_in_days = 30 + memory_store_retention_period_in_hours = 8 + } + + tags = { + Name = var.resource_name + } +} + +output "resource_aka" { + value = aws_timestreamwrite_table.named_test_resource.arn +} + +output "account_id" { + value = data.aws_caller_identity.current.account_id +} + +output "region_name" { + value = data.aws_region.primary.name +} + +output "aws_partition" { + value = data.aws_partition.current.partition +} + +output "resource_name" { + value = var.resource_name +} diff --git a/aws/plugin.go b/aws/plugin.go index 75f0dee19..fbf0a5917 100644 --- a/aws/plugin.go +++ b/aws/plugin.go @@ -509,6 +509,8 @@ func Plugin(ctx context.Context) *plugin.Plugin { "aws_ssoadmin_permission_set": tableAwsSsoAdminPermissionSet(ctx), "aws_sts_caller_identity": tableAwsSTSCallerIdentity(ctx), "aws_tagging_resource": tableAwsTaggingResource(ctx), + "aws_timestreamwrite_database": tableAwsTimestreamwriteDatabase(ctx), + "aws_timestreamwrite_table": tableAwsTimestreamwriteTable(ctx), "aws_transfer_server": tableAwsTransferServer(ctx), "aws_transfer_user": tableAwsTransferUser(ctx), "aws_trusted_advisor_check_summary": tableAwsTrustedAdvisorCheckSummary(ctx), diff --git a/aws/service.go b/aws/service.go index f1e9d58f1..7418758c8 100644 --- a/aws/service.go +++ b/aws/service.go @@ -132,6 +132,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ssoadmin" "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/aws/aws-sdk-go-v2/service/support" + "github.com/aws/aws-sdk-go-v2/service/timestreamwrite" "github.com/aws/aws-sdk-go-v2/service/transfer" "github.com/aws/aws-sdk-go-v2/service/waf" "github.com/aws/aws-sdk-go-v2/service/wafregional" @@ -202,6 +203,7 @@ import ( ssmEndpoint "github.com/aws/aws-sdk-go/service/ssm" ssmIncidentsEndpoint "github.com/aws/aws-sdk-go/service/ssmincidents" ssoEndpoint "github.com/aws/aws-sdk-go/service/sso" + timestreamwriteEndpoint "github.com/aws/aws-sdk-go/service/timestreamwrite" transferEndpoint "github.com/aws/aws-sdk-go/service/transfer" wafregionalEndpoint "github.com/aws/aws-sdk-go/service/wafregional" wafv2Endpoint "github.com/aws/aws-sdk-go/service/wafv2" @@ -1564,6 +1566,17 @@ func TransferClient(ctx context.Context, d *plugin.QueryData) (*transfer.Client, return transfer.NewFromConfig(*cfg), nil } +func TimestreamwriteClient(ctx context.Context, d *plugin.QueryData) (*timestreamwrite.Client, error) { + cfg, err := getClientForQuerySupportedRegion(ctx, d, timestreamwriteEndpoint.EndpointsID) + if err != nil { + return nil, err + } + if cfg == nil { + return nil, nil + } + return timestreamwrite.NewFromConfig(*cfg), nil +} + func WAFClient(ctx context.Context, d *plugin.QueryData) (*waf.Client, error) { // WAF Classic a global service with a single DNS endpoint // (waf.amazonaws.com). diff --git a/aws/table_aws_timestreamwrite_database.go b/aws/table_aws_timestreamwrite_database.go new file mode 100644 index 000000000..fa5cb66bc --- /dev/null +++ b/aws/table_aws_timestreamwrite_database.go @@ -0,0 +1,170 @@ +package aws + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/timestreamwrite" + + timestreamwritev1 "github.com/aws/aws-sdk-go/service/timestreamwrite" + + "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" +) + +//// TABLE DEFINITION + +func tableAwsTimestreamwriteDatabase(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "aws_timestreamwrite_database", + Description: "AWS Timestreamwrite Database", + Get: &plugin.GetConfig{ + KeyColumns: plugin.SingleColumn("database_name"), + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + Hydrate: getAwsTimestreamwriteDatabase, + Tags: map[string]string{"service": "timestream-write", "action": "DescribeDatabase"}, + }, + List: &plugin.ListConfig{ + Hydrate: listAwsTimestreamwriteDatabases, + Tags: map[string]string{"service": "timestream-write", "action": "ListDatabases"}, + }, + GetMatrixItemFunc: SupportedRegionMatrix(timestreamwritev1.EndpointsID), + Columns: awsRegionalColumns([]*plugin.Column{ + { + Name: "database_name", + Description: "The name of the Timestream database.", + Type: proto.ColumnType_STRING, + }, + { + Name: "arn", + Description: "The Amazon Resource Name that uniquely identifies this database.", + Type: proto.ColumnType_STRING, + }, + { + Name: "creation_time", + Description: "The time when the database was created, calculated from the Unix epoch time.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "last_updated_time", + Description: "The last time that this database was updated.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "kms_key_id", + Description: "The identifier of the KMS key used to encrypt the data stored in the database.", + Type: proto.ColumnType_STRING, + }, + { + Name: "table_count", + Description: "The total number of tables found within a Timestream database.", + Type: proto.ColumnType_INT, + }, + + // Steampipe standard columns + { + Name: "title", + Description: resourceInterfaceDescription("title"), + Type: proto.ColumnType_STRING, + Transform: transform.FromField("DatabaseName"), + }, + { + Name: "akas", + Description: resourceInterfaceDescription("akas"), + Type: proto.ColumnType_JSON, + Transform: transform.FromField("Arn").Transform(transform.EnsureStringArray), + }, + }), + } +} + +//// LIST FUNCTION + +func listAwsTimestreamwriteDatabases(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + // Create session + svc, err := TimestreamwriteClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_database.listAwsTimestreamwriteDatabases", "client_error", err) + return nil, err + } + if svc == nil { + return nil, nil // Unsupported region check + } + + // Limiting the results + maxLimit := int32(20) + if d.QueryContext.Limit != nil { + limit := int32(*d.QueryContext.Limit) + if limit < maxLimit { + maxLimit = limit + } + } + + input := ×treamwrite.ListDatabasesInput{ + MaxResults: &maxLimit, + } + + paginator := timestreamwrite.NewListDatabasesPaginator(svc, input, func(o *timestreamwrite.ListDatabasesPaginatorOptions) { + o.Limit = maxLimit + o.StopOnDuplicateToken = true + }) + + // List call + for paginator.HasMorePages() { + // apply rate limiting + d.WaitForListRateLimit(ctx) + + output, err := paginator.NextPage(ctx) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_database.listAwsTimestreamwriteDatabases", "api_error", err) + return nil, err + } + + for _, item := range output.Databases { + d.StreamListItem(ctx, item) + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + return nil, err +} + +//// HYDRATE FUNCTIONS + +func getAwsTimestreamwriteDatabase(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + + svc, err := TimestreamwriteClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_database.getAwsTimestreamwriteDatabase", "connection_error", err) + return nil, err + } + + dbName := d.EqualsQualString("database_name") + + // Empty Check + if dbName == "" { + return nil, nil + } + + // Build the params + params := ×treamwrite.DescribeDatabaseInput{ + DatabaseName: &dbName, + } + + // Get call + op, err := svc.DescribeDatabase(ctx, params) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_database.getAwsTimestreamwriteDatabase", "api_error", err) + return nil, err + } + + if op.Database != nil { + return op.Database, nil + } + return nil, nil +} diff --git a/aws/table_aws_timestreamwrite_table.go b/aws/table_aws_timestreamwrite_table.go new file mode 100644 index 000000000..76b3744bb --- /dev/null +++ b/aws/table_aws_timestreamwrite_table.go @@ -0,0 +1,198 @@ +package aws + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/timestreamwrite" + + timestreamwritev1 "github.com/aws/aws-sdk-go/service/timestreamwrite" + + "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" +) + +//// TABLE DEFINITION + +func tableAwsTimestreamwriteTable(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "aws_timestreamwrite_table", + Description: "AWS Timestreamwrite Table", + Get: &plugin.GetConfig{ + KeyColumns: plugin.AllColumns([]string{"table_name", "database_name"}), + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + Hydrate: getAwsTimestreamwriteTable, + Tags: map[string]string{"service": "timestream-write", "action": "DescribeTable"}, + }, + List: &plugin.ListConfig{ + Hydrate: listAwsTimestreamwriteTables, + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + KeyColumns: plugin.KeyColumnSlice{ + {Name: "database_name", Require: plugin.Optional}, + }, + Tags: map[string]string{"service": "timestream-write", "action": "ListTables"}, + }, + GetMatrixItemFunc: SupportedRegionMatrix(timestreamwritev1.EndpointsID), + Columns: awsRegionalColumns([]*plugin.Column{ + { + Name: "table_name", + Description: "The name of the Timestream table.", + Type: proto.ColumnType_STRING, + }, + { + Name: "arn", + Description: "The Amazon Resource Name that uniquely identifies this table.", + Type: proto.ColumnType_STRING, + }, + { + Name: "table_status", + Description: "The current state of the table. Possible values are: 'ACTIVE', 'DELETING', or 'RESTORING'.", + Type: proto.ColumnType_STRING, + }, + { + Name: "creation_time", + Description: "The time when the Timestream table was created.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "last_updated_time", + Description: "The time when the Timestream table was last updated.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "database_name", + Description: "The name of the Timestream database that contains this table.", + Type: proto.ColumnType_STRING, + }, + { + Name: "schema", + Description: "The schema of the table.", + Type: proto.ColumnType_JSON, + }, + { + Name: "magnetic_store_write_properties", + Description: "Contains properties to set on the table when enabling magnetic store writes.", + Type: proto.ColumnType_JSON, + }, + { + Name: "retention_properties", + Description: "The retention duration for the memory store and magnetic store.", + Type: proto.ColumnType_JSON, + }, + + // Steampipe standard columns + { + Name: "title", + Description: resourceInterfaceDescription("title"), + Type: proto.ColumnType_STRING, + Transform: transform.FromField("TableName"), + }, + { + Name: "akas", + Description: resourceInterfaceDescription("akas"), + Type: proto.ColumnType_JSON, + Transform: transform.FromField("Arn").Transform(transform.EnsureStringArray), + }, + }), + } +} + +//// LIST FUNCTION + +func listAwsTimestreamwriteTables(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + // Create session + svc, err := TimestreamwriteClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_table.listAwsTimestreamwriteTables", "client_error", err) + return nil, err + } + if svc == nil { + return nil, nil + } + // Limiting the results + maxLimit := int32(20) + if d.QueryContext.Limit != nil { + limit := int32(*d.QueryContext.Limit) + if limit < maxLimit { + maxLimit = limit + } + } + + dbName := d.EqualsQualString("database_name") + + input := ×treamwrite.ListTablesInput{ + MaxResults: &maxLimit, + } + + if dbName != "" { + input.DatabaseName = &dbName + } + + paginator := timestreamwrite.NewListTablesPaginator(svc, input, func(o *timestreamwrite.ListTablesPaginatorOptions) { + o.Limit = maxLimit + o.StopOnDuplicateToken = true + }) + + // List call + for paginator.HasMorePages() { + // apply rate limiting + d.WaitForListRateLimit(ctx) + + output, err := paginator.NextPage(ctx) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_table.listAwsTimestreamwriteTables", "api_error", err) + return nil, err + } + + for _, item := range output.Tables { + d.StreamListItem(ctx, item) + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + return nil, err +} + +//// HYDRATE FUNCTIONS + +func getAwsTimestreamwriteTable(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + + svc, err := TimestreamwriteClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_table.getAwsTimestreamwriteTable", "connection_error", err) + return nil, err + } + + tableName := d.EqualsQualString("table_name") + dbName := d.EqualsQualString("database_name") + + // Empty Check + if tableName == "" || dbName == "" { + return nil, nil + } + + // Build the params + params := ×treamwrite.DescribeTableInput{ + DatabaseName: &dbName, + TableName: &tableName, + } + + // Get call + op, err := svc.DescribeTable(ctx, params) + if err != nil { + plugin.Logger(ctx).Error("aws_timestreamwrite_table.getAwsTimestreamwriteTable", "api_error", err) + return nil, err + } + + if op.Table != nil { + return op.Table, nil + } + return nil, nil +} diff --git a/docs/tables/aws_timestreamwrite_database.md b/docs/tables/aws_timestreamwrite_database.md new file mode 100644 index 000000000..413bd2b13 --- /dev/null +++ b/docs/tables/aws_timestreamwrite_database.md @@ -0,0 +1,137 @@ +--- +title: "Steampipe Table: aws_timestreamwrite_database - Query AWS Timestream Databases using SQL" +description: "Allows users to query AWS Timestream databases, providing detailed information on database configurations, statuses, and associated tables." +--- + +# Table: aws_timestreamwrite_database - Query AWS Timestream Databases using SQL + +AWS Timestream is a fast, scalable, and fully managed time-series database service for IoT and operational applications. It is designed to store and analyze trillions of events per day at a fraction of the cost of relational databases. The `aws_timestreamwrite_database` table in Steampipe allows you to query information about Timestream databases in your AWS environment. This includes details like database creation time, encryption settings, table count, and more. + +## Table Usage Guide + +The `aws_timestreamwrite_database` table enables DevOps engineers, cloud administrators, and data analysts to gather detailed insights on their Timestream databases. You can query various aspects of the database, such as its KMS encryption key, number of tables, and creation time. This table is particularly useful for monitoring database health, ensuring security compliance, and managing database configurations. + +## Examples + +### Basic database information +Retrieve basic information about your AWS Timestream databases, including their name, ARN, creation time, and region. This can be useful for getting an overview of the databases deployed in your AWS account. + +```sql+postgres +select + database_name, + arn, + creation_time, + region, + kms_key_id +from + aws_timestreamwrite_database; +``` + +```sql+sqlite +select + database_name, + arn, + creation_time, + region, + kms_key_id +from + aws_timestreamwrite_database; +``` + +### List databases with a specific KMS key +Identify databases that are encrypted with a specific KMS key. This can help in ensuring that your data is secured according to your organization’s encryption policies. + +```sql+postgres +select + database_name, + arn, + kms_key_id +from + aws_timestreamwrite_database +where + kms_key_id = 'your-kms-key-id'; +``` + +```sql+sqlite +select + database_name, + arn, + kms_key_id +from + aws_timestreamwrite_database +where + kms_key_id = 'your-kms-key-id'; +``` + +### List databases by creation date +Retrieve databases ordered by their creation date, which can be useful for auditing purposes or understanding the lifecycle of your Timestream databases. + +```sql+postgres +select + database_name, + arn, + creation_time +from + aws_timestreamwrite_database +order by + creation_time desc; +``` + +```sql+sqlite +select + database_name, + arn, + creation_time +from + aws_timestreamwrite_database +order by + creation_time desc; +``` + +### List databases with the most tables +Identify the databases that contain the most tables, which can help in understanding data distribution and load across your Timestream environment. + +```sql+postgres +select + database_name, + arn, + table_count +from + aws_timestreamwrite_database +order by + table_count desc; +``` + +```sql+sqlite +select + database_name, + arn, + table_count +from + aws_timestreamwrite_database +order by + table_count desc; +``` + +### Get database details with last updated time +Retrieve detailed information about your databases, including when they were last updated, to monitor changes and updates over time. + +```sql+postgres +select + database_name, + arn, + last_updated_time, + region +from + aws_timestreamwrite_database; +``` + +```sql+sqlite +select + database_name, + arn, + last_updated_time, + region +from + aws_timestreamwrite_database; +``` \ No newline at end of file diff --git a/docs/tables/aws_timestreamwrite_table.md b/docs/tables/aws_timestreamwrite_table.md new file mode 100644 index 000000000..5a6189b9e --- /dev/null +++ b/docs/tables/aws_timestreamwrite_table.md @@ -0,0 +1,164 @@ +--- +title: "Steampipe Table: aws_timestreamwrite_table - Query AWS Timestream Tables using SQL" +description: "Allows users to query AWS Timestream tables, providing detailed information on table configurations, statuses, and retention properties." +--- + +# Table: aws_timestreamwrite_table - Query AWS Timestream Tables using SQL + +AWS Timestream is a fast, scalable, and fully managed time-series database service for IoT and operational applications. It is designed to store and analyze trillions of events per day at a fraction of the cost of relational databases. The `aws_timestreamwrite_table` table in Steampipe allows you to query information about Timestream tables in your AWS environment. This includes details like table status, creation time, retention properties, and more. + +## Table Usage Guide + +The `aws_timestreamwrite_table` table enables DevOps engineers, cloud administrators, and data analysts to gather detailed insights on their Timestream tables. You can query various aspects of the table, such as its schema, retention policies, and status. This table is particularly useful for monitoring table health, ensuring data retention compliance, and managing table configurations. + +## Examples + +### Basic info +Retrieve basic information about your AWS Timestream tables, including their name, ARN, status, and creation time. This can be useful for getting an overview of the tables deployed in your AWS account. + +```sql+postgres +select + table_name, + arn, + table_status, + creation_time, + last_updated_time, + region +from + aws_timestreamwrite_table; +``` + +```sql+sqlite +select + table_name, + arn, + table_status, + creation_time, + last_updated_time, + region +from + aws_timestreamwrite_table; +``` + +### List active tables +Fetch a list of tables that are currently active. This can help in identifying which tables are in use and available for writing and querying data. + +```sql+postgres +select + table_name, + arn, + table_status +from + aws_timestreamwrite_table +where + table_status = 'ACTIVE'; +``` + +```sql+sqlite +select + table_name, + arn, + table_status +from + aws_timestreamwrite_table +where + table_status = 'ACTIVE'; +``` + +### List tables with specific retention settings +Query tables that have specific retention settings in the memory store or magnetic store. This is useful for ensuring that your data retention policies are being enforced properly. + +```sql+postgres +select + table_name, + arn, + retention_properties +from + aws_timestreamwrite_table +where + retention_properties ->> 'MemoryStoreRetentionPeriodInHours' = '24' + and retention_properties ->> 'MagneticStoreRetentionPeriodInDays' = '7'; +``` + +```sql+sqlite +select + table_name, + arn, + retention_properties +from + aws_timestreamwrite_table +where + json_extract(retention_properties, '$.MemoryStoreRetentionPeriodInHours') = '24' + and json_extract(retention_properties, '$.MagneticStoreRetentionPeriodInDays') = '7'; +``` + +### List tables with magnetic store writes enabled +Identify tables where magnetic store writes are enabled. This can help in understanding which tables are set up for long-term storage and potentially lower-cost storage. + +```sql+postgres +select + table_name, + arn, + magnetic_store_write_properties +from + aws_timestreamwrite_table +where + magnetic_store_write_properties ->> 'EnableMagneticStoreWrites' = 'true'; +``` + +```sql+sqlite +select + table_name, + arn, + magnetic_store_write_properties +from + aws_timestreamwrite_table +where + json_extract(magnetic_store_write_properties, '$.EnableMagneticStoreWrites') = 'true'; +``` + +### List tables by creation date +Retrieve tables ordered by their creation date, which can be useful for auditing purposes or understanding the lifecycle of your Timestream tables. + +```sql+postgres +select + table_name, + arn, + creation_time +from + aws_timestreamwrite_table +order by + creation_time desc; +``` + +```sql+sqlite +select + table_name, + arn, + creation_time +from + aws_timestreamwrite_table +order by + creation_time desc; +``` + +### Get table schema details +Query the schema of your Timestream tables to understand the structure and types of data that are being stored. + +```sql+postgres +select + table_name, + arn, + schema +from + aws_timestreamwrite_table; +``` + +```sql+sqlite +select + table_name, + arn, + schema +from + aws_timestreamwrite_table; +``` \ No newline at end of file diff --git a/go.mod b/go.mod index 4a5fea350..a97895385 100644 --- a/go.mod +++ b/go.mod @@ -124,6 +124,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssoadmin v1.25.5 github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 github.com/aws/aws-sdk-go-v2/service/support v1.21.4 + github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.25.9 github.com/aws/aws-sdk-go-v2/service/transfer v1.45.0 github.com/aws/aws-sdk-go-v2/service/waf v1.20.4 github.com/aws/aws-sdk-go-v2/service/wafregional v1.21.4 @@ -170,7 +171,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.7 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 // indirect github.com/aws/aws-sdk-go-v2/service/ssmincidents v1.30.4 diff --git a/go.sum b/go.sum index 9b8ae6244..d42e735b1 100644 --- a/go.sum +++ b/go.sum @@ -357,8 +357,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1x github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9 h1:UXqEWQI0n+q0QixzU0yUUQBZXRd5037qdInTIHFTl98= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.9/go.mod h1:xP6Gq6fzGZT8w/ZN+XvGMZ2RU1LeEs7b2yUP5DN8NY4= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.6 h1:6tayEze2Y+hiL3kdnEUxSPsP+pJsUfwLSFspFl1ru9Q= -github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.6/go.mod h1:qVNb/9IOVsLCZh0x2lnagrBwQ9fxajUpXS7OZfIsKn0= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.8 h1:yEeIld7Fh/2iM4pYeQw8a3kH6OYcyIn6lwKlUFiVk7Y= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.8/go.mod h1:lZJMX2Z5/rQ6OlSbBnW1WWScK6ngLt43xtqM8voMm2w= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9 h1:Wx0rlZoEJR7JwlSZcHnEa7CNjrSIyVxMFWGAaXy4fJY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.9/go.mod h1:aVMHdE0aHO3v+f/iw01fmXV/5DbfQ3Bi9nN7nd9bE9Y= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.7 h1:uO5XR6QGBcmPyo2gxofYJLFkcVQ4izOoGDNenlZhTEk= @@ -469,6 +469,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.10 h1:69tpbPED7jKPyzMcrwSvhWcJ9bP github.com/aws/aws-sdk-go-v2/service/sts v1.28.10/go.mod h1:0Aqn1MnEuitqfsCNyKsdKLhDUOr4txD/g19EfiUqgws= github.com/aws/aws-sdk-go-v2/service/support v1.21.4 h1:LGPzkSN77fiJKxfQF5AGT1gbKMmdtESl1ij+JpSDED0= github.com/aws/aws-sdk-go-v2/service/support v1.21.4/go.mod h1:3aB5W1UW7c5z86tENabIcgkWNF58VE8FqU6F329xfAs= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.25.9 h1:KonoyRc5h7yli15/p0vpoKBJNuF2k9Ee42leZshX/ME= +github.com/aws/aws-sdk-go-v2/service/timestreamwrite v1.25.9/go.mod h1:rSN/IbugNV4Uw9R3QWV5hElqmXKahjRv9Z3jND+t1Kw= github.com/aws/aws-sdk-go-v2/service/transfer v1.45.0 h1:t8j8kiVkaRtffvv3rhu4dZD4MZgzNDkVa6x3kO4yhmk= github.com/aws/aws-sdk-go-v2/service/transfer v1.45.0/go.mod h1:z3NpUj6ziVpg9XHEMdA0xpD/lgjPuZb9R/PBV6Mieb0= github.com/aws/aws-sdk-go-v2/service/waf v1.20.4 h1:VTmfAa/NuztyCftePCAKWxeYiEPiTR3lkkCTtA8eEfw=