@@ -3,8 +3,6 @@ package provider
33import (
44 "context"
55 "fmt"
6- "strings"
7-
86 "github.com/hashicorp/go-tfe"
97 "github.com/hashicorp/terraform-plugin-framework/path"
108 "github.com/hashicorp/terraform-plugin-framework/resource"
@@ -16,14 +14,16 @@ import (
1614 "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator"
1715 "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
1816 "github.com/hashicorp/terraform-plugin-framework/types"
17+ "github.com/hashicorp/terraform-plugin-framework/diag"
18+ "strings"
1919 "github.com/hashicorp/terraform-plugin-framework/resource/schema/numberplanmodifier"
20+ "github.com/hashicorp/terraform-plugin-framework-validators/numbervalidator"
2021)
2122
2223// Ensure provider defined types fully satisfy framework interfaces.
2324var _ resource.Resource = & resourceTFEDataRetentionPolicy {}
2425var _ resource.ResourceWithConfigure = & resourceTFEDataRetentionPolicy {}
2526var _ resource.ResourceWithImportState = & resourceTFEDataRetentionPolicy {}
26- var _ resource.ResourceWithModifyPlan = & resourceTFEDataRetentionPolicy {}
2727
2828func NewDataRetentionPolicyResource () resource.Resource {
2929 return & resourceTFEDataRetentionPolicy {}
@@ -38,10 +38,6 @@ func (r *resourceTFEDataRetentionPolicy) Metadata(ctx context.Context, req resou
3838 resp .TypeName = req .ProviderTypeName + "_data_retention_policy"
3939}
4040
41- func (r * resourceTFEDataRetentionPolicy ) ModifyPlan (ctx context.Context , req resource.ModifyPlanRequest , resp * resource.ModifyPlanResponse ) {
42- modifyPlanForDefaultOrganizationChange (ctx , r .config .Organization , req .State , req .Config , req .Plan , resp )
43- }
44-
4541func (r * resourceTFEDataRetentionPolicy ) Schema (ctx context.Context , req resource.SchemaRequest , resp * resource.SchemaResponse ) {
4642 resp .Schema = schema.Schema {
4743 Description : "Manages the data retention policies for a specific workspace or an the entire organization." ,
@@ -60,6 +56,7 @@ func (r *resourceTFEDataRetentionPolicy) Schema(ctx context.Context, req resourc
6056 Optional : true ,
6157 Computed : true ,
6258 PlanModifiers : []planmodifier.String {
59+ stringplanmodifier .UseStateForUnknown (),
6360 stringplanmodifier .RequiresReplace (),
6461 },
6562 },
@@ -77,17 +74,17 @@ func (r *resourceTFEDataRetentionPolicy) Schema(ctx context.Context, req resourc
7774 Attributes : map [string ]schema.Attribute {
7875 "days" : schema.NumberAttribute {
7976 Description : "Number of days" ,
80- Required : true ,
77+ Optional : true ,
8178 PlanModifiers : []planmodifier.Number {
8279 numberplanmodifier .RequiresReplace (),
8380 },
81+ Validators : []validator.Number {
82+ numbervalidator .ExactlyOneOf (
83+ path .MatchRelative ().AtParent ().AtParent ().AtName ("dont_delete" ),
84+ ),
85+ },
8486 },
8587 },
86- Validators : []validator.Object {
87- objectvalidator .ExactlyOneOf (
88- path .MatchRelative ().AtParent ().AtName ("dont_delete" ),
89- ),
90- },
9188 },
9289 "dont_delete" : schema.SingleNestedBlock {
9390 Attributes : map [string ]schema.Attribute {},
@@ -128,11 +125,7 @@ func (r *resourceTFEDataRetentionPolicy) Create(ctx context.Context, req resourc
128125 return
129126 }
130127
131- var organization string
132- if plan .WorkspaceId .IsNull () {
133- resp .Diagnostics .Append (r .config .dataOrDefaultOrganization (ctx , req .Plan , & organization )... )
134- plan .Organization = types .StringValue (organization )
135- }
128+ r .ensureOrganizationIsSet (ctx , & plan , req .Plan , & resp .Diagnostics )
136129
137130 if resp .Diagnostics .HasError () {
138131 return
@@ -150,6 +143,19 @@ func (r *resourceTFEDataRetentionPolicy) Create(ctx context.Context, req resourc
150143
151144}
152145
146+ func (r * resourceTFEDataRetentionPolicy ) ensureOrganizationIsSet (ctx context.Context , model * modelTFEDataRetentionPolicy , data AttrGettable , diags * diag.Diagnostics ) {
147+ if ! model .Organization .IsUnknown () || model .Organization .ValueString () != "" {
148+ // skip this method if the organization has already been set
149+ return
150+ }
151+
152+ if model .WorkspaceId .IsNull () {
153+ var organization string
154+ diags .Append (r .config .dataOrDefaultOrganization (ctx , data , & organization )... )
155+ model .Organization = types .StringValue (organization )
156+ }
157+ }
158+
153159func (r * resourceTFEDataRetentionPolicy ) createDeleteOlderThanRetentionPolicy (ctx context.Context , plan modelTFEDataRetentionPolicy , resp * resource.CreateResponse ) {
154160 deleteOlderThan := & modelTFEDeleteOlderThan {}
155161
@@ -183,8 +189,12 @@ func (r *resourceTFEDataRetentionPolicy) createDeleteOlderThanRetentionPolicy(ct
183189 return
184190 }
185191
192+ // set organization if it is still not known after creating the data retention policy
193+ r .ensureOrganizationSetAfterApply (& result , & resp .Diagnostics )
194+
186195 // Save data into Terraform state
187- resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
196+ diags = resp .State .Set (ctx , & result )
197+ resp .Diagnostics .Append (diags ... )
188198}
189199
190200func (r * resourceTFEDataRetentionPolicy ) createDontDeleteRetentionPolicy (ctx context.Context , plan modelTFEDataRetentionPolicy , resp * resource.CreateResponse ) {
@@ -213,8 +223,23 @@ func (r *resourceTFEDataRetentionPolicy) createDontDeleteRetentionPolicy(ctx con
213223
214224 result := modelFromTFEDataRetentionPolicyDontDelete (plan , dataRetentionPolicy )
215225
226+ // set organization if it is still not known after creating the data retention policy
227+ r .ensureOrganizationSetAfterApply (& result , & resp .Diagnostics )
228+
216229 // Save data into Terraform state
217- resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
230+ diags = resp .State .Set (ctx , & result )
231+ resp .Diagnostics .Append (diags ... )
232+ }
233+
234+ func (r * resourceTFEDataRetentionPolicy ) ensureOrganizationSetAfterApply (policy * modelTFEDataRetentionPolicy , diags * diag.Diagnostics ) {
235+ if policy .Organization .IsUnknown () {
236+ workspace , err := r .config .Client .Workspaces .ReadByID (ctx , policy .WorkspaceId .ValueString ())
237+ if err != nil {
238+ diags .AddError ("Unable to create data retention policy" , err .Error ())
239+ return
240+ }
241+ policy .Organization = types .StringValue (workspace .Organization .Name )
242+ }
218243}
219244
220245func (r * resourceTFEDataRetentionPolicy ) Read (ctx context.Context , req resource.ReadRequest , resp * resource.ReadResponse ) {
@@ -289,18 +314,50 @@ func (r *resourceTFEDataRetentionPolicy) Delete(ctx context.Context, req resourc
289314}
290315
291316func (r * resourceTFEDataRetentionPolicy ) ImportState (ctx context.Context , req resource.ImportStateRequest , resp * resource.ImportStateResponse ) {
292- s := strings .SplitN (req .ID , "/" , 2 )
317+ s := strings .Split (req .ID , "/" )
318+ if len (s ) >= 3 {
319+ resp .Diagnostics .AddError ("Error importing workspace settings" , fmt .Sprintf (
320+ "invalid workspace input format: %s (expected <ORGANIZATION>/<WORKSPACE NAME> or <ORGANIZATION>)" ,
321+ req .ID ,
322+ ))
323+ } else if len (s ) == 2 {
324+ workspaceID , err := fetchWorkspaceExternalID (s [0 ]+ "/" + s [1 ], r .config .Client )
325+ if err != nil {
326+ resp .Diagnostics .AddError ("Error importing data retention policy" , fmt .Sprintf (
327+ "error retrieving workspace with name %s from organization %s: %s" , s [1 ], s [0 ], err .Error (),
328+ ))
329+ }
293330
294- if len (s ) != 2 && len (s ) != 1 {
295- resp .Diagnostics .AddError (
296- "Error importing variable" ,
297- fmt .Sprintf ("Invalid variable import format: %s (expected <ORGANIZATION>/<WORKSPACE ID> or <ORGANIZATION>)" , req .ID ),
298- )
299- return
331+ policy , err := r .config .Client .Workspaces .ReadDataRetentionPolicyChoice (ctx , workspaceID )
332+ if err != nil {
333+ resp .Diagnostics .AddError ("Error importing data retention policy" , fmt .Sprintf (
334+ "error retrieving data policy for workspace %s from organization %s: %s" , s [1 ], s [0 ], err .Error (),
335+ ))
336+ }
337+
338+ req .ID = r .getPolicyID (policy )
339+ resp .Diagnostics .Append (resp .State .SetAttribute (ctx , path .Root ("workspace_id" ), workspaceID )... )
340+ resp .Diagnostics .Append (resp .State .SetAttribute (ctx , path .Root ("organization" ), s [0 ])... )
341+ } else if len (s ) == 1 {
342+ policy , err := r .config .Client .Organizations .ReadDataRetentionPolicyChoice (ctx , s [0 ])
343+ if err != nil {
344+ resp .Diagnostics .AddError ("Error importing data retention policy" , fmt .Sprintf (
345+ "error retrieving data policy for organization %s: %s" , s [0 ], err .Error (),
346+ ))
347+ }
348+ req .ID = r .getPolicyID (policy )
349+ resp .Diagnostics .Append (resp .State .SetAttribute (ctx , path .Root ("organization" ), s [0 ])... )
350+ }
351+ }
352+
353+ func (r * resourceTFEDataRetentionPolicy ) getPolicyID (policy * tfe.DataRetentionPolicyChoice ) string {
354+ if policy .DataRetentionPolicyDeleteOlder != nil {
355+ return policy .DataRetentionPolicyDeleteOlder .ID
356+ }
357+
358+ if policy .DataRetentionPolicyDontDelete != nil {
359+ return policy .DataRetentionPolicyDontDelete .ID
300360 }
301- org := s [0 ]
302- wsId := s [1 ]
303361
304- resp .Diagnostics .Append (resp .State .SetAttribute (ctx , path .Root ("organization" ), org )... )
305- resp .Diagnostics .Append (resp .State .SetAttribute (ctx , path .Root ("workspace_id" ), wsId )... )
362+ return policy .ConvertToLegacyStruct ().ID
306363}
0 commit comments