chore: work save

This commit is contained in:
Marcel_Henselin 2026-01-27 16:43:53 +01:00
parent a60b1db1f4
commit 3e3f13d36d
7 changed files with 214 additions and 46 deletions

View file

@ -38,6 +38,26 @@ func setGetInstanceResponseGetBackupScheduleAttributeType(arg *GetInstanceRespon
type GetInstanceResponseGetBackupScheduleArgType = string
type GetInstanceResponseGetBackupScheduleRetType = string
/*
types and functions for encryption
*/
// isModel
type GetInstanceResponseGetEncryptionAttributeType = *InstanceEncryption
type GetInstanceResponseGetEncryptionArgType = InstanceEncryption
type GetInstanceResponseGetEncryptionRetType = InstanceEncryption
func getGetInstanceResponseGetEncryptionAttributeTypeOk(arg GetInstanceResponseGetEncryptionAttributeType) (ret GetInstanceResponseGetEncryptionRetType, ok bool) {
if arg == nil {
return ret, false
}
return *arg, true
}
func setGetInstanceResponseGetEncryptionAttributeType(arg *GetInstanceResponseGetEncryptionAttributeType, val GetInstanceResponseGetEncryptionRetType) {
*arg = &val
}
/*
types and functions for flavorId
*/
@ -247,6 +267,7 @@ type GetInstanceResponse struct {
// The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.
// REQUIRED
BackupSchedule GetInstanceResponseGetBackupScheduleAttributeType `json:"backupSchedule" required:"true"`
Encryption GetInstanceResponseGetEncryptionAttributeType `json:"encryption,omitempty"`
// The id of the instance flavor.
// REQUIRED
FlavorId GetInstanceResponseGetFlavorIdAttributeType `json:"flavorId" required:"true"`
@ -323,6 +344,29 @@ func (o *GetInstanceResponse) SetBackupSchedule(v GetInstanceResponseGetBackupSc
setGetInstanceResponseGetBackupScheduleAttributeType(&o.BackupSchedule, v)
}
// GetEncryption returns the Encryption field value if set, zero value otherwise.
func (o *GetInstanceResponse) GetEncryption() (res GetInstanceResponseGetEncryptionRetType) {
res, _ = o.GetEncryptionOk()
return
}
// GetEncryptionOk returns a tuple with the Encryption field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *GetInstanceResponse) GetEncryptionOk() (ret GetInstanceResponseGetEncryptionRetType, ok bool) {
return getGetInstanceResponseGetEncryptionAttributeTypeOk(o.Encryption)
}
// HasEncryption returns a boolean if a field has been set.
func (o *GetInstanceResponse) HasEncryption() bool {
_, ok := o.GetEncryptionOk()
return ok
}
// SetEncryption gets a reference to the given InstanceEncryption and assigns it to the Encryption field.
func (o *GetInstanceResponse) SetEncryption(v GetInstanceResponseGetEncryptionRetType) {
setGetInstanceResponseGetEncryptionAttributeType(&o.Encryption, v)
}
// GetFlavorId returns the FlavorId field value
func (o *GetInstanceResponse) GetFlavorId() (ret GetInstanceResponseGetFlavorIdRetType) {
ret, _ = o.GetFlavorIdOk()

View file

@ -62,6 +62,7 @@ resource "stackitprivatepreview_sqlserverflexalpha_instance" "sqlsrv-nosna" {
#keyring_id = stackit_kms_keyring.keyring.keyring_id
#key_version = 1
#key_id = var.key_id
# key with scope public
key_id = "fe039bcf-8d7b-431a-801d-9e81371a6b7b"
keyring_id = var.keyring_id
key_version = var.key_version

View file

@ -14,7 +14,9 @@ usage() {
CONFIG_FOLDER=$(dirname "$0")
BINARY=terraform
while getopts ":b:hdit" arg; do
ADD=""
while getopts ":b:hdirt" arg; do
case $arg in
b) # Set binary (default is terraform).
BINARY=${OPTARG}
@ -30,6 +32,10 @@ while getopts ":b:hdit" arg; do
export TF_LOG
shift
;;
r) # Set log level to INFO.
ADD="-refresh-only"
shift
;;
t) # Set log level to TRACE.
TF_LOG=TRACE
export TF_LOG
@ -44,4 +50,4 @@ done
TERRAFORM_CONFIG=${CONFIG_FOLDER}/config.tfrc
export TERRAFORM_CONFIG
${BINARY} "$@"
${BINARY} "$@" ${ADD}

View file

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
postgresflexalphadatasource "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/datasources_gen"
postgresflexalpharesource "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
@ -14,40 +15,61 @@ import (
)
func mapGetInstanceResponseToModel(ctx context.Context, m *postgresflexalpharesource.InstanceModel, resp *postgresflex.GetInstanceResponse) error {
tflog.Info(ctx, ">>>> MSH DEBUG <<<<", map[string]interface{}{
"id": m.Id.ValueString(),
"instance_id": m.InstanceId.ValueString(),
"backup_schedule": m.BackupSchedule.ValueString(),
"flavor_id": m.FlavorId.ValueString(),
"encryption.kek_key_id": m.Encryption.KekKeyId.ValueString(),
"encryption.kek_key_ring_id": m.Encryption.KekKeyRingId.ValueString(),
"encryption.kek_key_version": m.Encryption.KekKeyVersion.ValueString(),
"encryption.service_account": m.Encryption.ServiceAccount.ValueString(),
"is_deletable": m.IsDeletable.ValueBool(),
"name": m.Name.ValueString(),
"status": m.Status.ValueString(),
"retention_days": m.RetentionDays.ValueInt64(),
"replicas": m.Replicas.ValueInt64(),
"network.instance_address": m.Network.InstanceAddress.ValueString(),
"network.router_address": m.Network.RouterAddress.ValueString(),
"version": m.Version.ValueString(),
"network.acl": m.Network.Acl.String(),
})
m.BackupSchedule = types.StringValue(resp.GetBackupSchedule())
// need to leave out encryption, as the GetInstance endpoint does not provide it
// m.Encryption = postgresflexalpharesource.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 resp.HasEncryption() {
m.Encryption = postgresflexalpharesource.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())
if m.Id.IsNull() || m.Id.IsUnknown() {
m.Id = utils.BuildInternalTerraformId(m.ProjectId.ValueString(), m.Region.ValueString(), m.InstanceId.ValueString())
}
m.InstanceId = types.StringPointerValue(resp.Id)
m.IsDeletable = types.BoolUnknown()
if isDel, ok := resp.GetIsDeletableOk(); ok {
m.IsDeletable = types.BoolValue(isDel)
}
m.Name = types.StringValue(resp.GetName())
//m.IsDeletable = types.BoolUnknown()
//if isDel, ok := resp.GetIsDeletableOk(); ok {
// m.IsDeletable = types.BoolValue(isDel)
m.IsDeletable = types.BoolValue(resp.GetIsDeletable())
//}
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
if diags.HasError() {
return fmt.Errorf("failed converting network acl from response")
}
netInstAdd := types.StringUnknown()
netInstAdd := types.StringValue("")
if instAdd, ok := resp.Network.GetInstanceAddressOk(); ok {
netInstAdd = types.StringValue(instAdd)
}
netRtrAdd := types.StringUnknown()
netRtrAdd := types.StringValue("")
if rtrAdd, ok := resp.Network.GetRouterAddressOk(); ok {
netRtrAdd = types.StringValue(rtrAdd)
}
@ -71,10 +93,11 @@ func mapGetInstanceResponseToModel(ctx context.Context, m *postgresflexalphareso
m.Name = types.StringValue(resp.GetName())
m.Status = types.StringUnknown()
if status, ok := resp.GetStatusOk(); ok {
m.Status = types.StringValue(string(status))
}
//m.Status = types.StringUnknown()
//if status, ok := resp.GetStatusOk(); ok {
// m.Status = types.StringValue(string(status))
//}
m.Status = types.StringValue(string(resp.GetStatus()))
storage, diags := postgresflexalpharesource.NewStorageValue(
postgresflexalpharesource.StorageValue{}.AttributeTypes(ctx),

View file

@ -2,14 +2,111 @@ fields:
- name: 'backup_schedule'
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'encryption.kek_key_id'
validators:
- validate.NoSeparator
modifiers:
- 'RequiresReplace'
- name: 'encryption.kek_key_ring_id'
validators:
- validate.NoSeparator
modifiers:
- 'RequiresReplace'
- name: 'encryption.kek_key_version'
validators:
- validate.NoSeparator
modifiers:
- 'RequiresReplace'
- name: 'encryption.service_account'
validators:
- validate.NoSeparator
modifiers:
- 'RequiresReplace'
- name: 'flavor_id'
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'id'
modifiers:
- 'UseStateForUnknown'
- name: 'instance_id'
validators:
- validate.NoSeparator
- validate.UUID
modifiers:
- 'UseStateForUnknown'
- name: 'is_deletable'
modifiers:
- 'UseStateForUnknown'
- name: 'name'
modifiers:
- 'UseStateForUnknown'
- name: 'network.access_scope'
validators:
- validate.NoSeparator
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'network.acl'
modifiers:
- 'UseStateForUnknown'
- name: 'network.access_scope'
- name: 'network.instance_address'
modifiers:
- 'UseStateForUnknown'
- name: 'network.router_address'
modifiers:
- 'UseStateForUnknown'
- name: 'project_id'
validators:
- validate.NoSeparator
- validate.UUID
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'region'
modifiers:
- 'RequiresReplace'
- name: 'replicas'
modifiers:
- 'UseStateForUnknown'
- name: 'retention_days'
modifiers:
- 'UseStateForUnknown'
- name: 'status'
modifiers:
- 'UseStateForUnknown'
- name: 'storage'
modifiers:
- 'UseStateForUnknown'
- name: 'storage.performance_class'
modifiers:
- 'UseStateForUnknown'
- 'RequiresReplace'
- name: 'storage.size'
modifiers:
- 'UseStateForUnknown'
- name: 'version'
modifiers:
- 'UseStateForUnknown'

View file

@ -23,6 +23,8 @@ import (
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
)
const packageName = "postgresflexalpha"
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &instanceResource{}
@ -212,13 +214,6 @@ func (r *instanceResource) Create(
return
}
model.InstanceId = types.StringValue(instanceId)
model.Id = utils.BuildInternalTerraformId(projectId, region, instanceId)
resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
if resp.Diagnostics.HasError() {
return
}
// Set data returned by API in identity
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
@ -301,6 +296,7 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
ctx = core.InitProviderContext(ctx)
// projectId := model.ProjectId.ValueString()
// region := r.providerData.GetRegionWithOverride(model.Region)
// instanceId := model.InstanceId.ValueString()
@ -334,14 +330,9 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, functionErrorSummary, "instance_id not found in config")
return
}
region = identityData.Region.ValueString()
instanceId = identityData.InstanceID.ValueString()
}
tflog.Info(ctx, "Reading instance model", map[string]interface{}{
"projectId": projectId,
"region": region,
"instanceId": instanceId,
})
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "region", region)
@ -453,7 +444,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
}
replInt32 := int32(model.Replicas.ValueInt64()) // nolint:gosec // check is performed above
payload := postgresflex.UpdateInstancePartiallyRequestPayload{
payload := postgresflex.UpdateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueStringPointer(),
FlavorId: model.FlavorId.ValueStringPointer(),
Name: model.Name.ValueStringPointer(),
@ -463,7 +454,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
),
Acl: &netAcl,
},
Replicas: postgresflex.UpdateInstancePartiallyRequestPayloadGetReplicasAttributeType(&replInt32),
Replicas: postgresflex.UpdateInstanceRequestPayloadGetReplicasAttributeType(&replInt32),
RetentionDays: model.RetentionDays.ValueInt64Pointer(),
Storage: &postgresflex.StorageUpdate{
Size: model.Storage.Size.ValueInt64Pointer(),
@ -472,12 +463,12 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
}
// Update existing instance
err := r.client.UpdateInstancePartiallyRequest(
err := r.client.UpdateInstanceRequest(
ctx,
projectId,
region,
instanceId,
).UpdateInstancePartiallyRequestPayload(payload).Execute()
).UpdateInstanceRequestPayload(payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", err.Error())
return
@ -549,8 +540,6 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
// ImportState imports a resource into the Terraform state on success.
// The expected format of the resource import identifier is: project_id,region,instance_id
func (r *instanceResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
tflog.Debug(ctx, "ImportState called with id:", map[string]interface{}{"id": req.ID})
ctx = core.InitProviderContext(ctx)
if req.ID != "" {

View file

@ -24,7 +24,7 @@ const (
InstanceStateFailed = "Failed"
)
// Interface needed for tests
// APIClientInstanceInterface Interface needed for tests
type APIClientInstanceInterface interface {
GetInstanceRequestExecute(ctx context.Context, projectId, region, instanceId string) (*sqlserverflex.GetInstanceResponse, error)
}
@ -53,6 +53,10 @@ func CreateInstanceWaitHandler(ctx context.Context, a APIClientInstanceInterface
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
return true, s, fmt.Errorf("create failed for instance with id %s", instanceId)
default:
tflog.Info(ctx, "Wait (create) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
})
return false, s, nil
}
})
@ -77,10 +81,14 @@ func UpdateInstanceWaitHandler(ctx context.Context, a APIClientInstanceInterface
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
return true, s, fmt.Errorf("update failed for instance with id %s", instanceId)
default:
tflog.Info(ctx, "Wait (update) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
})
return false, s, nil
}
})
handler.SetSleepBeforeWait(2 * time.Second)
handler.SetSleepBeforeWait(15 * time.Second)
handler.SetTimeout(45 * time.Minute)
return handler
}