Skip to content

Commit

Permalink
Merge branch 'main' into feat/arm-arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
jaspervdj-snyk committed Jun 29, 2023
2 parents c3c9637 + 0a06e6b commit 890836d
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 38 deletions.
3 changes: 3 additions & 0 deletions changes/unreleased/Changed-20230628-174616.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Changed
body: 'refactor: arm EvaluationContext'
time: 2023-06-28T17:46:16.926549028+02:00
6 changes: 5 additions & 1 deletion pkg/input/arm.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,11 @@ func (l *armConfiguration) process() {
resourceSet[id] = struct{}{}
}
exprEvaluator := expressionEvaluator{
evalCtx: arm.NewEvaluationContext(resourceSet, l.variables),
evalCtx: &arm.EvaluationContext{
DiscoveredResourceSet: resourceSet,
Variables: l.variables,
Functions: arm.BuiltinFunctions(),
},
}

// Process resources
Expand Down
31 changes: 13 additions & 18 deletions pkg/input/arm/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,20 @@ import (
// references to implementations of functions, and the other fields exist to
// pass data to certain function impls other than what is already in their args.
type EvaluationContext struct {
discoveredResourceSet map[string]struct{}
variables map[string]interface{}
funcs map[string]armFnImpl
DiscoveredResourceSet map[string]struct{}
Variables map[string]interface{}
Functions map[string]Function
}

func NewEvaluationContext(discoveredResourceSet map[string]struct{}, variables map[string]interface{}) *EvaluationContext {
evalCtx := &EvaluationContext{
discoveredResourceSet: discoveredResourceSet,
variables: variables,
funcs: map[string]armFnImpl{
"concat": concatImpl,
"resourceGroup": resourceGroupImpl,
},
type Function func(e *EvaluationContext, args ...interface{}) (interface{}, error)

func BuiltinFunctions() map[string]Function {
return map[string]Function{
"concat": concatImpl,
"resourceGroup": resourceGroupImpl,
"resourceId": resourceIDImpl,
"variables": variablesImpl,
}
evalCtx.funcs["resourceId"] = evalCtx.resourceIDImpl
evalCtx.funcs["variables"] = evalCtx.variablesImpl
return evalCtx
}

// Detects whether an ARM string is an expression (enclosed by []), and
Expand Down Expand Up @@ -74,7 +71,7 @@ func extractAndEscapeTemplateString(input string) string {
)
}

func (e EvaluationContext) eval(input string) (interface{}, error) {
func (e *EvaluationContext) eval(input string) (interface{}, error) {
tokens, err := tokenize(input)
if err != nil {
return nil, err
Expand All @@ -86,8 +83,6 @@ func (e EvaluationContext) eval(input string) (interface{}, error) {
return e.evalExpr(expr)
}

func (e EvaluationContext) evalExpr(expr expression) (interface{}, error) {
func (e *EvaluationContext) evalExpr(expr expression) (interface{}, error) {
return expr.eval(e)
}

type armFnImpl func(args ...interface{}) (interface{}, error)
2 changes: 1 addition & 1 deletion pkg/input/arm/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestEvalTemplateStrings(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
evalCtx := NewEvaluationContext(nil, nil)
evalCtx := &EvaluationContext{Functions: BuiltinFunctions()}
val, err := evalCtx.EvaluateTemplateString(tc.input)
require.NoError(t, err)
require.Equal(t, tc.expected, val)
Expand Down
14 changes: 7 additions & 7 deletions pkg/input/arm/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import (
)

type expression interface {
eval(evalCtx EvaluationContext) (interface{}, error)
eval(evalCtx *EvaluationContext) (interface{}, error)
}

type stringLiteralExpr string

func (s stringLiteralExpr) eval(evalCtx EvaluationContext) (interface{}, error) {
func (s stringLiteralExpr) eval(evalCtx *EvaluationContext) (interface{}, error) {
return string(s), nil
}

Expand All @@ -34,8 +34,8 @@ type functionExpr struct {
args []expression
}

func (f functionExpr) eval(evalCtx EvaluationContext) (interface{}, error) {
impl, ok := evalCtx.funcs[f.name]
func (f functionExpr) eval(evalCtx *EvaluationContext) (interface{}, error) {
impl, ok := evalCtx.Functions[f.name]
if !ok {
return nil, Error{underlying: fmt.Errorf("unsupported function: %s", f.name), kind: UnsupportedFunction}
}
Expand All @@ -48,15 +48,15 @@ func (f functionExpr) eval(evalCtx EvaluationContext) (interface{}, error) {
return nil, Error{underlying: err, kind: EvalError}
}
}
return impl(argVals...)
return impl(evalCtx, argVals...)
}

type propertyExpr struct {
obj expression
property string
}

func (p propertyExpr) eval(evalCtx EvaluationContext) (interface{}, error) {
func (p propertyExpr) eval(evalCtx *EvaluationContext) (interface{}, error) {
obj, err := p.obj.eval(evalCtx)
if err != nil {
return nil, err
Expand All @@ -81,7 +81,7 @@ func makePropertyExpr(e expression, properties []string) expression {

type arrayExpr []expression

func (e arrayExpr) eval(evalCtx EvaluationContext) (interface{}, error) {
func (e arrayExpr) eval(evalCtx *EvaluationContext) (interface{}, error) {
vals := []interface{}{}
for _, expr := range e {
val, err := expr.eval(evalCtx)
Expand Down
12 changes: 6 additions & 6 deletions pkg/input/arm/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var resourceTypePattern = regexp.MustCompile(`^Microsoft\.\w+[/\w]*$`)

// Note that concat can operate on arrays too, we just haven't implemented
// support for this yet.
func concatImpl(args ...interface{}) (interface{}, error) {
func concatImpl(e *EvaluationContext, args ...interface{}) (interface{}, error) {
res := ""
for _, arg := range args {
argStr, ok := arg.(string)
Expand All @@ -41,7 +41,7 @@ func concatImpl(args ...interface{}) (interface{}, error) {

// Return a stub
// https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-scope#resourcegroup
func resourceGroupImpl(args ...interface{}) (interface{}, error) {
func resourceGroupImpl(e *EvaluationContext, args ...interface{}) (interface{}, error) {
if len(args) != 0 {
return nil, fmt.Errorf("expected zero args to resourceGroup(), got %d", len(args))
}
Expand All @@ -58,7 +58,7 @@ func resourceGroupImpl(args ...interface{}) (interface{}, error) {
}

// https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource#resourceid
func (e *EvaluationContext) resourceIDImpl(args ...interface{}) (interface{}, error) {
func resourceIDImpl(e *EvaluationContext, args ...interface{}) (interface{}, error) {
strargs, err := assertAllStrings(args...)
if err != nil {
return nil, err
Expand All @@ -74,7 +74,7 @@ func (e *EvaluationContext) resourceIDImpl(args ...interface{}) (interface{}, er

// Normalize resource IDs to declared/discovered ones in the input, so that
// these can be associated with each other by policy queries.
if _, ok := e.discoveredResourceSet[resourceID]; ok {
if _, ok := e.DiscoveredResourceSet[resourceID]; ok {
return resourceID, nil
}

Expand Down Expand Up @@ -171,7 +171,7 @@ func assertAllStrings(args ...interface{}) ([]string, error) {
return strargs, nil
}

func (e *EvaluationContext) variablesImpl(args ...interface{}) (interface{}, error) {
func variablesImpl(e *EvaluationContext, args ...interface{}) (interface{}, error) {
strargs, err := assertAllStrings(args...)
if err != nil {
return nil, err
Expand All @@ -180,7 +180,7 @@ func (e *EvaluationContext) variablesImpl(args ...interface{}) (interface{}, err
return nil, fmt.Errorf("variables: expected 1 arg, got %d", len(strargs))
}
key := strargs[0]
val, ok := e.variables[key]
val, ok := e.Variables[key]
if !ok {
return nil, fmt.Errorf("no variable found for key %s", key)
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/input/arm/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import (
"github.com/stretchr/testify/require"
)

var evalCtx = NewEvaluationContext(
map[string]struct{}{
var evalCtx = &EvaluationContext{
DiscoveredResourceSet: map[string]struct{}{
"Microsoft.ServiceBus/namespaces/a-discovered-namespace": {},
},
nil,
)
Functions: BuiltinFunctions(),
}

func TestResourceIDImpl(t *testing.T) {
for _, tc := range []struct {
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestResourceIDImpl(t *testing.T) {
},
} {
t.Run(tc.name, func(t *testing.T) {
output, err := evalCtx.resourceIDImpl(tc.args...)
output, err := resourceIDImpl(evalCtx, tc.args...)
require.NoError(t, err)
require.Equal(t, tc.expectedOutput, output)
})
Expand Down

0 comments on commit 890836d

Please sign in to comment.