Skip to content

Commit 8eeb933

Browse files
authored
Merge pull request #40661 from trevorbonas/f-timestreaminfluxdb_db_instance-more-updatable-arguments
Add new arguments from CreateDbInstance and UpdateDbInstance
2 parents 3ad110d + 226b838 commit 8eeb933

File tree

6 files changed

+510
-56
lines changed

6 files changed

+510
-56
lines changed

.changelog/40661.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_timestreaminfluxdb_db_instance: Add `network_type` and `port` attributes. The following can now be updated in place: `allocated_storage`, `db_instance_type`, `db_storage_type` and `deployment_type`
3+
```

internal/service/timestreaminfluxdb/db_instance.go

Lines changed: 89 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,24 @@ package timestreaminfluxdb
66
import (
77
"context"
88
"errors"
9+
"math"
910
"time"
1011

1112
"github.com/YakDriver/regexache"
1213
"github.com/aws/aws-sdk-go-v2/aws"
1314
"github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb"
1415
awstypes "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb/types"
1516
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
17+
"github.com/hashicorp/terraform-plugin-framework-validators/int32validator"
1618
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
1719
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
1820
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
1921
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
22+
"github.com/hashicorp/terraform-plugin-framework/path"
2023
"github.com/hashicorp/terraform-plugin-framework/resource"
2124
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
2225
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
23-
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
26+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int32planmodifier"
2427
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
2528
"github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
2629
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
@@ -32,7 +35,7 @@ import (
3235
"github.com/hashicorp/terraform-provider-aws/internal/errs"
3336
"github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag"
3437
"github.com/hashicorp/terraform-provider-aws/internal/framework"
35-
"github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
38+
fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
3639
fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types"
3740
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
3841
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
@@ -68,9 +71,6 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
6871
Attributes: map[string]schema.Attribute{
6972
names.AttrAllocatedStorage: schema.Int64Attribute{
7073
Required: true,
71-
PlanModifiers: []planmodifier.Int64{
72-
int64planmodifier.RequiresReplace(),
73-
},
7474
Validators: []validator.Int64{
7575
int64validator.Between(20, 16384),
7676
},
@@ -101,11 +101,8 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
101101
that each data point persists). A bucket belongs to an organization.`,
102102
},
103103
"db_instance_type": schema.StringAttribute{
104-
CustomType: fwtypes.StringEnumType[awstypes.DbInstanceType](),
105-
Required: true,
106-
PlanModifiers: []planmodifier.String{
107-
stringplanmodifier.RequiresReplace(),
108-
},
104+
CustomType: fwtypes.StringEnumType[awstypes.DbInstanceType](),
105+
Required: true,
109106
Description: `The Timestream for InfluxDB DB instance type to run InfluxDB on.`,
110107
},
111108
"db_parameter_group_identifier": schema.StringAttribute{
@@ -129,7 +126,6 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
129126
Optional: true,
130127
Computed: true,
131128
PlanModifiers: []planmodifier.String{
132-
stringplanmodifier.RequiresReplace(),
133129
stringplanmodifier.UseStateForUnknown(),
134130
},
135131
Description: `The Timestream for InfluxDB DB storage type to read and write InfluxDB data.
@@ -142,7 +138,6 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
142138
Optional: true,
143139
Computed: true,
144140
PlanModifiers: []planmodifier.String{
145-
stringplanmodifier.RequiresReplace(),
146141
stringplanmodifier.UseStateForUnknown(),
147142
},
148143
Description: `Specifies whether the DB instance will be deployed as a standalone instance or
@@ -183,6 +178,18 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
183178
prefix included in the endpoint. DB instance names must be unique per customer
184179
and per region.`,
185180
},
181+
"network_type": schema.StringAttribute{
182+
CustomType: fwtypes.StringEnumType[awstypes.NetworkType](),
183+
Optional: true,
184+
Computed: true,
185+
PlanModifiers: []planmodifier.String{
186+
stringplanmodifier.RequiresReplace(),
187+
stringplanmodifier.UseStateForUnknown(),
188+
},
189+
Description: `Specifies whether the networkType of the Timestream for InfluxDB instance is
190+
IPV4, which can communicate over IPv4 protocol only, or DUAL, which can communicate
191+
over both IPv4 and IPv6 protocols.`,
192+
},
186193
names.AttrTags: tftags.TagsAttribute(),
187194
names.AttrTagsAll: tftags.TagsAttributeComputedOnly(),
188195
"organization": schema.StringAttribute{
@@ -211,6 +218,18 @@ func (r *resourceDBInstance) Schema(ctx context.Context, req resource.SchemaRequ
211218
also use the InfluxDB CLI to create an operator token. These attributes will be
212219
stored in a Secret created in AWS SecretManager in your account.`,
213220
},
221+
names.AttrPort: schema.Int32Attribute{
222+
Optional: true,
223+
Computed: true,
224+
PlanModifiers: []planmodifier.Int32{
225+
int32planmodifier.UseStateForUnknown(),
226+
},
227+
Validators: []validator.Int32{
228+
int32validator.Between(1024, 65535),
229+
int32validator.NoneOf(2375, 2376, 7788, 7789, 7790, 7791, 7792, 7793, 7794, 7795, 7796, 7797, 7798, 7799, 8090, 51678, 51679, 51680),
230+
},
231+
Description: `The port number on which InfluxDB accepts connections.`,
232+
},
214233
names.AttrPubliclyAccessible: schema.BoolAttribute{
215234
Optional: true,
216235
Computed: true,
@@ -349,17 +368,15 @@ func (r *resourceDBInstance) Create(ctx context.Context, req resource.CreateRequ
349368
return
350369
}
351370

352-
in := timestreaminfluxdb.CreateDbInstanceInput{}
353-
354-
resp.Diagnostics.Append(flex.Expand(ctx, plan, &in)...)
355-
371+
input := timestreaminfluxdb.CreateDbInstanceInput{}
372+
resp.Diagnostics.Append(fwflex.Expand(ctx, plan, &input)...)
356373
if resp.Diagnostics.HasError() {
357374
return
358375
}
359376

360-
in.Tags = getTagsIn(ctx)
377+
input.Tags = getTagsIn(ctx)
361378

362-
out, err := conn.CreateDbInstance(ctx, &in)
379+
out, err := conn.CreateDbInstance(ctx, &input)
363380
if err != nil {
364381
resp.Diagnostics.AddError(
365382
create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionCreating, ResNameDBInstance, plan.Name.String(), err),
@@ -377,27 +394,26 @@ func (r *resourceDBInstance) Create(ctx context.Context, req resource.CreateRequ
377394
}
378395

379396
state := plan
380-
state.ID = flex.StringToFramework(ctx, out.Id)
397+
state.ID = fwflex.StringToFramework(ctx, out.Id)
381398

382399
createTimeout := r.CreateTimeout(ctx, plan.Timeouts)
383400
output, err := waitDBInstanceCreated(ctx, conn, state.ID.ValueString(), createTimeout)
384-
385401
if err != nil {
402+
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), out.Id)...)
386403
resp.Diagnostics.AddError(
387404
create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionWaitingForCreation, ResNameDBInstance, plan.Name.String(), err),
388405
err.Error(),
389406
)
390407
return
391408
}
392409

