fix(dns): store IDs immediately after provisioning (#1022)
relates to STACKITTPR-373
This commit is contained in:
parent
f0433984f4
commit
4103c33fd2
4 changed files with 133 additions and 18 deletions
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
|
|
@ -218,7 +217,16 @@ func (r *recordSetResource) Create(ctx context.Context, req resource.CreateReque
|
|||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating record set", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
ctx = tflog.SetField(ctx, "record_set_id", *recordSetResp.Rrset.Id)
|
||||
|
||||
// Write id attributes to state before polling via the wait handler - just in case anything goes wrong during the wait handler
|
||||
utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]any{
|
||||
"project_id": projectId,
|
||||
"zone_id": zoneId,
|
||||
"record_set_id": *recordSetResp.Rrset.Id,
|
||||
})
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
waitResp, err := wait.CreateRecordSetWaitHandler(ctx, r.client, projectId, zoneId, *recordSetResp.Rrset.Id).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -372,9 +380,11 @@ func (r *recordSetResource) ImportState(ctx context.Context, req resource.Import
|
|||
return
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...)
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("zone_id"), idParts[1])...)
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("record_set_id"), idParts[2])...)
|
||||
utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]interface{}{
|
||||
"project_id": idParts[0],
|
||||
"zone_id": idParts[1],
|
||||
"record_set_id": idParts[2],
|
||||
})
|
||||
tflog.Info(ctx, "DNS record set state imported")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
|
|
@ -280,8 +279,7 @@ func (r *zoneResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
|||
func (r *zoneResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
// Retrieve values from plan
|
||||
var model Model
|
||||
diags := req.Plan.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &model)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
|
@ -301,9 +299,17 @@ func (r *zoneResource) Create(ctx context.Context, req resource.CreateRequest, r
|
|||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating zone", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
zoneId := *createResp.Zone.Id
|
||||
|
||||
ctx = tflog.SetField(ctx, "zone_id", zoneId)
|
||||
// Write id attributes to state before polling via the wait handler - just in case anything goes wrong during the wait handler
|
||||
zoneId := *createResp.Zone.Id
|
||||
utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]interface{}{
|
||||
"project_id": projectId,
|
||||
"zone_id": zoneId,
|
||||
})
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
waitResp, err := wait.CreateZoneWaitHandler(ctx, r.client, projectId, zoneId).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating zone", fmt.Sprintf("Zone creation waiting: %v", err))
|
||||
|
|
@ -317,8 +323,7 @@ func (r *zoneResource) Create(ctx context.Context, req resource.CreateRequest, r
|
|||
return
|
||||
}
|
||||
// Set state to fully populated data
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, model)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
|
@ -451,13 +456,11 @@ func (r *zoneResource) ImportState(ctx context.Context, req resource.ImportState
|
|||
return
|
||||
}
|
||||
|
||||
projectId := idParts[0]
|
||||
zoneId := idParts[1]
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "zone_id", zoneId)
|
||||
utils.SetAndLogStateFields(ctx, &resp.Diagnostics, &resp.State, map[string]interface{}{
|
||||
"project_id": idParts[0],
|
||||
"zone_id": idParts[1],
|
||||
})
|
||||
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), projectId)...)
|
||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("zone_id"), zoneId)...)
|
||||
tflog.Info(ctx, "DNS zone state imported")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
|
|
@ -186,3 +188,11 @@ func CheckListRemoval(ctx context.Context, configModelList, planModelList types.
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetAndLogStateFields writes the given map of key-value pairs to the state
|
||||
func SetAndLogStateFields(ctx context.Context, diags *diag.Diagnostics, state *tfsdk.State, values map[string]any) {
|
||||
for key, val := range values {
|
||||
ctx = tflog.SetField(ctx, key, val)
|
||||
diags.Append(state.SetAttribute(ctx, path.Root(key), val)...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
|
|
@ -551,3 +554,92 @@ func TestCheckListRemoval(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAndLogStateFields(t *testing.T) {
|
||||
testSchema := schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"project_id": schema.StringAttribute{},
|
||||
"instance_id": schema.StringAttribute{},
|
||||
},
|
||||
}
|
||||
|
||||
type args struct {
|
||||
diags *diag.Diagnostics
|
||||
state *tfsdk.State
|
||||
values map[string]interface{}
|
||||
}
|
||||
type want struct {
|
||||
hasError bool
|
||||
state *tfsdk.State
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
{
|
||||
name: "empty map",
|
||||
args: args{
|
||||
diags: &diag.Diagnostics{},
|
||||
state: &tfsdk.State{},
|
||||
values: map[string]interface{}{},
|
||||
},
|
||||
want: want{
|
||||
hasError: false,
|
||||
state: &tfsdk.State{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "base",
|
||||
args: args{
|
||||
diags: &diag.Diagnostics{},
|
||||
state: func() *tfsdk.State {
|
||||
ctx := context.Background()
|
||||
state := tfsdk.State{
|
||||
Raw: tftypes.NewValue(testSchema.Type().TerraformType(ctx), map[string]tftypes.Value{
|
||||
"project_id": tftypes.NewValue(tftypes.String, "9b15d120-86f8-45f5-81d8-a554f09c7582"),
|
||||
"instance_id": tftypes.NewValue(tftypes.String, nil),
|
||||
}),
|
||||
Schema: testSchema,
|
||||
}
|
||||
return &state
|
||||
}(),
|
||||
values: map[string]interface{}{
|
||||
"project_id": "a414f971-3f7a-4e9a-8671-51a8acb7bcc8",
|
||||
"instance_id": "97073250-8cad-46c3-8424-6258ac0b3731",
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
hasError: false,
|
||||
state: func() *tfsdk.State {
|
||||
ctx := context.Background()
|
||||
state := tfsdk.State{
|
||||
Raw: tftypes.NewValue(testSchema.Type().TerraformType(ctx), map[string]tftypes.Value{
|
||||
"project_id": tftypes.NewValue(tftypes.String, nil),
|
||||
"instance_id": tftypes.NewValue(tftypes.String, nil),
|
||||
}),
|
||||
Schema: testSchema,
|
||||
}
|
||||
state.SetAttribute(ctx, path.Root("project_id"), "a414f971-3f7a-4e9a-8671-51a8acb7bcc8")
|
||||
state.SetAttribute(ctx, path.Root("instance_id"), "97073250-8cad-46c3-8424-6258ac0b3731")
|
||||
return &state
|
||||
}(),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
SetAndLogStateFields(ctx, tt.args.diags, tt.args.state, tt.args.values)
|
||||
|
||||
if tt.args.diags.HasError() != tt.want.hasError {
|
||||
t.Errorf("TestSetAndLogStateFields() error count = %v, hasErr %v", tt.args.diags.ErrorsCount(), tt.want.hasError)
|
||||
}
|
||||
|
||||
diff := cmp.Diff(tt.args.state, tt.want.state)
|
||||
if diff != "" {
|
||||
t.Fatalf("Data does not match: %s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue