chore: adjust pagination for postgres database and flavor listing (#20)
* feat: implement pagination for database listing * fix: change database_id attribute type from string to int64 * refactor: rename getDatabase to getDatabaseById for clarity * fix: improve error handling for database not found scenario * feat: add validation for database_id and name attributes; implement separate functions for fetching databases by ID and name * feat: implement database client interface and update database fetching functions * refactor: rename matcher to filter for clarity and update pagination logic * feat: implement flavors retrieval with pagination and filtering support * refactor: rename flavor import for consistency and clarity * feat: add support for InstanceStatePending in wait handler logic * refactor: simplify GetFlavorsRequest and GetFlavorsRequestExecute by removing pagination parameters * refactor: improve readability of test cases by formatting function signatures and restructuring test runs * refactor: remove pagination parameters from GetFlavorsRequest in test case * refactor: simplify function signatures and improve readability in datasource and resource files * refactor: add descriptions for user-related attributes in datasource schema * refactor: enhance user resource schema with additional attributes and improve logging * refactor: delete unused file * refactor: standardize formatting and improve function naming for user resource management * refactor: remove skip from TestMapFields and update roles initialization in resource tests * fix: golangci lint issues * fix: golangci lint issues again * fix: golangci lint issues again
This commit is contained in:
parent
0150fea302
commit
979220be66
26 changed files with 3630 additions and 2759 deletions
|
|
@ -89,6 +89,10 @@ func (r *userDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, r
|
|||
"user_id": "User ID.",
|
||||
"instance_id": "ID of the PostgresFlex instance.",
|
||||
"project_id": "STACKIT project ID to which the instance is associated.",
|
||||
"username": "The name of the user.",
|
||||
"roles": "The roles assigned to the user.",
|
||||
"host": "The host address for the user to connect to the instance.",
|
||||
"port": "The port number for the user to connect to the instance.",
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
"status": "The current status of the user.",
|
||||
"connection_string": "The connection string for the user to the instance.",
|
||||
|
|
@ -125,17 +129,21 @@ func (r *userDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, r
|
|||
},
|
||||
},
|
||||
"username": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["username"],
|
||||
Computed: true,
|
||||
},
|
||||
"roles": schema.SetAttribute{
|
||||
Description: descriptions["roles"],
|
||||
ElementType: types.StringType,
|
||||
Computed: true,
|
||||
},
|
||||
"host": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["host"],
|
||||
Computed: true,
|
||||
},
|
||||
"port": schema.Int64Attribute{
|
||||
Computed: true,
|
||||
Description: descriptions["port"],
|
||||
Computed: true,
|
||||
},
|
||||
"region": schema.StringAttribute{
|
||||
// the region cannot be found automatically, so it has to be passed
|
||||
|
|
@ -143,10 +151,12 @@ func (r *userDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, r
|
|||
Description: descriptions["region"],
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["status"],
|
||||
Computed: true,
|
||||
},
|
||||
"connection_string": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["connection_string"],
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ package postgresflexalpha
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
||||
"github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha/wait"
|
||||
postgresflexUtils "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
|
||||
|
||||
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
|
||||
|
|
@ -41,16 +42,15 @@ var (
|
|||
)
|
||||
|
||||
type Model struct {
|
||||
Id types.String `tfsdk:"id"` // needed by TF
|
||||
UserId types.Int64 `tfsdk:"user_id"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Username types.String `tfsdk:"username"`
|
||||
Roles types.Set `tfsdk:"roles"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
//Host types.String `tfsdk:"host"`
|
||||
//Port types.Int64 `tfsdk:"port"`
|
||||
//Uri types.String `tfsdk:"uri"`
|
||||
Id types.String `tfsdk:"id"` // needed by TF
|
||||
UserId types.Int64 `tfsdk:"user_id"`
|
||||
InstanceId types.String `tfsdk:"instance_id"`
|
||||
ProjectId types.String `tfsdk:"project_id"`
|
||||
Username types.String `tfsdk:"username"`
|
||||
Roles types.Set `tfsdk:"roles"`
|
||||
Password types.String `tfsdk:"password"`
|
||||
Host types.String `tfsdk:"host"`
|
||||
Port types.Int64 `tfsdk:"port"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Status types.String `tfsdk:"status"`
|
||||
ConnectionString types.String `tfsdk:"connection_string"`
|
||||
|
|
@ -124,8 +124,7 @@ func (r *userResource) Configure(ctx context.Context, req resource.ConfigureRequ
|
|||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *userResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
// rolesOptions := []string{"login", "createdb", "createrole"}
|
||||
rolesOptions := []string{"login", "createdb"}
|
||||
rolesOptions := []string{"login", "createdb", "createrole"}
|
||||
|
||||
descriptions := map[string]string{
|
||||
"main": "Postgres Flex user resource schema. Must have a `region` specified in the provider configuration.",
|
||||
|
|
@ -133,9 +132,13 @@ func (r *userResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
|||
"user_id": "User ID.",
|
||||
"instance_id": "ID of the PostgresFlex instance.",
|
||||
"project_id": "STACKIT project ID to which the instance is associated.",
|
||||
"username": "The name of the user.",
|
||||
"roles": "Database access levels for the user. " + utils.FormatPossibleValues(rolesOptions...),
|
||||
"region": "The resource region. If not defined, the provider region is used.",
|
||||
"status": "The current status of the user.",
|
||||
"password": "The password for the user. This is only set upon creation.",
|
||||
"host": "The host of the Postgres Flex instance.",
|
||||
"port": "The port of the Postgres Flex instance.",
|
||||
"connection_string": "The connection string for the user to the instance.",
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +185,7 @@ func (r *userResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
|||
},
|
||||
},
|
||||
"username": schema.StringAttribute{
|
||||
Description: descriptions["username"],
|
||||
Required: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
// stringplanmodifier.RequiresReplace(),
|
||||
|
|
@ -198,19 +202,18 @@ func (r *userResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
|||
},
|
||||
},
|
||||
"password": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
Description: descriptions["password"],
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"host": schema.StringAttribute{
|
||||
Description: descriptions["host"],
|
||||
Computed: true,
|
||||
},
|
||||
"port": schema.Int64Attribute{
|
||||
Description: descriptions["port"],
|
||||
Computed: true,
|
||||
},
|
||||
//"host": schema.StringAttribute{
|
||||
// Computed: true,
|
||||
//},
|
||||
//"port": schema.Int64Attribute{
|
||||
// Computed: true,
|
||||
//},
|
||||
//"uri": schema.StringAttribute{
|
||||
// Computed: true,
|
||||
// Sensitive: true,
|
||||
//},
|
||||
"region": schema.StringAttribute{
|
||||
Optional: true,
|
||||
// must be computed to allow for storing the override value from the provider
|
||||
|
|
@ -221,10 +224,12 @@ func (r *userResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
|
|||
},
|
||||
},
|
||||
"status": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["status"],
|
||||
Computed: true,
|
||||
},
|
||||
"connection_string": schema.StringAttribute{
|
||||
Computed: true,
|
||||
Description: descriptions["connection_string"],
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -244,21 +249,12 @@ func (r *userResource) Create(
|
|||
}
|
||||
|
||||
ctx = core.InitProviderContext(ctx)
|
||||
ctx = r.setTFLogFields(ctx, &model)
|
||||
arg := r.getClientArg(&model)
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
region := model.Region.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
|
||||
var roles []string
|
||||
if !model.Roles.IsNull() && !model.Roles.IsUnknown() {
|
||||
diags = model.Roles.ElementsAs(ctx, &roles, false)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var roles = r.expandRoles(ctx, model.Roles, &resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Generate API request body from model
|
||||
|
|
@ -270,10 +266,11 @@ func (r *userResource) Create(
|
|||
// Create new user
|
||||
userResp, err := r.client.CreateUserRequest(
|
||||
ctx,
|
||||
projectId,
|
||||
region,
|
||||
instanceId,
|
||||
arg.projectId,
|
||||
arg.region,
|
||||
arg.instanceId,
|
||||
).CreateUserRequestPayload(*payload).Execute()
|
||||
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
|
|
@ -290,16 +287,22 @@ func (r *userResource) Create(
|
|||
)
|
||||
return
|
||||
}
|
||||
userId := *userResp.Id
|
||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||
// Map response body to schema
|
||||
err = mapFieldsCreate(userResp, toPayloadRoles(&roles), &model, region)
|
||||
model.UserId = types.Int64PointerValue(userResp.Id)
|
||||
model.Password = types.StringPointerValue(userResp.Password)
|
||||
|
||||
ctx = tflog.SetField(ctx, "user_id", *userResp.Id)
|
||||
|
||||
exists, err := r.getUserResource(ctx, &model)
|
||||
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
if !exists {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
&resp.Diagnostics,
|
||||
"Error creating user",
|
||||
fmt.Sprintf("Processing API payload: %v", err),
|
||||
ctx, &resp.Diagnostics, "Error creating user",
|
||||
fmt.Sprintf("User ID '%v' resource not found after creation", model.UserId.ValueInt64()),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
|
@ -327,40 +330,20 @@ func (r *userResource) Read(
|
|||
|
||||
ctx = core.InitProviderContext(ctx)
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
userId := model.UserId.ValueInt64()
|
||||
region := r.providerData.GetRegionWithOverride(model.Region)
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
exists, err := r.getUserResource(ctx, &model)
|
||||
|
||||
recordSetResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||
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 {
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading user", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(recordSetResp, &model, region)
|
||||
if err != nil {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
&resp.Diagnostics,
|
||||
"Error reading user",
|
||||
fmt.Sprintf("Processing API payload: %v", err),
|
||||
)
|
||||
if !exists {
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
// Set refreshed state
|
||||
diags = resp.State.Set(ctx, model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -384,15 +367,8 @@ func (r *userResource) Update(
|
|||
}
|
||||
|
||||
ctx = core.InitProviderContext(ctx)
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
userId := model.UserId.ValueInt64()
|
||||
region := model.Region.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
ctx = r.setTFLogFields(ctx, &model)
|
||||
arg := r.getClientArg(&model)
|
||||
|
||||
// Retrieve values from state
|
||||
var stateModel Model
|
||||
|
|
@ -402,13 +378,9 @@ func (r *userResource) Update(
|
|||
return
|
||||
}
|
||||
|
||||
var roles []string
|
||||
if !model.Roles.IsNull() && !model.Roles.IsUnknown() {
|
||||
diags = model.Roles.ElementsAs(ctx, &roles, false)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
var roles = r.expandRoles(ctx, model.Roles, &resp.Diagnostics)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// Generate API request body from model
|
||||
|
|
@ -421,10 +393,10 @@ func (r *userResource) Update(
|
|||
// Update existing instance
|
||||
err = r.client.UpdateUserRequest(
|
||||
ctx,
|
||||
projectId,
|
||||
region,
|
||||
instanceId,
|
||||
userId,
|
||||
arg.projectId,
|
||||
arg.region,
|
||||
arg.instanceId,
|
||||
arg.userId,
|
||||
).UpdateUserRequestPayload(*payload).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", err.Error())
|
||||
|
|
@ -433,20 +405,17 @@ func (r *userResource) Update(
|
|||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
userResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||
exists, err := r.getUserResource(ctx, &stateModel)
|
||||
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
// Map response body to schema
|
||||
err = mapFields(userResp, &stateModel, region)
|
||||
if err != nil {
|
||||
if !exists {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
&resp.Diagnostics,
|
||||
"Error updating user",
|
||||
fmt.Sprintf("Processing API payload: %v", err),
|
||||
ctx, &resp.Diagnostics, "Error updating user",
|
||||
fmt.Sprintf("User ID '%v' resource not found after update", stateModel.UserId.ValueInt64()),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
|
@ -474,34 +443,32 @@ func (r *userResource) Delete(
|
|||
}
|
||||
|
||||
ctx = core.InitProviderContext(ctx)
|
||||
|
||||
projectId := model.ProjectId.ValueString()
|
||||
instanceId := model.InstanceId.ValueString()
|
||||
userId := model.UserId.ValueInt64()
|
||||
region := model.Region.ValueString()
|
||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||
ctx = tflog.SetField(ctx, "region", region)
|
||||
ctx = r.setTFLogFields(ctx, &model)
|
||||
arg := r.getClientArg(&model)
|
||||
|
||||
// Delete existing record set
|
||||
err := r.client.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||
err := r.client.DeleteUserRequest(ctx, arg.projectId, arg.region, arg.instanceId, arg.userId).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting user", fmt.Sprintf("Calling API: %v", err))
|
||||
}
|
||||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
_, err = wait.DeleteUserWaitHandler(ctx, r.client, projectId, region, instanceId, userId).WaitWithContext(ctx)
|
||||
exists, err := r.getUserResource(ctx, &model)
|
||||
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("Instance deletion waiting: %v", err),
|
||||
ctx, &resp.Diagnostics, "Error deleting user",
|
||||
fmt.Sprintf("User ID '%v' resource still exists after deletion", model.UserId.ValueInt64()),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
resp.State.RemoveResource(ctx)
|
||||
|
||||
tflog.Info(ctx, "Postgres Flex user deleted")
|
||||
}
|
||||
|
||||
|
|
@ -538,57 +505,6 @@ func (r *userResource) ImportState(
|
|||
tflog.Info(ctx, "postgresflexalpha user state imported")
|
||||
}
|
||||
|
||||
func mapFieldsCreate(
|
||||
userResp *postgresflex.CreateUserResponse,
|
||||
rolesArg *[]postgresflex.UserRole,
|
||||
model *Model,
|
||||
region string,
|
||||
) error {
|
||||
if userResp == nil {
|
||||
return fmt.Errorf("response is nil")
|
||||
}
|
||||
if model == nil {
|
||||
return fmt.Errorf("model input is nil")
|
||||
}
|
||||
user := userResp
|
||||
|
||||
if user.Id == nil {
|
||||
return fmt.Errorf("user id not present")
|
||||
}
|
||||
userId := *user.Id
|
||||
model.Id = utils.BuildInternalTerraformId(
|
||||
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
|
||||
)
|
||||
model.UserId = types.Int64Value(userId)
|
||||
model.Username = types.StringPointerValue(user.Name)
|
||||
|
||||
if user.Password == nil {
|
||||
return fmt.Errorf("user password not present")
|
||||
}
|
||||
|
||||
if rolesArg == nil {
|
||||
model.Roles = types.SetNull(types.StringType)
|
||||
} else {
|
||||
var roles []attr.Value
|
||||
for _, role := range *rolesArg {
|
||||
roles = append(roles, types.StringValue(string(role)))
|
||||
}
|
||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||
}
|
||||
model.Roles = rolesSet
|
||||
}
|
||||
|
||||
model.Password = types.StringPointerValue(user.Password)
|
||||
model.Region = types.StringValue(region)
|
||||
model.Status = types.StringPointerValue(user.Status)
|
||||
//model.Host = types.StringPointerValue()
|
||||
model.ConnectionString = types.StringPointerValue(user.ConnectionString)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapFields(userResp *postgresflex.GetUserResponse, model *Model, region string) error {
|
||||
if userResp == nil {
|
||||
return fmt.Errorf("response is nil")
|
||||
|
|
@ -625,14 +541,77 @@ func mapFields(userResp *postgresflex.GetUserResponse, model *Model, region stri
|
|||
}
|
||||
model.Roles = rolesSet
|
||||
}
|
||||
//model.Host = types.StringPointerValue(user.Host)
|
||||
//model.Port = types.Int64PointerValue(user.Port)
|
||||
model.Host = types.StringPointerValue(user.Host)
|
||||
model.Port = types.Int64PointerValue(user.Port)
|
||||
model.Region = types.StringValue(region)
|
||||
model.Status = types.StringPointerValue(user.Status)
|
||||
model.ConnectionString = types.StringPointerValue(user.ConnectionString)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 *Model) (bool, error) {
|
||||
ctx = r.setTFLogFields(ctx, model)
|
||||
arg := r.getClientArg(model)
|
||||
|
||||
// API Call
|
||||
userResp, err := r.client.GetUserRequest(ctx, arg.projectId, arg.region, arg.instanceId, arg.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 := mapFields(userResp, model, arg.region); err != nil {
|
||||
return false, fmt.Errorf("error mapping user resource: %w", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type clientArg struct {
|
||||
projectId string
|
||||
instanceId string
|
||||
region string
|
||||
userId int64
|
||||
}
|
||||
|
||||
// getClientArg constructs client arguments from the model.
|
||||
func (r *userResource) getClientArg(model *Model) *clientArg {
|
||||
return &clientArg{
|
||||
projectId: model.ProjectId.ValueString(),
|
||||
instanceId: model.InstanceId.ValueString(),
|
||||
region: r.providerData.GetRegionWithOverride(model.Region),
|
||||
userId: model.UserId.ValueInt64(),
|
||||
}
|
||||
}
|
||||
|
||||
// setTFLogFields adds relevant fields to the context for terraform logging purposes.
|
||||
func (r *userResource) setTFLogFields(ctx context.Context, model *Model) context.Context {
|
||||
usrCtx := r.getClientArg(model)
|
||||
|
||||
ctx = tflog.SetField(ctx, "project_id", usrCtx.projectId)
|
||||
ctx = tflog.SetField(ctx, "instance_id", usrCtx.instanceId)
|
||||
ctx = tflog.SetField(ctx, "user_id", usrCtx.userId)
|
||||
ctx = tflog.SetField(ctx, "region", usrCtx.region)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (r *userResource) expandRoles(ctx context.Context, rolesSet types.Set, diags *diag.Diagnostics) []string {
|
||||
if rolesSet.IsNull() || rolesSet.IsUnknown() {
|
||||
return nil
|
||||
}
|
||||
var roles []string
|
||||
diags.Append(rolesSet.ElementsAs(ctx, &roles, false)...)
|
||||
return roles
|
||||
}
|
||||
|
||||
func toCreatePayload(model *Model, roles *[]string) (*postgresflex.CreateUserRequestPayload, error) {
|
||||
if model == nil {
|
||||
return nil, fmt.Errorf("nil model")
|
||||
|
|
|
|||
|
|
@ -14,22 +14,16 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
const testRegion = "region"
|
||||
tests := []struct {
|
||||
description string
|
||||
input *postgresflexalpha.CreateUserResponse
|
||||
updateRoles *postgresflexalpha.UpdateUserRequestPayload
|
||||
input *postgresflexalpha.GetUserResponse
|
||||
region string
|
||||
expected Model
|
||||
isValid bool
|
||||
}{
|
||||
{
|
||||
"default_values",
|
||||
&postgresflexalpha.CreateUserResponse{
|
||||
Id: utils.Ptr(int64(1)),
|
||||
Password: utils.Ptr(""),
|
||||
&postgresflexalpha.GetUserResponse{
|
||||
Id: utils.Ptr(int64(1)),
|
||||
},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{
|
||||
Roles: &[]postgresflexalpha.UserRole{},
|
||||
},
|
||||
|
||||
testRegion,
|
||||
Model{
|
||||
Id: types.StringValue("pid,region,iid,1"),
|
||||
|
|
@ -37,11 +31,10 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
InstanceId: types.StringValue("iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Username: types.StringNull(),
|
||||
Roles: types.SetValueMust(types.StringType, []attr.Value{}),
|
||||
Password: types.StringValue(""),
|
||||
Roles: types.SetNull(types.StringType),
|
||||
Password: types.StringNull(),
|
||||
Host: types.StringNull(),
|
||||
Port: types.Int64Null(),
|
||||
Uri: types.StringNull(),
|
||||
Region: types.StringValue(testRegion),
|
||||
Status: types.StringNull(),
|
||||
ConnectionString: types.StringNull(),
|
||||
|
|
@ -50,16 +43,12 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"simple_values",
|
||||
&postgresflexalpha.CreateUserResponse{
|
||||
&postgresflexalpha.GetUserResponse{
|
||||
Id: utils.Ptr(int64(1)),
|
||||
Name: utils.Ptr("username"),
|
||||
Password: utils.Ptr("password"),
|
||||
ConnectionString: utils.Ptr("connection_string"),
|
||||
Status: utils.Ptr("status"),
|
||||
},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{
|
||||
Roles: &[]postgresflexalpha.UserRole{},
|
||||
},
|
||||
testRegion,
|
||||
Model{
|
||||
Id: types.StringValue("pid,region,iid,1"),
|
||||
|
|
@ -67,11 +56,10 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
InstanceId: types.StringValue("iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Username: types.StringValue("username"),
|
||||
Roles: types.SetValueMust(types.StringType, []attr.Value{}),
|
||||
Password: types.StringValue("password"),
|
||||
Roles: types.SetNull(types.StringType),
|
||||
Password: types.StringNull(),
|
||||
Host: types.StringNull(),
|
||||
Port: types.Int64Null(),
|
||||
Uri: types.StringNull(),
|
||||
Region: types.StringValue(testRegion),
|
||||
Status: types.StringValue("status"),
|
||||
ConnectionString: types.StringValue("connection_string"),
|
||||
|
|
@ -80,16 +68,12 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"null_fields_and_int_conversions",
|
||||
&postgresflexalpha.CreateUserResponse{
|
||||
&postgresflexalpha.GetUserResponse{
|
||||
Id: utils.Ptr(int64(1)),
|
||||
Name: nil,
|
||||
Password: utils.Ptr(""),
|
||||
ConnectionString: nil,
|
||||
Status: nil,
|
||||
},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{
|
||||
Roles: &[]postgresflexalpha.UserRole{},
|
||||
},
|
||||
testRegion,
|
||||
Model{
|
||||
Id: types.StringValue("pid,region,iid,1"),
|
||||
|
|
@ -97,11 +81,10 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
InstanceId: types.StringValue("iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Username: types.StringNull(),
|
||||
Roles: types.SetValueMust(types.StringType, []attr.Value{}),
|
||||
Password: types.StringValue(""),
|
||||
Roles: types.SetNull(types.StringType),
|
||||
Password: types.StringNull(),
|
||||
Host: types.StringNull(),
|
||||
Port: types.Int64Null(),
|
||||
Uri: types.StringNull(),
|
||||
Region: types.StringValue(testRegion),
|
||||
Status: types.StringNull(),
|
||||
ConnectionString: types.StringNull(),
|
||||
|
|
@ -111,35 +94,20 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
{
|
||||
"nil_response",
|
||||
nil,
|
||||
nil,
|
||||
testRegion,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil_response_2",
|
||||
&postgresflexalpha.CreateUserResponse{},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{},
|
||||
&postgresflexalpha.GetUserResponse{},
|
||||
testRegion,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no_resource_id",
|
||||
&postgresflexalpha.CreateUserResponse{},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{},
|
||||
testRegion,
|
||||
Model{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"no_password",
|
||||
&postgresflexalpha.CreateUserResponse{
|
||||
Id: utils.Ptr(int64(1)),
|
||||
},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{
|
||||
Roles: &[]postgresflexalpha.UserRole{},
|
||||
},
|
||||
&postgresflexalpha.GetUserResponse{},
|
||||
testRegion,
|
||||
Model{},
|
||||
false,
|
||||
|
|
@ -152,11 +120,8 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
ProjectId: tt.expected.ProjectId,
|
||||
InstanceId: tt.expected.InstanceId,
|
||||
}
|
||||
var roles *[]postgresflexalpha.UserRole
|
||||
if tt.updateRoles != nil {
|
||||
roles = tt.updateRoles.Roles
|
||||
}
|
||||
err := mapFieldsCreate(tt.input, roles, state, tt.region)
|
||||
|
||||
err := mapFields(tt.input, state, tt.region)
|
||||
if !tt.isValid && err == nil {
|
||||
t.Fatalf("Should have failed")
|
||||
}
|
||||
|
|
@ -175,7 +140,6 @@ func TestMapFieldsCreate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapFields(t *testing.T) {
|
||||
t.Skip("Skipping - needs refactoring")
|
||||
const testRegion = "region"
|
||||
tests := []struct {
|
||||
description string
|
||||
|
|
@ -252,7 +216,7 @@ func TestMapFields(t *testing.T) {
|
|||
InstanceId: types.StringValue("iid"),
|
||||
ProjectId: types.StringValue("pid"),
|
||||
Username: types.StringNull(),
|
||||
Roles: types.SetValueMust(types.StringType, []attr.Value{}),
|
||||
Roles: types.SetNull(types.StringType),
|
||||
Host: types.StringNull(),
|
||||
Port: types.Int64Value(2123456789),
|
||||
Region: types.StringValue(testRegion),
|
||||
|
|
@ -424,6 +388,7 @@ func TestToUpdatePayload(t *testing.T) {
|
|||
"role_2",
|
||||
},
|
||||
&postgresflexalpha.UpdateUserRequestPayload{
|
||||
Name: utils.Ptr("username"),
|
||||
Roles: &[]postgresflexalpha.UserRole{
|
||||
"role_1",
|
||||
"role_2",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue