Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,34 @@ This [Dockerfile](./Dockerfile) builds a docker image with the k6 binary.

## Configuration

### Running on Elastic Cloud
### Running in Production

> [!NOTE]
> The examples below use Elastic Cloud, which allows to connect via `K6_ELASTICSEARCH_CLOUD_ID`. Alternatively you can also specify the connection URL with `K6_ELASTICSEARCH_URL`.

You can run the new k6 binary against a Cloud cluster with:
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_USER=elastic
export K6_ELASTICSEARCH_PASSWORD=your-password-here

./k6 run script.js -o output-elasticsearch
./k6 run ./examples/script.js -o output-elasticsearch
```

or alternatively via an [API key](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html) (see also how to [create an API key in Kibana](https://www.elastic.co/guide/en/kibana/current/api-keys.html)):
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_API_KEY=your-base64-encoded-api-key-here

./k6 run ./examples/script.js -o output-elasticsearch
```

or a [service account token](https://www.elastic.co/guide/en/elasticsearch/reference/current/service-accounts.html#service-accounts-tokens):
```shell
export K6_ELASTICSEARCH_CLOUD_ID=your-cloud-id-here
export K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN=your-service-account-token-here

./k6 run ./examples/script.js -o output-elasticsearch
```

### Running a local cluster
Expand Down
51 changes: 37 additions & 14 deletions pkg/esoutput/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,25 @@ type Config struct {
CACert null.String `json:"caCertFile" envconfig:"K6_ELASTICSEARCH_CA_CERT_FILE"`
InsecureSkipVerify null.Bool `json:"insecureSkipVerify" envconfig:"K6_ELASTICSEARCH_INSECURE_SKIP_VERIFY"`

User null.String `json:"user" envconfig:"K6_ELASTICSEARCH_USER"`
Password null.String `json:"password" envconfig:"K6_ELASTICSEARCH_PASSWORD"`
User null.String `json:"user" envconfig:"K6_ELASTICSEARCH_USER"`
Password null.String `json:"password" envconfig:"K6_ELASTICSEARCH_PASSWORD"`
APIKey null.String `json:"apiKey" envconfig:"K6_ELASTICSEARCH_API_KEY"`
ServiceAccountToken null.String `json:"serviceAccountToken" envconfig:"K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN"`

FlushPeriod types.NullDuration `json:"flushPeriod" envconfig:"K6_ELASTICSEARCH_FLUSH_PERIOD"`
}

func NewConfig() Config {
return Config{
Url: null.StringFrom("http://localhost:9200"),
CloudID: null.NewString("", false),
CACert: null.NewString("", false),
InsecureSkipVerify: null.BoolFrom(false),
User: null.NewString("", false),
Password: null.NewString("", false),
FlushPeriod: types.NullDurationFrom(defaultFlushPeriod),
Url: null.StringFrom("http://localhost:9200"),
CloudID: null.NewString("", false),
APIKey: null.NewString("", false),
CACert: null.NewString("", false),
InsecureSkipVerify: null.BoolFrom(false),
User: null.NewString("", false),
Password: null.NewString("", false),
ServiceAccountToken: null.NewString("", false),
FlushPeriod: types.NullDurationFrom(defaultFlushPeriod),
}
}

Expand All @@ -71,6 +75,9 @@ func (base Config) Apply(applied Config) Config {
if applied.CloudID.Valid {
base.CloudID = applied.CloudID
}
if applied.APIKey.Valid {
base.APIKey = applied.APIKey
}

if applied.CACert.Valid {
base.CACert = applied.CACert
Expand All @@ -87,6 +94,10 @@ func (base Config) Apply(applied Config) Config {
base.Password = applied.Password
}

if applied.ServiceAccountToken.Valid {
base.ServiceAccountToken = applied.ServiceAccountToken
}

if applied.FlushPeriod.Valid {
base.FlushPeriod = applied.FlushPeriod
}
Expand Down Expand Up @@ -125,6 +136,12 @@ func ParseArg(arg string) (Config, error) {
if v, ok := params["password"].(string); ok {
c.Password = null.StringFrom(v)
}
if v, ok := params["apiKey"].(string); ok {
c.APIKey = null.StringFrom(v)
}
if v, ok := params["serviceAccountToken"].(string); ok {
c.ServiceAccountToken = null.StringFrom(v)
}

if v, ok := params["flushPeriod"].(string); ok {
if err := c.FlushPeriod.UnmarshalText([]byte(v)); err != nil {
Expand Down Expand Up @@ -165,15 +182,15 @@ func GetConsolidatedConfig(jsonRawConf json.RawMessage, env map[string]string, a
}
}

if url, urlDefined := env["K6_ELASTICSEARCH_URL"]; urlDefined {
if url, defined := env["K6_ELASTICSEARCH_URL"]; defined {
result.Url = null.StringFrom(url)
}

if cloudId, cloudIdDefined := env["K6_ELASTICSEARCH_CLOUD_ID"]; cloudIdDefined {
if cloudId, defined := env["K6_ELASTICSEARCH_CLOUD_ID"]; defined {
result.CloudID = null.StringFrom(cloudId)
}

if ca, caDefined := env["K6_ELASTICSEARCH_CA_CERT_FILE"]; caDefined {
if ca, defined := env["K6_ELASTICSEARCH_CA_CERT_FILE"]; defined {
result.CACert = null.StringFrom(ca)
}

Expand All @@ -185,13 +202,19 @@ func GetConsolidatedConfig(jsonRawConf json.RawMessage, env map[string]string, a
}
}

if user, userDefined := env["K6_ELASTICSEARCH_USER"]; userDefined {
if user, defined := env["K6_ELASTICSEARCH_USER"]; defined {
result.User = null.StringFrom(user)
}

if password, passwordDefined := env["K6_ELASTICSEARCH_PASSWORD"]; passwordDefined {
if password, defined := env["K6_ELASTICSEARCH_PASSWORD"]; defined {
result.Password = null.StringFrom(password)
}
if apiKey, defined := env["K6_ELASTICSEARCH_API_KEY"]; defined {
result.APIKey = null.StringFrom(apiKey)
}
if serviceAccountToken, defined := env["K6_ELASTICSEARCH_SERVICE_ACCOUNT_TOKEN"]; defined {
result.ServiceAccountToken = null.StringFrom(serviceAccountToken)
}

if arg != "" {
argConf, err := ParseArg(arg)
Expand Down
12 changes: 9 additions & 3 deletions pkg/esoutput/esoutput.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import (
_ "embed"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"

Expand Down Expand Up @@ -80,7 +80,7 @@ func New(params output.Params) (output.Output, error) {

var esConfig es.Config

// Cloud id takes precendence over a URL (which is localhost by default)
// Cloud id takes precedence over a URL (which is localhost by default)
if config.CloudID.Valid {
esConfig.CloudID = config.CloudID.String
} else if config.Url.Valid {
Expand All @@ -92,8 +92,14 @@ func New(params output.Params) (output.Output, error) {
if config.Password.Valid {
esConfig.Password = config.Password.String
}
if config.APIKey.Valid {
esConfig.APIKey = config.APIKey.String
}
if config.ServiceAccountToken.Valid {
esConfig.ServiceToken = config.ServiceAccountToken.String
}
if config.CACert.Valid {
cert, err := ioutil.ReadFile(config.CACert.String)
cert, err := os.ReadFile(config.CACert.String)
if err != nil {
return nil, err
}
Expand Down