| 
 | 1 | +package preview  | 
 | 2 | + | 
 | 3 | +import (  | 
 | 4 | +	"fmt"  | 
 | 5 | + | 
 | 6 | +	"github.com/aquasecurity/trivy/pkg/iac/terraform"  | 
 | 7 | +	tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context"  | 
 | 8 | +	"github.com/hashicorp/hcl/v2"  | 
 | 9 | +	"github.com/hashicorp/hcl/v2/ext/typeexpr"  | 
 | 10 | +	"github.com/zclconf/go-cty/cty"  | 
 | 11 | +	"github.com/zclconf/go-cty/cty/convert"  | 
 | 12 | + | 
 | 13 | +	"github.com/coder/preview/hclext"  | 
 | 14 | +)  | 
 | 15 | + | 
 | 16 | +func ParameterContextsEvalHook(input Input, diags hcl.Diagnostics) func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) {  | 
 | 17 | +	return func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) {  | 
 | 18 | +		data := blocks.OfType("data")  | 
 | 19 | +		for _, block := range data {  | 
 | 20 | +			if block.TypeLabel() != "coder_parameter" {  | 
 | 21 | +				continue  | 
 | 22 | +			}  | 
 | 23 | + | 
 | 24 | +			if !block.GetAttribute("value").IsNil() {  | 
 | 25 | +				continue // Wow a value exists?!. This feels like a bug.  | 
 | 26 | +			}  | 
 | 27 | + | 
 | 28 | +			name := block.NameLabel()  | 
 | 29 | +			var defDiags hcl.Diagnostics  | 
 | 30 | +			var value cty.Value  | 
 | 31 | +			pv, ok := input.RichParameterValue(name)  | 
 | 32 | +			if ok {  | 
 | 33 | +				// TODO: Handle non-string types  | 
 | 34 | +				value = cty.StringVal(pv.Value)  | 
 | 35 | +			} else {  | 
 | 36 | +				// get the default value  | 
 | 37 | +				value, defDiags = evaluateCoderParameterDefault(block)  | 
 | 38 | +				diags = diags.Extend(defDiags)  | 
 | 39 | +			}  | 
 | 40 | + | 
 | 41 | +			// Set the default value as the 'value' attribute  | 
 | 42 | +			path := []string{"data"}  | 
 | 43 | +			path = append(path, block.Labels()...)  | 
 | 44 | +			path = append(path, "value")  | 
 | 45 | +			// The current context is in the `coder_parameter` block.  | 
 | 46 | +			// Use the parent context to "export" the value  | 
 | 47 | +			ctx.Set(value, path...)  | 
 | 48 | +			//block.Context().Parent().Set(value, path...)  | 
 | 49 | +		}  | 
 | 50 | +	}  | 
 | 51 | +}  | 
 | 52 | + | 
 | 53 | +func evaluateCoderParameterDefault(b *terraform.Block) (cty.Value, hcl.Diagnostics) {  | 
 | 54 | +	//if b.Label() == "" {  | 
 | 55 | +	//	return cty.NilVal,  errors.New("empty label - cannot resolve")  | 
 | 56 | +	//}  | 
 | 57 | + | 
 | 58 | +	attributes := b.Attributes()  | 
 | 59 | +	if attributes == nil {  | 
 | 60 | +		r := b.HCLBlock().Body.MissingItemRange()  | 
 | 61 | +		return cty.NilVal, hcl.Diagnostics{  | 
 | 62 | +			{  | 
 | 63 | +				Severity: hcl.DiagWarning,  | 
 | 64 | +				Summary:  "'coder_parameter' block has no attributes",  | 
 | 65 | +				Detail:   "No default value will be set for this paramete",  | 
 | 66 | +				Subject:  &r,  | 
 | 67 | +			},  | 
 | 68 | +		}  | 
 | 69 | +	}  | 
 | 70 | + | 
 | 71 | +	var valType cty.Type  | 
 | 72 | +	var defaults *typeexpr.Defaults  | 
 | 73 | +	// TODO: `"string"` fails, it should be `string`  | 
 | 74 | +	typeAttr, exists := attributes["type"]  | 
 | 75 | +	if exists {  | 
 | 76 | +		ty, def, err := hclext.DecodeVarType(typeAttr.HCLAttribute().Expr)  | 
 | 77 | +		if err != nil {  | 
 | 78 | +			return cty.NilVal, hcl.Diagnostics{  | 
 | 79 | +				{  | 
 | 80 | +					Severity:    hcl.DiagWarning,  | 
 | 81 | +					Summary:     fmt.Sprintf("Decoding parameter type for %q", b.FullName()),  | 
 | 82 | +					Detail:      err.Error(),  | 
 | 83 | +					Subject:     &typeAttr.HCLAttribute().Range,  | 
 | 84 | +					Context:     &b.HCLBlock().DefRange,  | 
 | 85 | +					Expression:  typeAttr.HCLAttribute().Expr,  | 
 | 86 | +					EvalContext: b.Context().Inner(),  | 
 | 87 | +				},  | 
 | 88 | +			}  | 
 | 89 | +		}  | 
 | 90 | +		valType = ty  | 
 | 91 | +		defaults = def  | 
 | 92 | +	} else {  | 
 | 93 | +		// Default to string type  | 
 | 94 | +		valType = cty.String  | 
 | 95 | +	}  | 
 | 96 | + | 
 | 97 | +	var val cty.Value  | 
 | 98 | + | 
 | 99 | +	def, exists := attributes["default"]  | 
 | 100 | +	if exists {  | 
 | 101 | +		val = def.NullableValue()  | 
 | 102 | +	} else {  | 
 | 103 | +		return cty.NilVal, nil  | 
 | 104 | +	}  | 
 | 105 | + | 
 | 106 | +	if valType != cty.NilType {  | 
 | 107 | +		if defaults != nil {  | 
 | 108 | +			val = defaults.Apply(val)  | 
 | 109 | +		}  | 
 | 110 | + | 
 | 111 | +		typedVal, err := convert.Convert(val, valType)  | 
 | 112 | +		if err != nil {  | 
 | 113 | +			return cty.NilVal, hcl.Diagnostics{  | 
 | 114 | +				{  | 
 | 115 | +					Severity:    hcl.DiagWarning,  | 
 | 116 | +					Summary:     "Converting default parameter value type",  | 
 | 117 | +					Detail:      err.Error(),  | 
 | 118 | +					Subject:     &def.HCLAttribute().Range,  | 
 | 119 | +					Context:     &b.HCLBlock().DefRange,  | 
 | 120 | +					Expression:  def.HCLAttribute().Expr,  | 
 | 121 | +					EvalContext: b.Context().Inner(),  | 
 | 122 | +				},  | 
 | 123 | +			}  | 
 | 124 | +		}  | 
 | 125 | +		return typedVal, nil  | 
 | 126 | +	}  | 
 | 127 | + | 
 | 128 | +	return val, nil  | 
 | 129 | + | 
 | 130 | +}  | 
0 commit comments