Skip to content

Commit

Permalink
Minor changes to Expression
Browse files Browse the repository at this point in the history
* Add `Reference.AsExpression()` to not leak logic of string format;
* Fix wrong expression format in tests;
* Add `Expression.Eval(Blueprint)`;
* Add `Dict.Eval(Blueprint)`.
  • Loading branch information
mr0re1 committed Apr 19, 2023
1 parent 120f5d3 commit 485e8e9
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 2 deletions.
4 changes: 2 additions & 2 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ func (s *MySuite) TestCheckBackends(c *C) {

{ // FAIL. Variable in defaults configuration
b := TerraformBackend{Type: "gcs"}
b.Configuration.Set("bucket", MustParseExpression("((var.trenta))").AsValue())
b.Configuration.Set("bucket", Reference{GlobalVar: true, Name: "trenta"}.AsExpression().AsValue())
c.Check(check(b), ErrorMatches, ".*can not use variables.*")
}

Expand All @@ -1217,7 +1217,7 @@ func (s *MySuite) TestCheckBackends(c *C) {
Set("bucket", cty.StringVal("trenta")).
Set("complex", cty.ObjectVal(map[string]cty.Value{
"alpha": cty.StringVal("a"),
"beta": MustParseExpression("((var.boba))").AsValue(),
"beta": Reference{GlobalVar: true, Name: "boba"}.AsExpression().AsValue(),
}))
c.Check(check(b), ErrorMatches, ".*can not use variables.*")
}
Expand Down
19 changes: 19 additions & 0 deletions pkg/config/dict.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,22 @@ func (d Dict) MarshalYAML() (interface{}, error) {
}
return g, nil
}

// Eval returns a copy of this Dict, where all Expressions
// are evaluated and replaced by result of evaluation.
func (d Dict) Eval(bp Blueprint) (Dict, error) {
var res Dict
for k, v := range d.Items() {
r, err := cty.Transform(v, func(p cty.Path, v cty.Value) (cty.Value, error) {
if e, is := IsExpressionValue(v); is {
return e.Eval(bp)
}
return v, nil
})
if err != nil {
return Dict{}, fmt.Errorf("error while trying to evaluate %#v: %w", k, err)
}
res.Set(k, r)
}
return res, nil
}
25 changes: 25 additions & 0 deletions pkg/config/dict_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,28 @@ zebra: *passtime
t.Errorf("diff (-want +got):\n%s", diff)
}
}

func TestEval(t *testing.T) {
bp := Blueprint{
Vars: NewDict(map[string]cty.Value{
"zebra": cty.StringVal("stripes"),
}),
}
d := NewDict(map[string]cty.Value{
"abyss": cty.ObjectVal(map[string]cty.Value{
"white": Reference{GlobalVar: true, Name: "zebra"}.AsExpression().AsValue(),
"green": cty.StringVal("grass"),
})})
want := NewDict(map[string]cty.Value{
"abyss": cty.ObjectVal(map[string]cty.Value{
"white": cty.StringVal("stripes"),
"green": cty.StringVal("grass"),
})})
got, err := d.Eval(bp)
if err != nil {
t.Fatalf("failed to eval: %v", err)
}
if diff := cmp.Diff(want.Items(), got.Items(), ctydebug.CmpOptions); diff != "" {
t.Errorf("diff (-want +got):\n%s", diff)
}
}
20 changes: 20 additions & 0 deletions pkg/config/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ type Reference struct {
Name string // required
}

// AsExpression returns a expression that represents the reference
func (r Reference) AsExpression() Expression {
if r.GlobalVar {
return MustParseExpression(fmt.Sprintf("var.%s", r.Name))
}
return MustParseExpression(fmt.Sprintf("module.%s.%s", r.Module, r.Name))
}

// MakeStringInterpolationError generates an error message guiding the user to proper escape syntax
func MakeStringInterpolationError(s string) error {
matchall := anyVariableExp.FindAllString(s, -1)
Expand Down Expand Up @@ -177,6 +185,18 @@ func MustParseExpression(s string) Expression {
}
}

// Eval evaluates the expression in the context of Blueprint
func (e Expression) Eval(bp Blueprint) (cty.Value, error) {
ctx := hcl.EvalContext{
Variables: map[string]cty.Value{"var": bp.Vars.AsObject()},
}
v, diag := e.e.Value(&ctx)
if diag.HasErrors() {
return cty.NilVal, diag
}
return v, nil
}

// Tokenize returns Tokens to be used for marshalling HCL
func (e Expression) Tokenize() hclwrite.Tokens {
return hclwrite.TokensForIdentifier(e.s)
Expand Down

0 comments on commit 485e8e9

Please sign in to comment.