Skip to content

Commit

Permalink
Added unhandled body concept for Notify block.
Browse files Browse the repository at this point in the history
  • Loading branch information
vhadianto committed Oct 21, 2023
1 parent 111ba9f commit 390176a
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 67 deletions.
38 changes: 19 additions & 19 deletions modconfig/flowpipe_pipeline_step.go
Original file line number Diff line number Diff line change
Expand Up @@ -2789,24 +2789,23 @@ func (p *PipelineStepBase) HandleDecodeBodyDiags(diags hcl.Diagnostics, attribut
for _, e := range diags {
if e.Severity == hcl.DiagError {
if e.Detail == `There is no variable named "step".` {
// traversals := expr.Variables()
// dependsOnAdded := false
// for _, traversal := range traversals {
// parts := hclhelpers.TraversalAsStringSlice(traversal)
// if len(parts) > 0 {
// // When the expression/traversal is referencing an index, the index is also included in the parts
// // for example: []string len: 5, cap: 5, ["step","sleep","sleep_1","0","duration"]
// if parts[0] == schema.BlockTypePipelineStep {
// dependsOn := parts[1] + "." + parts[2]
// p.AppendDependsOn(dependsOn)
// dependsOnAdded = true
// }
// }
// }
// if dependsOnAdded {
// resolvedDiags++
// }
resolvedDiags++
traversals := e.Expression.Variables()
dependsOnAdded := false
for _, traversal := range traversals {
parts := hclhelpers.TraversalAsStringSlice(traversal)
if len(parts) > 0 {
// When the expression/traversal is referencing an index, the index is also included in the parts
// for example: []string len: 5, cap: 5, ["step","sleep","sleep_1","0","duration"]
if parts[0] == schema.BlockTypePipelineStep {
dependsOn := parts[1] + "." + parts[2]
p.AppendDependsOn(dependsOn)
dependsOnAdded = true
}
}
}
if dependsOnAdded {
resolvedDiags++
}
} else if e.Detail == `There is no variable named "each".` || e.Detail == `There is no variable named "param".` || e.Detail == "Unsuitable value: value must be known" {
// hcl.decodeBody returns 2 error messages:
// 1. There's no variable named "param", AND
Expand All @@ -2822,10 +2821,11 @@ func (p *PipelineStepBase) HandleDecodeBodyDiags(diags hcl.Diagnostics, attribut
if resolvedDiags == len(diags) {

// * Don't forget to add this, if you change the logic ensure that the code flow still
// * calls AddUnresolvedAttribute
// * calls AddUnresolvedBody
p.AddUnresolvedBody(attributeName, body)
return hcl.Diagnostics{}
}

// There's an error here
return diags

Expand Down
33 changes: 31 additions & 2 deletions modconfig/flowpipe_trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,22 @@ func (t *TriggerSchedule) SetAttributes(mod *Mod, trigger *Trigger, hclAttribute
for name, attr := range hclAttributes {
switch name {
case schema.AttributeTypeSchedule:
val, _ := attr.Expr.Value(nil)
val, moreDiags := attr.Expr.Value(evalContext)
if len(moreDiags) > 0 {
diags = append(diags, moreDiags...)
continue
}

if val.Type() != cty.String {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "The given schedule is not a string",
Detail: "The given schedule is not a string",
Subject: &attr.Range,
})
continue
}

t.Schedule = val.AsString()

// validate cron format
Expand Down Expand Up @@ -225,7 +240,21 @@ func (t *TriggerInterval) SetAttributes(mod *Mod, trigger *Trigger, hclAttribute
for name, attr := range hclAttributes {
switch name {
case schema.AttributeTypeSchedule:
val, _ := attr.Expr.Value(evalContext)
val, moreDiags := attr.Expr.Value(evalContext)
if len(moreDiags) > 0 {
diags = append(diags, moreDiags...)
continue
}

if val.Type() != cty.String {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "The given interval is not a string",
Detail: "The given interval is not a string",
Subject: &attr.Range,
})
continue
}
t.Schedule = val.AsString()

if !helpers.StringSliceContains(validIntervals, strings.ToLower(t.Schedule)) {
Expand Down
48 changes: 48 additions & 0 deletions modconfig/parsed_property_path.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
package modconfig

import (
"fmt"
"strings"

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/turbot/pipe-fittings/hclhelpers"
"github.com/turbot/pipe-fittings/perr"
"github.com/turbot/pipe-fittings/schema"
)

func PropertyPathFromExpression(expr hcl.Expression) (bool, *ParsedPropertyPath, error) {
var propertyPathStr string
var isArray bool

dep_loop:
for {
switch e := expr.(type) {
case *hclsyntax.ScopeTraversalExpr:
propertyPathStr = hclhelpers.TraversalAsString(e.Traversal)
break dep_loop
case *hclsyntax.SplatExpr:
root := hclhelpers.TraversalAsString(e.Source.(*hclsyntax.ScopeTraversalExpr).Traversal)
var suffix string
// if there is a property path, add it
if each, ok := e.Each.(*hclsyntax.RelativeTraversalExpr); ok {
suffix = fmt.Sprintf(".%s", hclhelpers.TraversalAsString(each.Traversal))
}
propertyPathStr = fmt.Sprintf("%s.*%s", root, suffix)
break dep_loop
case *hclsyntax.TupleConsExpr:
// TACTICAL
// handle the case where an arg value is given as a runtime dependency inside an array, for example
// arns = [input.arn]
// this is a common pattern where a runtime depdency gives a scalar value, but an array is needed for the arg
// NOTE: this code only supports a SINGLE item in the array
if len(e.Exprs) != 1 {
return false, nil, fmt.Errorf("unsupported runtime dependency expression - only a single runtime depdency item may be wrapped in an array")
}
isArray = true
expr = e.Exprs[0]
// fall through to rerun loop with updated expr
default:
// unhandled expression type
return false, nil, fmt.Errorf("unexpected runtime dependency expression type")
}
}

propertyPath, err := ParseResourcePropertyPath(propertyPathStr)
if err != nil {
return false, nil, err
}
return isArray, propertyPath, nil
}

type ParsedPropertyPath struct {
Mod string
ItemType string
Expand Down
48 changes: 2 additions & 46 deletions parse/decode_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func identifyRuntimeDependenciesFromObject(attr *hcl.Attribute, targetProperty,
}

func getRuntimeDepFromExpression(expr hcl.Expression, targetProperty, parentProperty string) (*modconfig.RuntimeDependency, error) {
isArray, propertyPath, err := propertyPathFromExpression(expr)
isArray, propertyPath, err := modconfig.PropertyPathFromExpression(expr)
if err != nil {
return nil, err
}
Expand All @@ -199,50 +199,6 @@ func getRuntimeDepFromExpression(expr hcl.Expression, targetProperty, parentProp
return ret, nil
}

func propertyPathFromExpression(expr hcl.Expression) (bool, *modconfig.ParsedPropertyPath, error) {
var propertyPathStr string
var isArray bool

dep_loop:
for {
switch e := expr.(type) {
case *hclsyntax.ScopeTraversalExpr:
propertyPathStr = hclhelpers.TraversalAsString(e.Traversal)
break dep_loop
case *hclsyntax.SplatExpr:
root := hclhelpers.TraversalAsString(e.Source.(*hclsyntax.ScopeTraversalExpr).Traversal)
var suffix string
// if there is a property path, add it
if each, ok := e.Each.(*hclsyntax.RelativeTraversalExpr); ok {
suffix = fmt.Sprintf(".%s", hclhelpers.TraversalAsString(each.Traversal))
}
propertyPathStr = fmt.Sprintf("%s.*%s", root, suffix)
break dep_loop
case *hclsyntax.TupleConsExpr:
// TACTICAL
// handle the case where an arg value is given as a runtime dependency inside an array, for example
// arns = [input.arn]
// this is a common pattern where a runtime depdency gives a scalar value, but an array is needed for the arg
// NOTE: this code only supports a SINGLE item in the array
if len(e.Exprs) != 1 {
return false, nil, fmt.Errorf("unsupported runtime dependency expression - only a single runtime depdency item may be wrapped in an array")
}
isArray = true
expr = e.Exprs[0]
// fall through to rerun loop with updated expr
default:
// unhandled expression type
return false, nil, fmt.Errorf("unexpected runtime dependency expression type")
}
}

propertyPath, err := modconfig.ParseResourcePropertyPath(propertyPathStr)
if err != nil {
return false, nil, err
}
return isArray, propertyPath, nil
}

func identifyRuntimeDependenciesFromArray(attr *hcl.Attribute, idx int, parentProperty string) (*modconfig.RuntimeDependency, error) {
// find the expression for this key
argsExpr, ok := attr.Expr.(*hclsyntax.TupleConsExpr)
Expand All @@ -251,7 +207,7 @@ func identifyRuntimeDependenciesFromArray(attr *hcl.Attribute, idx int, parentPr
}
for i, item := range argsExpr.Exprs {
if i == idx {
isArray, propertyPath, err := propertyPathFromExpression(item)
isArray, propertyPath, err := modconfig.PropertyPathFromExpression(item)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 390176a

Please sign in to comment.