7
7
"context"
8
8
"errors"
9
9
"fmt"
10
- "log"
11
10
"regexp"
12
11
"strings"
13
12
@@ -23,6 +22,9 @@ import (
23
22
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
24
23
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
25
24
"github.com/hashicorp/terraform-plugin-framework/types"
25
+ "github.com/hashicorp/terraform-plugin-log/tflog"
26
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/helpers"
27
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/planmodifiers"
26
28
)
27
29
28
30
var (
@@ -43,11 +45,12 @@ type modelTFEPolicySetParameter struct {
43
45
ID types.String `tfsdk:"id"`
44
46
Key types.String `tfsdk:"key"`
45
47
Value types.String `tfsdk:"value"`
48
+ ValueWO types.String `tfsdk:"value_wo"`
46
49
Sensitive types.Bool `tfsdk:"sensitive"`
47
50
PolicySetID types.String `tfsdk:"policy_set_id"`
48
51
}
49
52
50
- func modelFromTFEPolicySetParameter (v * tfe.PolicySetParameter , lastValue types.String ) modelTFEPolicySetParameter {
53
+ func modelFromTFEPolicySetParameter (v * tfe.PolicySetParameter , lastValue types.String , isWriteOnly bool ) modelTFEPolicySetParameter {
51
54
p := modelTFEPolicySetParameter {
52
55
ID : types .StringValue (v .ID ),
53
56
Key : types .StringValue (v .Key ),
@@ -62,6 +65,11 @@ func modelFromTFEPolicySetParameter(v *tfe.PolicySetParameter, lastValue types.S
62
65
p .Value = lastValue
63
66
}
64
67
68
+ // If the variable is write-only, clear the value.
69
+ if isWriteOnly {
70
+ p .Value = types .StringValue ("" )
71
+ }
72
+
65
73
return p
66
74
}
67
75
@@ -126,6 +134,22 @@ func (r *resourceTFEPolicySetParameter) Schema(ctx context.Context, req resource
126
134
Computed : true ,
127
135
Default : stringdefault .StaticString ("" ),
128
136
Sensitive : true ,
137
+ Validators : []validator.String {
138
+ stringvalidator .ConflictsWith (path .MatchRoot ("value_wo" )),
139
+ },
140
+ },
141
+
142
+ "value_wo" : schema.StringAttribute {
143
+ Optional : true ,
144
+ WriteOnly : true ,
145
+ Sensitive : true ,
146
+ Description : "Value of the parameter in write-only mode" ,
147
+ Validators : []validator.String {
148
+ stringvalidator .ConflictsWith (path .MatchRoot ("value" )),
149
+ },
150
+ PlanModifiers : []planmodifier.String {
151
+ planmodifiers .NewReplaceForWriteOnlyStringValue ("value_wo" ),
152
+ },
129
153
},
130
154
131
155
"sensitive" : schema.BoolAttribute {
@@ -168,30 +192,46 @@ func (r *resourceTFEPolicySetParameter) Schema(ctx context.Context, req resource
168
192
}
169
193
170
194
func (r * resourceTFEPolicySetParameter ) Create (ctx context.Context , req resource.CreateRequest , resp * resource.CreateResponse ) {
171
- // Read the Terraform plan into the model
172
- var plan modelTFEPolicySetParameter
195
+ // Read the Terraform plan and config into the model
196
+ var plan , config modelTFEPolicySetParameter
173
197
resp .Diagnostics .Append (req .Plan .Get (ctx , & plan )... )
198
+ resp .Diagnostics .Append (req .Config .Get (ctx , & config )... )
174
199
if resp .Diagnostics .HasError () {
175
200
return
176
201
}
177
202
178
203
// Create an options struct
179
204
options := tfe.PolicySetParameterCreateOptions {
180
205
Key : plan .Key .ValueStringPointer (),
181
- Value : plan .Value .ValueStringPointer (),
182
206
Category : tfe .Category (tfe .CategoryPolicySet ),
183
207
Sensitive : plan .Sensitive .ValueBoolPointer (),
184
208
}
185
209
210
+ // Set Value from `value_wo` if set, otherwise use the normal value
211
+ isWriteOnly := ! config .ValueWO .IsNull ()
212
+ if isWriteOnly {
213
+ options .Value = config .ValueWO .ValueStringPointer ()
214
+ } else {
215
+ options .Value = plan .Value .ValueStringPointer ()
216
+ }
217
+
186
218
// Create the policy set parameter
187
- log . Printf ( "[DEBUG] Create %s parameter: %s" , tfe .CategoryPolicySet , plan .Key .ValueString ())
219
+ tflog . Debug ( ctx , fmt . Sprintf ( " Create %s parameter: %s" , tfe .CategoryPolicySet , plan .Key .ValueString () ))
188
220
p , err := r .config .Client .PolicySetParameters .Create (ctx , plan .PolicySetID .ValueString (), options )
189
221
if err != nil {
190
222
resp .Diagnostics .AddError (fmt .Sprintf ("Error creating %s parameter %s" , tfe .CategoryPolicySet , plan .Key ), err .Error ())
191
223
return
192
224
}
193
225
194
- result := modelFromTFEPolicySetParameter (p , plan .Value )
226
+ // Store the hashed write-only value in the private state
227
+ store := r .writeOnlyValueStore (resp .Private )
228
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .ValueWO )... )
229
+ if resp .Diagnostics .HasError () {
230
+ return
231
+ }
232
+
233
+ // Update state
234
+ result := modelFromTFEPolicySetParameter (p , plan .Value , isWriteOnly )
195
235
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
196
236
}
197
237
@@ -211,33 +251,36 @@ func (r *resourceTFEPolicySetParameter) Read(ctx context.Context, req resource.R
211
251
}
212
252
213
253
// Read the policy set parameter
214
- log . Printf ( "[DEBUG] Read parameter: %s" , state .ID )
254
+ tflog . Debug ( ctx , fmt . Sprintf ( " Read parameter: %s" , state .ID ) )
215
255
p , err := r .config .Client .PolicySetParameters .Read (ctx , state .PolicySetID .ValueString (), state .ID .ValueString ())
216
256
if err != nil {
217
257
if errors .Is (err , tfe .ErrResourceNotFound ) {
218
- log . Printf ( "[DEBUG] Parameter %s no longer exists" , state .ID )
258
+ tflog . Debug ( ctx , fmt . Sprintf ( " Parameter %s no longer exists" , state .ID ) )
219
259
resp .State .RemoveResource (ctx )
220
260
}
221
261
222
262
resp .Diagnostics .AddError (fmt .Sprintf ("Error reading %s parameter %s" , tfe .CategoryPolicySet , state .ID ), err .Error ())
223
263
return
224
264
}
225
265
226
- result := modelFromTFEPolicySetParameter (p , state .Value )
266
+ // Check if the parameter is write-only
267
+ isWriteOnly , diags := r .writeOnlyValueStore (resp .Private ).PriorValueExists (ctx )
268
+ resp .Diagnostics .Append (diags ... )
269
+ if diags .HasError () {
270
+ return
271
+ }
272
+
273
+ result := modelFromTFEPolicySetParameter (p , state .Value , isWriteOnly )
227
274
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
228
275
}
229
276
230
277
// Update implements resource.Resource
231
278
func (r * resourceTFEPolicySetParameter ) Update (ctx context.Context , req resource.UpdateRequest , resp * resource.UpdateResponse ) {
232
- // Read the Terraform plan into the model
233
- var plan modelTFEPolicySetParameter
279
+ // Read the Terraform plan, state, and config into the model
280
+ var plan , state , config modelTFEPolicySetParameter
234
281
resp .Diagnostics .Append (req .Plan .Get (ctx , & plan )... )
235
- if resp .Diagnostics .HasError () {
236
- return
237
- }
238
- // Read the Terraform state into the model
239
- var state modelTFEPolicySetParameter
240
282
resp .Diagnostics .Append (req .State .Get (ctx , & state )... )
283
+ resp .Diagnostics .Append (req .Config .Get (ctx , & config )... )
241
284
if resp .Diagnostics .HasError () {
242
285
return
243
286
}
@@ -256,13 +299,21 @@ func (r *resourceTFEPolicySetParameter) Update(ctx context.Context, req resource
256
299
}
257
300
258
301
// Update the policy set parameter
259
- log . Printf ( "[DEBUG] Update parameter: %s" , plan .ID .ValueString ())
302
+ tflog . Debug ( ctx , fmt . Sprintf ( " Update parameter: %s" , plan .ID .ValueString () ))
260
303
p , err := r .config .Client .PolicySetParameters .Update (ctx , plan .PolicySetID .ValueString (), plan .ID .ValueString (), options )
261
304
if err != nil {
262
305
resp .Diagnostics .AddError (fmt .Sprintf ("Error updating parameter %s" , plan .ID ), err .Error ())
263
306
}
264
307
265
- result := modelFromTFEPolicySetParameter (p , plan .Value )
308
+ // Store the hashed write-only value in the private state
309
+ store := r .writeOnlyValueStore (resp .Private )
310
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .ValueWO )... )
311
+ if resp .Diagnostics .HasError () {
312
+ return
313
+ }
314
+
315
+ // Update state
316
+ result := modelFromTFEPolicySetParameter (p , plan .Value , ! config .ValueWO .IsNull ())
266
317
resp .Diagnostics .Append (resp .State .Set (ctx , & result )... )
267
318
}
268
319
@@ -283,7 +334,7 @@ func (r *resourceTFEPolicySetParameter) Delete(ctx context.Context, req resource
283
334
}
284
335
285
336
// Delete the policy set parameter
286
- log . Printf ( "[DEBUG] Delete parameter: %s" , state .ID )
337
+ tflog . Debug ( ctx , fmt . Sprintf ( " Delete parameter: %s" , state .ID ) )
287
338
err = r .config .Client .PolicySetParameters .Delete (ctx , state .PolicySetID .ValueString (), state .ID .ValueString ())
288
339
if err != nil && ! errors .Is (err , tfe .ErrResourceNotFound ) {
289
340
resp .Diagnostics .AddError (
@@ -313,3 +364,7 @@ func (r *resourceTFEPolicySetParameter) ImportState(ctx context.Context, req res
313
364
diags := resp .State .Set (ctx , & data )
314
365
resp .Diagnostics .Append (diags ... )
315
366
}
367
+
368
+ func (r * resourceTFEPolicySetParameter ) writeOnlyValueStore (private helpers.PrivateState ) * helpers.WriteOnlyValueStore {
369
+ return helpers .NewWriteOnlyValueStore (private , "value_wo" )
370
+ }
0 commit comments