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

New resource: Timestream Write database resource #15463

Merged
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
3 changes: 3 additions & 0 deletions .changelog/15463.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_timestreamwrite_database
```
1 change: 1 addition & 0 deletions aws/internal/keyvaluetags/generators/listtags/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ var serviceNames = []string{
"ssoadmin",
"storagegateway",
"swf",
"timestreamwrite",
"transfer",
"waf",
"wafregional",
Expand Down
1 change: 1 addition & 0 deletions aws/internal/keyvaluetags/generators/servicetags/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ var sliceServiceNames = []string{
"ssoadmin",
"storagegateway",
"swf",
"timestreamwrite",
"transfer",
"waf",
"wafregional",
Expand Down
1 change: 1 addition & 0 deletions aws/internal/keyvaluetags/generators/updatetags/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ var serviceNames = []string{
"storagegateway",
"swf",
"synthetics",
"timestreamwrite",
"transfer",
"waf",
"wafregional",
Expand Down
18 changes: 18 additions & 0 deletions aws/internal/keyvaluetags/list_tags_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ import (
"github.com/aws/aws-sdk-go/service/storagegateway"
"github.com/aws/aws-sdk-go/service/swf"
"github.com/aws/aws-sdk-go/service/synthetics"
"github.com/aws/aws-sdk-go/service/timestreamwrite"
"github.com/aws/aws-sdk-go/service/transfer"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
Expand Down Expand Up @@ -349,6 +350,8 @@ func ServiceClientType(serviceName string) string {
funcType = reflect.TypeOf(swf.New)
case "synthetics":
funcType = reflect.TypeOf(synthetics.New)
case "timestreamwrite":
funcType = reflect.TypeOf(timestreamwrite.New)
case "transfer":
funcType = reflect.TypeOf(transfer.New)
case "waf":
Expand Down Expand Up @@ -752,6 +755,8 @@ func ServiceTagInputIdentifierField(serviceName string) string {
return "ResourceId"
case "storagegateway":
return "ResourceARN"
case "timestreamwrite":
return "ResourceARN"
case "transfer":
return "Arn"
case "waf":
Expand Down
28 changes: 28 additions & 0 deletions aws/internal/keyvaluetags/service_tags_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions aws/internal/keyvaluetags/update_tags_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,7 @@ func Provider() *schema.Provider {
"aws_subnet": resourceAwsSubnet(),
"aws_swf_domain": resourceAwsSwfDomain(),
"aws_synthetics_canary": resourceAwsSyntheticsCanary(),
"aws_timestreamwrite_database": resourceAwsTimestreamWriteDatabase(),
"aws_transfer_server": resourceAwsTransferServer(),
"aws_transfer_ssh_key": resourceAwsTransferSshKey(),
"aws_transfer_user": resourceAwsTransferUser(),
Expand Down
202 changes: 202 additions & 0 deletions aws/resource_aws_timestreamwrite_database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package aws

import (
"context"
"fmt"
"log"
"regexp"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/timestreamwrite"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsTimestreamWriteDatabase() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceAwsTimestreamWriteDatabaseCreate,
ReadWithoutTimeout: resourceAwsTimestreamWriteDatabaseRead,
UpdateWithoutTimeout: resourceAwsTimestreamWriteDatabaseUpdate,
DeleteWithoutTimeout: resourceAwsTimestreamWriteDatabaseDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},

"database_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(3, 64),
validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9_.-]+$`), "must only include alphanumeric, underscore, period, or hyphen characters"),
),
},

"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
// The Timestream API accepts the KmsKeyId as an ID, ARN, alias, or alias ARN but always returns the ARN of the key.
// The ARN is of the format 'arn:aws:kms:REGION:ACCOUNT_ID:key/KMS_KEY_ID'. Appropriate diff suppression
// would require an extra API call to the kms service's DescribeKey method to decipher aliases.
// To avoid importing an extra service in this resource, input here is restricted to only ARNs.
ValidateFunc: validateArn,
},

"table_count": {
Type: schema.TypeInt,
Computed: true,
yardensachs marked this conversation as resolved.
Show resolved Hide resolved
},

"tags": tagsSchema(),

"tags_all": tagsSchemaComputed(),
},

CustomizeDiff: SetTagsDiff,
}
}

func resourceAwsTimestreamWriteDatabaseCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).timestreamwriteconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{})))

dbName := d.Get("database_name").(string)

input := &timestreamwrite.CreateDatabaseInput{
DatabaseName: aws.String(dbName),
}

if v, ok := d.GetOk("kms_key_id"); ok {
input.KmsKeyId = aws.String(v.(string))
}

if len(tags) > 0 {
input.Tags = tags.IgnoreAws().TimestreamwriteTags()
}

resp, err := conn.CreateDatabaseWithContext(ctx, input)

if err != nil {
return diag.FromErr(fmt.Errorf("error creating Timestream Database (%s): %w", dbName, err))
}

if resp == nil || resp.Database == nil {
return diag.FromErr(fmt.Errorf("error creating Timestream Database (%s): empty output", dbName))
}

d.SetId(aws.StringValue(resp.Database.DatabaseName))

return resourceAwsTimestreamWriteDatabaseRead(ctx, d, meta)
}

func resourceAwsTimestreamWriteDatabaseRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).timestreamwriteconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

input := &timestreamwrite.DescribeDatabaseInput{
DatabaseName: aws.String(d.Id()),
}

resp, err := conn.DescribeDatabaseWithContext(ctx, input)

if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, timestreamwrite.ErrCodeResourceNotFoundException) {
log.Printf("[WARN] Timestream Database %s not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return diag.FromErr(fmt.Errorf("error reading Timestream Database (%s): %w", d.Id(), err))
}

if resp == nil || resp.Database == nil {
return diag.FromErr(fmt.Errorf("error reading Timestream Database (%s): empty output", d.Id()))
}

db := resp.Database
arn := aws.StringValue(db.Arn)

d.Set("arn", arn)
d.Set("database_name", db.DatabaseName)
d.Set("kms_key_id", db.KmsKeyId)
d.Set("table_count", db.TableCount)

tags, err := keyvaluetags.TimestreamwriteListTags(conn, arn)

if err != nil {
return diag.FromErr(fmt.Errorf("error listing tags for Timestream Database (%s): %w", arn, err))
}

tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return diag.FromErr(fmt.Errorf("error setting tags: %w", err))
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return diag.FromErr(fmt.Errorf("error setting tags_all: %w", err))
}

return nil
}

func resourceAwsTimestreamWriteDatabaseUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).timestreamwriteconn

if d.HasChange("kms_key_id") {
input := &timestreamwrite.UpdateDatabaseInput{
DatabaseName: aws.String(d.Id()),
KmsKeyId: aws.String(d.Get("kms_key_id").(string)),
}

_, err := conn.UpdateDatabaseWithContext(ctx, input)

if err != nil {
return diag.FromErr(fmt.Errorf("error updating Timestream Database (%s): %w", d.Id(), err))
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := keyvaluetags.TimestreamwriteUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return diag.FromErr(fmt.Errorf("error updating Timestream Database (%s) tags: %w", d.Get("arn").(string), err))
}
}

return resourceAwsTimestreamWriteDatabaseRead(ctx, d, meta)
}

func resourceAwsTimestreamWriteDatabaseDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).timestreamwriteconn

input := &timestreamwrite.DeleteDatabaseInput{
DatabaseName: aws.String(d.Id()),
}

_, err := conn.DeleteDatabaseWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, timestreamwrite.ErrCodeResourceNotFoundException) {
return nil
}

if err != nil {
return diag.FromErr(fmt.Errorf("error deleting Timestream Database (%s): %w", d.Id(), err))
}

return nil
}
Loading