Skip to content

Commit ef275f5

Browse files
committed
fix(TestRun): if spec.arguments is invalid, pass error and stop reconciliation
1 parent 8946b35 commit ef275f5

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-11
lines changed

api/v1alpha1/testrun_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ func init() {
205205
SchemeBuilder.Register(&TestRun{}, &TestRunList{})
206206
}
207207

208+
func (k6 *TestRunSpec) Validate() error {
209+
// Currently, we validate "manually" only arguments field.
210+
_, err := types.ParseCLI(k6.Arguments)
211+
return err
212+
}
213+
208214
// Parse extracts Script data bits from K6 spec and performs basic validation
209215
func (k6 TestRunSpec) ParseScript() (*types.Script, error) {
210216
spec := k6.Script

internal/controller/k6_initialize.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ func InitializeJobs(ctx context.Context, log logr.Logger, k6 *v1alpha1.TestRun,
2121
// initializer is a quick job so check in frequently
2222
res = ctrl.Result{RequeueAfter: time.Second * 5}
2323

24-
cli := types.ParseCLI(k6.GetSpec().Arguments)
24+
// validation has already happened, so error here can be ignored
25+
cli, _ := types.ParseCLI(k6.GetSpec().Arguments)
2526

2627
var initializer *batchv1.Job
2728
if initializer, err = jobs.NewInitializerJob(k6, cli.ArchiveArgs); err != nil {
@@ -50,7 +51,8 @@ func RunValidations(ctx context.Context, log logr.Logger, k6 *v1alpha1.TestRun,
5051
// initializer is a quick job so check in frequently
5152
res = ctrl.Result{RequeueAfter: time.Second * 5}
5253

53-
cli := types.ParseCLI(k6.GetSpec().Arguments)
54+
// validation has already happened, so error here can be ignored
55+
cli, _ := types.ParseCLI(k6.GetSpec().Arguments)
5456

5557
inspectOutput, inspectReady, err := inspectTestRun(ctx, log, k6, r.Client)
5658
if err != nil {
@@ -63,7 +65,7 @@ func RunValidations(ctx context.Context, log logr.Logger, k6 *v1alpha1.TestRun,
6365
WithAbort()
6466
cloud.SendTestRunEvents(r.k6CloudClient, k6.TestRunID(), log, events)
6567
} else {
66-
// if there is any error, we have to reflect it on the K6 manifest
68+
// if there is any error, we have to reflect it on the TestRun manifest
6769
k6.GetStatus().Stage = "error"
6870
if _, err := r.UpdateStatus(ctx, k6, log); err != nil {
6971
return ctrl.Result{}, ready, err

internal/controller/testrun_controller.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ func (r *TestRunReconciler) reconcile(ctx context.Context, req ctrl.Request, log
126126
case "":
127127
log.Info("Initialize test")
128128

129+
if err := k6.GetSpec().Validate(); err != nil {
130+
log.Error(err, "Invalid TestRun")
131+
log.Info("Changing stage of TestRun status to error")
132+
k6.GetStatus().Stage = "error"
133+
_, err := r.UpdateStatus(ctx, k6, log)
134+
return ctrl.Result{}, err
135+
}
136+
129137
v1alpha1.Initialize(k6)
130138

131139
if _, err := r.UpdateStatus(ctx, k6, log); err != nil {

pkg/types/k6cli.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package types
22

3-
import "strings"
3+
import (
4+
"fmt"
5+
"strings"
6+
)
47

58
// CLI is an internal type to support k6 invocation in initialization stage.
69
// Not all k6 commands allow the same set of arguments so CLI is an object
@@ -12,7 +15,7 @@ type CLI struct {
1215
HasCloudOut bool
1316
}
1417

15-
func ParseCLI(arguments string) *CLI {
18+
func ParseCLI(arguments string) (*CLI, error) {
1619
lastArgV := func(start int, args []string) (end int) {
1720
end = start
1821
for end < len(args) {
@@ -25,7 +28,10 @@ func ParseCLI(arguments string) *CLI {
2528
return
2629
}
2730

28-
var cli CLI
31+
var (
32+
cli CLI
33+
err error
34+
)
2935

3036
args := strings.Split(arguments, " ")
3137
i := 0
@@ -66,8 +72,11 @@ func ParseCLI(arguments string) *CLI {
6672
cli.ArchiveArgs += strings.Join(args[i:end], " ")
6773
}
6874
i = end
75+
} else {
76+
err = fmt.Errorf("encountered an invalid value for k6 CLI argument: `%s`", args[i])
77+
break
6978
}
7079
}
7180

72-
return &cli
81+
return &cli, err
7382
}

pkg/types/k6cli_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,48 @@ import (
88

99
func Test_ParseCLI(t *testing.T) {
1010
tests := []struct {
11-
name string
12-
argLine string
13-
cli CLI
11+
name string
12+
argLine string
13+
cli CLI
14+
validArguments bool
1415
}{
1516
{
1617
"EmptyArgs",
1718
"",
1819
CLI{},
20+
false,
1921
},
2022
{
2123
"ShortArchiveArgs",
2224
"-u 10 -d 5",
2325
CLI{
2426
ArchiveArgs: "-u 10 -d 5",
2527
},
28+
false,
2629
},
2730
{
2831
"LongArchiveArgs",
2932
"--vus 10 --duration 5",
3033
CLI{
3134
ArchiveArgs: "--vus 10 --duration 5",
3235
},
36+
false,
3337
},
3438
{
3539
"ShortNonArchiveArg",
3640
"-u 10 -d 5 -l",
3741
CLI{
3842
ArchiveArgs: "-u 10 -d 5",
3943
},
44+
false,
4045
},
4146
{
4247
"LongNonArchiveArgs",
4348
"--vus 10 --duration 5 --linger",
4449
CLI{
4550
ArchiveArgs: "--vus 10 --duration 5",
4651
},
52+
false,
4753
},
4854
{
4955
"OutWithoutCloudArgs",
@@ -52,6 +58,7 @@ func Test_ParseCLI(t *testing.T) {
5258
ArchiveArgs: "--vus 10",
5359
HasCloudOut: false,
5460
},
61+
false,
5562
},
5663
{
5764
"OutWithCloudArgs",
@@ -60,6 +67,7 @@ func Test_ParseCLI(t *testing.T) {
6067
ArchiveArgs: "--vus 10",
6168
HasCloudOut: true,
6269
},
70+
false,
6371
},
6472
{
6573
"VerboseOutWithCloudArgs",
@@ -68,6 +76,7 @@ func Test_ParseCLI(t *testing.T) {
6876
ArchiveArgs: "--vus 10",
6977
HasCloudOut: true,
7078
},
79+
false,
7180
},
7281
{
7382
"OmitLogOutput",
@@ -76,15 +85,23 @@ func Test_ParseCLI(t *testing.T) {
7685
ArchiveArgs: "--no-thresholds",
7786
HasCloudOut: true,
7887
},
88+
false,
89+
},
90+
{
91+
"InvalidArguments",
92+
`run this-argument-does-not-matter.js -o json`,
93+
CLI{},
94+
true,
7995
},
8096
}
8197

8298
for _, test := range tests {
8399
test := test
84100
t.Run(test.name, func(t *testing.T) {
85101
t.Parallel()
86-
cli := ParseCLI(test.argLine)
102+
cli, err := ParseCLI(test.argLine)
87103

104+
assert.Equal(t, test.validArguments, err != nil)
88105
assert.Equal(t, test.cli.ArchiveArgs, cli.ArchiveArgs)
89106
assert.Equal(t, test.cli.HasCloudOut, cli.HasCloudOut)
90107
})

0 commit comments

Comments
 (0)