393-
resp.Diagnostics.Append(flex.Flatten(ctx, output, &state)...)
394-
410+
resp.Diagnostics.Append(fwflex.Flatten(ctx, output, &state)...)
395411
if resp.Diagnostics.HasError() {
396412
return
397413
}
398414

399415
// flatten using legacy since this computed output may be null
400-
state.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
416+
state.SecondaryAvailabilityZone = fwflex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
401417

402418
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
403419
}
@@ -412,7 +428,6 @@ func (r *resourceDBInstance) Read(ctx context.Context, req resource.ReadRequest,
412428
}
413429

414430
output, err := findDBInstanceByID(ctx, conn, state.ID.ValueString())
415-
416431
if tfresource.NotFound(err) {
417432
resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err))
418433
resp.State.RemoveResource(ctx)
@@ -427,14 +442,13 @@ func (r *resourceDBInstance) Read(ctx context.Context, req resource.ReadRequest,
427442
return
428443
}
429444

430-
resp.Diagnostics.Append(flex.Flatten(ctx, output, &state)...)
431-
445+
resp.Diagnostics.Append(fwflex.Flatten(ctx, output, &state)...)
432446
if resp.Diagnostics.HasError() {
433447
return
434448
}
435449

436450
// flatten using legacy since this computed output may be null
437-
state.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
451+
state.SecondaryAvailabilityZone = fwflex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
438452

439453
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
440454
}
@@ -449,19 +463,22 @@ func (r *resourceDBInstance) Update(ctx context.Context, req resource.UpdateRequ
449463
return
450464
}
451465

