fix: postgres_fixes #54
5 changed files with 116 additions and 78 deletions
|
|
@ -51,8 +51,8 @@ func mapFields(
|
|||
return nil
|
||||
}
|
||||
|
||||
// mapResourceFields maps fields from a ListDatabase API response to a resourceModel for the resource.
|
||||
func mapResourceFields(source *postgresflexalpha.ListDatabase, model *resourceModel) error {
|
||||
// mapResourceFields maps fields from a GetDatabase API response to a resourceModel for the resource.
|
||||
func mapResourceFields(source *postgresflexalpha.GetDatabaseResponse, model *resourceModel) error {
|
||||
if source == nil {
|
||||
return fmt.Errorf("response is nil")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,22 +6,22 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
|
||||
"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/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"
|
||||
postgresflexalpha2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/resources_gen"
|
||||
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
|
||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
|
||||
postgresflexalpha3 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -236,8 +236,10 @@ func (r *databaseResource) Create(
|
|||
return
|
||||
}
|
||||
|
||||
// TODO: wait handler bauen
|
||||
database, err := getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId)
|
||||
database, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, region, instanceId, databaseId).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
|
|
@ -305,14 +307,17 @@ func (r *databaseResource) Read(
|
|||
ctx = tflog.SetField(ctx, "region", region)
|
||||
ctx = tflog.SetField(ctx, "database_id", databaseId)
|
||||
|
||||
databaseResp, err := getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId)
|
||||
databaseResp, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, region, instanceId, databaseId).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
|
||||
if (ok && oapiErr.StatusCode == http.StatusNotFound) || errors.Is(err, errDatabaseNotFound) {
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Calling API: %v", err))
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
&resp.Diagnostics,
|
||||
"Error creating database",
|
||||
fmt.Sprintf("Getting database details after creation: %v", err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -434,15 +439,12 @@ func (r *databaseResource) Update(
|
|||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
// Map response body to schema
|
||||
databaseResp, err := getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId64)
|
||||
databaseResp, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, region, instanceId, databaseId64).
|
||||
SetTimeout(15 * time.Minute).
|
||||
SetSleepBeforeWait(15 * time.Second).
|
||||
WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
|
||||
if (ok && oapiErr.StatusCode == http.StatusNotFound) || errors.Is(err, errDatabaseNotFound) {
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Calling API: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "error updating database", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ type APIClientUserInterface interface {
|
|||
*postgresflex.GetUserResponse,
|
||||
error,
|
||||
)
|
||||
|
||||
GetDatabaseRequestExecute(
|
||||
ctx context.Context,
|
||||
projectId string,
|
||||
region string,
|
||||
instanceId string,
|
||||
databaseId int32,
|
||||
) (*postgresflex.GetDatabaseResponse, error)
|
||||
}
|
||||
|
||||
// CreateInstanceWaitHandler will wait for instance creation
|
||||
|
|
@ -236,3 +244,31 @@ func GetUserByIdWaitHandler(
|
|||
)
|
||||
return handler
|
||||
}
|
||||
|
||||
// GetDatabaseByIdWaitHandler will wait for instance creation
|
||||
func GetDatabaseByIdWaitHandler(
|
||||
ctx context.Context,
|
||||
a APIClientUserInterface,
|
||||
projectId, instanceId, region string,
|
||||
databaseId int64,
|
||||
) *wait.AsyncActionHandler[postgresflex.GetDatabaseResponse] {
|
||||
handler := wait.New(
|
||||
func() (waitFinished bool, response *postgresflex.GetDatabaseResponse, err error) {
|
||||
dbId32 := int32(databaseId)
|
||||
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, dbId32)
|
||||
if err != nil {
|
||||
var oapiErr *oapierror.GenericOpenAPIError
|
||||
ok := errors.As(err, &oapiErr)
|
||||
if !ok {
|
||||
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
|
||||
}
|
||||
if oapiErr.StatusCode != http.StatusNotFound {
|
||||
return false, nil, err
|
||||
}
|
||||
return false, nil, nil
|
||||
}
|
||||
return true, s, nil
|
||||
},
|
||||
)
|
||||
return handler
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue