diff --git a/cmd/cloud.go b/cmd/cloud.go index 4fa2d26959a..0f4e3ecfe55 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -30,6 +30,7 @@ import ( "time" "github.com/kelseyhightower/envconfig" + "github.com/loadimpact/k6/lib" "github.com/loadimpact/k6/stats/cloud" "github.com/loadimpact/k6/ui" "github.com/pkg/errors" @@ -168,7 +169,7 @@ This will execute the test on the Load Impact cloud service. Use "k6 login cloud case <-ticker.C: testProgress, progressErr = client.GetTestProgress(refID) if progressErr == nil { - if (testProgress.RunStatus > 2) || (exitOnRunning && testProgress.RunStatus == 2) { + if (testProgress.RunStatus > lib.RunStatusRunning) || (exitOnRunning && testProgress.RunStatus == lib.RunStatusRunning) { shouldExitLoop = true } progress.Progress = testProgress.Progress @@ -180,17 +181,22 @@ This will execute the test on the Load Impact cloud service. Use "k6 login cloud break runningLoop } case sig := <-sigC: - log.WithField("sig", sig).Debug("Exiting in response to signal") + log.WithField("sig", sig).Print("Exiting in response to signal...") err := client.StopCloudTestRun(refID) if err != nil { log.WithError(err).Error("Stop cloud test error") } - shouldExitLoop = true + shouldExitLoop = true // Exit after the next GetTestProgress call } } + + if testProgress == nil { + return ExitCode{errors.New("Test progress error"), 98} + } + fmt.Fprintf(stdout, " test status: %s\n", ui.ValueColor.Sprint(testProgress.RunStatusText)) - if testProgress.ResultStatus == 1 { + if testProgress.ResultStatus == cloud.ResultStatusFailed { return ExitCode{errors.New("The test has failed"), 99} } diff --git a/cmd/login_influxdb.go b/cmd/login_influxdb.go index 0836469ce62..b384814d12f 100644 --- a/cmd/login_influxdb.go +++ b/cmd/login_influxdb.go @@ -54,34 +54,28 @@ This will set the default server used when just "-o influxdb" is passed.`, } conf = conf.Apply(urlConf) } - if conf.Addr == "" { - conf.Addr = "http://localhost:8086" - } - if conf.DB == "" { - conf.DB = "k6" - } form := ui.Form{ Fields: []ui.Field{ ui.StringField{ Key: "Addr", Label: "Address", - Default: conf.Addr, + Default: conf.Addr.String, }, ui.StringField{ Key: "DB", Label: "Database", - Default: conf.DB, + Default: conf.DB.String, }, ui.StringField{ Key: "Username", Label: "Username", - Default: conf.Username, + Default: conf.Username.String, }, ui.StringField{ Key: "Password", Label: "Password", - Default: conf.Password, + Default: conf.Password.String, }, }, } diff --git a/core/engine.go b/core/engine.go index a3441a42cc2..c11eb704ced 100644 --- a/core/engine.go +++ b/core/engine.go @@ -107,7 +107,7 @@ func NewEngine(ex lib.Executor, o lib.Options) (*Engine, error) { return e, nil } -func (e *Engine) setRunStatus(status int) { +func (e *Engine) setRunStatus(status lib.RunStatus) { if len(e.Collectors) == 0 { return } diff --git a/lib/collector.go b/lib/collector.go index 40d315161f7..e3b77837b02 100644 --- a/lib/collector.go +++ b/lib/collector.go @@ -26,13 +26,24 @@ import ( "github.com/loadimpact/k6/stats" ) -// Run Status used by cloud collector +// RunStatus values can be used by k6 to denote how a script run ends +// and by the cloud executor and collector so that k6 knows the current +// status of a particular script run. +type RunStatus int + +// Possible run status values; iota isn't used intentionally const ( - RunStatusFinished = 3 - RunStatusAbortedUser = 5 - RunStatusAbortedSystem = 6 - RunStatusAbortedScriptError = 7 - RunStatusAbortedThreshold = 8 + RunStatusCreated RunStatus = -2 + RunStatusValidated RunStatus = -1 + RunStatusQueued RunStatus = 0 + RunStatusInitializing RunStatus = 1 + RunStatusRunning RunStatus = 2 + RunStatusFinished RunStatus = 3 + RunStatusTimedOut RunStatus = 4 + RunStatusAbortedUser RunStatus = 5 + RunStatusAbortedSystem RunStatus = 6 + RunStatusAbortedScriptError RunStatus = 7 + RunStatusAbortedThreshold RunStatus = 8 ) // A Collector abstracts the process of funneling samples to an external storage backend, @@ -57,5 +68,5 @@ type Collector interface { GetRequiredSystemTags() TagSet // Set run status - SetRunStatus(status int) + SetRunStatus(status RunStatus) } diff --git a/lib/types/types.go b/lib/types/types.go index 451068aaf23..a6e6305837f 100644 --- a/lib/types/types.go +++ b/lib/types/types.go @@ -23,9 +23,64 @@ package types import ( "bytes" "encoding/json" + "fmt" + "reflect" "time" + + null "gopkg.in/guregu/null.v3" ) +func NullDecoder(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { + typeFrom := f.String() + typeTo := t.String() + + expectedType := "" + switch typeTo { + case "null.String": + if typeFrom == reflect.String.String() { + return null.StringFrom(data.(string)), nil + } + expectedType = reflect.String.String() + case "null.Bool": + if typeFrom == reflect.Bool.String() { + return null.BoolFrom(data.(bool)), nil + } + expectedType = reflect.Bool.String() + case "null.Int": + if typeFrom == reflect.Int.String() { + return null.IntFrom(int64(data.(int))), nil + } + if typeFrom == reflect.Int32.String() { + return null.IntFrom(int64(data.(int32))), nil + } + if typeFrom == reflect.Int64.String() { + return null.IntFrom(data.(int64)), nil + } + expectedType = reflect.Int.String() + case "null.Float": + if typeFrom == reflect.Float32.String() { + return null.FloatFrom(float64(data.(float32))), nil + } + if typeFrom == reflect.Float64.String() { + return null.FloatFrom(data.(float64)), nil + } + expectedType = reflect.Float32.String() + " or " + reflect.Float64.String() + case "types.NullDuration": + if typeFrom == reflect.String.String() { + var d NullDuration + err := d.UnmarshalText([]byte(data.(string))) + return d, err + } + expectedType = reflect.String.String() + } + + if expectedType != "" { + return data, fmt.Errorf("expected '%s', got '%s'", expectedType, typeFrom) + } + + return data, nil +} + // Duration is an alias for time.Duration that de/serialises to JSON as human-readable strings. type Duration time.Duration diff --git a/lib/types/types_test.go b/lib/types/types_test.go index 3cf3da1dcd2..d98db6473f2 100644 --- a/lib/types/types_test.go +++ b/lib/types/types_test.go @@ -22,12 +22,83 @@ package types import ( "encoding/json" + "fmt" "testing" "time" + "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + null "gopkg.in/guregu/null.v3" ) +func TestNullDecoder(t *testing.T) { + type foo struct { + Strs []string + Str null.String + Boolean null.Bool + Integer null.Int + Integer32 null.Int + Integer64 null.Int + Float32 null.Float + Float64 null.Float + Dur NullDuration + } + f := foo{} + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: NullDecoder, + Result: &f, + }) + require.NoError(t, err) + + conf := map[string]interface{}{ + "strs": []string{"fake"}, + "str": "bar", + "boolean": true, + "integer": 42, + "integer32": int32(42), + "integer64": int64(42), + "float32": float32(3.14), + "float64": float64(3.14), + "dur": "1m", + } + + err = dec.Decode(conf) + require.NoError(t, err) + + require.Equal(t, foo{ + Strs: []string{"fake"}, + Str: null.StringFrom("bar"), + Boolean: null.BoolFrom(true), + Integer: null.IntFrom(42), + Integer32: null.IntFrom(42), + Integer64: null.IntFrom(42), + Float32: null.FloatFrom(3.140000104904175), + Float64: null.FloatFrom(3.14), + Dur: NewNullDuration(1*time.Minute, true), + }, f) + + input := map[string][]interface{}{ + "Str": {true, "string", "bool"}, + "Boolean": {"invalid", "bool", "string"}, + "Integer": {"invalid", "int", "string"}, + "Integer32": {true, "int", "bool"}, + "Integer64": {"invalid", "int", "string"}, + "Float32": {true, "float32 or float64", "bool"}, + "Float64": {"invalid", "float32 or float64", "string"}, + "Dur": {10, "string", "int"}, + } + + for k, v := range input { + t.Run("Error Message/"+k, func(t *testing.T) { + err = dec.Decode(map[string]interface{}{ + k: v[0], + }) + assert.EqualError(t, err, fmt.Sprintf("1 error(s) decoding:\n\n* error decoding '%s': expected '%s', got '%s'", k, v[1], v[2])) + }) + } +} + func TestDuration(t *testing.T) { t.Run("String", func(t *testing.T) { assert.Equal(t, "1m15s", Duration(75*time.Second).String()) diff --git a/release notes/upcoming.md b/release notes/upcoming.md index e53b117943f..e4aaf6baeb4 100644 --- a/release notes/upcoming.md +++ b/release notes/upcoming.md @@ -35,6 +35,7 @@ Previously most metrics were emitted only when a script iteration ended. With th ## Bugs fixed! * Metrics emitted by `setup()` and `teardown()` are not discarded anymore. They are emitted and have the implicit root `group` tag values of `setup` and `teardown` respectively (#678) +* Fixed a potential `nil` pointer error when the `k6 cloud` command is interrupted. (#682) ## Breaking Changes diff --git a/stats/cloud/api.go b/stats/cloud/api.go index f78945e4b1f..dd51da19429 100644 --- a/stats/cloud/api.go +++ b/stats/cloud/api.go @@ -33,6 +33,13 @@ import ( "github.com/pkg/errors" ) +type ResultStatus int + +const ( + ResultStatusPassed ResultStatus = 0 + ResultStatusFailed ResultStatus = 1 +) + type ThresholdResult map[string]map[string]bool type TestRun struct { @@ -50,10 +57,10 @@ type CreateTestRunResponse struct { } type TestProgressResponse struct { - RunStatusText string `json:"run_status_text"` - RunStatus int `json:"run_status"` - ResultStatus int `json:"result_status"` - Progress float64 `json:"progress"` + RunStatusText string `json:"run_status_text"` + RunStatus lib.RunStatus `json:"run_status"` + ResultStatus ResultStatus `json:"result_status"` + Progress float64 `json:"progress"` } type LoginResponse struct { @@ -156,17 +163,17 @@ func (c *Client) StartCloudTestRun(name string, projectID int64, arc *lib.Archiv return ctrr.ReferenceID, nil } -func (c *Client) TestFinished(referenceID string, thresholds ThresholdResult, tained bool, runStatus int) error { +func (c *Client) TestFinished(referenceID string, thresholds ThresholdResult, tained bool, runStatus lib.RunStatus) error { url := fmt.Sprintf("%s/tests/%s", c.baseURL, referenceID) - resultStatus := 0 + resultStatus := ResultStatusPassed if tained { - resultStatus = 1 + resultStatus = ResultStatusFailed } data := struct { - ResultStatus int `json:"result_status"` - RunStatus int `json:"run_status"` + ResultStatus ResultStatus `json:"result_status"` + RunStatus lib.RunStatus `json:"run_status"` Thresholds ThresholdResult `json:"thresholds"` }{ resultStatus, diff --git a/stats/cloud/collector.go b/stats/cloud/collector.go index 16e20261e72..eb2a351aacc 100644 --- a/stats/cloud/collector.go +++ b/stats/cloud/collector.go @@ -51,7 +51,7 @@ type Collector struct { client *Client anonymous bool - runStatus int + runStatus lib.RunStatus bufferMutex sync.Mutex bufferHTTPTrails []*netext.Trail @@ -457,6 +457,6 @@ func (c *Collector) GetRequiredSystemTags() lib.TagSet { return lib.GetTagSet("name", "method", "status", "error", "check", "group") } -func (c *Collector) SetRunStatus(status int) { +func (c *Collector) SetRunStatus(status lib.RunStatus) { c.runStatus = status } diff --git a/stats/dummy/collector.go b/stats/dummy/collector.go index 21524af7a8b..f5ad2f9a8ae 100644 --- a/stats/dummy/collector.go +++ b/stats/dummy/collector.go @@ -30,7 +30,7 @@ import ( // Collector implements the lib.Collector interface and should be used only for testing type Collector struct { - runStatus int + RunStatus lib.RunStatus SampleContainers []stats.SampleContainer Samples []stats.Sample @@ -48,7 +48,7 @@ func (c *Collector) MakeConfig() interface{} { return nil } // Run just blocks until the context is done func (c *Collector) Run(ctx context.Context) { <-ctx.Done() - log.Debugf("finished status: %s", c.runStatus) + log.Debugf("finished status: %s", c.RunStatus) } // Collect just appends all of the samples passed to it to the internal sample slice. @@ -74,6 +74,7 @@ func (c *Collector) GetRequiredSystemTags() lib.TagSet { return lib.TagSet{} // There are no required tags for this collector } -func (c *Collector) SetRunStatus(status int) { - c.runStatus = status +// SetRunStatus just saves the passed status for later inspection +func (c *Collector) SetRunStatus(status lib.RunStatus) { + c.RunStatus = status } diff --git a/stats/influxdb/collector.go b/stats/influxdb/collector.go index 75ed4eee819..9041c030a7d 100644 --- a/stats/influxdb/collector.go +++ b/stats/influxdb/collector.go @@ -94,7 +94,7 @@ func (c *Collector) Collect(scs []stats.SampleContainer) { } func (c *Collector) Link() string { - return c.Config.Addr + return c.Config.Addr.String } func (c *Collector) commit() { @@ -192,4 +192,5 @@ func (c *Collector) GetRequiredSystemTags() lib.TagSet { return lib.TagSet{} // There are no required tags for this collector } -func (c *Collector) SetRunStatus(status int) {} +// SetRunStatus does nothing in the InfluxDB collector +func (c *Collector) SetRunStatus(status lib.RunStatus) {} diff --git a/stats/influxdb/config.go b/stats/influxdb/config.go index c9b443abeb5..52298b7290b 100644 --- a/stats/influxdb/config.go +++ b/stats/influxdb/config.go @@ -26,58 +26,63 @@ import ( "strings" "github.com/kubernetes/helm/pkg/strvals" + "github.com/loadimpact/k6/lib/types" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + null "gopkg.in/guregu/null.v3" ) type Config struct { // Connection. - Addr string `json:"addr" envconfig:"INFLUXDB_ADDR"` - Username string `json:"username,omitempty" envconfig:"INFLUXDB_USERNAME"` - Password string `json:"password,omitempty" envconfig:"INFLUXDB_PASSWORD"` - Insecure bool `json:"insecure,omitempty" envconfig:"INFLUXDB_INSECURE"` - PayloadSize int `json:"payloadSize,omitempty" envconfig:"INFLUXDB_PAYLOAD_SIZE"` + Addr null.String `json:"addr" envconfig:"INFLUXDB_ADDR"` + Username null.String `json:"username,omitempty" envconfig:"INFLUXDB_USERNAME"` + Password null.String `json:"password,omitempty" envconfig:"INFLUXDB_PASSWORD"` + Insecure null.Bool `json:"insecure,omitempty" envconfig:"INFLUXDB_INSECURE"` + PayloadSize null.Int `json:"payloadSize,omitempty" envconfig:"INFLUXDB_PAYLOAD_SIZE"` // Samples. - DB string `json:"db" envconfig:"INFLUXDB_DB"` - Precision string `json:"precision,omitempty" envconfig:"INFLUXDB_PRECISION"` - Retention string `json:"retention,omitempty" envconfig:"INFLUXDB_RETENTION"` - Consistency string `json:"consistency,omitempty" envconfig:"INFLUXDB_CONSISTENCY"` - TagsAsFields []string `json:"tagsAsFields,omitempty" envconfig:"INFLUXDB_TAGS_AS_FIELDS"` + DB null.String `json:"db" envconfig:"INFLUXDB_DB"` + Precision null.String `json:"precision,omitempty" envconfig:"INFLUXDB_PRECISION"` + Retention null.String `json:"retention,omitempty" envconfig:"INFLUXDB_RETENTION"` + Consistency null.String `json:"consistency,omitempty" envconfig:"INFLUXDB_CONSISTENCY"` + TagsAsFields []string `json:"tagsAsFields,omitempty" envconfig:"INFLUXDB_TAGS_AS_FIELDS"` } func NewConfig() *Config { - c := &Config{TagsAsFields: []string{"vu", "iter", "url"}} + c := &Config{ + Addr: null.NewString("http://localhost:8086", false), + DB: null.NewString("k6", false), + TagsAsFields: []string{"vu", "iter", "url"}, + } return c } func (c Config) Apply(cfg Config) Config { - //TODO: fix this, use nullable values like all other configs... - if cfg.Addr != "" { + if cfg.Addr.Valid { c.Addr = cfg.Addr } - if cfg.Username != "" { + if cfg.Username.Valid { c.Username = cfg.Username } - if cfg.Password != "" { + if cfg.Password.Valid { c.Password = cfg.Password } - if cfg.Insecure { + if cfg.Insecure.Valid { c.Insecure = cfg.Insecure } - if cfg.PayloadSize > 0 { + if cfg.PayloadSize.Valid && cfg.PayloadSize.Int64 > 0 { c.PayloadSize = cfg.PayloadSize } - if cfg.DB != "" { + if cfg.DB.Valid { c.DB = cfg.DB } - if cfg.Precision != "" { + if cfg.Precision.Valid { c.Precision = cfg.Precision } - if cfg.Retention != "" { + if cfg.Retention.Valid { c.Retention = cfg.Retention } - if cfg.Consistency != "" { + if cfg.Consistency.Valid { c.Consistency = cfg.Consistency } if len(cfg.TagsAsFields) > 0 { @@ -105,8 +110,15 @@ func ParseMap(m map[string]interface{}) (Config, error) { if v, ok := m["tagsAsFields"].(string); ok { m["tagsAsFields"] = []string{v} } + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: types.NullDecoder, + Result: &c, + }) + if err != nil { + return c, err + } - err := mapstructure.Decode(m, &c) + err = dec.Decode(m) return c, err } @@ -117,14 +129,15 @@ func ParseURL(text string) (Config, error) { return c, err } if u.Host != "" { - c.Addr = u.Scheme + "://" + u.Host + c.Addr = null.StringFrom(u.Scheme + "://" + u.Host) } if db := strings.TrimPrefix(u.Path, "/"); db != "" { - c.DB = db + c.DB = null.StringFrom(db) } if u.User != nil { - c.Username = u.User.Username() - c.Password, _ = u.User.Password() + c.Username = null.StringFrom(u.User.Username()) + pass, _ := u.User.Password() + c.Password = null.StringFrom(pass) } for k, vs := range u.Query() { switch k { @@ -132,20 +145,22 @@ func ParseURL(text string) (Config, error) { switch vs[0] { case "": case "false": - c.Insecure = false + c.Insecure = null.BoolFrom(false) case "true": - c.Insecure = true + c.Insecure = null.BoolFrom(true) default: return c, errors.Errorf("insecure must be true or false, not %s", vs[0]) } case "payload_size": - c.PayloadSize, err = strconv.Atoi(vs[0]) + var size int + size, err = strconv.Atoi(vs[0]) + c.PayloadSize = null.IntFrom(int64(size)) case "precision": - c.Precision = vs[0] + c.Precision = null.StringFrom(vs[0]) case "retention": - c.Retention = vs[0] + c.Retention = null.StringFrom(vs[0]) case "consistency": - c.Consistency = vs[0] + c.Consistency = null.StringFrom(vs[0]) case "tagsAsFields": c.TagsAsFields = vs default: diff --git a/stats/influxdb/config_test.go b/stats/influxdb/config_test.go index 414875c1bda..d3db7021c92 100644 --- a/stats/influxdb/config_test.go +++ b/stats/influxdb/config_test.go @@ -24,15 +24,17 @@ import ( "testing" "github.com/stretchr/testify/assert" + null "gopkg.in/guregu/null.v3" ) func TestParseArg(t *testing.T) { testdata := map[string]Config{ - "": {}, - "db=dbname": {DB: "dbname"}, - "addr=http://localhost:8086": {Addr: "http://localhost:8086"}, - "addr=http://localhost:8086,db=dbname": {Addr: "http://localhost:8086", DB: "dbname"}, - "addr=http://localhost:8086,db=dbname,insecure=false,payloadSize=69": {Addr: "http://localhost:8086", DB: "dbname", Insecure: false, PayloadSize: 69}, + "": {}, + "db=dbname": {DB: null.StringFrom("dbname")}, + "addr=http://localhost:8086": {Addr: null.StringFrom("http://localhost:8086")}, + "addr=http://localhost:8086,db=dbname": {Addr: null.StringFrom("http://localhost:8086"), DB: null.StringFrom("dbname")}, + "addr=http://localhost:8086,db=dbname,insecure=false,payloadSize=69,": {Addr: null.StringFrom("http://localhost:8086"), DB: null.StringFrom("dbname"), Insecure: null.BoolFrom(false), PayloadSize: null.IntFrom(69)}, + "addr=http://localhost:8086,db=dbname,insecure=false,payloadSize=69,tagsAsFields={fake}": {Addr: null.StringFrom("http://localhost:8086"), DB: null.StringFrom("dbname"), Insecure: null.BoolFrom(false), PayloadSize: null.IntFrom(69), TagsAsFields: []string{"fake"}}, } for str, expConfig := range testdata { @@ -48,20 +50,20 @@ func TestParseArg(t *testing.T) { func TestParseURL(t *testing.T) { testdata := map[string]Config{ "": {}, - "dbname": {DB: "dbname"}, - "/dbname": {DB: "dbname"}, - "http://localhost:8086": {Addr: "http://localhost:8086"}, - "http://localhost:8086/dbname": {Addr: "http://localhost:8086", DB: "dbname"}, + "dbname": {DB: null.StringFrom("dbname")}, + "/dbname": {DB: null.StringFrom("dbname")}, + "http://localhost:8086": {Addr: null.StringFrom("http://localhost:8086")}, + "http://localhost:8086/dbname": {Addr: null.StringFrom("http://localhost:8086"), DB: null.StringFrom("dbname")}, } queries := map[string]struct { Config Config Err string }{ "?": {Config{}, ""}, - "?insecure=false": {Config{Insecure: false}, ""}, - "?insecure=true": {Config{Insecure: true}, ""}, + "?insecure=false": {Config{Insecure: null.BoolFrom(false)}, ""}, + "?insecure=true": {Config{Insecure: null.BoolFrom(true)}, ""}, "?insecure=ture": {Config{}, "insecure must be true or false, not ture"}, - "?payload_size=69": {Config{PayloadSize: 69}, ""}, + "?payload_size=69": {Config{PayloadSize: null.IntFrom(69)}, ""}, "?payload_size=a": {Config{}, "strconv.Atoi: parsing \"a\": invalid syntax"}, } for str, data := range testdata { diff --git a/stats/influxdb/util.go b/stats/influxdb/util.go index c2f4b074c56..4f88975836a 100644 --- a/stats/influxdb/util.go +++ b/stats/influxdb/util.go @@ -24,35 +24,36 @@ import ( "strings" client "github.com/influxdata/influxdb/client/v2" + null "gopkg.in/guregu/null.v3" ) func MakeClient(conf Config) (client.Client, error) { - if strings.HasPrefix(conf.Addr, "udp://") { + if strings.HasPrefix(conf.Addr.String, "udp://") { return client.NewUDPClient(client.UDPConfig{ - Addr: strings.TrimPrefix(conf.Addr, "udp://"), - PayloadSize: conf.PayloadSize, + Addr: strings.TrimPrefix(conf.Addr.String, "udp://"), + PayloadSize: int(conf.PayloadSize.Int64), }) } - if conf.Addr == "" { - conf.Addr = "http://localhost:8086" + if conf.Addr.String == "" { + conf.Addr = null.StringFrom("http://localhost:8086") } return client.NewHTTPClient(client.HTTPConfig{ - Addr: conf.Addr, - Username: conf.Username, - Password: conf.Password, + Addr: conf.Addr.String, + Username: conf.Username.String, + Password: conf.Password.String, UserAgent: "k6", - InsecureSkipVerify: conf.Insecure, + InsecureSkipVerify: conf.Insecure.Bool, }) } func MakeBatchConfig(conf Config) client.BatchPointsConfig { - if conf.DB == "" { - conf.DB = "k6" + if !conf.DB.Valid || conf.DB.String == "" { + conf.DB = null.StringFrom("k6") } return client.BatchPointsConfig{ - Precision: conf.Precision, - Database: conf.DB, - RetentionPolicy: conf.Retention, - WriteConsistency: conf.Consistency, + Precision: conf.Precision.String, + Database: conf.DB.String, + RetentionPolicy: conf.Retention.String, + WriteConsistency: conf.Consistency.String, } } diff --git a/stats/influxdb/util_test.go b/stats/influxdb/util_test.go index d793b12a456..2ad746d1082 100644 --- a/stats/influxdb/util_test.go +++ b/stats/influxdb/util_test.go @@ -25,6 +25,7 @@ import ( client "github.com/influxdata/influxdb/client/v2" "github.com/stretchr/testify/assert" + null "gopkg.in/guregu/null.v3" ) func TestMakeBatchConfig(t *testing.T) { @@ -37,7 +38,7 @@ func TestMakeBatchConfig(t *testing.T) { t.Run("DB Set", func(t *testing.T) { assert.Equal(t, client.BatchPointsConfig{Database: "dbname"}, - MakeBatchConfig(Config{DB: "dbname"}), + MakeBatchConfig(Config{DB: null.StringFrom("dbname")}), ) }) } diff --git a/stats/json/collector.go b/stats/json/collector.go index 9f8d8ce012c..d0a9b1a0fa6 100644 --- a/stats/json/collector.go +++ b/stats/json/collector.go @@ -72,7 +72,7 @@ func (c *Collector) Init() error { return nil } -func (c *Collector) SetRunStatus(status int) {} +func (c *Collector) SetRunStatus(status lib.RunStatus) {} func (c *Collector) Run(ctx context.Context) { log.WithField("filename", c.fname).Debug("JSON: Writing JSON metrics") diff --git a/stats/kafka/collector.go b/stats/kafka/collector.go index 91194c8d7a9..1de508ead47 100644 --- a/stats/kafka/collector.go +++ b/stats/kafka/collector.go @@ -103,7 +103,8 @@ func (c *Collector) GetRequiredSystemTags() lib.TagSet { return lib.TagSet{} // There are no required tags for this collector } -func (c *Collector) SetRunStatus(status int) {} +// SetRunStatus does nothing in the Kafka collector +func (c *Collector) SetRunStatus(status lib.RunStatus) {} func (c *Collector) formatSamples(samples stats.Samples) ([]string, error) { var metrics []string