Skip to content
This repository was archived by the owner on Dec 2, 2025. It is now read-only.

Commit 24f9473

Browse files
author
parauliya
committed
Added testcases for template validations
Signed-off-by: parauliya <aman@infracloud.io>
1 parent 0678cbc commit 24f9473

File tree

9 files changed

+108
-95
lines changed

9 files changed

+108
-95
lines changed

cmd/tink-worker/action.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,13 @@ func executeAction(ctx context.Context, action *pb.WorkflowAction, wfID string)
4343
return pb.ActionState_ACTION_IN_PROGRESS, errors.Wrap(err, "DOCKER CREATE")
4444
}
4545
l.With("containerID", id, "command", action.GetOnTimeout()).Info("container created")
46-
47-
var timeCtx context.Context
48-
var cancel context.CancelFunc
46+
// Setting time context for action
47+
timeCtx := ctx
4948
if action.Timeout > 0 {
50-
timeCtx, cancel = context.WithTimeout(context.Background(), time.Duration(action.Timeout)*time.Second)
51-
} else {
52-
timeCtx, cancel = context.WithTimeout(context.Background(), 1*time.Hour)
49+
var cancel context.CancelFunc
50+
timeCtx, cancel = context.WithTimeout(ctx, time.Duration(action.Timeout)*time.Second)
51+
defer cancel()
5352
}
54-
defer cancel()
5553
err = startContainer(timeCtx, l, id)
5654
if err != nil {
5755
return pb.ActionState_ACTION_IN_PROGRESS, errors.Wrap(err, "DOCKER RUN")

db/mock/mock.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type DB struct {
2222
GetWorkflowActionsFunc func(ctx context.Context, wfID string) (*pb.WorkflowActionList, error)
2323
UpdateWorkflowStateFunc func(ctx context.Context, wfContext *pb.WorkflowContext) error
2424
InsertIntoWorkflowEventTableFunc func(ctx context.Context, wfEvent *pb.WorkflowActionStatus, time time.Time) error
25-
2625
// template
26+
TemplateDB map[string]interface{}
2727
GetTemplateFunc func(ctx context.Context, id string) (string, string, error)
2828
}

db/mock/template.go

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,26 @@ import (
88
"github.com/google/uuid"
99
)
1010

11-
type template struct {
12-
id uuid.UUID
13-
data string
11+
type Template struct {
12+
ID uuid.UUID
13+
Data string
1414
}
1515

16-
var templateDB = map[string]interface{}{}
17-
1816
// CreateTemplate creates a new workflow template
1917
func (d DB) CreateTemplate(ctx context.Context, name string, data string, id uuid.UUID) error {
20-
if len(templateDB) > 0 {
21-
if _, ok := templateDB[name]; ok {
22-
return errors.New("Template name already exist in the database")
23-
}
24-
templateDB[name] = template{
25-
id: id,
26-
data: data,
27-
}
18+
if d.TemplateDB == nil {
19+
d.TemplateDB = make(map[string]interface{})
20+
}
21+
22+
if _, ok := d.TemplateDB[name]; ok {
23+
return errors.New("Template name already exist in the database")
24+
}
2825

29-
} else {
30-
templateDB[name] = template{
31-
id: id,
32-
data: data,
33-
}
26+
d.TemplateDB[name] = Template{
27+
ID: id,
28+
Data: data,
3429
}
30+
3531
return nil
3632
}
3733

@@ -42,12 +38,10 @@ func (d DB) GetTemplate(ctx context.Context, id string) (string, string, error)
4238

4339
// DeleteTemplate deletes a workflow template
4440
func (d DB) DeleteTemplate(ctx context.Context, name string) error {
45-
if len(templateDB) > 0 {
46-
if _, ok := templateDB[name]; !ok {
47-
return errors.New("Template name does not exist")
48-
}
49-
delete(templateDB, name)
41+
if d.TemplateDB != nil {
42+
delete(d.TemplateDB, name)
5043
}
44+
5145
return nil
5246
}
5347

@@ -63,7 +57,5 @@ func (d DB) UpdateTemplate(ctx context.Context, name string, data string, id uui
6357

6458
// ClearTemplateDB clear all the templates
6559
func (d DB) ClearTemplateDB() {
66-
for name := range templateDB {
67-
delete(templateDB, name)
68-
}
60+
d.TemplateDB = make(map[string]interface{})
6961
}

db/template.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/golang/protobuf/ptypes/timestamp"
1010
"github.com/google/uuid"
1111
"github.com/pkg/errors"
12+
"github.com/tinkerbell/tink/pkg"
1213
)
1314

1415
// CreateTemplate creates a new workflow template
@@ -18,6 +19,15 @@ func (d TinkDB) CreateTemplate(ctx context.Context, name string, data string, id
1819
return errors.Wrap(err, "BEGIN transaction")
1920
}
2021

22+
wf, err := pkg.ParseYAML([]byte(data))
23+
if err != nil {
24+
return err
25+
}
26+
err = pkg.ValidateTemplate(wf)
27+
if err != nil {
28+
return err
29+
}
30+
2131
_, err = tx.Exec(`
2232
INSERT INTO
2333
template (created_at, updated_at, name, data, id)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ require (
3232
github.com/spf13/viper v1.4.0
3333
github.com/stretchr/testify v1.3.0
3434
go.mongodb.org/mongo-driver v1.1.2 // indirect
35+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
3536
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
3637
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect
3738
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect

grpc-server/template_test.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,23 @@ tasks:
2222
timeout: 60`
2323

2424
template2 = `version: "0.1"
25-
name: hello_world_workflow
25+
name: hello_world_again_workflow
2626
global_timeout: 600
2727
tasks:
2828
- name: "hello world again"
29-
worker: "{{.device_1}}"
29+
worker: "{{.device_2}}"
3030
actions:
31-
- name: "hello_world_again"
31+
- name: "hello_world_again"
3232
image: hello-world
3333
timeout: 60`
3434
)
3535

3636
func TestCreateTemplate(t *testing.T) {
3737
type (
3838
args struct {
39-
db mock.DB
40-
name []string
41-
templates []string
39+
db mock.DB
40+
name string
41+
template string
4242
}
4343
want struct {
4444
expectedError bool
@@ -50,9 +50,11 @@ func TestCreateTemplate(t *testing.T) {
5050
}{
5151
"SuccessfullTemplateCreation": {
5252
args: args{
53-
db: mock.DB{},
54-
name: []string{"template_1"},
55-
templates: []string{template1},
53+
db: mock.DB{
54+
TemplateDB: make(map[string]interface{}),
55+
},
56+
name: "template_1",
57+
template: template1,
5658
},
5759
want: want{
5860
expectedError: false,
@@ -61,9 +63,13 @@ func TestCreateTemplate(t *testing.T) {
6163

6264
"SuccessfullMultipleTemplateCreation": {
6365
args: args{
64-
db: mock.DB{},
65-
name: []string{"template_1", "template_2"},
66-
templates: []string{template1, template2},
66+
db: mock.DB{
67+
TemplateDB: map[string]interface{}{
68+
"template_1": template1,
69+
},
70+
},
71+
name: "template_2",
72+
template: template2,
6773
},
6874
want: want{
6975
expectedError: false,
@@ -72,35 +78,31 @@ func TestCreateTemplate(t *testing.T) {
7278

7379
"FailedMultipleTemplateCreationWithSameName": {
7480
args: args{
75-
db: mock.DB{},
76-
name: []string{"template_1", "template_1"},
77-
templates: []string{template1, template2},
81+
db: mock.DB{
82+
TemplateDB: map[string]interface{}{
83+
"template_1": template1,
84+
},
85+
},
86+
name: "template_1",
87+
template: template2,
7888
},
7989
want: want{
8090
expectedError: true,
8191
},
8292
},
8393
}
84-
for name, tc := range testCases {
94+
95+
for name := range testCases {
96+
tc := testCases[name]
8597
t.Run(name, func(t *testing.T) {
98+
t.Parallel()
8699
s := testServer(tc.args.db)
87-
tc.args.db.ClearTemplateDB()
88-
index := 0
89-
res, err := s.CreateTemplate(context.TODO(), &pb.WorkflowTemplate{Name: tc.args.name[index], Data: tc.args.templates[index]})
90-
assert.Nil(t, err)
91-
assert.NotNil(t, res)
92-
if err == nil && len(tc.args.templates) > 1 {
93-
index++
94-
_, err = s.CreateTemplate(context.TODO(), &pb.WorkflowTemplate{Name: tc.args.name[index], Data: tc.args.templates[index]})
95-
} else {
96-
return
97-
}
98-
if err != nil {
100+
res, err := s.CreateTemplate(context.TODO(), &pb.WorkflowTemplate{Name: tc.args.name, Data: tc.args.template})
101+
if tc.want.expectedError {
99102
assert.Error(t, err)
100-
assert.True(t, tc.want.expectedError)
101103
} else {
102104
assert.Nil(t, err)
103-
assert.False(t, tc.want.expectedError)
105+
assert.NotEmpty(t, res)
104106
}
105107
})
106108
}

grpc-server/workflow_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ func TestCreateWorkflow(t *testing.T) {
9393

9494
for name, tc := range testCases {
9595
t.Run(name, func(t *testing.T) {
96+
t.Parallel()
9697
s := testServer(tc.args.db)
9798
res, err := s.CreateWorkflow(context.TODO(), &workflow.CreateRequest{
9899
Hardware: tc.args.wfHardware,

pkg/template_validator.go

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package pkg
22

33
import (
4-
"fmt"
5-
64
"github.com/docker/distribution/reference"
5+
"github.com/pkg/errors"
76
"gopkg.in/yaml.v2"
87
)
98

109
const (
11-
errEmptyName = "task/action name cannot be empty: %v"
12-
errInvalidLength = "task/action name cannot have more than 200 characters: %v"
13-
errDuplicateTaskName = "two tasks in a template cannot have same name: %v"
14-
errInvalidActionImage = "invalid action image: %v"
15-
errDuplicateActionName = "two actions in a task cannot have same name: %v"
10+
errEmptyName = "task/action name cannot be empty: "
11+
errInvalidLength = "task/action name cannot have more than 200 characters: "
12+
errDuplicateTaskName = "two tasks in a template cannot have same name: "
13+
errInvalidActionImage = "invalid action image: "
14+
errDuplicateActionName = "two actions in a task cannot have same name: "
1615
)
1716

1817
// ParseYAML parses the template yaml content
@@ -30,50 +29,49 @@ func ParseYAML(yamlContent []byte) (*Workflow, error) {
3029
func ValidateTemplate(wf *Workflow) error {
3130
taskNameMap := make(map[string]struct{})
3231
for _, task := range wf.Tasks {
33-
err := hasValidLength(task.Name)
34-
if err != nil {
35-
return err
32+
if hasEmptyName(task.Name) {
33+
return errors.New(errEmptyName + task.Name)
34+
}
35+
if !hasValidLength(task.Name) {
36+
return errors.New(errInvalidLength + task.Name)
3637
}
3738
_, ok := taskNameMap[task.Name]
3839
if ok {
39-
return fmt.Errorf(errDuplicateTaskName, task.Name)
40+
return errors.New(errDuplicateTaskName + task.Name)
4041
}
4142
taskNameMap[task.Name] = struct{}{}
4243
actionNameMap := make(map[string]struct{})
4344
for _, action := range task.Actions {
44-
err := hasValidLength(action.Name)
45-
if err != nil {
46-
return err
45+
if hasEmptyName(action.Name) {
46+
return errors.New(errEmptyName + action.Name)
47+
}
48+
49+
if !hasValidLength(action.Name) {
50+
return errors.New(errInvalidLength + action.Name)
4751
}
48-
err = isValidImageName(action.Image)
49-
if err != nil {
50-
return fmt.Errorf(errInvalidActionImage, action.Image)
52+
53+
if !hasValidImageName(action.Image) {
54+
return errors.New(errInvalidActionImage + action.Image)
5155
}
5256

5357
_, ok := actionNameMap[action.Name]
5458
if ok {
55-
return fmt.Errorf(errDuplicateActionName, action.Name)
59+
return errors.New(errDuplicateActionName + action.Name)
5660
}
5761
actionNameMap[action.Name] = struct{}{}
5862
}
5963
}
6064
return nil
6165
}
6266

63-
func hasValidLength(name string) error {
64-
if name == "" {
65-
return fmt.Errorf(errEmptyName, name)
66-
}
67-
if len(name) > 200 {
68-
return fmt.Errorf(errInvalidLength, name)
69-
}
70-
return nil
67+
func hasEmptyName(name string) bool {
68+
return name == ""
69+
}
70+
func hasValidLength(name string) bool {
71+
return len(name) < 200
7172
}
7273

73-
func isValidImageName(name string) error {
74+
func hasValidImageName(name string) bool {
7475
_, err := reference.ParseNormalizedNamed(name)
75-
if err != nil {
76-
return err
77-
}
78-
return nil
76+
return err == nil
7977
}

pkg/template_validator_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ func TestValidateTemplate(t *testing.T) {
9797
wf: workflow(withDuplicateActionName()),
9898
expectedError: true,
9999
},
100+
{
101+
name: "long action name",
102+
wf: workflow(withLongActionName()),
103+
expectedError: true,
104+
},
100105
{
101106
name: "valid task name",
102107
wf: workflow(),
@@ -122,6 +127,12 @@ func withLongTaskName() workflowModifier {
122127
}
123128
}
124129

130+
func withLongActionName() workflowModifier {
131+
return func(wf *Workflow) {
132+
wf.Tasks[0].Actions[0].Name = "this action has a very long name to test whether we recevice an error or not if an action has very long name, one that would probably go beyond the limit of not having an action name with more than two hundred characters"
133+
}
134+
}
135+
125136
func withInvalidTaskName() workflowModifier {
126137
return func(wf *Workflow) { wf.Tasks[0].Name = "" }
127138
}

0 commit comments

Comments
 (0)