@@ -5,10 +5,8 @@ package provider
5
5
6
6
import (
7
7
"context"
8
- "encoding/json"
9
8
"errors"
10
9
"fmt"
11
- "log"
12
10
"strings"
13
11
14
12
tfe "github.com/hashicorp/go-tfe"
@@ -25,6 +23,8 @@ import (
25
23
"github.com/hashicorp/terraform-plugin-framework/types"
26
24
"github.com/hashicorp/terraform-plugin-log/tflog"
27
25
26
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/helpers"
27
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/planmodifiers"
28
28
customValidators "github.com/hashicorp/terraform-provider-tfe/internal/provider/validators"
29
29
)
30
30
@@ -154,7 +154,7 @@ func (r *resourceOrgRunTask) Schema(ctx context.Context, req resource.SchemaRequ
154
154
stringvalidator .ConflictsWith (path .MatchRoot ("hmac_key" )),
155
155
},
156
156
PlanModifiers : []planmodifier.String {
157
- & replaceHMACKeyWOPlanModifier {} ,
157
+ planmodifiers . NewReplaceForWriteOnlyStringValue ( "hmac_key_wo" ) ,
158
158
},
159
159
},
160
160
"enabled" : schema.BoolAttribute {
@@ -171,67 +171,6 @@ func (r *resourceOrgRunTask) Schema(ctx context.Context, req resource.SchemaRequ
171
171
}
172
172
}
173
173
174
- func (r * resourceOrgRunTask ) isWriteOnlyHMACKeyInPrivateState (ctx context.Context , req resource.ReadRequest , resp * resource.ReadResponse ) bool {
175
- storedValueWO , diags := req .Private .GetKey (ctx , "hmac_key_wo" )
176
- resp .Diagnostics .Append (diags ... )
177
- return len (storedValueWO ) != 0
178
- }
179
-
180
- type replaceHMACKeyWOPlanModifier struct {}
181
-
182
- func (v * replaceHMACKeyWOPlanModifier ) Description (ctx context.Context ) string {
183
- return "The resource will be replaced when the value of hmac_key_wo has changed"
184
- }
185
-
186
- func (v * replaceHMACKeyWOPlanModifier ) MarkdownDescription (ctx context.Context ) string {
187
- return v .Description (ctx )
188
- }
189
-
190
- func (v * replaceHMACKeyWOPlanModifier ) PlanModifyString (ctx context.Context , request planmodifier.StringRequest , response * planmodifier.StringResponse ) {
191
- // Write-only argument values cannot produce a Terraform plan difference. The prior state value for a write-only argument will always be null and the planned state value will also be null, therefore, it cannot produce a diff on its own. The one exception to this case is if the write-only argument is added to requires_replace during Plan Modification, in that case, the write-only argument will always cause a diff/trigger a resource recreation.
192
- var configHMACKeyWO types.String
193
- diag := request .Config .GetAttribute (ctx , path .Root ("hmac_key_wo" ), & configHMACKeyWO )
194
- response .Diagnostics .Append (diag ... )
195
- if response .Diagnostics .HasError () {
196
- return
197
- }
198
-
199
- storedHMACWO , diags := request .Private .GetKey (ctx , "hmac_key_wo" )
200
- response .Diagnostics .Append (diags ... )
201
- if response .Diagnostics .HasError () {
202
- return
203
- }
204
-
205
- if configHMACKeyWO .IsNull () {
206
- if len (storedHMACWO ) != 0 {
207
- response .RequiresReplace = true
208
- }
209
- return
210
- }
211
-
212
- if len (storedHMACWO ) == 0 {
213
- log .Printf ("[DEBUG] Replacing resource because `hmac_key_wo` attribute has been added to a pre-existing variable resource" )
214
- response .RequiresReplace = true
215
- return
216
- }
217
-
218
- var hashedStoredHMACWO string
219
- err := json .Unmarshal (storedHMACWO , & hashedStoredHMACWO )
220
- if err != nil {
221
- response .Diagnostics .AddError ("Error unmarshalling stored hmac_key_wo" , err .Error ())
222
- return
223
- }
224
-
225
- hashedConfigHMACKeyWO := generateSHA256Hash (configHMACKeyWO .ValueString ())
226
-
227
- // when an ephemeral value is being used, they will generate a new token on every run.
228
- // So the previous hmac_key_wo will not match the current one.
229
- if hashedStoredHMACWO != hashedConfigHMACKeyWO {
230
- log .Printf ("[DEBUG] Replacing resource because the value of `hmac_key_wo` attribute has changed" )
231
- response .RequiresReplace = true
232
- }
233
- }
234
-
235
174
func (r * resourceOrgRunTask ) Read (ctx context.Context , req resource.ReadRequest , resp * resource.ReadResponse ) {
236
175
var state modelTFEOrganizationRunTaskV0
237
176
@@ -254,12 +193,13 @@ func (r *resourceOrgRunTask) Read(ctx context.Context, req resource.ReadRequest,
254
193
return
255
194
}
256
195
257
- isWriteOnlyValue := r .isWriteOnlyHMACKeyInPrivateState (ctx , req , resp ) // to avoid reading from written-only values
258
- if resp .Diagnostics .HasError () {
196
+ isWriteOnly , diags := r .writeOnlyValueStore (resp .Private ).PriorValueExists (ctx )
197
+ resp .Diagnostics .Append (diags ... )
198
+ if diags .HasError () {
259
199
return
260
200
}
261
201
// update state
262
- result := modelFromTFEOrganizationRunTask (task , state .HMACKey , isWriteOnlyValue )
202
+ result := modelFromTFEOrganizationRunTask (task , state .HMACKey , isWriteOnly )
263
203
// Save updated data into Terraform state
264
204
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
265
205
}
@@ -294,7 +234,7 @@ func (r *resourceOrgRunTask) Create(ctx context.Context, req resource.CreateRequ
294
234
Enabled : plan .Enabled .ValueBoolPointer (),
295
235
Description : plan .Description .ValueStringPointer (),
296
236
}
297
-
237
+ // Set Value from "hmac_key_wo" if set, otherwise use the normal value
298
238
if ! config .HMACKeyWO .IsNull () {
299
239
options .HMACKey = config .HMACKeyWO .ValueStringPointer ()
300
240
} else {
@@ -309,16 +249,9 @@ func (r *resourceOrgRunTask) Create(ctx context.Context, req resource.CreateRequ
309
249
}
310
250
311
251
result := modelFromTFEOrganizationRunTask (task , plan .HMACKey , ! config .HMACKeyWO .IsNull ())
312
- if ! config .HMACKeyWO .IsNull () {
313
- // Use the resource's private state to store secure hashes of write-only argument values, the provider during planmodify will use the hash to determine if a write-only argument value has changed in later Terraform runs.
314
- hashedValue := generateSHA256Hash (config .HMACKeyWO .ValueString ())
315
- diags := resp .Private .SetKey (ctx , "hmac_key_wo" , fmt .Appendf (nil , `"%s"` , hashedValue ))
316
- resp .Diagnostics .Append (diags ... )
317
- } else {
318
- // if the key is not configured as write-only, then remove HMACKeyWO key from private state. Setting a key with an empty byte slice is interpreted by the framework as a request to remove the key from the ProviderData map.
319
- diags := resp .Private .SetKey (ctx , "hmac_key_wo" , []byte ("" ))
320
- resp .Diagnostics .Append (diags ... )
321
- }
252
+ // Store the hashed write-only value in the private state
253
+ store := r .writeOnlyValueStore (resp .Private )
254
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .HMACKeyWO )... )
322
255
323
256
// Save data into Terraform state
324
257
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
@@ -371,9 +304,14 @@ func (r *resourceOrgRunTask) Update(ctx context.Context, req resource.UpdateRequ
371
304
return
372
305
}
373
306
374
- result := modelFromTFEOrganizationRunTask (task , plan .HMACKey , ! config .HMACKeyWO .IsNull ())
375
- r .updatePrivateState (ctx , resp , config .HMACKeyWO )
307
+ // Store the hashed write-only value in the private state
308
+ store := r .writeOnlyValueStore (resp .Private )
309
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .HMACKeyWO )... )
310
+ if resp .Diagnostics .HasError () {
311
+ return
312
+ }
376
313
314
+ result := modelFromTFEOrganizationRunTask (task , plan .HMACKey , ! config .HMACKeyWO .IsNull ())
377
315
// Save data into Terraform state
378
316
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
379
317
}
@@ -430,17 +368,6 @@ func (r *resourceOrgRunTask) ImportState(ctx context.Context, req resource.Impor
430
368
}
431
369
}
432
370
433
- func (r * resourceOrgRunTask ) updatePrivateState (ctx context.Context , resp * resource.UpdateResponse , configHMACKeyWO types.String ) {
434
- if ! configHMACKeyWO .IsNull () {
435
- // Use the resource's private state to store secure hashes of write-only argument values, planModify will use the hash to determine if a write-only argument value has changed in later Terraform runs.
436
- hashedValue := generateSHA256Hash (configHMACKeyWO .ValueString ())
437
- diags := resp .Private .SetKey (ctx , "hmac_key_wo" , fmt .Appendf (nil , `"%s"` , hashedValue ))
438
- resp .Diagnostics .Append (diags ... )
439
- } else {
440
- // if key is not configured as write-only, remove hmacKeyWO key from private state
441
- diags := resp .Private .SetKey (ctx , "hmac_key_wo" , []byte ("" ))
442
- resp .Diagnostics .Append (diags ... )
443
- }
371
+ func (r * resourceOrgRunTask ) writeOnlyValueStore (private helpers.PrivateState ) * helpers.WriteOnlyValueStore {
372
+ return helpers .NewWriteOnlyValueStore (private , "hmac_key_wo" )
444
373
}
445
-
446
- var _ planmodifier.String = & replaceHMACKeyWOPlanModifier {}
0 commit comments