fix: pgsql user waiter
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 5s
CI Workflow / CI (pull_request) Failing after 19m55s
CI Workflow / Code coverage report (pull_request) Has been skipped
CI Workflow / Test readiness for publishing provider (pull_request) Successful in 31m10s

This commit is contained in:
Marcel S. Henselin 2026-02-13 09:14:27 +01:00
parent f2c9af8fc5
commit 440e8bf900
5 changed files with 116 additions and 78 deletions

View file

@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
@ -80,7 +79,7 @@ func toUpdatePayload(model *resourceModel, roles *[]string) (
}
return &postgresflex.UpdateUserRequestPayload{
Name: conversion.StringValueToPointer(model.Name),
Name: model.Name.ValueStringPointer(),
Roles: toPayloadRoles(roles),
}, nil
}
@ -96,7 +95,7 @@ func toCreatePayload(model *resourceModel, roles *[]string) (*postgresflex.Creat
return &postgresflex.CreateUserRequestPayload{
Roles: toPayloadRoles(roles),
Name: conversion.StringValueToPointer(model.Name),
Name: model.Name.ValueStringPointer(),
}, nil
}

View file

@ -3,10 +3,8 @@ package postgresflexalpha
import (
"context"
_ "embed"
"errors"
"fmt"
"math"
"net/http"
"strconv"
"strings"
"time"
@ -22,7 +20,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
@ -243,12 +240,25 @@ func (r *userResource) Create(
return
}
if waitResp.Id == nil {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"create user",
"Instance creation waiting: returned id is nil",
)
return
}
if waitResp.Id == nil || *waitResp.Id != id {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"create user",
"Instance creation waiting: returned id is nil or wrong",
fmt.Sprintf(
"Instance creation waiting: returned id is wrong: %+v - %+v",
waitResp.Id,
id,
),
)
return
}
@ -311,7 +321,7 @@ func (r *userResource) Read(
return
}
if waitResp.Id == nil || *waitResp.Id != arg.userId {
if waitResp.Id == nil || *waitResp.Id != model.UserId.ValueInt64() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -424,21 +434,40 @@ func (r *userResource) Update(
}
// Verify update
exists, err := r.getUserResource(ctx, &stateModel, arg)
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
ctx,
r.client,
arg.projectId,
arg.instanceId,
arg.region,
model.UserId.ValueInt64(),
).SetSleepBeforeWait(
10 * time.Second,
).SetTimeout(
15 * time.Minute,
).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", fmt.Sprintf("Calling API: %v", err))
return
}
if !exists {
core.LogAndAddError(
ctx, &resp.Diagnostics, "Error updating user",
fmt.Sprintf("User ID '%v' resource not found after update", stateModel.UserId.ValueInt64()),
ctx,
&resp.Diagnostics,
"read user",
fmt.Sprintf("Instance creation waiting: %v", err),
)
return
}
if waitResp.Id == nil || *waitResp.Id != model.UserId.ValueInt64() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"read user",
"Instance creation waiting: returned id is nil or wrong",
)
return
}
arg.userId = *waitResp.Id
// Set state to fully populated data
diags = resp.State.Set(ctx, stateModel)
resp.Diagnostics.Append(diags...)
@ -497,19 +526,19 @@ func (r *userResource) Delete(
ctx = core.LogResponse(ctx)
// Verify deletion
exists, err := r.getUserResource(ctx, &model, arg)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting user", fmt.Sprintf("Calling API: %v", err))
return
}
if exists {
core.LogAndAddError(
ctx, &resp.Diagnostics, "Error deleting user",
fmt.Sprintf("User ID '%v' resource still exists after deletion", model.UserId.ValueInt64()),
)
return
}
// TODO: Verify deletion
//exists, err := r.getUserResource(ctx, &model, arg)
//if err != nil {
// core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting user", fmt.Sprintf("Calling API: %v", err))
// return
//}
//if exists {
// core.LogAndAddError(
// ctx, &resp.Diagnostics, "Error deleting user",
// fmt.Sprintf("User ID '%v' resource still exists after deletion", model.UserId.ValueInt64()),
// )
// return
//}
resp.State.RemoveResource(ctx)
@ -540,34 +569,6 @@ func (r *userResource) IdentitySchema(
}
}
// getUserResource refreshes the resource state by calling the API and mapping the response to the model.
// Returns true if the resource state was successfully refreshed, false if the resource does not exist.
func (r *userResource) getUserResource(ctx context.Context, model *resourceModel, arg *clientArg) (bool, error) {
if arg.userId > math.MaxInt32 {
return false, errors.New("error in type conversion: int value too large (userId)")
}
userId := int32(arg.userId)
// API Call
userResp, err := r.client.GetUserRequest(ctx, arg.projectId, arg.region, arg.instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound {
return false, nil
}
return false, fmt.Errorf("error fetching user resource: %w", err)
}
if err := mapResourceFields(userResp, model, arg.region); err != nil {
return false, fmt.Errorf("error mapping user resource: %w", err)
}
return true, nil
}
// clientArg holds the arguments for API calls.
type clientArg struct {
projectId string