feat: plan modifiers handling
This commit is contained in:
parent
c9c6dd1852
commit
7c4ca25791
13 changed files with 428 additions and 555 deletions
|
|
@ -0,0 +1,11 @@
|
|||
fields:
|
||||
- name: 'backup_schedule'
|
||||
modifiers:
|
||||
- 'UseStateForUnknown'
|
||||
- 'RequiresReplace'
|
||||
- name: 'encryption.kek_key_id'
|
||||
modifiers:
|
||||
- 'RequiresReplace'
|
||||
- name: 'network.acl'
|
||||
modifiers:
|
||||
- 'RequiresReplace'
|
||||
|
|
@ -2,6 +2,7 @@ package postgresflexalpha
|
|||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
|
|
@ -9,6 +10,7 @@ import (
|
|||
|
||||
"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"
|
||||
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
|
||||
|
|
@ -28,7 +30,7 @@ var (
|
|||
_ resource.ResourceWithImportState = &instanceResource{}
|
||||
_ resource.ResourceWithModifyPlan = &instanceResource{}
|
||||
_ resource.ResourceWithValidateConfig = &instanceResource{}
|
||||
// _ resource.ResourceWithIdentity = &instanceResource{}
|
||||
_ resource.ResourceWithIdentity = &instanceResource{}
|
||||
)
|
||||
|
||||
// NewInstanceResource is a helper function to simplify the provider implementation.
|
||||
|
|
@ -42,6 +44,12 @@ type instanceResource struct {
|
|||
providerData core.ProviderData
|
||||
}
|
||||
|
||||
type InstanceResourceIdentityModel struct {
|
||||
ProjectID types.String `tfsdk:"project_id"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
InstanceID types.String `tfsdk:"instance_id"`
|
||||
}
|
||||
|
||||
func (r *instanceResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
|
||||
var data postgresflexalpha.InstanceModel
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
|
@ -115,9 +123,44 @@ func (r *instanceResource) Configure(
|
|||
tflog.Info(ctx, "Postgres Flex instance client configured")
|
||||
}
|
||||
|
||||
/*
|
||||
until tfplugingen framework can handle plan modifiers, we use a function to add them
|
||||
*/
|
||||
|
||||
//go:embed planModifiers.yaml
|
||||
var modifiersFileByte []byte
|
||||
|
||||
// Schema defines the schema for the resource.
|
||||
func (r *instanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = postgresflexalpha.InstanceResourceSchema(ctx)
|
||||
schema := postgresflexalpha.InstanceResourceSchema(ctx)
|
||||
fields, err := postgresflexUtils.ReadModifiersConfig(modifiersFileByte)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("error during read modifiers config file", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = postgresflexUtils.AddPlanModifiersToResourceSchema(fields, &schema)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("error adding plan modifiers", err.Error())
|
||||
return
|
||||
}
|
||||
resp.Schema = schema
|
||||
}
|
||||
|
||||
func (r *instanceResource) IdentitySchema(_ context.Context, _ resource.IdentitySchemaRequest, resp *resource.IdentitySchemaResponse) {
|
||||
resp.IdentitySchema = identityschema.Schema{
|
||||
Attributes: map[string]identityschema.Attribute{
|
||||
"project_id": identityschema.StringAttribute{
|
||||
RequiredForImport: true, // must be set during import by the practitioner
|
||||
},
|
||||
"region": identityschema.StringAttribute{
|
||||
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||
},
|
||||
"instance_id": identityschema.StringAttribute{
|
||||
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Create creates the resource and sets the initial Terraform state.
|
||||
|
|
@ -158,7 +201,7 @@ func (r *instanceResource) Create(
|
|||
// Create new instance
|
||||
createResp, err := r.client.CreateInstanceRequest(ctx, projectId, region).CreateInstanceRequestPayload(payload).Execute()
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Calling API: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "error creating instance", fmt.Sprintf("Calling API: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +215,17 @@ func (r *instanceResource) Create(
|
|||
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
|
||||
}
|
||||
|
||||
waitResp, err := wait.CreateInstanceWaitHandler(ctx, r.client, projectId, region, instanceId).WaitWithContext(ctx)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating instance", fmt.Sprintf("Wait handler error: %v", err))
|
||||
|
|
@ -225,6 +279,7 @@ func modelToCreateInstancePayload(netAcl []string, model postgresflexalpha.Insta
|
|||
|
||||
// Read refreshes the Terraform state with the latest data.
|
||||
func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
|
||||
functionError := "read instance failed"
|
||||
var model postgresflexalpha.InstanceModel
|
||||
diags := req.State.Get(ctx, &model)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
|
|
@ -232,6 +287,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
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()
|
||||
|
|
@ -248,15 +310,32 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", err.Error())
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, functionError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx = core.LogResponse(ctx)
|
||||
|
||||
respInstanceID, ok := instanceResp.GetIdOk()
|
||||
if !ok {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, functionError, "response provided no ID")
|
||||
return
|
||||
}
|
||||
if !model.InstanceId.IsUnknown() && !model.InstanceId.IsNull() {
|
||||
if respInstanceID != instanceId {
|
||||
core.LogAndAddError(
|
||||
ctx,
|
||||
&resp.Diagnostics,
|
||||
functionError,
|
||||
"ID in response did not match ID in state",
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = mapGetInstanceResponseToModel(ctx, &model, instanceResp)
|
||||
if err != nil {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading instance", fmt.Sprintf("Processing API payload: %v", err))
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, functionError, fmt.Sprintf("Processing API payload: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +345,17 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
|
|||
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, "Postgres Flex instance read")
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue