99 "strings"
1010
1111 "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
12+ "github.com/hashicorp/terraform-plugin-framework/attr"
1213 "github.com/hashicorp/terraform-plugin-framework/diag"
1314 "github.com/hashicorp/terraform-plugin-framework/resource"
1415 "github.com/hashicorp/terraform-plugin-framework/resource/schema"
@@ -17,6 +18,7 @@ import (
1718 "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
1819 "github.com/hashicorp/terraform-plugin-framework/schema/validator"
1920 "github.com/hashicorp/terraform-plugin-framework/types"
21+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
2022 "github.com/hashicorp/terraform-plugin-log/tflog"
2123 "github.com/stackitcloud/stackit-sdk-go/core/oapierror"
2224 sfs "github.com/stackitcloud/stackit-sdk-go/services/sfs/v1api"
@@ -27,6 +29,7 @@ import (
2729 "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
2830 sfsUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/sfs/utils"
2931 "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
32+ stringplanmodifierUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/planmodifiers/stringplanmodifier"
3033 "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
3134)
3235
@@ -47,10 +50,21 @@ type Model struct {
4750 Name types.String `tfsdk:"name"`
4851 PerformanceClass types.String `tfsdk:"performance_class"`
4952 SizeGigabytes types.Int32 `tfsdk:"size_gigabytes"`
53+ SnapshotPolicy types.Object `tfsdk:"snapshot_policy"`
5054 Region types.String `tfsdk:"region"`
5155 SnapshotsAreVisible types.Bool `tfsdk:"snapshots_are_visible"`
5256}
5357
58+ type SnapshotPolicyModel struct {
59+ Id types.String `tfsdk:"id"`
60+ Name types.String `tfsdk:"name"`
61+ }
62+
63+ var snapshotPolicyTypes = map [string ]attr.Type {
64+ "id" : basetypes.StringType {},
65+ "name" : basetypes.StringType {},
66+ }
67+
5468// NewResourcePoolResource is a helper function to simplify the provider implementation.
5569func NewResourcePoolResource () resource.Resource {
5670 return & resourcePoolResource {}
@@ -200,6 +214,26 @@ func (r *resourcePoolResource) Schema(_ context.Context, _ resource.SchemaReques
200214 Computed : true ,
201215 Default : booldefault .StaticBool (false ),
202216 },
217+ "snapshot_policy" : schema.SingleNestedAttribute {
218+ Description : `Name of the snapshot policy.` ,
219+ Optional : true ,
220+ Attributes : map [string ]schema.Attribute {
221+ "id" : schema.StringAttribute {
222+ Description : "ID of the snapshot policy." ,
223+ Required : true , // must be set when snapshot_policy != null
224+ Validators : []validator.String {
225+ validate .UUID (),
226+ },
227+ },
228+ "name" : schema.StringAttribute {
229+ Description : "Name of the snapshot policy." ,
230+ Computed : true ,
231+ PlanModifiers : []planmodifier.String {
232+ stringplanmodifierUtils .UseStateForUnknownIf (stringplanmodifierUtils .StringChanged , "id" , "sets `UseStateForUnknown` only if `id` has not changed" ),
233+ },
234+ },
235+ },
236+ },
203237 },
204238 }
205239}
@@ -221,7 +255,7 @@ func (r *resourcePoolResource) Create(ctx context.Context, req resource.CreateRe
221255
222256 ctx = core .InitProviderContext (ctx )
223257
224- payload , err := toCreatePayload (& model )
258+ payload , err := toCreatePayload (ctx , & model )
225259 if err != nil {
226260 core .LogAndAddError (ctx , & resp .Diagnostics , "Error creating resource pool" , fmt .Sprintf ("Cannot create payload: %v" , err ))
227261 return
@@ -314,9 +348,8 @@ func (r *resourcePoolResource) Read(ctx context.Context, req resource.ReadReques
314348
315349 response , err := r .client .DefaultAPI .GetResourcePool (ctx , projectId , region , resourcePoolId ).Execute ()
316350 if err != nil {
317- var openapiError * oapierror.GenericOpenAPIError
318- if errors .As (err , & openapiError ) {
319- if openapiError .StatusCode == http .StatusNotFound {
351+ if openapiError , ok := errors.AsType [* oapierror.GenericOpenAPIError ](err ); ok {
352+ if openapiError .StatusCode == http .StatusNotFound || openapiError .StatusCode == http .StatusGone {
320353 resp .State .RemoveResource (ctx )
321354 return
322355 }
@@ -368,7 +401,7 @@ func (r *resourcePoolResource) Update(ctx context.Context, req resource.UpdateRe
368401 return
369402 }
370403
371- payload , err := toUpdatePayload (& model )
404+ payload , err := toUpdatePayload (ctx , & model )
372405 if err != nil {
373406 core .LogAndAddError (ctx , & resp .Diagnostics , "Update resource pool" , fmt .Sprintf ("cannot create payload: %v" , err ))
374407 return
@@ -520,10 +553,22 @@ func mapFields(ctx context.Context, region string, resourcePool *sfs.ResourcePoo
520553 model .SizeGigabytes = types .Int32PointerValue (resourcePool .Space .SizeGigabytes )
521554 }
522555
556+ model .SnapshotPolicy = types .ObjectNull (snapshotPolicyTypes )
557+ if snapshotPolicy := resourcePool .SnapshotPolicy .Get (); snapshotPolicy != nil {
558+ snapshotPolicyTf , diags := types .ObjectValue (snapshotPolicyTypes , map [string ]attr.Value {
559+ "id" : types .StringPointerValue (snapshotPolicy .Id ),
560+ "name" : types .StringPointerValue (snapshotPolicy .Name ),
561+ })
562+ if diags .HasError () {
563+ return fmt .Errorf ("failed to map snapshot policy: %w" , core .DiagsToError (diags ))
564+ }
565+ model .SnapshotPolicy = snapshotPolicyTf
566+ }
567+
523568 return nil
524569}
525570
526- func toCreatePayload (model * Model ) (* sfs.CreateResourcePoolPayload , error ) {
571+ func toCreatePayload (ctx context. Context , model * Model ) (* sfs.CreateResourcePoolPayload , error ) {
527572 if model == nil {
528573 return nil , fmt .Errorf ("nil model" )
529574 }
@@ -538,18 +583,28 @@ func toCreatePayload(model *Model) (*sfs.CreateResourcePoolPayload, error) {
538583 aclList = tmp
539584 }
540585
586+ snapshotPolicy := & SnapshotPolicyModel {}
587+ if ! utils .IsUndefined (model .SnapshotPolicy ) {
588+ diags := model .SnapshotPolicy .As (ctx , snapshotPolicy , basetypes.ObjectAsOptions {})
589+ if diags .HasError () {
590+ return nil , fmt .Errorf ("cannot convert snapshot policy: %w" , core .DiagsToError (diags ))
591+ }
592+ }
593+
541594 result := & sfs.CreateResourcePoolPayload {
542595 AvailabilityZone : model .AvailabilityZone .ValueString (),
543596 IpAcl : aclList ,
544597 Name : model .Name .ValueString (),
545598 PerformanceClass : model .PerformanceClass .ValueString (),
546599 SizeGigabytes : model .SizeGigabytes .ValueInt32 (),
547600 SnapshotsAreVisible : model .SnapshotsAreVisible .ValueBoolPointer (),
601+ SnapshotPolicyId : snapshotPolicy .Id .ValueStringPointer (),
548602 }
603+
549604 return result , nil
550605}
551606
552- func toUpdatePayload (model * Model ) (* sfs.UpdateResourcePoolPayload , error ) {
607+ func toUpdatePayload (ctx context. Context , model * Model ) (* sfs.UpdateResourcePoolPayload , error ) {
553608 if model == nil {
554609 return nil , fmt .Errorf ("nil model" )
555610 }
@@ -564,11 +619,20 @@ func toUpdatePayload(model *Model) (*sfs.UpdateResourcePoolPayload, error) {
564619 aclList = tmp
565620 }
566621
622+ snapshotPolicy := & SnapshotPolicyModel {}
623+ if ! utils .IsUndefined (model .SnapshotPolicy ) {
624+ diags := model .SnapshotPolicy .As (ctx , snapshotPolicy , basetypes.ObjectAsOptions {})
625+ if diags .HasError () {
626+ return nil , fmt .Errorf ("cannot convert snapshot policy: %w" , core .DiagsToError (diags ))
627+ }
628+ }
629+
567630 result := & sfs.UpdateResourcePoolPayload {
568631 IpAcl : aclList ,
569632 PerformanceClass : model .PerformanceClass .ValueStringPointer (),
570633 SizeGigabytes : * sfs .NewNullableInt32 (model .SizeGigabytes .ValueInt32Pointer ()),
571634 SnapshotsAreVisible : model .SnapshotsAreVisible .ValueBoolPointer (),
635+ SnapshotPolicyId : * sfs .NewNullableString (snapshotPolicy .Id .ValueStringPointer ()),
572636 }
573637 return result , nil
574638}
0 commit comments