diff --git a/.changelog/37963.txt b/.changelog/37963.txt new file mode 100644 index 00000000000..9a02403ed61 --- /dev/null +++ b/.changelog/37963.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_timestreaminfluxdb_db_instance +``` \ No newline at end of file diff --git a/.teamcity/components/generated/services_all.kt b/.teamcity/components/generated/services_all.kt index e72ea61ef4e..bc952e98be0 100644 --- a/.teamcity/components/generated/services_all.kt +++ b/.teamcity/components/generated/services_all.kt @@ -227,7 +227,7 @@ val services = mapOf( "sts" to ServiceSpec("STS (Security Token)"), "swf" to ServiceSpec("SWF (Simple Workflow)"), "synthetics" to ServiceSpec("CloudWatch Synthetics", parallelismOverride = 10), - "timestreaminfluxdb" to ServiceSpec("Timestream for InfluxDB"), + "timestreaminfluxdb" to ServiceSpec("Timestream for InfluxDB", vpcLock = true, parallelismOverride = 3), "timestreamwrite" to ServiceSpec("Timestream Write"), "transcribe" to ServiceSpec("Transcribe"), "transfer" to ServiceSpec("Transfer Family", vpcLock = true), diff --git a/internal/generate/teamcity/acctest_services.hcl b/internal/generate/teamcity/acctest_services.hcl index 51e8a8155df..c3836ae463d 100644 --- a/internal/generate/teamcity/acctest_services.hcl +++ b/internal/generate/teamcity/acctest_services.hcl @@ -235,6 +235,11 @@ service "synthetics" { parallelism = 10 } +service "timestreaminfluxdb" { + vpc_lock = true + parallelism = 3 +} + service "transfer" { vpc_lock = true } diff --git a/internal/service/timestreaminfluxdb/db_instance.go b/internal/service/timestreaminfluxdb/db_instance.go new file mode 100644 index 00000000000..60158012a75 --- /dev/null +++ b/internal/service/timestreaminfluxdb/db_instance.go @@ -0,0 +1,665 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package timestreaminfluxdb + +import ( + "context" + "errors" + "time" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" + awstypes "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource("aws_timestreaminfluxdb_db_instance", name="DB Instance") +// @Tags(identifierAttribute="arn") +// @Testing(existsType="github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb;timestreaminfluxdb.GetDbInstanceOutput") +// @Testing(importIgnore="bucket;username;organization;password") +func newResourceDBInstance(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceDBInstance{} + + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +const ( + ResNameDBInstance = "DB Instance" +) + +type resourceDBInstance struct { + framework.ResourceWithConfigure + framework.WithTimeouts + framework.WithImportByID +} + +func (r *resourceDBInstance) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_timestreaminfluxdb_db_instance" +} + +func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + names.AttrAllocatedStorage: schema.Int64Attribute{ + Required: true, + PlanModifiers: []planmodifier.Int64{ + int64planmodifier.RequiresReplace(), + }, + Validators: []validator.Int64{ + int64validator.Between(20, 16384), + }, + Description: `The amount of storage to allocate for your DB storage type in GiB (gibibytes).`, + }, + names.AttrARN: framework.ARNAttributeComputedOnly(), + names.AttrAvailabilityZone: schema.StringAttribute{ + Computed: true, + Description: `The Availability Zone in which the DB instance resides.`, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + names.AttrBucket: schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(2, 64), + stringvalidator.RegexMatches( + regexache.MustCompile("^[^_][^\"]*$"), + "", + ), + }, + Description: `The name of the initial InfluxDB bucket. All InfluxDB data is stored in a bucket. + A bucket combines the concept of a database and a retention period (the duration of time + that each data point persists). A bucket belongs to an organization.`, + }, + "db_instance_type": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.DbInstanceType](), + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Description: `The Timestream for InfluxDB DB instance type to run InfluxDB on.`, + }, + "db_parameter_group_identifier": schema.StringAttribute{ + Optional: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplaceIf( + dbParameterGroupIdentifierReplaceIf, "Replace db_parameter_group_identifier diff", "Replace db_parameter_group_identifier diff", + ), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(3, 64), + stringvalidator.RegexMatches( + regexache.MustCompile("^[a-zA-Z0-9]+$"), + "", + ), + }, + Description: `The id of the DB parameter group assigned to your DB instance.`, + }, + "db_storage_type": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.DbStorageType](), + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + stringplanmodifier.UseStateForUnknown(), + }, + Description: `The Timestream for InfluxDB DB storage type to read and write InfluxDB data. + You can choose between 3 different types of provisioned Influx IOPS included storage according + to your workloads requirements: Influx IO Included 3000 IOPS, Influx IO Included 12000 IOPS, + Influx IO Included 16000 IOPS.`, + }, + "deployment_type": schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.DeploymentType](), + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + stringplanmodifier.UseStateForUnknown(), + }, + Description: `Specifies whether the DB instance will be deployed as a standalone instance or + with a Multi-AZ standby for high availability.`, + }, + names.AttrEndpoint: schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + Description: `The endpoint used to connect to InfluxDB. The default InfluxDB port is 8086.`, + }, + names.AttrID: framework.IDAttribute(), + "influx_auth_parameters_secret_arn": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + Description: `The Amazon Resource Name (ARN) of the AWS Secrets Manager secret containing the + initial InfluxDB authorization parameters. The secret value is a JSON formatted + key-value pair holding InfluxDB authorization values: organization, bucket, + username, and password.`, + }, + names.AttrName: schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(3, 40), + stringvalidator.RegexMatches( + regexache.MustCompile("^[a-zA-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$"), + "", + ), + }, + Description: `The name that uniquely identifies the DB instance when interacting with the + Amazon Timestream for InfluxDB API and CLI commands. This name will also be a + prefix included in the endpoint. DB instance names must be unique per customer + and per region.`, + }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + "organization": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 64), + }, + Description: `The name of the initial organization for the initial admin user in InfluxDB. An + InfluxDB organization is a workspace for a group of users.`, + }, + names.AttrPassword: schema.StringAttribute{ + Required: true, + Sensitive: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.LengthBetween(8, 64), + stringvalidator.RegexMatches(regexache.MustCompile("^[a-zA-Z0-9]+$"), ""), + }, + Description: `The password of the initial admin user created in InfluxDB. This password will + allow you to access the InfluxDB UI to perform various administrative tasks and + also use the InfluxDB CLI to create an operator token. These attributes will be + stored in a Secret created in AWS SecretManager in your account.`, + }, + names.AttrPubliclyAccessible: schema.BoolAttribute{ + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.RequiresReplace(), + boolplanmodifier.UseStateForUnknown(), + }, + Description: `Configures the DB instance with a public IP to facilitate access.`, + }, + "secondary_availability_zone": schema.StringAttribute{ + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + Description: `The Availability Zone in which the standby instance is located when deploying + with a MultiAZ standby instance.`, + }, + names.AttrUsername: schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexache.MustCompile("^[a-zA-Z]([a-zA-Z0-9]*(-[a-zA-Z0-9]+)*)?$"), + `Must start with a letter and can't end with a hyphen or contain two + consecutive hyphens`, + ), + }, + Description: `The username of the initial admin user created in InfluxDB. + Must start with a letter and can't end with a hyphen or contain two + consecutive hyphens. For example, my-user1. This username will allow + you to access the InfluxDB UI to perform various administrative tasks + and also use the InfluxDB CLI to create an operator token. These + attributes will be stored in a Secret created in Amazon Secrets + Manager in your account`, + }, + names.AttrVPCSecurityGroupIDs: schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, + Required: true, + PlanModifiers: []planmodifier.Set{ + setplanmodifier.RequiresReplace(), + }, + Validators: []validator.Set{ + setvalidator.SizeBetween(1, 5), + setvalidator.ValueStringsAre( + stringvalidator.LengthAtMost(64), + stringvalidator.RegexMatches(regexache.MustCompile("^sg-[a-z0-9]+$"), ""), + ), + }, + Description: `A list of VPC security group IDs to associate with the DB instance.`, + }, + "vpc_subnet_ids": schema.SetAttribute{ + CustomType: fwtypes.SetOfStringType, + Required: true, + PlanModifiers: []planmodifier.Set{ + setplanmodifier.RequiresReplace(), + }, + Validators: []validator.Set{ + setvalidator.SizeBetween(1, 3), + setvalidator.ValueStringsAre( + stringvalidator.LengthAtMost(64), + stringvalidator.RegexMatches(regexache.MustCompile("^subnet-[a-z0-9]+$"), ""), + ), + }, + Description: `A list of VPC subnet IDs to associate with the DB instance. Provide at least + two VPC subnet IDs in different availability zones when deploying with a Multi-AZ standby.`, + }, + }, + Blocks: map[string]schema.Block{ + "log_delivery_configuration": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[logDeliveryConfigurationData](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + Description: `Configuration for sending InfluxDB engine logs to a specified S3 bucket.`, + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "s3_configuration": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[s3ConfigurationData](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + names.AttrBucketName: schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(3, 63), + stringvalidator.RegexMatches(regexache.MustCompile("^[0-9a-z]+[0-9a-z\\.\\-]*[0-9a-z]+$"), ""), + }, + Description: `The name of the S3 bucket to deliver logs to.`, + }, + names.AttrEnabled: schema.BoolAttribute{ + Required: true, + Description: `Indicates whether log delivery to the S3 bucket is enabled.`, + }, + }, + }, + Description: `Configuration for S3 bucket log delivery.`, + }, + }, + }, + }, + names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Update: true, + Delete: true, + }), + }, + } +} + +func dbParameterGroupIdentifierReplaceIf(ctx context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) { + if req.State.Raw.IsNull() || req.Plan.Raw.IsNull() { + return + } + var plan, state resourceDBInstanceData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + dbParameterGroupIdentifierRemoved := !state.DBParameterGroupIdentifier.IsNull() && plan.DBParameterGroupIdentifier.IsNull() + + resp.RequiresReplace = dbParameterGroupIdentifierRemoved +} + +func (r *resourceDBInstance) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().TimestreamInfluxDBClient(ctx) + + var plan resourceDBInstanceData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + in := timestreaminfluxdb.CreateDbInstanceInput{} + + resp.Diagnostics.Append(flex.Expand(ctx, plan, &in)...) + + if resp.Diagnostics.HasError() { + return + } + + in.Tags = getTagsIn(ctx) + + out, err := conn.CreateDbInstance(ctx, &in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionCreating, ResNameDBInstance, plan.Name.String(), err), + err.Error(), + ) + return + } + + if out == nil || out.Id == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionCreating, ResNameDBInstance, plan.Name.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + state := plan + state.ID = flex.StringToFramework(ctx, out.Id) + + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) + output, err := waitDBInstanceCreated(ctx, conn, state.ID.ValueString(), createTimeout) + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionWaitingForCreation, ResNameDBInstance, plan.Name.String(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + // flatten using legacy since this computed output may be null + state.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone) + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceDBInstance) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().TimestreamInfluxDBClient(ctx) + + var state resourceDBInstanceData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + output, err := findDBInstanceByID(ctx, conn, state.ID.ValueString()) + + if tfresource.NotFound(err) { + resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) + resp.State.RemoveResource(ctx) + return + } + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionSetting, ResNameDBInstance, state.ID.String(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, output, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + // flatten using legacy since this computed output may be null + state.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone) + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceDBInstance) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().TimestreamInfluxDBClient(ctx) + + var plan, state resourceDBInstanceData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + if !plan.DBParameterGroupIdentifier.Equal(state.DBParameterGroupIdentifier) || + !plan.LogDeliveryConfiguration.Equal(state.LogDeliveryConfiguration) { + in := timestreaminfluxdb.UpdateDbInstanceInput{ + Identifier: aws.String(plan.ID.ValueString()), + } + + resp.Diagnostics.Append(flex.Expand(ctx, plan, &in)...) + + if resp.Diagnostics.HasError() { + return + } + + _, err := conn.UpdateDbInstance(ctx, &in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionUpdating, ResNameDBInstance, plan.ID.String(), err), + err.Error(), + ) + return + } + + updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) + output, err := waitDBInstanceUpdated(ctx, conn, plan.ID.ValueString(), updateTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionWaitingForUpdate, ResNameDBInstance, plan.ID.String(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...) + + if resp.Diagnostics.HasError() { + return + } + + // flatten using legacy since this computed output may be null + plan.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceDBInstance) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().TimestreamInfluxDBClient(ctx) + + var state resourceDBInstanceData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + in := ×treaminfluxdb.DeleteDbInstanceInput{ + Identifier: aws.String(state.ID.ValueString()), + } + + _, err := conn.DeleteDbInstance(ctx, in) + if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionDeleting, ResNameDBInstance, state.ID.String(), err), + err.Error(), + ) + return + } + + deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) + _, err = waitDBInstanceDeleted(ctx, conn, state.ID.ValueString(), deleteTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionWaitingForDeletion, ResNameDBInstance, state.ID.String(), err), + err.Error(), + ) + return + } +} + +func (r *resourceDBInstance) ModifyPlan(ctx context.Context, request resource.ModifyPlanRequest, response *resource.ModifyPlanResponse) { + r.SetTagsAll(ctx, request, response) +} + +func waitDBInstanceCreated(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.StatusCreating), + Target: enum.Slice(awstypes.StatusAvailable), + Refresh: statusDBInstance(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*timestreaminfluxdb.GetDbInstanceOutput); ok { + return out, err + } + + return nil, err +} + +func waitDBInstanceUpdated(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.StatusModifying, awstypes.StatusUpdating), + Target: enum.Slice(awstypes.StatusAvailable), + Refresh: statusDBInstance(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*timestreaminfluxdb.GetDbInstanceOutput); ok { + return out, err + } + + return nil, err +} + +func waitDBInstanceDeleted(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.StatusDeleting), + Target: []string{}, + Refresh: statusDBInstance(ctx, conn, id), + Timeout: timeout, + Delay: 30 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*timestreaminfluxdb.GetDbInstanceOutput); ok { + return out, err + } + + return nil, err +} + +func statusDBInstance(ctx context.Context, conn *timestreaminfluxdb.Client, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findDBInstanceByID(ctx, conn, id) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + return out, string(out.Status), nil + } +} + +func findDBInstanceByID(ctx context.Context, conn *timestreaminfluxdb.Client, id string) (*timestreaminfluxdb.GetDbInstanceOutput, error) { + in := ×treaminfluxdb.GetDbInstanceInput{ + Identifier: aws.String(id), + } + + out, err := conn.GetDbInstance(ctx, in) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if out == nil || out.Id == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +type resourceDBInstanceData struct { + AllocatedStorage types.Int64 `tfsdk:"allocated_storage"` + ARN types.String `tfsdk:"arn"` + AvailabilityZone types.String `tfsdk:"availability_zone"` + Bucket types.String `tfsdk:"bucket"` + DBInstanceType fwtypes.StringEnum[awstypes.DbInstanceType] `tfsdk:"db_instance_type"` + DBParameterGroupIdentifier types.String `tfsdk:"db_parameter_group_identifier"` + DBStorageType fwtypes.StringEnum[awstypes.DbStorageType] `tfsdk:"db_storage_type"` + DeploymentType fwtypes.StringEnum[awstypes.DeploymentType] `tfsdk:"deployment_type"` + Endpoint types.String `tfsdk:"endpoint"` + ID types.String `tfsdk:"id"` + InfluxAuthParametersSecretARN types.String `tfsdk:"influx_auth_parameters_secret_arn"` + LogDeliveryConfiguration fwtypes.ListNestedObjectValueOf[logDeliveryConfigurationData] `tfsdk:"log_delivery_configuration"` + Name types.String `tfsdk:"name"` + Organization types.String `tfsdk:"organization"` + Password types.String `tfsdk:"password"` + PubliclyAccessible types.Bool `tfsdk:"publicly_accessible"` + SecondaryAvailabilityZone types.String `tfsdk:"secondary_availability_zone"` + Tags types.Map `tfsdk:"tags"` + TagsAll types.Map `tfsdk:"tags_all"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + Username types.String `tfsdk:"username"` + VPCSecurityGroupIDs fwtypes.SetValueOf[types.String] `tfsdk:"vpc_security_group_ids"` + VPCSubnetIDs fwtypes.SetValueOf[types.String] `tfsdk:"vpc_subnet_ids"` +} + +type logDeliveryConfigurationData struct { + S3Configuration fwtypes.ListNestedObjectValueOf[s3ConfigurationData] `tfsdk:"s3_configuration"` +} + +type s3ConfigurationData struct { + BucketName types.String `tfsdk:"bucket_name"` + Enabled types.Bool `tfsdk:"enabled"` +} diff --git a/internal/service/timestreaminfluxdb/db_instance_tags_gen_test.go b/internal/service/timestreaminfluxdb/db_instance_tags_gen_test.go new file mode 100644 index 00000000000..8101734c4f1 --- /dev/null +++ b/internal/service/timestreaminfluxdb/db_instance_tags_gen_test.go @@ -0,0 +1,1890 @@ +// Code generated by internal/generate/tagstests/main.go; DO NOT EDIT. + +package timestreaminfluxdb_test + +import ( + "testing" + + "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" + "github.com/hashicorp/terraform-plugin-testing/config" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccTimestreamInfluxDBDBInstance_tags(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1Updated), + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1Updated), + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_null(t *testing.T) { + t.Skip("Tags with null values are not correctly handled with the Plugin Framework") + + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: nil, + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: nil, + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + PlanOnly: true, + ExpectNonEmptyPlan: false, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_AddOnUpdate(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_EmptyTag_OnCreate(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_EmptyTag_OnUpdate_Add(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + acctest.CtKey2: config.StringVariable(""), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + acctest.CtKey2: knownvalue.StringExact(""), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + acctest.CtKey2: knownvalue.StringExact(""), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + acctest.CtKey2: knownvalue.StringExact(""), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + acctest.CtKey2: config.StringVariable(""), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_EmptyTag_OnUpdate_Replace(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + }, + }, + { + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_providerOnly(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1Updated), + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1Updated), + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1Updated), + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey2: knownvalue.StringExact(acctest.CtValue2), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey2: config.StringVariable(acctest.CtValue2), + }), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_nonOverlapping(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: config.StringVariable(acctest.CtResourceValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact(acctest.CtProviderValue1), + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact(acctest.CtProviderValue1), + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: config.StringVariable(acctest.CtResourceValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable("providervalue1updated"), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: config.StringVariable(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: config.StringVariable(acctest.CtResourceValue2), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact("providervalue1updated"), + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact("providervalue1updated"), + acctest.CtResourceKey1: knownvalue.StringExact(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable("providervalue1updated"), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: config.StringVariable(acctest.CtResourceValue1Updated), + acctest.CtResourceKey2: config.StringVariable(acctest.CtResourceValue2), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{})), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_overlapping(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + acctest.CtOverlapKey2: config.StringVariable("providervalue2"), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue1), + acctest.CtOverlapKey2: config.StringVariable(acctest.CtResourceValue2), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + acctest.CtOverlapKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + acctest.CtOverlapKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + acctest.CtOverlapKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue1), + acctest.CtOverlapKey2: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + acctest.CtOverlapKey2: config.StringVariable("providervalue2"), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue1), + acctest.CtOverlapKey2: config.StringVariable(acctest.CtResourceValue2), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue2), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue2), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue2), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtOverlapKey1: knownvalue.StringExact(acctest.CtResourceValue2), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtOverlapKey1: config.StringVariable(acctest.CtResourceValue2), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_updateToProviderOnly(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_updateToResourceOnly(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_emptyResourceTag(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_emptyProviderOnlyTag(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + acctest.CtResourceTags: nil, + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(""), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(""), + }), + acctest.CtResourceTags: nil, + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_nullOverlappingResourceTag(t *testing.T) { + t.Skip("Tags with null values are not correctly handled with the Plugin Framework") + + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: nil, + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtProviderValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtProviderValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: nil, + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_DefaultTags_nullNonOverlappingResourceTag(t *testing.T) { + t.Skip("Tags with null values are not correctly handled with the Plugin Framework") + + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: nil, + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact(acctest.CtProviderValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.Null()), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtProviderKey1: knownvalue.StringExact(acctest.CtProviderValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags_defaults/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtProviderTags: config.MapVariable(map[string]config.Variable{ + acctest.CtProviderKey1: config.StringVariable(acctest.CtProviderValue1), + }), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtResourceKey1: nil, + }), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_ComputedTag_OnCreate(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable("computedkey1"), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, "tags.computedkey1", "null_resource.test", names.AttrID), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapSizeExact(1)), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTags).AtMapKey("computedkey1")), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTagsAll)), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable("computedkey1"), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_ComputedTag_OnUpdate_Add(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed2/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable("computedkey1"), + "knownTagKey": config.StringVariable(acctest.CtKey1), + "knownTagValue": config.StringVariable(acctest.CtValue1), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, "tags.computedkey1", "null_resource.test", names.AttrID), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapSizeExact(2)), + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapPartial(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTags).AtMapKey("computedkey1")), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTagsAll)), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed2/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable("computedkey1"), + "knownTagKey": config.StringVariable(acctest.CtKey1), + "knownTagValue": config.StringVariable(acctest.CtValue1), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_tags_ComputedTag_OnUpdate_Replace(t *testing.T) { + ctx := acctest.Context(t) + var v timestreaminfluxdb.GetDbInstanceOutput + resourceName := "aws_timestreaminfluxdb_db_instance.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tags/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + acctest.CtResourceTags: config.MapVariable(map[string]config.Variable{ + acctest.CtKey1: config.StringVariable(acctest.CtValue1), + }), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionCreate), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + plancheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTagsAll), knownvalue.MapExact(map[string]knownvalue.Check{ + acctest.CtKey1: knownvalue.StringExact(acctest.CtValue1), + })), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable(acctest.CtKey1), + }, + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &v), + resource.TestCheckResourceAttrPair(resourceName, acctest.CtTagsKey1, "null_resource.test", names.AttrID), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(resourceName, tfjsonpath.New(names.AttrTags), knownvalue.MapSizeExact(1)), + }, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionUpdate), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTags).AtMapKey(acctest.CtKey1)), + plancheck.ExpectUnknownValue(resourceName, tfjsonpath.New(names.AttrTagsAll)), + }, + PostApplyPreRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + PostApplyPostRefresh: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction(resourceName, plancheck.ResourceActionNoop), + }, + }, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + ConfigDirectory: config.StaticDirectory("testdata/DBInstance/tagsComputed1/"), + ConfigVariables: config.Variables{ + acctest.CtRName: config.StringVariable(rName), + "unknownTagKey": config.StringVariable(acctest.CtKey1), + }, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + names.AttrBucket, names.AttrUsername, "organization", names.AttrPassword, + }, + }, + }, + }) +} diff --git a/internal/service/timestreaminfluxdb/db_instance_test.go b/internal/service/timestreaminfluxdb/db_instance_test.go new file mode 100644 index 00000000000..89da100d0d7 --- /dev/null +++ b/internal/service/timestreaminfluxdb/db_instance_test.go @@ -0,0 +1,427 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package timestreaminfluxdb_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" + awstypes "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tftimestreaminfluxdb "github.com/hashicorp/terraform-provider-aws/internal/service/timestreaminfluxdb" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccTimestreamInfluxDBDBInstance_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var dbInstance timestreaminfluxdb.GetDbInstanceOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_timestreaminfluxdb_db_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDBInstanceConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "timestream-influxdb", regexache.MustCompile(`db-instance/+.`)), + resource.TestCheckResourceAttrSet(resourceName, names.AttrAvailabilityZone), + resource.TestCheckResourceAttr(resourceName, "db_storage_type", string(awstypes.DbStorageTypeInfluxIoIncludedT1)), + resource.TestCheckResourceAttr(resourceName, "deployment_type", string(awstypes.DeploymentTypeSingleAz)), + resource.TestCheckResourceAttrSet(resourceName, "influx_auth_parameters_secret_arn"), + resource.TestCheckResourceAttr(resourceName, names.AttrPubliclyAccessible, acctest.CtFalse), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrBucket, names.AttrUsername, names.AttrPassword, "organization"}, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var dbInstance timestreaminfluxdb.GetDbInstanceOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_timestreaminfluxdb_db_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDBInstanceConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tftimestreaminfluxdb.ResourceDBInstance, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_logDeliveryConfiguration(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var dbInstance1, dbInstance2 timestreaminfluxdb.GetDbInstanceOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_timestreaminfluxdb_db_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDBInstanceConfig_logDeliveryConfigurationEnabled(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance1), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.%", acctest.Ct2), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.bucket_name", rName), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.enabled", acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrBucket, names.AttrUsername, names.AttrPassword, "organization"}, + }, + { + Config: testAccDBInstanceConfig_logDeliveryConfigurationEnabled(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance2), + testAccCheckDBInstanceNotRecreated(&dbInstance1, &dbInstance2), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.%", acctest.Ct2), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.bucket_name", rName), + resource.TestCheckResourceAttr(resourceName, "log_delivery_configuration.0.s3_configuration.0.enabled", acctest.CtFalse), + ), + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_publiclyAccessible(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var dbInstance timestreaminfluxdb.GetDbInstanceOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_timestreaminfluxdb_db_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDBInstanceConfig_publiclyAccessible(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance), + resource.TestCheckResourceAttrSet(resourceName, names.AttrEndpoint), + resource.TestCheckResourceAttr(resourceName, names.AttrPubliclyAccessible, acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrBucket, names.AttrUsername, names.AttrPassword, "organization"}, + }, + }, + }) +} + +func TestAccTimestreamInfluxDBDBInstance_deploymentTypeMultiAzStandby(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var dbInstance timestreaminfluxdb.GetDbInstanceOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_timestreaminfluxdb_db_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.TimestreamInfluxDBServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDBInstanceDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDBInstanceConfig_deploymentTypeMultiAzStandby(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDBInstanceExists(ctx, resourceName, &dbInstance), + // DB instance will not be publicly accessible and will not have an endpoint. + // DB instance will have a secondary availability zone. + resource.TestCheckResourceAttrSet(resourceName, "secondary_availability_zone"), + resource.TestCheckResourceAttr(resourceName, "deployment_type", string(awstypes.DeploymentTypeWithMultiazStandby)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrBucket, names.AttrUsername, names.AttrPassword, "organization"}, + }, + }, + }) +} + +func testAccCheckDBInstanceDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).TimestreamInfluxDBClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_timestreaminfluxdb_db_instance" { + continue + } + + _, err := tftimestreaminfluxdb.FindDBInstanceByID(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingDestroyed, tftimestreaminfluxdb.ResNameDBInstance, rs.Primary.ID, err) + } + + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingDestroyed, tftimestreaminfluxdb.ResNameDBInstance, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckDBInstanceExists(ctx context.Context, name string, dbInstance *timestreaminfluxdb.GetDbInstanceOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingExistence, tftimestreaminfluxdb.ResNameDBInstance, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingExistence, tftimestreaminfluxdb.ResNameDBInstance, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).TimestreamInfluxDBClient(ctx) + resp, err := tftimestreaminfluxdb.FindDBInstanceByID(ctx, conn, rs.Primary.ID) + + if err != nil { + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingExistence, tftimestreaminfluxdb.ResNameDBInstance, rs.Primary.ID, err) + } + + *dbInstance = *resp + + return nil + } +} + +func testAccPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).TimestreamInfluxDBClient(ctx) + + input := ×treaminfluxdb.ListDbInstancesInput{} + _, err := conn.ListDbInstances(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccCheckDBInstanceNotRecreated(before, after *timestreaminfluxdb.GetDbInstanceOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + if before, after := aws.ToString(before.Id), aws.ToString(after.Id); before != after { + return create.Error(names.TimestreamInfluxDB, create.ErrActionCheckingNotRecreated, tftimestreaminfluxdb.ResNameDBInstance, before, errors.New("recreated")) + } + + return nil + } +} + +func testAccDBInstanceConfig_base(rName string, subnetCount int) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, subnetCount), ` +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} +`) +} + +// Minimal configuration. +func testAccDBInstanceConfig_basic(rName string) string { + return acctest.ConfigCompose(testAccDBInstanceConfig_base(rName, 1), fmt.Sprintf(` +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = %[1]q + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" +} +`, rName)) +} + +// Configuration with log_delivery_configuration set and enabled. +func testAccDBInstanceConfig_logDeliveryConfigurationEnabled(rName string, enabled bool) string { + return acctest.ConfigCompose(testAccDBInstanceConfig_base(rName, 1), fmt.Sprintf(` +resource "aws_s3_bucket" "test" { + bucket = %[1]q + force_destroy = true +} + +data "aws_iam_policy_document" "test" { + statement { + actions = ["s3:PutObject"] + principals { + type = "Service" + identifiers = ["timestream-influxdb.amazonaws.com"] + } + resources = [ + "${aws_s3_bucket.test.arn}/*" + ] + } +} + +resource "aws_s3_bucket_policy" "test" { + bucket = aws_s3_bucket.test.id + policy = data.aws_iam_policy_document.test.json +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = %[1]q + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + publicly_accessible = false + bucket = "initial" + organization = "organization" + + log_delivery_configuration { + s3_configuration { + bucket_name = aws_s3_bucket.test.bucket + enabled = %[2]t + } + } +} +`, rName, enabled)) +} + +func testAccDBInstanceConfig_publiclyAccessible(rName string) string { + return acctest.ConfigCompose(testAccDBInstanceConfig_base(rName, 1), fmt.Sprintf(` +resource "aws_internet_gateway" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_route" "test" { + route_table_id = aws_vpc.test.main_route_table_id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.test.id +} + +resource "aws_route_table_association" "test" { + subnet_id = aws_subnet.test[0].id + route_table_id = aws_vpc.test.main_route_table_id +} + +resource "aws_vpc_security_group_ingress_rule" "test" { + security_group_id = aws_security_group.test.id + referenced_security_group_id = aws_security_group.test.id + ip_protocol = -1 +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = %[1]q + allocated_storage = 20 + username = "admin" + password = "testpassword" + db_storage_type = "InfluxIOIncludedT1" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + publicly_accessible = true +} +`, rName)) +} + +func testAccDBInstanceConfig_deploymentTypeMultiAzStandby(rName string) string { + return acctest.ConfigCompose(testAccDBInstanceConfig_base(rName, 2), fmt.Sprintf(` +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = %[1]q + allocated_storage = 20 + username = "admin" + password = "testpassword" + db_storage_type = "InfluxIOIncludedT1" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + deployment_type = "WITH_MULTIAZ_STANDBY" +} +`, rName)) +} diff --git a/internal/service/timestreaminfluxdb/exports_test.go b/internal/service/timestreaminfluxdb/exports_test.go new file mode 100644 index 00000000000..55949817f99 --- /dev/null +++ b/internal/service/timestreaminfluxdb/exports_test.go @@ -0,0 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package timestreaminfluxdb + +// Exports for use in tests only. +var ( + ResourceDBInstance = newResourceDBInstance + + FindDBInstanceByID = findDBInstanceByID +) diff --git a/internal/service/timestreaminfluxdb/generate.go b/internal/service/timestreaminfluxdb/generate.go index 1e1eab7dd3a..4ccb17d23dd 100644 --- a/internal/service/timestreaminfluxdb/generate.go +++ b/internal/service/timestreaminfluxdb/generate.go @@ -3,6 +3,7 @@ //go:generate go run ../../generate/servicepackage/main.go //go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -KVTValues -SkipTypesImp -ListTags -ServiceTagsMap -UpdateTags +//go:generate go run ../../generate/tagstests/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. package timestreaminfluxdb diff --git a/internal/service/timestreaminfluxdb/service_package_gen.go b/internal/service/timestreaminfluxdb/service_package_gen.go index 570f77d4e59..b0e4d990ed2 100644 --- a/internal/service/timestreaminfluxdb/service_package_gen.go +++ b/internal/service/timestreaminfluxdb/service_package_gen.go @@ -19,7 +19,15 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceDBInstance, + Name: "DB Instance", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }, + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { diff --git a/internal/service/timestreaminfluxdb/sweep.go b/internal/service/timestreaminfluxdb/sweep.go new file mode 100644 index 00000000000..f71a959bef7 --- /dev/null +++ b/internal/service/timestreaminfluxdb/sweep.go @@ -0,0 +1,66 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package timestreaminfluxdb + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/sweep" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/framework" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func RegisterSweepers() { + resource.AddTestSweepers("aws_timestreaminfluxdb_db_instance", &resource.Sweeper{ + Name: "aws_timestreaminfluxdb_db_instance", + F: sweepDBInstances, + }) +} + +func sweepDBInstances(region string) error { + ctx := sweep.Context(region) + client, err := sweep.SharedRegionalSweepClient(ctx, region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + input := ×treaminfluxdb.ListDbInstancesInput{} + conn := client.TimestreamInfluxDBClient(ctx) + sweepResources := make([]sweep.Sweepable, 0) + + pages := timestreaminfluxdb.NewListDbInstancesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping TimestreamInfluxDB DB instance sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing TimestreamInfluxDB DB instances (%s): %w", region, err) + } + + for _, v := range page.Items { + id := aws.ToString(v.Id) + log.Printf("[INFO] Deleting TimestreamInfluxDB DB instance: %s", id) + + sweepResources = append(sweepResources, framework.NewSweepResource(newResourceDBInstance, client, + framework.NewAttribute(names.AttrID, id), + )) + } + } + + err = sweep.SweepOrchestrator(ctx, sweepResources) + + if err != nil { + return fmt.Errorf("error sweeping TimestreamInfluxDB DB instances (%s): %w", region, err) + } + + return nil +} diff --git a/internal/service/timestreaminfluxdb/testdata/DBInstance/tags/main_gen.tf b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags/main_gen.tf new file mode 100644 index 00000000000..a1d76dc69aa --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags/main_gen.tf @@ -0,0 +1,54 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + tags = var.resource_tags +} +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "resource_tags" { + description = "Tags to set on resource. To specify no tags, set to `null`" + # Not setting a default, so that this must explicitly be set to `null` to specify no tags + type = map(string) + nullable = true +} diff --git a/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed1/main_gen.tf b/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed1/main_gen.tf new file mode 100644 index 00000000000..25904d01aed --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed1/main_gen.tf @@ -0,0 +1,58 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +provider "null" {} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + tags = { + (var.unknownTagKey) = null_resource.test.id + } +} +resource "null_resource" "test" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "unknownTagKey" { + type = string + nullable = false +} diff --git a/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed2/main_gen.tf b/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed2/main_gen.tf new file mode 100644 index 00000000000..1519346353e --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/DBInstance/tagsComputed2/main_gen.tf @@ -0,0 +1,69 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +provider "null" {} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + tags = { + (var.unknownTagKey) = null_resource.test.id + (var.knownTagKey) = var.knownTagValue + } +} +resource "null_resource" "test" {} + +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "unknownTagKey" { + type = string + nullable = false +} + +variable "knownTagKey" { + type = string + nullable = false +} + +variable "knownTagValue" { + type = string + nullable = false +} diff --git a/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_defaults/main_gen.tf b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_defaults/main_gen.tf new file mode 100644 index 00000000000..61e52d28841 --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_defaults/main_gen.tf @@ -0,0 +1,65 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +provider "aws" { + default_tags { + tags = var.provider_tags + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + tags = var.resource_tags +} +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "resource_tags" { + description = "Tags to set on resource. To specify no tags, set to `null`" + # Not setting a default, so that this must explicitly be set to `null` to specify no tags + type = map(string) + nullable = true +} + +variable "provider_tags" { + type = map(string) + nullable = false +} diff --git a/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_ignore/main_gen.tf b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_ignore/main_gen.tf new file mode 100644 index 00000000000..48c166490e4 --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/DBInstance/tags_ignore/main_gen.tf @@ -0,0 +1,74 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +provider "aws" { + default_tags { + tags = var.provider_tags + } + ignore_tags { + keys = var.ignore_tag_keys + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + + tags = var.resource_tags +} +variable "rName" { + description = "Name for resource" + type = string + nullable = false +} + +variable "resource_tags" { + description = "Tags to set on resource. To specify no tags, set to `null`" + # Not setting a default, so that this must explicitly be set to `null` to specify no tags + type = map(string) + nullable = true +} + +variable "provider_tags" { + type = map(string) + nullable = true + default = null +} + +variable "ignore_tag_keys" { + type = set(string) + nullable = false +} diff --git a/internal/service/timestreaminfluxdb/testdata/tmpl/db_instance_tags.gtpl b/internal/service/timestreaminfluxdb/testdata/tmpl/db_instance_tags.gtpl new file mode 100644 index 00000000000..6ca926b208e --- /dev/null +++ b/internal/service/timestreaminfluxdb/testdata/tmpl/db_instance_tags.gtpl @@ -0,0 +1,39 @@ +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" +} + +data "aws_availability_zones" "available" { + exclude_zone_ids = ["usw2-az4", "usgw1-az2"] + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_subnet" "test" { + count = 1 + + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[count.index] + cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index) +} + +resource "aws_security_group" "test" { + vpc_id = aws_vpc.test.id +} + +resource "aws_timestreaminfluxdb_db_instance" "test" { + name = var.rName + allocated_storage = 20 + username = "admin" + password = "testpassword" + vpc_subnet_ids = aws_subnet.test.*.id + vpc_security_group_ids = [aws_security_group.test.id] + db_instance_type = "db.influx.medium" + bucket = "initial" + organization = "organization" + +{{- template "tags" . }} +} \ No newline at end of file diff --git a/internal/sweep/register_gen_test.go b/internal/sweep/register_gen_test.go index 75d56172af3..74a9297fdb3 100644 --- a/internal/sweep/register_gen_test.go +++ b/internal/sweep/register_gen_test.go @@ -151,6 +151,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/service/storagegateway" "github.com/hashicorp/terraform-provider-aws/internal/service/swf" "github.com/hashicorp/terraform-provider-aws/internal/service/synthetics" + "github.com/hashicorp/terraform-provider-aws/internal/service/timestreaminfluxdb" "github.com/hashicorp/terraform-provider-aws/internal/service/timestreamwrite" "github.com/hashicorp/terraform-provider-aws/internal/service/transcribe" "github.com/hashicorp/terraform-provider-aws/internal/service/transfer" @@ -312,6 +313,7 @@ func registerSweepers() { storagegateway.RegisterSweepers() swf.RegisterSweepers() synthetics.RegisterSweepers() + timestreaminfluxdb.RegisterSweepers() timestreamwrite.RegisterSweepers() transcribe.RegisterSweepers() transfer.RegisterSweepers() diff --git a/website/docs/r/timestreaminfluxdb_db_instance.html.markdown b/website/docs/r/timestreaminfluxdb_db_instance.html.markdown new file mode 100644 index 00000000000..f3bf9294f5e --- /dev/null +++ b/website/docs/r/timestreaminfluxdb_db_instance.html.markdown @@ -0,0 +1,278 @@ +--- +subcategory: "Timestream for InfluxDB" +layout: "aws" +page_title: "AWS: aws_timestreaminfluxdb_db_instance" +description: |- + Terraform resource for managing an Amazon Timestream for InfluxDB Db Instance. +--- + +# Resource: aws_timestreaminfluxdb_db_instance + +Terraform resource for managing an Amazon Timestream for InfluxDB Db Instance. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_timestreaminfluxdb_db_instance" "example" { + allocated_storage = 20 + bucket = "example-bucket-name" + db_instance_type = "db.influx.medium" + username = "admin" + password = "example-password" + organization = "organization" + vpc_subnet_ids = [aws_subnet.exampleid] + vpc_security_group_ids = [aws_security_group.example.id] + name = "example-db-instance" +} +``` + +### Usage with Prerequisite Resources + +All Timestream for InfluxDB instances require a VPC, subnet, and security group. The following example shows how these prerequisite resources can be created and used with `aws_timestreaminfluxdb_db_instance`. + +```terraform +resource "aws_vpc" "example" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "example" { + vpc_id = aws_vpc.example.id + cidr_block = "10.0.1.0/24" +} + +resource "aws_security_group" "example" { + name = "example" + vpc_id = aws_vpc.example.id +} + +resource "aws_timestreaminfluxdb_db_instance" "example" { + allocated_storage = 20 + bucket = "example-bucket-name" + db_instance_type = "db.influx.medium" + username = "admin" + password = "example-password" + organization = "organization" + vpc_subnet_ids = [aws_subnet.example.id] + vpc_security_group_ids = [aws_security_group.example.id] + name = "example-db-instance" +} +``` + +### Usage with Public Internet Access Enabled + +The following configuration shows how to define the necessary resources and arguments to allow public internet access on your Timestream for InfluxDB instance's endpoint on port `8086`. After applying this configuration, the instance's InfluxDB UI can be accessed by visiting your instance's endpoint at port `8086`. + +```terraform +resource "aws_vpc" "example" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "example" { + vpc_id = aws_vpc.example.id + cidr_block = "10.0.1.0/24" +} + +resource "aws_security_group" "example" { + name = "example" + vpc_id = aws_vpc.example.id +} + +resource "aws_internet_gateway" "example" { + vpc_id = aws_vpc.example.id + + tags = { + Name = "example" + } +} + +resource "aws_route" "test_route" { + route_table_id = aws_vpc.example.main_route_table_id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.example.id +} + +resource "aws_route_table_association" "test_route_table_association" { + subnet_id = aws_subnet.test_subnet.id + route_table_id = aws_vpc.example.main_route_table_id +} + +resource "aws_vpc_security_group_ingress_rule" "example" { + security_group_id = aws_security_group.example.id + referenced_security_group_id = aws_security_group.example.id + ip_protocol = -1 +} + +resource "aws_vpc_security_group_ingress_rule" "example" { + security_group_id = aws_security_group.example.id + cidr_ipv4 = "0.0.0.0/0" + ip_protocol = "tcp" + from_port = 8086 + to_port = 8086 +} + +resource "aws_timestreaminfluxdb_db_instance" "example" { + allocated_storage = 20 + bucket = "example-bucket-name" + db_instance_type = "db.influx.medium" + username = "admin" + password = "example-password" + organization = "organization" + vpc_subnet_ids = [aws_subnet.example.id] + vpc_security_group_ids = [aws_security_group.example.id] + name = "example-db-instance" + publicly_accessible = true # False by default +} +``` + +### Usage with S3 Log Delivery Enabled + +You can use an S3 bucket to store logs generated by your Timestream for InfluxDB instance. The following example shows what resources and arguments are required to configure an S3 bucket for logging, including the IAM policy that needs to be set in order to allow Timestream for InfluxDB to place logs in your S3 bucket. The configuration of the required VPC, security group, and subnet have been left out of the example for brevity. + +```terraform +resource "aws_s3_bucket" "example" { + bucket = "example-s3-bucket" +} + +data "aws_iam_policy_document" "example" { + statement { + actions = ["s3:PutObject"] + principals { + type = "Service" + identifiers = ["timestream-influxdb.amazonaws.com"] + } + resources = [ + "${aws_s3_bucket.example.arn}/*" + ] + } +} + +resource "aws_s3_bucket_policy" "example" { + bucket = aws_s3_bucket.example.id + policy = data.aws_iam_policy_document.example.json +} + +resource "aws_timestreaminfluxdb_db_instance" "example" { + allocated_storage = 20 + bucket = "example-bucket-name" + db_instance_type = "db.influx.medium" + username = "admin" + password = "example-password" + organization = "organization" + vpc_subnet_ids = [aws_subnet.example.id] + vpc_security_group_ids = [aws_security_group.example.id] + name = "example-db-instance" + + log_delivery_configuration { + s3_configuration { + bucket_name = aws_s3_bucket.example.name + enabled = true + } + } +} +``` + +### Usage with MultiAZ Deployment + +To use multi-region availability, at least two subnets must be created in different availability zones and used with your Timestream for InfluxDB instance. + +```terraform +resource "aws_subnet" "example_1" { + vpc_id = aws_vpc.example.id + cidr_block = "10.0.1.0/24" + availability_zone = "us-west-2a" +} + +resource "aws_subnet" "example_2" { + vpc_id = aws_vpc.example.id + cidr_block = "10.0.2.0/24" + availability_zone = "us-west-2b" +} + +resource "aws_timestreaminfluxdb_db_instance" "example" { + allocated_storage = 20 + bucket = "example-bucket-name" + db_instance_type = "db.influx.medium" + deployment_type = "WITH_MULTIAZ_STANDBY" + username = "admin" + password = "example-password" + organization = "organization" + vpc_subnet_ids = [aws_subnet.example_1.id, aws_subnet.example_2.id] + vpc_security_group_ids = [aws_security_group.example.id] + name = "example-db-instance" +} +``` + +## Argument Reference + +The following arguments are required: + +* `allocated_storage` - (Required) Amount of storage in GiB (gibibytes). The minimum value is 20, the maximum value is 16384. +* `bucket` - (Required) Name of the initial InfluxDB bucket. All InfluxDB data is stored in a bucket. A bucket combines the concept of a database and a retention period (the duration of time that each data point persists). A bucket belongs to an organization. Along with `organization`, `username`, and `password`, this argument will be stored in the secret referred to by the `influx_auth_parameters_secret_arn` attribute. +* `db_instance_type` - (Required) Timestream for InfluxDB DB instance type to run InfluxDB on. Valid options are: `"db.influx.medium"`, `"db.influx.large"`, `"db.influx.xlarge"`, `"db.influx.2xlarge"`, `"db.influx.4xlarge"`, `"db.influx.8xlarge"`, `"db.influx.12xlarge"`, and `"db.influx.16xlarge"`. +* `name` - (Required) Name that uniquely identifies the DB instance when interacting with the Amazon Timestream for InfluxDB API and CLI commands. This name will also be a prefix included in the endpoint. DB instance names must be unique per customer and per region. The argument must start with a letter, cannot contain consecutive hyphens (`-`) and cannot end with a hyphen. +* `password` - (Required) Password of the initial admin user created in InfluxDB. This password will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. Along with `bucket`, `username`, and `organization`, this argument will be stored in the secret referred to by the `influx_auth_parameters_secret_arn` attribute. +* `organization` - (Required) Name of the initial organization for the initial admin user in InfluxDB. An InfluxDB organization is a workspace for a group of users. Along with `bucket`, `username`, and `password`, this argument will be stored in the secret referred to by the `influx_auth_parameters_secret_arn` attribute. +* `username` - (Required) Username of the initial admin user created in InfluxDB. Must start with a letter and can't end with a hyphen or contain two consecutive hyphens. This username will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. Along with `bucket`, `organization`, and `password`, this argument will be stored in the secret referred to by the `influx_auth_parameters_secret_arn` attribute. +* `vpc_security_group_ids` - (Required) List of VPC security group IDs to associate with the DB instance. +* `vpc_subnet_ids` - (Required) List of VPC subnet IDs to associate with the DB instance. Provide at least two VPC subnet IDs in different availability zones when deploying with a Multi-AZ standby. + +The following arguments are optional: + +* `db_parameter_group_identifier` - (Optional) ID of the DB parameter group assigned to your DB instance. If added to an existing Timestream for InfluxDB instance or given a new value, will cause an in-place update to the instance. However, if an instance already has a value for `db_parameter_group_identifier`, removing `db_parameter_group_identifier` will cause the instance to be destroyed and recreated. +* `db_storage_type` - (Default `"InfluxIOIncludedT1"`) Timestream for InfluxDB DB storage type to read and write InfluxDB data. You can choose between 3 different types of provisioned Influx IOPS included storage according to your workloads requirements: Influx IO Included 3000 IOPS, Influx IO Included 12000 IOPS, Influx IO Included 16000 IOPS. Valid options are: `"InfluxIOIncludedT1"`, `"InfluxIOIncludedT2"`, and `"InfluxIOIncludedT1"`. If you use `"InfluxIOIncludedT2" or "InfluxIOIncludedT3", the minimum value for `allocated_storage` is 400. +* `deployment_type` - (Default `"SINGLE_AZ"`) Specifies whether the DB instance will be deployed as a standalone instance or with a Multi-AZ standby for high availability. Valid options are: `"SINGLE_AZ"`, `"WITH_MULTIAZ_STANDBY"`. +* `log_delivery_configuration` - (Optional) Configuration for sending InfluxDB engine logs to a specified S3 bucket. +* `publicly_accessible` - (Default `false`) Configures the DB instance with a public IP to facilitate access. Other resources, such as a VPC, a subnet, an internet gateway, and a route table with routes, are also required to enabled public access, in addition to this argument. See "[Usage with Public Internet Access Enabled](#usage-with-public-internet-access-enabled)" for an example configuration with all required resources for public internet access. +* `tags` - (Optional) Map of tags assigned to the resource. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +### Nested Fields + +#### `log_delivery_configuration` + +* `s3_configuration` - (Required) Configuration for S3 bucket log delivery. + +#### `s3_configuration` + +* `bucket_name` - (Required) Name of the S3 bucket to deliver logs to. +* `enabled` - (Required) Indicates whether log delivery to the S3 bucket is enabled. + +**Note**: Only three arguments do updates in-place: `db_parameter_group_identifier`, `log_delivery_configuration`, and `tags`. Changes to any other argument after a DB instance has been deployed will cause destruction and re-creation of the DB instance. Additionally, when `db_parameter_group_identifier` is added to a DB instance or modified, the DB instance will be updated in-place but if `db_parameter_group_identifier` is removed from a DB instance, the DB instance will be destroyed and re-created. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the Timestream for InfluxDB Instance. +* `availability_zone` - Availability Zone in which the DB instance resides. +* `endpoint` - Endpoint used to connect to InfluxDB. The default InfluxDB port is 8086. +* `id` - ID of the Timestream for InfluxDB instance. +* `influx_auth_parameters_secret_arn` - ARN of the AWS Secrets Manager secret containing the initial InfluxDB authorization parameters. The secret value is a JSON formatted key-value pair holding InfluxDB authorization values: organization, bucket, username, and password. This secret will be read by the `aws_timestreaminfluxdb_db_instance` resource in order to support importing: deleting the secret or secret values can cause errors. +* `secondary_availability_zone` - Availability Zone in which the standby instance is located when deploying with a MultiAZ standby instance. +* `tags_all` - Map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Timestream for InfluxDB Db Instance using its identifier. For example: + +```terraform +import { + to = aws_timestreaminfluxdb_db_instance.example + id = "12345abcde" +} +``` + +Using `terraform import`, import Timestream for InfluxDB Db Instance using its identifier. For example: + +```console +% terraform import aws_timestreaminfluxdb_db_instance.example 12345abcde +```