From add9937c52b833d3af3ab2bf01cd0ef9a5cca166 Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 20:40:57 +0200 Subject: [PATCH 1/6] Fix sample scripts --- samples/custom_metrics.js | 12 ++++++------ samples/grpc.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/samples/custom_metrics.js b/samples/custom_metrics.js index 4917c2a1ed7..0f3e969f1c8 100644 --- a/samples/custom_metrics.js +++ b/samples/custom_metrics.js @@ -3,11 +3,11 @@ import { Counter, Gauge, Rate, Trend } from "k6/metrics"; import { check } from "k6"; /* - * Custom metrics are useful when you want to track something that is not + * Custom metrics are useful when you want to track something that is not * provided out of the box. - * + * * There are four types of custom metrics: Counter, Gauge, Rate and Trend. - * + * * - Counter: a sum of all values added to the metric * - Gauge: a value that change to whatever you set it to * - Rate: rate of "truthiness", how many values out of total are !=0 @@ -22,7 +22,7 @@ let myTrend = new Trend("my_trend"); let maxResponseTime = 0.0; -export default function() { +export default function () { let res = http.get("http://httpbin.org/"); let passed = check(res, { "status is 200": (r) => r.status === 200 }); @@ -36,6 +36,6 @@ export default function() { // Add check success or failure to keep track of rate myRate.add(passed); - // Keep track of DNS+TCP-connecting part of the response time - myTrend.add(res.timings.looking_up + res.timings.connecting); + // Keep track of TCP-connecting and TLS handshaking part of the response time + myTrend.add(res.timings.connecting + res.timings.tls_handshaking); } diff --git a/samples/grpc.js b/samples/grpc.js index 5019d269663..cda5adfe0b4 100644 --- a/samples/grpc.js +++ b/samples/grpc.js @@ -2,7 +2,7 @@ import grpc from 'k6/net/grpc'; import { check } from "k6"; let client = new grpc.Client(); -client.load([], "samples/grpc_server/route_guide.proto") +client.load([], "./grpc_server/route_guide.proto") export default () => { From 47616330719670051518af94f242917fb4b79c8b Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 21:00:22 +0200 Subject: [PATCH 2/6] Fix stats.MetricType and stats.ValueType encoding --- stats/cloud/cloud_easyjson.go | 8 +++---- stats/stats.go | 44 ++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/stats/cloud/cloud_easyjson.go b/stats/cloud/cloud_easyjson.go index d0d5a75d476..2772977e414 100644 --- a/stats/cloud/cloud_easyjson.go +++ b/stats/cloud/cloud_easyjson.go @@ -459,8 +459,8 @@ func easyjson9def2ecdDecodeGithubComLoadimpactK6StatsCloud4(in *jlexer.Lexer, ou case "time": out.Time = int64(in.Int64Str()) case "type": - if data := in.Raw(); in.Ok() { - in.AddError((out.Type).UnmarshalJSON(data)) + if data := in.UnsafeBytes(); in.Ok() { + in.AddError((out.Type).UnmarshalText(data)) } case "tags": if in.IsNull() { @@ -544,8 +544,8 @@ func easyjson9def2ecdDecodeGithubComLoadimpactK6StatsCloud5(in *jlexer.Lexer, ou case "time": out.Time = int64(in.Int64Str()) case "type": - if data := in.Raw(); in.Ok() { - in.AddError((out.Type).UnmarshalJSON(data)) + if data := in.UnsafeBytes(); in.Ok() { + in.AddError((out.Type).UnmarshalText(data)) } case "tags": if in.IsNull() { diff --git a/stats/stats.go b/stats/stats.go index 1e266551712..59b73558d50 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -35,14 +35,14 @@ import ( ) const ( - counterString = `"counter"` - gaugeString = `"gauge"` - trendString = `"trend"` - rateString = `"rate"` - - defaultString = `"default"` - timeString = `"time"` - dataString = `"data"` + counterString = "counter" + gaugeString = "gauge" + trendString = "trend" + rateString = "rate" + + defaultString = "default" + timeString = "time" + dataString = "data" ) // Possible values for MetricType. @@ -71,6 +71,15 @@ type MetricType int // MarshalJSON serializes a MetricType as a human readable string. func (t MetricType) MarshalJSON() ([]byte, error) { + txt, err := t.MarshalText() + if err != nil { + return nil, err + } + return []byte(`"` + string(txt) + `"`), nil +} + +// MarshalText serializes a MetricType as a human readable string. +func (t MetricType) MarshalText() ([]byte, error) { switch t { case Counter: return []byte(counterString), nil @@ -85,8 +94,8 @@ func (t MetricType) MarshalJSON() ([]byte, error) { } } -// UnmarshalJSON deserializes a MetricType from a string representation. -func (t *MetricType) UnmarshalJSON(data []byte) error { +// UnmarshalText deserializes a MetricType from a string representation. +func (t *MetricType) UnmarshalText(data []byte) error { switch string(data) { case counterString: *t = Counter @@ -121,8 +130,17 @@ func (t MetricType) String() string { // The type of values a metric contains. type ValueType int -// MarshalJSON serializes a ValueType as a human readable string. +// MarshalJSON serializes a ValueType to a JSON string. func (t ValueType) MarshalJSON() ([]byte, error) { + txt, err := t.MarshalText() + if err != nil { + return nil, err + } + return []byte(`"` + string(txt) + `"`), nil +} + +// MarshalText serializes a ValueType as a human readable string. +func (t ValueType) MarshalText() ([]byte, error) { switch t { case Default: return []byte(defaultString), nil @@ -135,8 +153,8 @@ func (t ValueType) MarshalJSON() ([]byte, error) { } } -// UnmarshalJSON deserializes a ValueType from a string representation. -func (t *ValueType) UnmarshalJSON(data []byte) error { +// UnmarshalText deserializes a ValueType from a string representation. +func (t *ValueType) UnmarshalText(data []byte) error { switch string(data) { case defaultString: *t = Default From 6ba169cf0f0850112600c83b0b5d2b632441cc05 Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 21:12:24 +0200 Subject: [PATCH 3/6] Order groups and checks chronologically in the end-of-test summary This closes https://github.com/loadimpact/k6/issues/1316 --- lib/models.go | 9 +++++++-- ui/summary.go | 4 ++-- ui/summary_test.go | 14 +++++++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/models.go b/lib/models.go index e7b69b29183..575ab35a416 100644 --- a/lib/models.go +++ b/lib/models.go @@ -109,8 +109,11 @@ type Group struct { ID string `json:"id"` // Groups and checks that are children of this group. - Groups map[string]*Group `json:"groups"` - Checks map[string]*Check `json:"checks"` + Groups map[string]*Group `json:"groups"` + OrderedGroups []*Group `json:"-"` + + Checks map[string]*Check `json:"checks"` + OrderedChecks []*Check `json:"-"` groupMutex sync.Mutex checkMutex sync.Mutex @@ -155,6 +158,7 @@ func (g *Group) Group(name string) (*Group, error) { return nil, err } g.Groups[name] = group + g.OrderedGroups = append(g.OrderedGroups, group) return group, nil } return group, nil @@ -172,6 +176,7 @@ func (g *Group) Check(name string) (*Check, error) { return nil, err } g.Checks[name] = check + g.OrderedChecks = append(g.OrderedChecks, check) return check, nil } return check, nil diff --git a/ui/summary.go b/ui/summary.go index dc981d8cc43..6a0519c43eb 100644 --- a/ui/summary.go +++ b/ui/summary.go @@ -195,7 +195,7 @@ func summarizeGroup(w io.Writer, indent string, group *lib.Group) { } var checkNames []string - for _, check := range group.Checks { + for _, check := range group.OrderedChecks { checkNames = append(checkNames, check.Name) } for _, name := range checkNames { @@ -206,7 +206,7 @@ func summarizeGroup(w io.Writer, indent string, group *lib.Group) { } var groupNames []string - for _, grp := range group.Groups { + for _, grp := range group.OrderedGroups { groupNames = append(groupNames, grp.Name) } for _, name := range groupNames { diff --git a/ui/summary_test.go b/ui/summary_test.go index b6a9e4d7ba2..5814e8947d4 100644 --- a/ui/summary_test.go +++ b/ui/summary_test.go @@ -37,7 +37,9 @@ import ( func TestSummary(t *testing.T) { t.Run("SummarizeMetrics", func(t *testing.T) { var ( - checksOut = " █ child\n\n ✗ check1\n ↳ 33% — ✓ 5 / ✗ 10\n\n" + + checksOut = " █ child\n\n" + + " ✗ check1\n ↳ 33% — ✓ 5 / ✗ 10\n" + + " ✗ check2\n ↳ 66% — ✓ 10 / ✗ 5\n\n" + " ✓ checks......: 100.00% ✓ 3 ✗ 0 \n" countOut = " ✗ http_reqs...: 3 3/s\n" gaugeOut = " vus.........: 1 min=1 max=1\n" @@ -58,10 +60,12 @@ func TestSummary(t *testing.T) { rootG, _ := lib.NewGroup("", nil) childG, _ := rootG.Group("child") - check, _ := lib.NewCheck("check1", childG) - check.Passes = 5 - check.Fails = 10 - childG.Checks["check1"] = check + check1, _ := childG.Check("check1") + check1.Passes = 5 + check1.Fails = 10 + check2, _ := childG.Check("check2") + check2.Passes = 10 + check2.Fails = 5 for _, tc := range testCases { tc := tc t.Run(fmt.Sprintf("%v", tc.stats), func(t *testing.T) { From f12d7b72463e6fe1b3f6a516944dc1daec2cee8f Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 21:56:09 +0200 Subject: [PATCH 4/6] Move no-summary, no-thresholds and summary-export to RuntimeOptions --- api/server_test.go | 2 +- api/v1/group_routes_test.go | 2 +- api/v1/metric_routes_test.go | 4 +-- api/v1/setup_teardown_routes_test.go | 2 +- api/v1/status_routes_test.go | 4 +-- cmd/config.go | 28 ++------------- cmd/run.go | 20 +++-------- cmd/runtime_options.go | 54 +++++++++++++++++++++++----- core/engine.go | 33 ++++++++--------- core/engine_test.go | 2 +- js/runner_test.go | 2 +- lib/runtime_options.go | 4 +++ 12 files changed, 82 insertions(+), 75 deletions(-) diff --git a/api/server_test.go b/api/server_test.go index ef300eadcdc..cafec68d9e8 100644 --- a/api/server_test.go +++ b/api/server_test.go @@ -82,7 +82,7 @@ func TestWithEngine(t *testing.T) { logger.SetOutput(testutils.NewTestOutput(t)) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, lib.Options{}, logger) + engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, logger) require.NoError(t, err) rw := httptest.NewRecorder() diff --git a/api/v1/group_routes_test.go b/api/v1/group_routes_test.go index 66701c89731..e2a30db52cf 100644 --- a/api/v1/group_routes_test.go +++ b/api/v1/group_routes_test.go @@ -51,7 +51,7 @@ func TestGetGroups(t *testing.T) { execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{Group: g0}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, lib.Options{}, logger) + engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, logger) require.NoError(t, err) t.Run("list", func(t *testing.T) { diff --git a/api/v1/metric_routes_test.go b/api/v1/metric_routes_test.go index dc9acb1581b..423a5eb5c5e 100644 --- a/api/v1/metric_routes_test.go +++ b/api/v1/metric_routes_test.go @@ -45,7 +45,7 @@ func TestGetMetrics(t *testing.T) { logger.SetOutput(testutils.NewTestOutput(t)) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, lib.Options{}, logger) + engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, logger) require.NoError(t, err) engine.Metrics = map[string]*stats.Metric{ @@ -88,7 +88,7 @@ func TestGetMetric(t *testing.T) { logger.SetOutput(testutils.NewTestOutput(t)) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, lib.Options{}, logger) + engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, logger) require.NoError(t, err) engine.Metrics = map[string]*stats.Metric{ diff --git a/api/v1/setup_teardown_routes_test.go b/api/v1/setup_teardown_routes_test.go index de9fed47444..bb9c5ad083e 100644 --- a/api/v1/setup_teardown_routes_test.go +++ b/api/v1/setup_teardown_routes_test.go @@ -155,7 +155,7 @@ func TestSetupData(t *testing.T) { }) execScheduler, err := local.NewExecutionScheduler(runner, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, runner.GetOptions(), logger) + engine, err := core.NewEngine(execScheduler, runner.GetOptions(), lib.RuntimeOptions{}, logger) require.NoError(t, err) globalCtx, globalCancel := context.WithCancel(context.Background()) diff --git a/api/v1/status_routes_test.go b/api/v1/status_routes_test.go index 473f2a25371..1378f97c5a9 100644 --- a/api/v1/status_routes_test.go +++ b/api/v1/status_routes_test.go @@ -47,7 +47,7 @@ func TestGetStatus(t *testing.T) { logger.SetOutput(testutils.NewTestOutput(t)) execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, lib.Options{}, logger) + engine, err := core.NewEngine(execScheduler, lib.Options{}, lib.RuntimeOptions{}, logger) require.NoError(t, err) rw := httptest.NewRecorder() @@ -101,7 +101,7 @@ func TestPatchStatus(t *testing.T) { t.Run(name, func(t *testing.T) { execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{Options: options}, logger) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, options, logger) + engine, err := core.NewEngine(execScheduler, options, lib.RuntimeOptions{}, logger) require.NoError(t, err) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() diff --git a/cmd/config.go b/cmd/config.go index de37f6a44bf..c6f3f32ff3b 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -53,25 +53,15 @@ func configFlagSet() *pflag.FlagSet { flags.StringArrayP("out", "o", []string{}, "`uri` for an external metrics database") flags.BoolP("linger", "l", false, "keep the API server alive past test end") flags.Bool("no-usage-report", false, "don't send anonymous stats to the developers") - 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 } type Config struct { lib.Options - Out []string `json:"out" envconfig:"K6_OUT"` - Linger null.Bool `json:"linger" envconfig:"K6_LINGER"` - NoUsageReport null.Bool `json:"noUsageReport" envconfig:"K6_NO_USAGE_REPORT"` - NoThresholds null.Bool `json:"noThresholds" envconfig:"K6_NO_THRESHOLDS"` - NoSummary null.Bool `json:"noSummary" envconfig:"K6_NO_SUMMARY"` - SummaryExport null.String `json:"summaryExport" envconfig:"K6_SUMMARY_EXPORT"` + Out []string `json:"out" envconfig:"K6_OUT"` + Linger null.Bool `json:"linger" envconfig:"K6_LINGER"` + NoUsageReport null.Bool `json:"noUsageReport" envconfig:"K6_NO_USAGE_REPORT"` Collectors struct { InfluxDB influxdb.Config `json:"influxdb"` @@ -103,15 +93,6 @@ func (c Config) Apply(cfg Config) Config { if cfg.NoUsageReport.Valid { c.NoUsageReport = cfg.NoUsageReport } - if cfg.NoThresholds.Valid { - c.NoThresholds = cfg.NoThresholds - } - if cfg.NoSummary.Valid { - c.NoSummary = cfg.NoSummary - } - if cfg.SummaryExport.Valid { - c.SummaryExport = cfg.SummaryExport - } c.Collectors.InfluxDB = c.Collectors.InfluxDB.Apply(cfg.Collectors.InfluxDB) c.Collectors.Cloud = c.Collectors.Cloud.Apply(cfg.Collectors.Cloud) c.Collectors.Kafka = c.Collectors.Kafka.Apply(cfg.Collectors.Kafka) @@ -136,9 +117,6 @@ func getConfig(flags *pflag.FlagSet) (Config, error) { Out: out, Linger: getNullBool(flags, "linger"), NoUsageReport: getNullBool(flags, "no-usage-report"), - NoThresholds: getNullBool(flags, "no-thresholds"), - NoSummary: getNullBool(flags, "no-summary"), - SummaryExport: getNullString(flags, "summary-export"), }, nil } diff --git a/cmd/run.go b/cmd/run.go index 0767f972ac1..133757a26c8 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -192,23 +192,11 @@ a commandline interface for interacting with it.`, // Create an engine. initBar.Modify(pb.WithConstProgress(0, "Init engine")) - engine, err := core.NewEngine(execScheduler, conf.Options, logger) + engine, err := core.NewEngine(execScheduler, conf.Options, runtimeOptions, logger) if err != nil { return err } - // TODO: refactor, the engine should have a copy of the config... - // Configure the engine. - if conf.NoThresholds.Valid { - engine.NoThresholds = conf.NoThresholds.Bool - } - if conf.NoSummary.Valid { - engine.NoSummary = conf.NoSummary.Bool - } - if conf.SummaryExport.Valid { - engine.SummaryExport = conf.SummaryExport.String != "" - } - executionPlan := execScheduler.GetExecutionPlan() // Create a collector and assign it to the engine if requested. initBar.Modify(pb.WithConstProgress(0, "Init metric outputs")) @@ -309,7 +297,7 @@ a commandline interface for interacting with it.`, TimeUnit: conf.Options.SummaryTimeUnit.String, } // Print the end-of-test summary. - if !conf.NoSummary.Bool { + if !runtimeOptions.NoSummary.Bool { fprintf(stdout, "\n") s := ui.NewSummary(conf.SummaryTrendStats) @@ -318,8 +306,8 @@ a commandline interface for interacting with it.`, fprintf(stdout, "\n") } - if conf.SummaryExport.ValueOrZero() != "" { //nolint:nestif - f, err := os.Create(conf.SummaryExport.String) + if runtimeOptions.SummaryExport.ValueOrZero() != "" { //nolint:nestif + f, err := os.Create(runtimeOptions.SummaryExport.String) if err != nil { logger.WithError(err).Error("failed to create summary export file") } else { diff --git a/cmd/runtime_options.go b/cmd/runtime_options.go index edc1680a1a2..d7f9badbfd2 100644 --- a/cmd/runtime_options.go +++ b/cmd/runtime_options.go @@ -21,6 +21,7 @@ package cmd import ( + "fmt" "regexp" "strconv" "strings" @@ -65,18 +66,47 @@ extended: base + Babel with ES2015 preset + core.js v2, slower and memory consuming but with greater JS support `) 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 !opts.CompatibilityMode.Valid { // If not explicitly set via CLI flags, look for an environment variable - if envVar, ok := environment["K6_COMPATIBILITY_MODE"]; ok { + 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) } } @@ -85,13 +115,19 @@ func getRuntimeOptions(flags *pflag.FlagSet, environment map[string]string) (lib return opts, err } - if !opts.IncludeSystemEnvVars.Valid { // If not explicitly set via CLI flags, look for an environment variable - if envVar, ok := environment["K6_INCLUDE_SYSTEM_ENV_VARS"]; ok { - val, err := strconv.ParseBool(envVar) - if err != nil { - return opts, err - } - opts.IncludeSystemEnvVars = null.BoolFrom(val) + 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) } } diff --git a/core/engine.go b/core/engine.go index 80c6191d95a..9953e018d7b 100644 --- a/core/engine.go +++ b/core/engine.go @@ -54,11 +54,9 @@ type Engine struct { ExecutionScheduler lib.ExecutionScheduler executionState *lib.ExecutionState - Options lib.Options - Collectors []lib.Collector - NoThresholds bool - NoSummary bool - SummaryExport bool + Options lib.Options + runtimeOptions lib.RuntimeOptions + Collectors []lib.Collector logger *logrus.Entry stopOnce sync.Once @@ -78,7 +76,9 @@ type Engine struct { } // NewEngine instantiates a new Engine, without doing any heavy initialization. -func NewEngine(ex lib.ExecutionScheduler, o lib.Options, logger *logrus.Logger) (*Engine, error) { +func NewEngine( + ex lib.ExecutionScheduler, opts lib.Options, rtOpts lib.RuntimeOptions, logger *logrus.Logger, +) (*Engine, error) { if ex == nil { return nil, errors.New("missing ExecutionScheduler instance") } @@ -87,14 +87,15 @@ func NewEngine(ex lib.ExecutionScheduler, o lib.Options, logger *logrus.Logger) ExecutionScheduler: ex, executionState: ex.GetState(), - Options: o, - Metrics: make(map[string]*stats.Metric), - Samples: make(chan stats.SampleContainer, o.MetricSamplesBufferSize.Int64), - stopChan: make(chan struct{}), - logger: logger.WithField("component", "engine"), + Options: opts, + runtimeOptions: rtOpts, + Metrics: make(map[string]*stats.Metric), + Samples: make(chan stats.SampleContainer, opts.MetricSamplesBufferSize.Int64), + stopChan: make(chan struct{}), + logger: logger.WithField("component", "engine"), } - e.thresholds = o.Thresholds + e.thresholds = opts.Thresholds e.submetrics = make(map[string][]*stats.Submetric) for name := range e.thresholds { if !strings.Contains(name, "{") { @@ -221,7 +222,7 @@ func (e *Engine) startBackgroundProcesses( //nolint:funlen }() // Run thresholds, if not disabled. - if !e.NoThresholds { + if !e.runtimeOptions.NoThresholds.Bool { processes.Add(1) go func() { defer processes.Done() @@ -260,7 +261,7 @@ func (e *Engine) processMetrics(globalCtx context.Context, processMetricsAfterRu } e.processSamples(sampleContainers) - if !e.NoThresholds { + if !e.runtimeOptions.NoThresholds.Bool { e.processThresholds() // Process the thresholds one final time } }() @@ -285,7 +286,7 @@ func (e *Engine) processMetrics(globalCtx context.Context, processMetricsAfterRu case <-processMetricsAfterRun: e.logger.Debug("Processing metrics and thresholds after the test run has ended...") processSamples() - if !e.NoThresholds { + if !e.runtimeOptions.NoThresholds.Bool { e.processThresholds() } processMetricsAfterRun <- struct{}{} @@ -438,7 +439,7 @@ func (e *Engine) processSamples(sampleContainers []stats.SampleContainer) { defer e.MetricsLock.Unlock() // TODO: run this and the below code in goroutines? - if !(e.NoSummary && e.NoThresholds && !e.SummaryExport) { + if !(e.runtimeOptions.NoSummary.Bool && e.runtimeOptions.NoThresholds.Bool) { e.processSamplesForMetrics(sampleContainers) } diff --git a/core/engine_test.go b/core/engine_test.go index 0bc27bc54fb..a6765b459cb 100644 --- a/core/engine_test.go +++ b/core/engine_test.go @@ -76,7 +76,7 @@ func newTestEngine( //nolint:golint execScheduler, err := local.NewExecutionScheduler(runner, logger) require.NoError(t, err) - engine, err = NewEngine(execScheduler, opts, logger) + engine, err = NewEngine(execScheduler, opts, lib.RuntimeOptions{}, logger) require.NoError(t, err) engine.Collectors = collectors diff --git a/js/runner_test.go b/js/runner_test.go index 39554defb5e..af9fca2275e 100644 --- a/js/runner_test.go +++ b/js/runner_test.go @@ -295,7 +295,7 @@ func TestSetupDataIsolation(t *testing.T) { execScheduler, err := local.NewExecutionScheduler(runner, testutils.NewLogger(t)) require.NoError(t, err) - engine, err := core.NewEngine(execScheduler, options, testutils.NewLogger(t)) + engine, err := core.NewEngine(execScheduler, options, lib.RuntimeOptions{}, testutils.NewLogger(t)) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) diff --git a/lib/runtime_options.go b/lib/runtime_options.go index b39d84ff3c6..719f378f891 100644 --- a/lib/runtime_options.go +++ b/lib/runtime_options.go @@ -54,6 +54,10 @@ type RuntimeOptions struct { // Environment variables passed onto the runner Env map[string]string `json:"env"` + + NoThresholds null.Bool `json:"noThresholds"` + NoSummary null.Bool `json:"noSummary"` + SummaryExport null.String `json:"summaryExport"` } // ValidateCompatibilityMode checks if the provided val is a valid compatibility mode From 3a0ac94248f9756a079e5eccd1652cc68555dd49 Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 23:04:16 +0200 Subject: [PATCH 5/6] Improve and expand the RuntimeOptions test --- cmd/runtime_options_test.go | 296 +++++++++++++++++++++++------------- 1 file changed, 191 insertions(+), 105 deletions(-) diff --git a/cmd/runtime_options_test.go b/cmd/runtime_options_test.go index 0d432e60a87..e3444bc07d5 100644 --- a/cmd/runtime_options_test.go +++ b/cmd/runtime_options_test.go @@ -37,12 +37,11 @@ import ( ) type runtimeOptionsTestCase struct { - useSysEnv bool // Whether to include the system env vars by default (run) or not (cloud/archive/inspect) - expErr bool - cliFlags []string - systemEnv map[string]string - expEnv map[string]string - expCompatMode null.String + useSysEnv bool // Whether to include the system env vars by default (run) or not (cloud/archive/inspect) + expErr bool + cliFlags []string + systemEnv map[string]string + expRTOpts lib.RuntimeOptions } //nolint:gochecknoglobals @@ -56,147 +55,235 @@ var runtimeOptionsTestCases = map[string]runtimeOptionsTestCase{ //nolint:gochec "empty env": { useSysEnv: true, // everything else is empty - expCompatMode: defaultCompatMode, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: nil, + }, }, "disabled sys env by default": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1"}, - expEnv: map[string]string{}, - expCompatMode: defaultCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{}, + }, }, "disabled sys env by default with ext compat mode": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1", "K6_COMPATIBILITY_MODE": "extended"}, - expEnv: map[string]string{}, - expCompatMode: extendedCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1", "K6_COMPATIBILITY_MODE": "extended"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, false), + CompatibilityMode: extendedCompatMode, + Env: map[string]string{}, + }, }, "disabled sys env by cli 1": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "val1", "K6_COMPATIBILITY_MODE": "base"}, - cliFlags: []string{"--include-system-env-vars=false"}, - expEnv: map[string]string{}, - expCompatMode: baseCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "val1", "K6_COMPATIBILITY_MODE": "base"}, + cliFlags: []string{"--include-system-env-vars=false"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, true), + CompatibilityMode: baseCompatMode, + Env: map[string]string{}, + }, }, "disabled sys env by cli 2": { - useSysEnv: true, - systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, - cliFlags: []string{"--include-system-env-vars=0", "--compatibility-mode=base"}, - expEnv: map[string]string{}, - expCompatMode: baseCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, + cliFlags: []string{"--include-system-env-vars=0", "--compatibility-mode=base"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, true), + CompatibilityMode: baseCompatMode, + Env: map[string]string{}, + }, }, "disabled sys env by env": { - useSysEnv: true, - systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "false", "K6_COMPATIBILITY_MODE": "extended"}, - expEnv: map[string]string{}, - expCompatMode: extendedCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "false", "K6_COMPATIBILITY_MODE": "extended"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, true), + CompatibilityMode: extendedCompatMode, + Env: map[string]string{}, + }, }, "enabled sys env by env": { - useSysEnv: false, - systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, - expEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, - expCompatMode: extendedCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, true), + CompatibilityMode: extendedCompatMode, + Env: map[string]string{"K6_INCLUDE_SYSTEM_ENV_VARS": "true", "K6_COMPATIBILITY_MODE": "extended"}, + }, }, "enabled sys env by default": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "val1"}, - cliFlags: []string{}, - expEnv: map[string]string{"test1": "val1"}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "val1"}, + cliFlags: []string{}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1"}, + }, }, "enabled sys env by cli 1": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1"}, - cliFlags: []string{"--include-system-env-vars"}, - expEnv: map[string]string{"test1": "val1"}, - expCompatMode: defaultCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1"}, + cliFlags: []string{"--include-system-env-vars"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, true), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1"}, + }, }, "enabled sys env by cli 2": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1"}, - cliFlags: []string{"--include-system-env-vars=true"}, - expEnv: map[string]string{"test1": "val1"}, - expCompatMode: defaultCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1"}, + cliFlags: []string{"--include-system-env-vars=true"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, true), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1"}, + }, }, "run only system env": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "val1"}, - cliFlags: []string{}, - expEnv: map[string]string{"test1": "val1"}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "val1"}, + cliFlags: []string{}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1"}, + }, }, "mixed system and cli env": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "val1", "test2": ""}, - cliFlags: []string{"--env", "test3=val3", "-e", "test4", "-e", "test5="}, - expEnv: map[string]string{"test1": "val1", "test2": "", "test3": "val3", "test4": "", "test5": ""}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "val1", "test2": ""}, + cliFlags: []string{"--env", "test3=val3", "-e", "test4", "-e", "test5="}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1", "test2": "", "test3": "val3", "test4": "", "test5": ""}, + }, }, "mixed system and cli env 2": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1", "test2": ""}, - cliFlags: []string{"--env", "test3=val3", "-e", "test4", "-e", "test5=", "--include-system-env-vars=1"}, - expEnv: map[string]string{"test1": "val1", "test2": "", "test3": "val3", "test4": "", "test5": ""}, - expCompatMode: defaultCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1", "test2": ""}, + cliFlags: []string{"--env", "test3=val3", "-e", "test4", "-e", "test5=", "--include-system-env-vars=1"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, true), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1", "test2": "", "test3": "val3", "test4": "", "test5": ""}, + }, }, "disabled system env with cli params": { - useSysEnv: false, - systemEnv: map[string]string{"test1": "val1"}, - cliFlags: []string{"-e", "test2=overwriten", "-e", "test2=val2"}, - expEnv: map[string]string{"test2": "val2"}, - expCompatMode: defaultCompatMode, + useSysEnv: false, + systemEnv: map[string]string{"test1": "val1"}, + cliFlags: []string{"-e", "test2=overwriten", "-e", "test2=val2"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test2": "val2"}, + }, }, "overwriting system env with cli param": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "val1sys"}, - cliFlags: []string{"--env", "test1=val1cli"}, - expEnv: map[string]string{"test1": "val1cli"}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "val1sys"}, + cliFlags: []string{"--env", "test1=val1cli"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "val1cli"}, + }, }, "error wrong compat mode env var value": { systemEnv: map[string]string{"K6_COMPATIBILITY_MODE": "asdf"}, expErr: true, }, + "error wrong compat mode env var value even with CLI flag": { + systemEnv: map[string]string{"K6_COMPATIBILITY_MODE": "asdf"}, + cliFlags: []string{"--compatibility-mode", "true"}, + expErr: true, + }, "error wrong compat mode cli flag value": { cliFlags: []string{"--compatibility-mode", "whatever"}, expErr: true, }, "error invalid cli var name 1": { - useSysEnv: true, - systemEnv: map[string]string{}, - cliFlags: []string{"--env", "test a=error"}, - expErr: true, - expEnv: map[string]string{}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{}, + cliFlags: []string{"--env", "test a=error"}, + expErr: true, }, "error invalid cli var name 2": { - useSysEnv: true, - systemEnv: map[string]string{}, - cliFlags: []string{"--env", "1var=error"}, - expErr: true, - expEnv: map[string]string{}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{}, + cliFlags: []string{"--env", "1var=error"}, + expErr: true, }, "error invalid cli var name 3": { - useSysEnv: true, - systemEnv: map[string]string{}, - cliFlags: []string{"--env", "уникод=unicode-disabled"}, - expErr: true, - expEnv: map[string]string{}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{}, + cliFlags: []string{"--env", "уникод=unicode-disabled"}, + expErr: true, }, "valid env vars with spaces": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "value 1"}, - cliFlags: []string{"--env", "test2=value 2"}, - expEnv: map[string]string{"test1": "value 1", "test2": "value 2"}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "value 1"}, + cliFlags: []string{"--env", "test2=value 2"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "value 1", "test2": "value 2"}, + }, }, "valid env vars with special chars": { - useSysEnv: true, - systemEnv: map[string]string{"test1": "value 1"}, - cliFlags: []string{"--env", "test2=value,2", "-e", `test3= , ,,, value, ,, 2!'@#,"`}, - expEnv: map[string]string{"test1": "value 1", "test2": "value,2", "test3": ` , ,,, value, ,, 2!'@#,"`}, - expCompatMode: defaultCompatMode, + useSysEnv: true, + systemEnv: map[string]string{"test1": "value 1"}, + cliFlags: []string{"--env", "test2=value,2", "-e", `test3= , ,,, value, ,, 2!'@#,"`}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(true, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{"test1": "value 1", "test2": "value,2", "test3": ` , ,,, value, ,, 2!'@#,"`}, + }, + }, + "summary and thresholds from env": { + useSysEnv: false, + systemEnv: map[string]string{"K6_NO_THRESHOLDS": "false", "K6_NO_SUMMARY": "0", "K6_SUMMARY_EXPORT": "foo"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{}, + NoThresholds: null.NewBool(false, true), + NoSummary: null.NewBool(false, true), + SummaryExport: null.NewString("foo", true), + }, + }, + "summary and thresholds from env overwritten by CLI": { + useSysEnv: false, + systemEnv: map[string]string{"K6_NO_THRESHOLDS": "FALSE", "K6_NO_SUMMARY": "0", "K6_SUMMARY_EXPORT": "foo"}, + cliFlags: []string{"--no-thresholds", "true", "--no-summary", "true", "--summary-export", "bar"}, + expRTOpts: lib.RuntimeOptions{ + IncludeSystemEnvVars: null.NewBool(false, false), + CompatibilityMode: defaultCompatMode, + Env: map[string]string{}, + NoThresholds: null.NewBool(true, true), + NoSummary: null.NewBool(true, true), + SummaryExport: null.NewString("bar", true), + }, + }, + "env var error detected even when CLI flags overwrite 1": { + useSysEnv: false, + systemEnv: map[string]string{"K6_NO_THRESHOLDS": "boo"}, + cliFlags: []string{"--no-thresholds", "true"}, + expErr: true, + }, + "env var error detected even when CLI flags overwrite 2": { + useSysEnv: false, + systemEnv: map[string]string{"K6_NO_SUMMARY": "hoo"}, + cliFlags: []string{"--no-summary", "true"}, + expErr: true, }, } @@ -210,8 +297,7 @@ func testRuntimeOptionsCase(t *testing.T, tc runtimeOptionsTestCase) { return } require.NoError(t, err) - require.EqualValues(t, tc.expEnv, rtOpts.Env) - assert.Equal(t, tc.expCompatMode, rtOpts.CompatibilityMode) + require.Equal(t, tc.expRTOpts, rtOpts) compatMode, err := lib.ValidateCompatibilityMode(rtOpts.CompatibilityMode.String) require.NoError(t, err) @@ -223,7 +309,7 @@ func testRuntimeOptionsCase(t *testing.T, tc runtimeOptionsTestCase) { fmt.Fprint(jsCode, "module.exports.default = function() {") } - for key, val := range tc.expEnv { + for key, val := range tc.expRTOpts.Env { fmt.Fprintf(jsCode, "if (__ENV.%s !== `%s`) { throw new Error('Invalid %s: ' + __ENV.%s); }", key, val, key, key, @@ -261,7 +347,7 @@ func testRuntimeOptionsCase(t *testing.T, tc runtimeOptionsTestCase) { _, err = getRunnerErr(lib.RuntimeOptions{}) require.NoError(t, err) - for key, val := range tc.expEnv { + for key, val := range tc.expRTOpts.Env { r, err := getRunnerErr(lib.RuntimeOptions{Env: map[string]string{key: "almost " + val}}) assert.NoError(t, err) assert.Equal(t, r.MakeArchive().Env[key], "almost "+val) From 10ac39f2f752dc1c38cf124c50d482233cd08451 Mon Sep 17 00:00:00 2001 From: Nedyalko Andreev Date: Sun, 10 Jan 2021 23:13:21 +0200 Subject: [PATCH 6/6] Use RuntimeOptions in js.Bundle --- js/bundle.go | 29 +++++++++++++++-------------- js/bundle_test.go | 4 ++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/js/bundle.go b/js/bundle.go index 69a8f8ec800..a59ed4f7b3a 100644 --- a/js/bundle.go +++ b/js/bundle.go @@ -30,6 +30,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/afero" + "gopkg.in/guregu/null.v3" "github.com/loadimpact/k6/js/common" "github.com/loadimpact/k6/js/compiler" @@ -49,8 +50,8 @@ type Bundle struct { BaseInitContext *InitContext - Env map[string]string - CompatibilityMode lib.CompatibilityMode + RuntimeOptions lib.RuntimeOptions + CompatibilityMode lib.CompatibilityMode // parsed value exports map[string]goja.Callable } @@ -90,7 +91,7 @@ func NewBundle( Program: pgm, BaseInitContext: NewInitContext(logger, rt, c, compatMode, new(context.Context), filesystems, loader.Dir(src.URL)), - Env: rtOpts.Env, + RuntimeOptions: rtOpts, CompatibilityMode: compatMode, exports: make(map[string]goja.Callable), } @@ -112,13 +113,12 @@ func NewBundleFromArchive(logger logrus.FieldLogger, arc *lib.Archive, rtOpts li return nil, errors.Errorf("expected bundle type 'js', got '%s'", arc.Type) } - compatModeStr := arc.CompatibilityMode - if rtOpts.CompatibilityMode.Valid { - // `k6 run --compatibility-mode=whatever archive.tar` should override + if !rtOpts.CompatibilityMode.Valid { + // `k6 run --compatibility-mode=whatever archive.tar` should override // whatever value is in the archive - compatModeStr = rtOpts.CompatibilityMode.String + rtOpts.CompatibilityMode = null.StringFrom(arc.CompatibilityMode) } - compatMode, err := lib.ValidateCompatibilityMode(compatModeStr) + compatMode, err := lib.ValidateCompatibilityMode(rtOpts.CompatibilityMode.String) if err != nil { return nil, err } @@ -140,6 +140,7 @@ func NewBundleFromArchive(logger logrus.FieldLogger, arc *lib.Archive, rtOpts li for k, v := range rtOpts.Env { env[k] = v } + rtOpts.Env = env bundle := &Bundle{ Filename: arc.FilenameURL, @@ -147,7 +148,7 @@ func NewBundleFromArchive(logger logrus.FieldLogger, arc *lib.Archive, rtOpts li Program: pgm, Options: arc.Options, BaseInitContext: initctx, - Env: env, + RuntimeOptions: rtOpts, CompatibilityMode: compatMode, exports: make(map[string]goja.Callable), } @@ -174,13 +175,13 @@ func (b *Bundle) makeArchive() *lib.Archive { FilenameURL: b.Filename, Data: []byte(b.Source), PwdURL: b.BaseInitContext.pwd, - Env: make(map[string]string, len(b.Env)), + Env: make(map[string]string, len(b.RuntimeOptions.Env)), CompatibilityMode: b.CompatibilityMode.String(), K6Version: consts.Version, Goos: runtime.GOOS, } // Copy env so changes in the archive are not reflected in the source Bundle - for k, v := range b.Env { + for k, v := range b.RuntimeOptions.Env { arc.Env[k] = v } @@ -245,7 +246,7 @@ func (b *Bundle) Instantiate(logger logrus.FieldLogger, vuID int64) (bi *BundleI Runtime: rt, Context: ctxPtr, exports: make(map[string]goja.Callable), - env: b.Env, + env: b.RuntimeOptions.Env, } // Grab any exported functions that could be executed. These were @@ -291,8 +292,8 @@ func (b *Bundle) instantiate(logger logrus.FieldLogger, rt *goja.Runtime, init * _ = module.Set("exports", exports) rt.Set("module", module) - env := make(map[string]string, len(b.Env)) - for key, value := range b.Env { + env := make(map[string]string, len(b.RuntimeOptions.Env)) + for key, value := range b.RuntimeOptions.Env { env[key] = value } rt.Set("__ENV", env) diff --git a/js/bundle_test.go b/js/bundle_test.go index 14028f3f2bd..09908db31b9 100644 --- a/js/bundle_test.go +++ b/js/bundle_test.go @@ -774,8 +774,8 @@ func TestBundleEnv(t *testing.T) { for name, b := range bundles { b := b t.Run(name, func(t *testing.T) { - assert.Equal(t, "1", b.Env["TEST_A"]) - assert.Equal(t, "", b.Env["TEST_B"]) + assert.Equal(t, "1", b.RuntimeOptions.Env["TEST_A"]) + assert.Equal(t, "", b.RuntimeOptions.Env["TEST_B"]) bi, err := b.Instantiate(logger, 0) if assert.NoError(t, err) {