From b5ff387e89a673742ed46fca0f16b0d1e3eaa374 Mon Sep 17 00:00:00 2001 From: Katrina Rogan Date: Fri, 18 Sep 2020 12:07:52 -0700 Subject: [PATCH] validate --- pkg/compiler/errors/compiler_error_test.go | 3 ++- pkg/compiler/errors/compiler_errors.go | 11 ++++++++++ pkg/compiler/workflow_compiler.go | 5 +++++ pkg/compiler/workflow_compiler_test.go | 24 ++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/pkg/compiler/errors/compiler_error_test.go b/pkg/compiler/errors/compiler_error_test.go index a3d1eb755..5a993aeff 100644 --- a/pkg/compiler/errors/compiler_error_test.go +++ b/pkg/compiler/errors/compiler_error_test.go @@ -32,6 +32,7 @@ func TestErrorCodes(t *testing.T) { UnreachableNodes: NewUnreachableNodesErr("", ""), UnrecognizedValue: NewUnrecognizedValueErr("", ""), WorkflowBuildError: NewWorkflowBuildError(errors.New("")), + NoNodesFound: NewNoNodesFoundErr(""), } for key, value := range testCases { @@ -47,6 +48,6 @@ func TestIncludeSource(t *testing.T) { SetConfig(Config{IncludeSource: true}) e = NewCycleDetectedInWorkflowErr("", "") - assert.Equal(t, e.source, "compiler_error_test.go:49") + assert.Equal(t, e.source, "compiler_error_test.go:50") SetConfig(Config{}) } diff --git a/pkg/compiler/errors/compiler_errors.go b/pkg/compiler/errors/compiler_errors.go index 86236c894..115f4d09b 100755 --- a/pkg/compiler/errors/compiler_errors.go +++ b/pkg/compiler/errors/compiler_errors.go @@ -72,6 +72,9 @@ const ( // A value isn't on the right syntax. SyntaxError ErrorCode = "SyntaxError" + + // A workflow is missing any nodes to execute + NoNodesFound ErrorCode = "NoNodesFound" ) func NewBranchNodeNotSpecified(branchNodeID string) *CompileError { @@ -246,6 +249,14 @@ func NewSyntaxError(nodeID string, element string, err error) *CompileError { ) } +func NewNoNodesFoundErr(graphID string) *CompileError { + return newError( + NoNodesFound, + fmt.Sprintf("Can't find any nodes in workflow [%v].", graphID), + graphID, + ) +} + func newError(code ErrorCode, description, nodeID string) (err *CompileError) { err = &CompileError{ code: code, diff --git a/pkg/compiler/workflow_compiler.go b/pkg/compiler/workflow_compiler.go index c8c8ddfb4..9ce69e7bf 100755 --- a/pkg/compiler/workflow_compiler.go +++ b/pkg/compiler/workflow_compiler.go @@ -148,6 +148,11 @@ func (w workflowBuilder) AddEdges(n c.NodeBuilder, errs errors.CompileErrors) (o // Contains the main validation logic for the coreWorkflow. If successful, it'll build an executable Workflow. func (w workflowBuilder) ValidateWorkflow(fg *flyteWorkflow, errs errors.CompileErrors) (c.Workflow, bool) { + if len(fg.Template.Nodes) == 0 { + errs.Collect(errors.NewNoNodesFoundErr(fg.Template.Id.String())) + return nil, !errs.HasErrors() + } + // Initialize workflow wf := w.newWorkflowBuilder(fg) wf.updateRequiredReferences() diff --git a/pkg/compiler/workflow_compiler_test.go b/pkg/compiler/workflow_compiler_test.go index 259f8ec1b..485768180 100755 --- a/pkg/compiler/workflow_compiler_test.go +++ b/pkg/compiler/workflow_compiler_test.go @@ -631,6 +631,30 @@ func TestCompileWorkflow(t *testing.T) { } } +func TestNoNodesFound(t *testing.T) { + inputWorkflow := &core.WorkflowTemplate{ + Id: &core.Identifier{Name: "repo"}, + Interface: &core.TypedInterface{ + Inputs: createVariableMap(map[string]*core.Variable{ + "x": { + Type: getIntegerLiteralType(), + }, + }), + Outputs: createVariableMap(map[string]*core.Variable{ + "x": { + Type: getIntegerLiteralType(), + }, + }), + }, + Nodes: []*core.Node{}, + Outputs: []*core.Binding{newVarBinding("node_456", "x", "x")}, + } + + _, errs := CompileWorkflow(inputWorkflow, []*core.WorkflowTemplate{}, + mustCompileTasks(make([]*core.TaskTemplate, 0)), []common.InterfaceProvider{}) + assert.Contains(t, errs.Error(), errors.NoNodesFound) +} + func mustCompileTasks(tasks []*core.TaskTemplate) []*core.CompiledTask { res := make([]*core.CompiledTask, 0, len(tasks)) for _, t := range tasks {