fix: refactor to use identity and different model mapping
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 5s
CI Workflow / Test readiness for publishing provider (pull_request) Successful in 22m50s
CI Workflow / CI (pull_request) Failing after 27m13s
CI Workflow / Code coverage report (pull_request) Has been skipped

This commit is contained in:
Marcel_Henselin 2026-02-03 19:00:44 +01:00
parent 762c39fbbd
commit 8d7323bbc1
9 changed files with 191 additions and 212 deletions

View file

@ -278,7 +278,7 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
// }
//}
err = mapDataSourceResponseToModel(ctx, instanceResp, &model, resp)
err = mapResponseToModel(ctx, instanceResp, &model, resp.Diagnostics)
//err = mapFields(ctx, instanceResp, &model, storage, encryption, network, region)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))

View file

@ -6,7 +6,7 @@ import (
"math"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
@ -14,200 +14,103 @@ import (
sqlserverflexResGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance/resources_gen"
)
func mapCreateResponseToModel(
func mapResponseToModel(
ctx context.Context,
resp *sqlserverflex.GetInstanceResponse,
m *sqlserverflexResGen.InstanceModel,
tfResp *resource.CreateResponse,
tfDiags diag.Diagnostics,
) error {
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
if resp.HasEncryption() {
m.Encryption = sqlserverflexResGen.NewEncryptionValueMust(
m.Encryption.AttributeTypes(ctx),
map[string]attr.Value{
"kek_key_id": types.StringValue(resp.Encryption.GetKekKeyId()),
"kek_key_ring_id": types.StringValue(resp.Encryption.GetKekKeyRingId()),
"kek_key_version": types.StringValue(resp.Encryption.GetKekKeyVersion()),
"service_account": types.StringValue(resp.Encryption.GetServiceAccount()),
},
)
}
m.Edition = types.StringValue(string(resp.GetEdition()))
m.Encryption = handleEncryption(m, resp)
m.FlavorId = types.StringValue(resp.GetFlavorId())
m.Id = types.StringValue(resp.GetId())
m.InstanceId = types.StringValue(resp.GetId())
m.IsDeletable = types.BoolValue(resp.GetIsDeletable())
m.Name = types.StringValue(resp.GetName())
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
tfResp.Diagnostics.Append(diags...)
tfDiags.Append(diags...)
if diags.HasError() {
return fmt.Errorf("error converting api response value")
return fmt.Errorf(
"error converting network acl response value",
)
}
m.Network = sqlserverflexResGen.NetworkValue{
AccessScope: types.StringValue(string(resp.Network.GetAccessScope())),
Acl: netAcl,
InstanceAddress: types.StringValue(resp.Network.GetInstanceAddress()),
RouterAddress: types.StringValue(resp.Network.GetRouterAddress()),
net, diags := sqlserverflexResGen.NewNetworkValue(
sqlserverflexResGen.NetworkValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"access_scope": types.StringValue(string(resp.Network.GetAccessScope())),
"acl": netAcl,
"instance_address": types.StringValue(resp.Network.GetInstanceAddress()),
"router_address": types.StringValue(resp.Network.GetRouterAddress()),
},
)
tfDiags.Append(diags...)
if diags.HasError() {
return fmt.Errorf(
"error converting network response value",
"access_scope",
types.StringValue(string(resp.Network.GetAccessScope())),
"acl",
netAcl,
"instance_address",
types.StringValue(resp.Network.GetInstanceAddress()),
"router_address",
types.StringValue(resp.Network.GetRouterAddress()),
)
}
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.Storage = sqlserverflexResGen.StorageValue{
Class: types.StringValue(resp.Storage.GetClass()),
Size: types.Int64Value(resp.Storage.GetSize()),
}
m.Status = types.StringValue(string(resp.GetStatus()))
m.Version = types.StringValue(string(resp.GetVersion()))
stor, diags := sqlserverflexResGen.NewStorageValue(
sqlserverflexResGen.StorageValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"class": types.StringValue(resp.Storage.GetClass()),
"size": types.Int64Value(resp.Storage.GetSize()),
},
)
tfDiags.Append(diags...)
if diags.HasError() {
return fmt.Errorf("error converting storage response value")
}
m.Storage = stor
m.Version = types.StringValue(string(resp.GetVersion()))
return nil
}
func mapReadResponseToModel(
ctx context.Context,
resp *sqlserverflex.GetInstanceResponse,
func handleEncryption(
m *sqlserverflexResGen.InstanceModel,
tfResp *resource.ReadResponse,
) error {
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
if resp.HasEncryption() {
m.Encryption = sqlserverflexResGen.NewEncryptionValueMust(
m.Encryption.AttributeTypes(ctx),
map[string]attr.Value{
"kek_key_id": types.StringValue(resp.Encryption.GetKekKeyId()),
"kek_key_ring_id": types.StringValue(resp.Encryption.GetKekKeyRingId()),
"kek_key_version": types.StringValue(resp.Encryption.GetKekKeyVersion()),
"service_account": types.StringValue(resp.Encryption.GetServiceAccount()),
},
)
}
m.FlavorId = types.StringValue(resp.GetFlavorId())
m.Id = types.StringValue(resp.GetId())
m.InstanceId = types.StringValue(resp.GetId())
m.Name = types.StringValue(resp.GetName())
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
tfResp.Diagnostics.Append(diags...)
if diags.HasError() {
return fmt.Errorf("error converting api response value")
}
m.Network = sqlserverflexResGen.NetworkValue{
AccessScope: types.StringValue(string(resp.Network.GetAccessScope())),
Acl: netAcl,
InstanceAddress: types.StringValue(resp.Network.GetInstanceAddress()),
RouterAddress: types.StringValue(resp.Network.GetRouterAddress()),
}
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.Storage = sqlserverflexResGen.StorageValue{
Class: types.StringValue(resp.Storage.GetClass()),
Size: types.Int64Value(resp.Storage.GetSize()),
}
m.Status = types.StringValue(string(resp.GetStatus()))
m.Version = types.StringValue(string(resp.GetVersion()))
return nil
}
func mapUpdateResponseToModel(
ctx context.Context,
resp *sqlserverflex.GetInstanceResponse,
m *sqlserverflexResGen.InstanceModel,
tfResp *resource.UpdateResponse,
) error {
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
) sqlserverflexResGen.EncryptionValue {
if !resp.HasEncryption() ||
resp.Encryption == nil ||
resp.Encryption.KekKeyId == nil ||
resp.Encryption.KekKeyRingId == nil ||
resp.Encryption.KekKeyVersion == nil ||
resp.Encryption.ServiceAccount == nil {
if resp.HasEncryption() {
m.Encryption = sqlserverflexResGen.NewEncryptionValueMust(
m.Encryption.AttributeTypes(ctx),
map[string]attr.Value{
"kek_key_id": types.StringValue(resp.Encryption.GetKekKeyId()),
"kek_key_ring_id": types.StringValue(resp.Encryption.GetKekKeyRingId()),
"kek_key_version": types.StringValue(resp.Encryption.GetKekKeyVersion()),
"service_account": types.StringValue(resp.Encryption.GetServiceAccount()),
},
)
if m.Encryption.IsNull() || m.Encryption.IsUnknown() {
return sqlserverflexResGen.NewEncryptionValueNull()
}
return m.Encryption
}
m.FlavorId = types.StringValue(resp.GetFlavorId())
m.Id = types.StringValue(resp.GetId())
m.InstanceId = types.StringValue(resp.GetId())
m.Name = types.StringValue(resp.GetName())
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
tfResp.Diagnostics.Append(diags...)
if diags.HasError() {
return fmt.Errorf("error converting api response value")
enc := sqlserverflexResGen.NewEncryptionValueNull()
if kVal, ok := resp.Encryption.GetKekKeyIdOk(); ok {
enc.KekKeyId = types.StringValue(kVal)
}
m.Network = sqlserverflexResGen.NetworkValue{
AccessScope: types.StringValue(string(resp.Network.GetAccessScope())),
Acl: netAcl,
InstanceAddress: types.StringValue(resp.Network.GetInstanceAddress()),
RouterAddress: types.StringValue(resp.Network.GetRouterAddress()),
if kkVal, ok := resp.Encryption.GetKekKeyRingIdOk(); ok {
enc.KekKeyRingId = types.StringValue(kkVal)
}
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.Storage = sqlserverflexResGen.StorageValue{
Class: types.StringValue(resp.Storage.GetClass()),
Size: types.Int64Value(resp.Storage.GetSize()),
if kkvVal, ok := resp.Encryption.GetKekKeyVersionOk(); ok {
enc.KekKeyVersion = types.StringValue(kkvVal)
}
m.Status = types.StringValue(string(resp.GetStatus()))
m.Version = types.StringValue(string(resp.GetVersion()))
return nil
}
func mapDataSourceResponseToModel(
ctx context.Context,
resp *sqlserverflex.GetInstanceResponse,
m *sqlserverflexResGen.InstanceModel,
tfResp *datasource.ReadResponse,
) error {
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
if resp.HasEncryption() {
m.Encryption = sqlserverflexResGen.NewEncryptionValueMust(
m.Encryption.AttributeTypes(ctx),
map[string]attr.Value{
"kek_key_id": types.StringValue(resp.Encryption.GetKekKeyId()),
"kek_key_ring_id": types.StringValue(resp.Encryption.GetKekKeyRingId()),
"kek_key_version": types.StringValue(resp.Encryption.GetKekKeyVersion()),
"service_account": types.StringValue(resp.Encryption.GetServiceAccount()),
},
)
if sa, ok := resp.Encryption.GetServiceAccountOk(); ok {
enc.ServiceAccount = types.StringValue(sa)
}
m.FlavorId = types.StringValue(resp.GetFlavorId())
m.Id = types.StringValue(resp.GetId())
m.InstanceId = types.StringValue(resp.GetId())
m.Name = types.StringValue(resp.GetName())
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
tfResp.Diagnostics.Append(diags...)
if diags.HasError() {
return fmt.Errorf("error converting api response value")
}
m.Network = sqlserverflexResGen.NetworkValue{
AccessScope: types.StringValue(string(resp.Network.GetAccessScope())),
Acl: netAcl,
InstanceAddress: types.StringValue(resp.Network.GetInstanceAddress()),
RouterAddress: types.StringValue(resp.Network.GetRouterAddress()),
}
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.Storage = sqlserverflexResGen.StorageValue{
Class: types.StringValue(resp.Storage.GetClass()),
Size: types.Int64Value(resp.Storage.GetSize()),
}
m.Status = types.StringValue(string(resp.GetStatus()))
m.Version = types.StringValue(string(resp.GetVersion()))
return nil
return enc
}
//func mapFields(
@ -357,6 +260,7 @@ func mapDataSourceResponseToModel(
//}
func toCreatePayload(
ctx context.Context,
model *sqlserverflexResGen.InstanceModel,
) (*sqlserverflex.CreateInstanceRequestPayload, error) {
if model == nil {
@ -390,11 +294,9 @@ func toCreatePayload(
)
var resList []string
aclList := model.Network.Acl.Elements()
for _, aclItem := range aclList {
if !aclItem.IsNull() && !aclItem.IsUnknown() {
resList = append(resList, aclItem.String())
}
diags := model.Network.Acl.ElementsAs(ctx, &resList, false)
if diags.HasError() {
return nil, fmt.Errorf("error converting network acl list")
}
networkPayload.Acl = &resList
}

View file

@ -21,7 +21,6 @@ fields:
- name: 'name'
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'backup_schedule'
modifiers:
@ -31,24 +30,28 @@ fields:
validators:
- validate.NoSeparator
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'encryption.kek_key_version'
validators:
- validate.NoSeparator
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'encryption.kek_key_ring_id'
validators:
- validate.NoSeparator
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'encryption.service_account'
validators:
- validate.NoSeparator
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'network.access_scope'
@ -76,6 +79,7 @@ fields:
- name: 'region'
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'retention_days'

View file

@ -92,16 +92,20 @@ func (r *instanceResource) ModifyPlan(
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
var configModel sqlserverflexalpha2.InstanceModel
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return
}
var configModel sqlserverflexalpha2.InstanceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...)
if resp.Diagnostics.HasError() {
return
}
if req.Plan.Raw.IsNull() {
return
}
var planModel sqlserverflexalpha2.InstanceModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
if resp.Diagnostics.HasError() {
@ -113,6 +117,18 @@ func (r *instanceResource) ModifyPlan(
return
}
var identityModel InstanceResourceIdentityModel
identityModel.ProjectID = planModel.ProjectId
identityModel.Region = planModel.Region
if !planModel.InstanceId.IsNull() && !planModel.InstanceId.IsUnknown() {
identityModel.InstanceID = planModel.InstanceId
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identityModel)...)
if resp.Diagnostics.HasError() {
return
}
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
if resp.Diagnostics.HasError() {
return
@ -416,15 +432,22 @@ func (r *instanceResource) Create(
return
}
// Read identity data
var identityData InstanceResourceIdentityModel
resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...)
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
region := model.Region.ValueString()
projectId := identityData.ProjectID.ValueString()
region := identityData.Region.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
// Generate API request body from model
payload, err := toCreatePayload(&model)
payload, err := toCreatePayload(ctx, &model)
if err != nil {
core.LogAndAddError(
ctx,
@ -448,6 +471,18 @@ func (r *instanceResource) Create(
ctx = core.LogResponse(ctx)
instanceId := *createResp.Id
// Set data returned by API in identity
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
return
}
utils.SetAndLogStateFields(
ctx, &resp.Diagnostics, &resp.State, map[string]any{
"id": utils.BuildInternalTerraformId(projectId, region, instanceId),
@ -466,7 +501,11 @@ func (r *instanceResource) Create(
projectId,
instanceId,
region,
).SetSleepBeforeWait(30 * time.Second).WaitWithContext(ctx)
).SetSleepBeforeWait(
30 * time.Second,
).SetTimeout(
90 * time.Minute,
).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(
ctx,
@ -489,7 +528,7 @@ func (r *instanceResource) Create(
// Map response body to schema
// err = mapFields(ctx, waitResp, &model, storage, encryption, network, region)
err = mapCreateResponseToModel(ctx, waitResp, &model, resp)
err = mapResponseToModel(ctx, waitResp, &model, resp.Diagnostics)
if err != nil {
core.LogAndAddError(
ctx,
@ -522,6 +561,13 @@ func (r *instanceResource) Read(
return
}
// Read identity data
var identityData InstanceResourceIdentityModel
resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...)
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
@ -547,7 +593,7 @@ func (r *instanceResource) Read(
// Map response body to schema
// err = mapFields(ctx, instanceResp, &model, storage, encryption, network, region)
err = mapReadResponseToModel(ctx, instanceResp, &model, resp)
err = mapResponseToModel(ctx, instanceResp, &model, resp.Diagnostics)
if err != nil {
core.LogAndAddError(
ctx,
@ -563,6 +609,17 @@ func (r *instanceResource) Read(
if resp.Diagnostics.HasError() {
return
}
// Set data returned by API in identity
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "SQLServer Flex instance read")
}
@ -627,7 +684,7 @@ func (r *instanceResource) Update(
}
// Map response body to schema
err = mapUpdateResponseToModel(ctx, waitResp, &model, resp)
err = mapResponseToModel(ctx, waitResp, &model, resp.Diagnostics)
// err = mapFields(ctx, waitResp, &model, storage, encryption, network, region)
if err != nil {
core.LogAndAddError(