@@ -17,6 +17,7 @@ import (
17
17
18
18
"github.com/aquasecurity/trivy/internal/testutil"
19
19
"github.com/aquasecurity/trivy/pkg/iac/terraform"
20
+ tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context"
20
21
"github.com/aquasecurity/trivy/pkg/log"
21
22
"github.com/aquasecurity/trivy/pkg/set"
22
23
)
@@ -2280,6 +2281,80 @@ func TestTFVarsFileDoesNotExist(t *testing.T) {
2280
2281
assert .ErrorContains (t , err , "file does not exist" )
2281
2282
}
2282
2283
2284
+ func Test_OptionsWithEvalHook (t * testing.T ) {
2285
+ fs := testutil .CreateFS (t , map [string ]string {
2286
+ "main.tf" : `
2287
+ data "your_custom_data" "this" {
2288
+ default = ["foo", "foh", "fum"]
2289
+ unaffected = "bar"
2290
+ }
2291
+
2292
+ // Testing the hook affects some value, which is used in another evaluateStep
2293
+ // action (expanding blocks)
2294
+ data "random_thing" "that" {
2295
+ dynamic "repeated" {
2296
+ for_each = data.your_custom_data.this.value
2297
+ content {
2298
+ value = repeated.value
2299
+ }
2300
+ }
2301
+ }
2302
+
2303
+ locals {
2304
+ referenced = data.your_custom_data.this.value
2305
+ static_ref = data.your_custom_data.this.unaffected
2306
+ }
2307
+ ` })
2308
+
2309
+ parser := New (fs , "" , OptionWithEvalHook (
2310
+ // A basic example of how to have a 'default' value for a data block.
2311
+ // To see a more practical example, see how 'evaluateVariable' handles
2312
+ // the 'default' value of a variable.
2313
+ func (ctx * tfcontext.Context , blocks terraform.Blocks , inputVars map [string ]cty.Value ) {
2314
+ dataBlocks := blocks .OfType ("data" )
2315
+ for _ , block := range dataBlocks {
2316
+ if len (block .Labels ()) >= 1 && block .Labels ()[0 ] == "your_custom_data" {
2317
+ def := block .GetAttribute ("default" )
2318
+ ctx .Set (cty .ObjectVal (map [string ]cty.Value {
2319
+ "value" : def .Value (),
2320
+ }), "data" , "your_custom_data" , "this" )
2321
+ }
2322
+ }
2323
+
2324
+ },
2325
+ ))
2326
+
2327
+ require .NoError (t , parser .ParseFS (t .Context (), "." ))
2328
+
2329
+ modules , _ , err := parser .EvaluateAll (t .Context ())
2330
+ require .NoError (t , err )
2331
+ assert .Len (t , modules , 1 )
2332
+
2333
+ rootModule := modules [0 ]
2334
+
2335
+ // Check the default value of the data block
2336
+ blocks := rootModule .GetDatasByType ("your_custom_data" )
2337
+ assert .Len (t , blocks , 1 )
2338
+ expList := cty .TupleVal ([]cty.Value {cty .StringVal ("foo" ), cty .StringVal ("foh" ), cty .StringVal ("fum" )})
2339
+ assert .True (t , expList .Equals (blocks [0 ].GetAttribute ("default" ).Value ()).True (), "default value matched list" )
2340
+ assert .Equal (t , "bar" , blocks [0 ].GetAttribute ("unaffected" ).Value ().AsString ())
2341
+
2342
+ // Check the referenced 'data.your_custom_data.this.value' exists in the eval
2343
+ // context, and it is the default value of the data block.
2344
+ locals := rootModule .GetBlocks ().OfType ("locals" )
2345
+ assert .Len (t , locals , 1 )
2346
+ assert .True (t , expList .Equals (locals [0 ].GetAttribute ("referenced" ).Value ()).True (), "referenced value matched list" )
2347
+ assert .Equal (t , "bar" , locals [0 ].GetAttribute ("static_ref" ).Value ().AsString ())
2348
+
2349
+ // Check the dynamic block is expanded correctly
2350
+ dynamicBlocks := rootModule .GetDatasByType ("random_thing" )
2351
+ assert .Len (t , dynamicBlocks , 1 )
2352
+ assert .Len (t , dynamicBlocks [0 ].GetBlocks ("repeated" ), 3 )
2353
+ for i , repeat := range dynamicBlocks [0 ].GetBlocks ("repeated" ) {
2354
+ assert .Equal (t , expList .Index (cty .NumberIntVal (int64 (i ))), repeat .GetAttribute ("value" ).Value ())
2355
+ }
2356
+ }
2357
+
2283
2358
func Test_OptionsWithTfVars (t * testing.T ) {
2284
2359
fs := testutil .CreateFS (t , map [string ]string {
2285
2360
"main.tf" : `resource "test" "this" {
0 commit comments