forked from grafana/k6
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathruntime_options.go
152 lines (135 loc) · 4.8 KB
/
runtime_options.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
147
148
149
150
151
152
/*
*
* k6 - a next-generation load testing tool
* Copyright (C) 2018 Load Impact
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package cmd
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/spf13/pflag"
"gopkg.in/guregu/null.v3"
"go.k6.io/k6/lib"
)
// TODO: move this whole file out of the cmd package? maybe when fixing
// https://github.com/k6io/k6/issues/883, since this code is fairly
// self-contained and easily testable now, without any global dependencies...
var userEnvVarName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
func parseEnvKeyValue(kv string) (string, string) {
if idx := strings.IndexRune(kv, '='); idx != -1 {
return kv[:idx], kv[idx+1:]
}
return kv, ""
}
func buildEnvMap(environ []string) map[string]string {
env := make(map[string]string, len(environ))
for _, kv := range environ {
k, v := parseEnvKeyValue(kv)
env[k] = v
}
return env
}
func runtimeOptionFlagSet(includeSysEnv bool) *pflag.FlagSet {
flags := pflag.NewFlagSet("", 0)
flags.SortFlags = false
flags.Bool("include-system-env-vars", includeSysEnv, "pass the real system environment variables to the runtime")
flags.String("compatibility-mode", "extended",
`JavaScript compiler compatibility mode, "extended" or "base"
base: pure goja - Golang JS VM supporting ES5.1+
extended: base + Babel with parts of ES2015 preset
slower to compile in case the script uses syntax unsupported by base
`)
flags.StringArrayP("env", "e", nil, "add/override environment variable with `VAR=value`")
flags.Bool("no-thresholds", false, "don't run thresholds")
flags.Bool("no-summary", false, "don't show the summary at the end of the test")
flags.String(
"summary-export",
"",
"output the end-of-test summary report to JSON file",
)
return flags
}
func saveBoolFromEnv(env map[string]string, varName string, placeholder *null.Bool) error {
strValue, ok := env[varName]
if !ok {
return nil
}
val, err := strconv.ParseBool(strValue)
if err != nil {
return fmt.Errorf("env var '%s' is not a valid boolean value: %w", varName, err)
}
// Only override if not explicitly set via the CLI flag
if !placeholder.Valid {
*placeholder = null.BoolFrom(val)
}
return nil
}
func getRuntimeOptions(flags *pflag.FlagSet, environment map[string]string) (lib.RuntimeOptions, error) {
// TODO: refactor with composable helpers as a part of #883, to reduce copy-paste
// TODO: get these options out of the JSON config file as well?
opts := lib.RuntimeOptions{
IncludeSystemEnvVars: getNullBool(flags, "include-system-env-vars"),
CompatibilityMode: getNullString(flags, "compatibility-mode"),
NoThresholds: getNullBool(flags, "no-thresholds"),
NoSummary: getNullBool(flags, "no-summary"),
SummaryExport: getNullString(flags, "summary-export"),
Env: make(map[string]string),
}
if envVar, ok := environment["K6_COMPATIBILITY_MODE"]; ok {
// Only override if not explicitly set via the CLI flag
if !opts.CompatibilityMode.Valid {
opts.CompatibilityMode = null.StringFrom(envVar)
}
}
if _, err := lib.ValidateCompatibilityMode(opts.CompatibilityMode.String); err != nil {
// some early validation
return opts, err
}
if err := saveBoolFromEnv(environment, "K6_INCLUDE_SYSTEM_ENV_VARS", &opts.IncludeSystemEnvVars); err != nil {
return opts, err
}
if err := saveBoolFromEnv(environment, "K6_NO_THRESHOLDS", &opts.NoThresholds); err != nil {
return opts, err
}
if err := saveBoolFromEnv(environment, "K6_NO_SUMMARY", &opts.NoSummary); err != nil {
return opts, err
}
if envVar, ok := environment["K6_SUMMARY_EXPORT"]; ok {
if !opts.SummaryExport.Valid {
opts.SummaryExport = null.StringFrom(envVar)
}
}
if opts.IncludeSystemEnvVars.Bool { // If enabled, gather the actual system environment variables
opts.Env = environment
}
// Set/overwrite environment variables with custom user-supplied values
envVars, err := flags.GetStringArray("env")
if err != nil {
return opts, err
}
for _, kv := range envVars {
k, v := parseEnvKeyValue(kv)
// Allow only alphanumeric ASCII variable names for now
if !userEnvVarName.MatchString(k) {
return opts, fmt.Errorf("invalid environment variable name '%s'", k)
}
opts.Env[k] = v
}
return opts, nil
}