Add support for marking sub workflows

This commit is contained in:
Denis Arh
2022-09-25 20:09:58 +02:00
parent 94b927c2bf
commit 769dfb085b
8 changed files with 148 additions and 28 deletions
+10 -9
View File
@@ -21,15 +21,16 @@ endpoints:
path: "/"
parameters:
get:
- { name: workflowID, type: "[]string", title: "Filter by workflow ID" }
- { name: query, type: "string", title: "Filter workflows" }
- { name: deleted, type: "uint", title: "Exclude (0, default), include (1) or return only (2) deleted workflows" }
- { name: disabled, type: "uint", title: "Exclude (0, default), include (1) or return only (2) disabled workflows" }
- { name: labels, type: "map[string]string", title: "Labels", parser: "label.ParseStrings" }
- { name: limit, type: "uint", title: "Limit" }
- { name: incTotal, type: "bool", title: "Include total rows counter" }
- { name: pageCursor, type: "string", title: "Page cursor" }
- { name: sort, type: "string", title: "Sort items" }
- { name: workflowID, type: "[]string", title: "Filter by workflow ID" }
- { name: query, type: "string", title: "Filter workflows" }
- { name: deleted, type: "uint", title: "Exclude (0, default), include (1) or return only (2) deleted workflows" }
- { name: disabled, type: "uint", title: "Exclude (0, default), include (1) or return only (2) disabled workflows" }
- { name: subWorkflow, type: "uint", title: "Exclude (0, default), include (1) or return only (2) sub workflows" }
- { name: labels, type: "map[string]string", title: "Labels", parser: "label.ParseStrings" }
- { name: limit, type: "uint", title: "Limit" }
- { name: incTotal, type: "bool", title: "Include total rows counter" }
- { name: pageCursor, type: "string", title: "Page cursor" }
- { name: sort, type: "string", title: "Sort items" }
- name: create
method: POST
title: Create workflow
+26 -9
View File
@@ -57,6 +57,11 @@ type (
// Exclude (0, default), include (1) or return only (2) disabled workflows
Disabled uint
// SubWorkflow GET parameter
//
// Exclude (0, default), include (1) or return only (2) sub workflows
SubWorkflow uint
// Labels GET parameter
//
// Labels
@@ -281,15 +286,16 @@ func NewWorkflowList() *WorkflowList {
// Auditable returns all auditable/loggable parameters
func (r WorkflowList) Auditable() map[string]interface{} {
return map[string]interface{}{
"workflowID": r.WorkflowID,
"query": r.Query,
"deleted": r.Deleted,
"disabled": r.Disabled,
"labels": r.Labels,
"limit": r.Limit,
"incTotal": r.IncTotal,
"pageCursor": r.PageCursor,
"sort": r.Sort,
"workflowID": r.WorkflowID,
"query": r.Query,
"deleted": r.Deleted,
"disabled": r.Disabled,
"subWorkflow": r.SubWorkflow,
"labels": r.Labels,
"limit": r.Limit,
"incTotal": r.IncTotal,
"pageCursor": r.PageCursor,
"sort": r.Sort,
}
}
@@ -313,6 +319,11 @@ func (r WorkflowList) GetDisabled() uint {
return r.Disabled
}
// Auditable returns all auditable/loggable parameters
func (r WorkflowList) GetSubWorkflow() uint {
return r.SubWorkflow
}
// Auditable returns all auditable/loggable parameters
func (r WorkflowList) GetLabels() map[string]string {
return r.Labels
@@ -374,6 +385,12 @@ func (r *WorkflowList) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := tmp["subWorkflow"]; ok && len(val) > 0 {
r.SubWorkflow, err = payload.ParseUint(val[0]), nil
if err != nil {
return err
}
}
if val, ok := tmp["labels[]"]; ok {
r.Labels, err = label.ParseStrings(val)
if err != nil {
+6 -5
View File
@@ -83,11 +83,12 @@ func (ctrl Workflow) List(ctx context.Context, r *request.WorkflowList) (interfa
var (
err error
f = types.WorkflowFilter{
WorkflowID: payload.ParseUint64s(r.WorkflowID),
Query: r.Query,
Labels: r.Labels,
Deleted: filter.State(r.Deleted),
Disabled: filter.State(r.Disabled),
WorkflowID: payload.ParseUint64s(r.WorkflowID),
Query: r.Query,
Labels: r.Labels,
Deleted: filter.State(r.Deleted),
Disabled: filter.State(r.Disabled),
SubWorkflow: filter.State(r.SubWorkflow),
}
)
+7
View File
@@ -712,6 +712,13 @@ func validateWorkflowTriggers(wf *types.Workflow, tt ...*types.Trigger) (wis typ
}
}
}
if wf.Meta != nil && wf.Meta.SubWorkflow {
wis = wis.Append(
errors.InvalidData("workflow marked as sub-workflow cannot have triggers"),
map[string]int{"trigger": i},
)
}
}
return
+52
View File
@@ -0,0 +1,52 @@
package service
import (
"github.com/cortezaproject/corteza-server/automation/types"
sysEvent "github.com/cortezaproject/corteza-server/system/service/event"
"github.com/stretchr/testify/require"
"testing"
)
func TestValidateWorkflowTriggersEmpty(t *testing.T) {
var (
req = require.New(t)
issues = validateWorkflowTriggers(
&types.Workflow{},
)
)
req.Empty(issues)
}
func TestValidateWorkflowTriggersRunAs(t *testing.T) {
var (
req = require.New(t)
soi = sysEvent.SystemOnInterval()
issues = validateWorkflowTriggers(
&types.Workflow{},
&types.Trigger{
Enabled: true,
ResourceType: soi.ResourceType(),
EventType: soi.EventType(),
},
)
)
req.Len(issues, 1)
req.Contains(issues[0].String(), "requires run-as to be set")
}
func TestValidateWorkflowTriggersSubWorkflow(t *testing.T) {
var (
req = require.New(t)
issues = validateWorkflowTriggers(
&types.Workflow{Meta: &types.WorkflowMeta{SubWorkflow: true}},
&types.Trigger{Enabled: true},
)
)
req.Len(issues, 1)
req.Contains(issues[0].String(), "marked as sub-workflow")
}
+7
View File
@@ -53,6 +53,9 @@ type (
Deleted filter.State `json:"deleted"`
Disabled filter.State `json:"disabled"`
// include sub-workflows
SubWorkflow filter.State `json:"subWorkflow"`
LabeledIDs []uint64 `json:"-"`
Labels map[string]string `json:"labels,omitempty"`
@@ -71,6 +74,10 @@ type (
Name string `json:"name"`
Description string `json:"description"`
Visual map[string]interface{} `json:"visual"`
// list as one of the sub-workflows, when set to true
// there should be no enabled triggers on this workflow
SubWorkflow bool `json:"subWorkflow,omitempty"`
}
WorkflowIssue struct {
+22
View File
@@ -2,6 +2,7 @@ package rdbms
import (
"fmt"
"github.com/cortezaproject/corteza-server/pkg/dal"
"strings"
"time"
@@ -304,6 +305,27 @@ func DefaultFilters() (f *extendedFilters) {
return ee, f, err
}
f.AutomationWorkflow = func(s *Store, f automationType.WorkflowFilter) (ee []goqu.Expression, _ automationType.WorkflowFilter, err error) {
if ee, f, err = AutomationWorkflowFilter(f); err != nil {
return
}
if f.SubWorkflow != filter.StateInclusive {
vattr := &dal.Attribute{Type: &dal.TypeBoolean{}}
litexp, _ := s.Dialect.DeepIdentJSON(goqu.C("meta"), "subWorkflow")
litexp, _ = s.Dialect.AttributeCast(vattr, litexp)
switch f.SubWorkflow {
case filter.StateExcluded:
ee = append(ee, goqu.Or(litexp.IsFalse(), litexp.IsNull()))
case filter.StateExclusive:
ee = append(ee, litexp.IsTrue())
}
}
return ee, f, err
}
return
}
+18 -5
View File
@@ -89,12 +89,17 @@ func testAutomationWorkflows(t *testing.T, s store.AutomationWorkflows) {
makeNew("two-one"),
makeNew("two-two"),
makeNew("two-deleted"),
func() *types.Workflow {
wf := makeNew("subwf")
wf.Meta = &types.WorkflowMeta{SubWorkflow: true}
return wf
}(),
}
count := len(prefill)
prefill[4].DeletedAt = &prefill[4].CreatedAt
valid := count - 1
valid := count - 2
req.NoError(s.TruncateAutomationWorkflows(ctx))
req.NoError(s.CreateAutomationWorkflow(ctx, prefill...))
@@ -102,12 +107,15 @@ func testAutomationWorkflows(t *testing.T, s store.AutomationWorkflows) {
// search for all valid
set, f, err := s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{})
req.NoError(err)
req.Len(set, valid) // we've deleted one
req.Len(set, valid) // all but deleted or workflows
// search for ALL
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{Deleted: filter.StateInclusive})
// search for ALL, including deleted and sub-workflows
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{
Deleted: filter.StateInclusive,
SubWorkflow: filter.StateInclusive,
})
req.NoError(err)
req.Len(set, count) // we've deleted one
req.Len(set, count)
// search for deleted only
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{Deleted: filter.StateExclusive})
@@ -119,6 +127,11 @@ func testAutomationWorkflows(t *testing.T, s store.AutomationWorkflows) {
req.NoError(err)
req.Len(set, 2)
// find just sub-workflows (one)
set, f, err = s.SearchAutomationWorkflows(ctx, types.WorkflowFilter{SubWorkflow: filter.StateExclusive})
req.NoError(err)
req.Len(set, 1)
_ = f // dummy
})
}