Repository: honeydipper/honeydipper
Pull request #247 (2020-05-20 00:32:58)

fix(workflow): truthy condition check should recognize <no value>
<!--
Thanks for contributing!

See https://github.com/honeydipper/honeydipper/blob/master/CODE_OF_CONDUCT.md for information on our contributor code of conduct, and https://github.com/honeydipper/honeydipper/tree/master/docs for more information on developing on Honeydipper.

If possible, please follow these guidelines for commit messages:
https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines

-->
#### Description
<!--
Add a description of your pull request.
-->

While testing the `deleteJob` function of `kubernetes` driver, I found out that the `until` condition check doesn't work.  It turns out that the undefined context variable presents as `<no value>` after interpolation. But, the condition check in the workflow engine doesn't recognize it and consider it as truey value.  This commit should fix it.

#### This PR fixes the following issues
<!--
Replace this comment with fixed issues in the following format:
Fixes #123
Fixes #124
-->



Patch:
diff --git a/internal/workflow/condition.go b/internal/workflow/condition.go
index 6b5d13d..692ef28 100644
--- a/internal/workflow/condition.go
+++ b/internal/workflow/condition.go
@@ -13,10 +13,10 @@ import (
 	"github.com/honeydipper/honeydipper/pkg/dipper"
 )
 
-// isTruey is a helper function to check if string represents Truey value
-func isTruey(c string) bool {
+// isTruthy is a helper function to check if string represents Truey value
+func isTruthy(c string) bool {
 	c = strings.ToLower(strings.TrimSpace(c))
-	return len(c) != 0 && c != "false" && c != "nil" && c != "0" && c != "{}" && c != "[]"
+	return len(c) != 0 && c != "false" && c != "nil" && c != "0" && c != "{}" && c != "[]" && c != "<no value>"
 }
 
 // checkCondition check if meet the condition to execute the workflow
@@ -24,28 +24,28 @@ func (w *Session) checkCondition() bool {
 	switch {
 	case len(w.workflow.If) > 0:
 		for _, c := range w.workflow.If {
-			if !isTruey(c) {
+			if !isTruthy(c) {
 				return false
 			}
 		}
 		return true
 	case len(w.workflow.IfAny) > 0:
 		for _, c := range w.workflow.IfAny {
-			if isTruey(c) {
+			if isTruthy(c) {
 				return true
 			}
 		}
 		return false
 	case len(w.workflow.Unless) > 0:
 		for _, c := range w.workflow.Unless {
-			if isTruey(c) {
+			if isTruthy(c) {
 				return false
 			}
 		}
 		return true
 	case len(w.workflow.UnlessAll) > 0:
 		for _, c := range w.workflow.UnlessAll {
-			if !isTruey(c) {
+			if !isTruthy(c) {
 				return true
 			}
 		}
@@ -79,7 +79,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 		envData := w.buildEnvData(msg)
 		for _, c := range w.workflow.While {
 			c = dipper.InterpolateStr(c, envData)
-			if !isTruey(c) {
+			if !isTruthy(c) {
 				return false
 			}
 		}
@@ -88,7 +88,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 		envData := w.buildEnvData(msg)
 		for _, c := range w.workflow.WhileAny {
 			c = dipper.InterpolateStr(c, envData)
-			if isTruey(c) {
+			if isTruthy(c) {
 				return true
 			}
 		}
@@ -97,7 +97,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 		envData := w.buildEnvData(msg)
 		for _, c := range w.workflow.Until {
 			c = dipper.InterpolateStr(c, envData)
-			if isTruey(c) {
+			if isTruthy(c) {
 				return false
 			}
 		}
@@ -106,7 +106,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 		envData := w.buildEnvData(msg)
 		for _, c := range w.workflow.UntilAll {
 			c = dipper.InterpolateStr(c, envData)
-			if !isTruey(c) {
+			if !isTruthy(c) {
 				return true
 			}
 		}


Test patch:
diff --git a/internal/workflow/condition_test.go b/internal/workflow/condition_test.go
index d4988d7..407c982 100644
--- a/internal/workflow/condition_test.go
+++ b/internal/workflow/condition_test.go
@@ -18,6 +18,10 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+func TestTruthyCheck(t *testing.T) {
+	assert.Falsef(t, isTruthy(dipper.InterpolateStr("{{ .something_undefined }}", map[string]interface{}{})), "interpolated <no value> should be false")
+}
+
 func TestConditionElse(t *testing.T) {
 	testcase := map[string]interface{}{
 		"workflow": &config.Workflow{If: []string{"false"}, Else: config.Workflow{CallDriver: "foo.bar"}},