/
base_config.go
146 lines (126 loc) · 4.63 KB
/
base_config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package executor
import (
"fmt"
"regexp"
"strings"
"time"
"gopkg.in/guregu/null.v3"
"github.com/ChipArtem/k6/lib"
"github.com/ChipArtem/k6/lib/consts"
"github.com/ChipArtem/k6/lib/types"
)
// DefaultGracefulStopValue is the graceful top value for all executors, unless
// it's manually changed by the gracefulStop in each one.
// TODO?: Discard? Or make this actually user-configurable somehow? hello #883...
var DefaultGracefulStopValue = 30 * time.Second //nolint:gochecknoglobals
var executorNameWhitelist = regexp.MustCompile(`^[0-9a-zA-Z_-]+$`)
const executorNameErr = "the executor name should contain only numbers, latin letters, underscores, and dashes"
// BaseConfig contains the common config fields for all executors
type BaseConfig struct {
Name string `json:"-"` // set via the JS object key
Type string `json:"executor"`
StartTime types.NullDuration `json:"startTime"`
GracefulStop types.NullDuration `json:"gracefulStop"`
Env map[string]string `json:"env"`
Exec null.String `json:"exec"` // function name, externally validated
Tags map[string]string `json:"tags"`
Options *lib.ScenarioOptions `json:"options,omitempty"`
// TODO: future extensions like distribution, others?
}
// NewBaseConfig returns a default base config with the default values
func NewBaseConfig(name, configType string) BaseConfig {
return BaseConfig{
Name: name,
Type: configType,
GracefulStop: types.NewNullDuration(DefaultGracefulStopValue, false),
}
}
// Validate checks some basic things like present name, type, and a positive start time
func (bc BaseConfig) Validate() (errors []error) {
// Some just-in-case checks, since those things are likely checked in other places or
// even assigned by us:
if bc.Name == "" {
errors = append(errors, fmt.Errorf("executor name can't be empty"))
}
if !executorNameWhitelist.MatchString(bc.Name) {
errors = append(errors, fmt.Errorf(executorNameErr))
}
if bc.Exec.Valid && bc.Exec.String == "" {
errors = append(errors, fmt.Errorf("exec value cannot be empty"))
}
if bc.Type == "" {
errors = append(errors, fmt.Errorf("missing or empty type field"))
}
// The actually reasonable checks:
if bc.StartTime.Duration < 0 {
errors = append(errors, fmt.Errorf("the startTime can't be negative"))
}
if bc.GracefulStop.Duration < 0 {
errors = append(errors, fmt.Errorf("the gracefulStop timeout can't be negative"))
}
return errors
}
// GetName returns the name of the executor.
func (bc BaseConfig) GetName() string {
return bc.Name
}
// GetType returns the executor's type as a string ID.
func (bc BaseConfig) GetType() string {
return bc.Type
}
// GetStartTime returns the starting time, relative to the beginning of the
// actual test, that this executor is supposed to execute.
func (bc BaseConfig) GetStartTime() time.Duration {
return bc.StartTime.TimeDuration()
}
// GetGracefulStop returns how long k6 is supposed to wait for any still
// running iterations to finish executing at the end of the normal executor
// duration, before it actually kills them.
//
// Of course, that doesn't count when the user manually interrupts the test,
// then iterations are immediately stopped.
func (bc BaseConfig) GetGracefulStop() time.Duration {
return bc.GracefulStop.TimeDuration()
}
// GetEnv returns any specific environment key=value pairs that
// are configured for the executor.
func (bc BaseConfig) GetEnv() map[string]string {
return bc.Env
}
// GetExec returns the configured custom exec value, if any.
func (bc BaseConfig) GetExec() string {
exec := bc.Exec.ValueOrZero()
if exec == "" {
exec = consts.DefaultFn
}
return exec
}
// GetScenarioOptions returns the options specific to a scenario.
func (bc BaseConfig) GetScenarioOptions() *lib.ScenarioOptions {
return bc.Options
}
// GetTags returns any custom tags configured for the executor.
func (bc BaseConfig) GetTags() map[string]string {
return bc.Tags
}
// IsDistributable returns true since by default all executors could be run in
// a distributed manner.
func (bc BaseConfig) IsDistributable() bool {
return true
}
// getBaseInfo is a helper method for the "parent" String methods.
func (bc BaseConfig) getBaseInfo(facts ...string) string {
if bc.Exec.Valid {
facts = append(facts, fmt.Sprintf("exec: %s", bc.Exec.String))
}
if bc.StartTime.Duration > 0 {
facts = append(facts, fmt.Sprintf("startTime: %s", bc.StartTime.Duration))
}
if bc.GracefulStop.Duration > 0 {
facts = append(facts, fmt.Sprintf("gracefulStop: %s", bc.GracefulStop.Duration))
}
if len(facts) == 0 {
return ""
}
return " (" + strings.Join(facts, ", ") + ")"
}