452-
if !plan.DBParameterGroupIdentifier.Equal(state.DBParameterGroupIdentifier) ||
453-
!plan.LogDeliveryConfiguration.Equal(state.LogDeliveryConfiguration) {
454-
in := timestreaminfluxdb.UpdateDbInstanceInput{
466+
diff, d := fwflex.Diff(ctx, plan, state)
467+
resp.Diagnostics.Append(d...)
468+
if resp.Diagnostics.HasError() {
469+
return
470+
}
471+
472+
if diff.HasChanges() {
473+
input := timestreaminfluxdb.UpdateDbInstanceInput{
455474
Identifier: plan.ID.ValueStringPointer(),
456475
}
457-
458-
resp.Diagnostics.Append(flex.Expand(ctx, plan, &in)...)
459-
476+
resp.Diagnostics.Append(fwflex.Expand(ctx, plan, &input, diff.IgnoredFieldNamesOpts()...)...)
460477
if resp.Diagnostics.HasError() {
461478
return
462479
}
463480

464-
_, err := conn.UpdateDbInstance(ctx, &in)
481+
_, err := conn.UpdateDbInstance(ctx, &input)
465482
if err != nil {
466483
resp.Diagnostics.AddError(
467484
create.ProblemStandardMessage(names.TimestreamInfluxDB, create.ErrActionUpdating, ResNameDBInstance, plan.ID.String(), err),
@@ -480,14 +497,16 @@ func (r *resourceDBInstance) Update(ctx context.Context, req resource.UpdateRequ
480497
return
481498
}
482499

483-
resp.Diagnostics.Append(flex.Flatten(ctx, output, &plan)...)
484-
500+
resp.Diagnostics.Append(fwflex.Flatten(ctx, output, &plan)...)
485501
if resp.Diagnostics.HasError() {
486502
return
487503
}
488504

489-
// flatten using legacy since this computed output may be null
490-
plan.SecondaryAvailabilityZone = flex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
505+
plan.SecondaryAvailabilityZone = fwflex.StringToFrameworkLegacy(ctx, output.SecondaryAvailabilityZone)
506+
}
507+
508+
if plan.SecondaryAvailabilityZone.IsUnknown() {
509+
plan.SecondaryAvailabilityZone = state.SecondaryAvailabilityZone
491510
}
492511

493512
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
@@ -529,6 +548,34 @@ func (r *resourceDBInstance) Delete(ctx context.Context, req resource.DeleteRequ
529548
}
530549
}
531550

551+
func (r *resourceDBInstance) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
552+
var allocatedStorage types.Int64
553+
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root(names.AttrAllocatedStorage), &allocatedStorage)...)
554+
if resp.Diagnostics.HasError() {
555+
return
556+
}
557+
558+
if allocatedStorage.IsNull() || allocatedStorage.IsUnknown() {
559+
return
560+
}
561+
562+
if allocatedStorage.ValueInt64() > math.MaxInt32 {
563+
resp.Diagnostics.AddError(
564+
"Invalid value for allocated_storage",
565+
"allocated_storage was greater than the maximum allowed value for int32",
566+
)
567+
return
568+
}
569+
570+
if allocatedStorage.ValueInt64() < math.MinInt32 {
571+
resp.Diagnostics.AddError(
572+
"Invalid value for allocated_storage",
573+
"allocated_storage was less than the minimum allowed value for int32",
574+
)
575+
return
576+
}
577+
}
578+
532579
func waitDBInstanceCreated(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) {
533580
stateConf := &retry.StateChangeConf{
534581
Pending: enum.Slice(awstypes.StatusCreating),
@@ -549,7 +596,7 @@ func waitDBInstanceCreated(ctx context.Context, conn *timestreaminfluxdb.Client,
549596

550597
func waitDBInstanceUpdated(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) {
551598
stateConf := &retry.StateChangeConf{
552-
Pending: enum.Slice(awstypes.StatusModifying, awstypes.StatusUpdating),
599+
Pending: enum.Slice(awstypes.StatusModifying, awstypes.StatusUpdating, awstypes.StatusUpdatingInstanceType, awstypes.StatusUpdatingDeploymentType),
553600
Target: enum.Slice(awstypes.StatusAvailable),
554601
Refresh: statusDBInstance(ctx, conn, id),
555602
Timeout: timeout,
@@ -567,7 +614,7 @@ func waitDBInstanceUpdated(ctx context.Context, conn *timestreaminfluxdb.Client,
567614

568615
func waitDBInstanceDeleted(ctx context.Context, conn *timestreaminfluxdb.Client, id string, timeout time.Duration) (*timestreaminfluxdb.GetDbInstanceOutput, error) {
569616
stateConf := &retry.StateChangeConf{
570-
Pending: enum.Slice(awstypes.StatusDeleting),
617+
Pending: enum.Slice(awstypes.StatusDeleting, awstypes.StatusDeleted),
571618
Target: []string{},
572619
Refresh: statusDBInstance(ctx, conn, id),
573620
Timeout: timeout,
@@ -635,8 +682,10 @@ type resourceDBInstanceData struct {
635682
InfluxAuthParametersSecretARN types.String `tfsdk:"influx_auth_parameters_secret_arn"`
636683
LogDeliveryConfiguration fwtypes.ListNestedObjectValueOf[logDeliveryConfigurationData] `tfsdk:"log_delivery_configuration"`
637684
Name types.String `tfsdk:"name"`
685+
NetworkType fwtypes.StringEnum[awstypes.NetworkType] `tfsdk:"network_type"`
638686
Organization types.String `tfsdk:"organization"`
639687
Password types.String `tfsdk:"password"`
688+
Port types.Int32 `tfsdk:"port"`
640689
PubliclyAccessible types.Bool `tfsdk:"publicly_accessible"`
641690
SecondaryAvailabilityZone types.String `tfsdk:"secondary_availability_zone"`
642691
Tags tftags.Map `tfsdk:"tags"`

0 commit comments

Comments
 (0)