Skip to content

Commit

Permalink
Merge pull request #1007 from loadimpact/new-schedulers
Browse files Browse the repository at this point in the history
New executors
  • Loading branch information
na-- authored Jul 6, 2020
2 parents c078a8f + 488a1fb commit e16c650
Show file tree
Hide file tree
Showing 259 changed files with 18,892 additions and 5,728 deletions.
9 changes: 5 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- image: circleci/golang:1.14
environment:
GOPATH: /home/circleci/.go_workspace
GOLANGCI_VERSION: v1.25.0
GOLANGCI_VERSION: v1.27.0
working_directory: /home/circleci/.go_workspace/src/github.com/loadimpact/k6
steps:
# Workaround for custom env vars not available in cache keys
Expand Down Expand Up @@ -108,12 +108,10 @@ jobs:
working_directory: /home/circleci/.go_workspace/src/github.com/loadimpact/k6
steps:
- checkout
- setup_remote_docker:
version: 17.11.0-ce
- setup_remote_docker
- run:
name: Setup repo and docker
command: |
git submodule update --init
docker info
echo "{\"https://index.docker.io/v1/\":{\"auth\":\"$DOCKER_AUTH\",\"email\":\"$DOCKER_EMAIL\"}}" >~/.dockercfg
- run:
Expand All @@ -138,6 +136,9 @@ jobs:
if [ "${CIRCLE_BRANCH}" == "master" ]; then
docker tag loadimpact/k6 loadimpact/k6:master
docker push loadimpact/k6:master
elif [ "${CIRCLE_BRANCH}" == "new-schedulers" ]; then
docker tag loadimpact/k6 loadimpact/k6:new-executors
docker push loadimpact/k6:new-executors
elif [[ "${CIRCLE_TAG}" =~ ^v[0-9]+(\.[0-9]+)*$ ]]; then
docker tag loadimpact/k6 loadimpact/k6:${CIRCLE_TAG:1}
docker push loadimpact/k6:latest
Expand Down
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ linters:
- gomodguard
- testpackage
- wsl
- gomnd
- goerr113 # most of the errors here are meant for humans
fast: false
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM golang:1.13-alpine as builder
FROM golang:1.14-alpine as builder
WORKDIR $GOPATH/src/github.com/loadimpact/k6
ADD . .
RUN apk --no-cache add git
RUN CGO_ENABLED=0 go install -a -trimpath -ldflags "-s -w -X github.com/loadimpact/k6/lib/consts.VersionDetails=$(date -u +"%FT%T%z")/$(git describe --always --long --dirty)"

FROM alpine:3.10
FROM alpine:3.11
RUN apk add --no-cache ca-certificates && \
adduser -D -u 12345 -g 12345 k6
COPY --from=builder /go/bin/k6 /usr/bin/k6
Expand Down
10 changes: 5 additions & 5 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Types of questions and where to ask:
- Why do you? -- [community.k6.io](https://community.k6.io/) or [Slack](https://k6.io/slack)
- When will you? -- [community.k6.io](https://community.k6.io/) or [Slack](https://k6.io/slack)

If your questions are about any of the commercial Load Impact services like managed cloud execution and Load Impact Insights, you can contact <[email protected]> or write in the `#loadimpact` channel in [Slack](https://k6.io/slack).
If your questions are about any of the commercial Load Impact services like managed cloud execution and k6 cloud output, you can contact <[email protected]> or write in the `#loadimpact` channel in [Slack](https://k6.io/slack).
11 changes: 7 additions & 4 deletions api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ import (
"github.com/sirupsen/logrus"
logtest "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/negroni"

"github.com/loadimpact/k6/api/common"
"github.com/loadimpact/k6/core"
"github.com/loadimpact/k6/core/local"
"github.com/loadimpact/k6/lib"
"github.com/loadimpact/k6/lib/testutils/minirunner"
)

func testHTTPHandler(rw http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -74,10 +77,10 @@ func TestLogger(t *testing.T) {
}

func TestWithEngine(t *testing.T) {
engine, err := core.NewEngine(nil, lib.Options{})
if !assert.NoError(t, err) {
return
}
execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{}, logrus.StandardLogger())
require.NoError(t, err)
engine, err := core.NewEngine(execScheduler, lib.Options{}, logrus.StandardLogger())
require.NoError(t, err)

rw := httptest.NewRecorder()
r := httptest.NewRequest("GET", "http://example.com/", nil)
Expand Down
72 changes: 63 additions & 9 deletions api/v1/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,79 @@ import (
"net/url"

"github.com/manyminds/api2go/jsonapi"
"github.com/sirupsen/logrus"

"github.com/loadimpact/k6/api/v1"
)

// Client is a simple HTTP client for the REST API.
type Client struct {
BaseURL *url.URL
BaseURL *url.URL
httpClient *http.Client
logger *logrus.Entry
}

func New(base string) (*Client, error) {
// Option function are helpers that enable the flexible configuration of the
// REST API client.
type Option func(*Client)

// New returns a newly configured REST API Client.
func New(base string, options ...Option) (*Client, error) {
baseURL, err := url.Parse("http://" + base)
if err != nil {
return nil, err
}
return &Client{BaseURL: baseURL}, nil
c := &Client{
BaseURL: baseURL,
httpClient: http.DefaultClient,
}

for _, option := range options {
option(c)
}

return c, nil
}

// WithHTTPClient configures the supplied HTTP client to be used when making
// REST API requests.
func WithHTTPClient(httpClient *http.Client) Option {
return Option(func(c *Client) {
c.httpClient = httpClient
})
}

func (c *Client) call(ctx context.Context, method string, rel *url.URL, body, out interface{}) error {
// WithLogger sets the specifield logger to the client.
func WithLogger(logger *logrus.Entry) Option {
return Option(func(c *Client) {
c.logger = logger
})
}

// Call executes the desired REST API request.
func (c *Client) Call(ctx context.Context, method string, rel *url.URL, body, out interface{}) (err error) {
if c.logger != nil {
c.logger.Debugf("[REST API] Making a %s request to '%s'", method, rel.String())
defer func() {
if err != nil {
c.logger.WithError(err).Error("[REST API] Error")
}
}()
}

var bodyReader io.ReadCloser
if body != nil {
bodyData, err := jsonapi.Marshal(body)
if err != nil {
return err
var bodyData []byte
switch val := body.(type) {
case []byte:
bodyData = val
case string:
bodyData = []byte(val)
default:
bodyData, err = jsonapi.Marshal(body)
if err != nil {
return err
}
}
bodyReader = ioutil.NopCloser(bytes.NewBuffer(bodyData))
}
Expand All @@ -63,7 +114,7 @@ func (c *Client) call(ctx context.Context, method string, rel *url.URL, body, ou
}
req = req.WithContext(ctx)

res, err := http.DefaultClient.Do(req)
res, err := c.httpClient.Do(req)
if err != nil {
return err
}
Expand All @@ -82,5 +133,8 @@ func (c *Client) call(ctx context.Context, method string, rel *url.URL, body, ou
return errs.Errors[0]
}

return jsonapi.Unmarshal(data, out)
if out != nil {
return jsonapi.Unmarshal(data, out)
}
return nil
}
7 changes: 3 additions & 4 deletions api/v1/client/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ import (
"context"
"net/url"

"github.com/loadimpact/k6/api/v1"
v1 "github.com/loadimpact/k6/api/v1"
)

var MetricsURL = &url.URL{Path: "/v1/metrics"}

// Metrics returns the current metrics summary.
func (c *Client) Metrics(ctx context.Context) (ret []v1.Metric, err error) {
return ret, c.call(ctx, "GET", MetricsURL, nil, &ret)
return ret, c.Call(ctx, "GET", &url.URL{Path: "/v1/metrics"}, nil, &ret)
}
11 changes: 6 additions & 5 deletions api/v1/client/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ import (
"context"
"net/url"

"github.com/loadimpact/k6/api/v1"
v1 "github.com/loadimpact/k6/api/v1"
)

var StatusURL = &url.URL{Path: "/v1/status"}

// Status returns the current k6 status.
func (c *Client) Status(ctx context.Context) (ret v1.Status, err error) {
return ret, c.call(ctx, "GET", StatusURL, nil, &ret)
return ret, c.Call(ctx, "GET", &url.URL{Path: "/v1/status"}, nil, &ret)
}

// SetStatus tries to change the current status and returns the new one if it
// was successful.
func (c *Client) SetStatus(ctx context.Context, patch v1.Status) (ret v1.Status, err error) {
return ret, c.call(ctx, "PATCH", StatusURL, patch, &ret)
return ret, c.Call(ctx, "PATCH", &url.URL{Path: "/v1/status"}, patch, &ret)
}
3 changes: 2 additions & 1 deletion api/v1/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
package v1

import (
"github.com/loadimpact/k6/lib"
"github.com/manyminds/api2go/jsonapi"
"github.com/pkg/errors"

"github.com/loadimpact/k6/lib"
)

type Check struct {
Expand Down
7 changes: 4 additions & 3 deletions api/v1/group_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import (
"net/http"

"github.com/julienschmidt/httprouter"
"github.com/loadimpact/k6/api/common"
"github.com/manyminds/api2go/jsonapi"

"github.com/loadimpact/k6/api/common"
)

func HandleGetGroups(rw http.ResponseWriter, r *http.Request, p httprouter.Params) {
engine := common.GetEngine(r.Context())

root := NewGroup(engine.Executor.GetRunner().GetDefaultGroup(), nil)
root := NewGroup(engine.ExecutionScheduler.GetRunner().GetDefaultGroup(), nil)
groups := FlattenGroup(root)

data, err := jsonapi.Marshal(groups)
Expand All @@ -47,7 +48,7 @@ func HandleGetGroup(rw http.ResponseWriter, r *http.Request, p httprouter.Params

engine := common.GetEngine(r.Context())

root := NewGroup(engine.Executor.GetRunner().GetDefaultGroup(), nil)
root := NewGroup(engine.ExecutionScheduler.GetRunner().GetDefaultGroup(), nil)
groups := FlattenGroup(root)

var group *Group
Expand Down
69 changes: 37 additions & 32 deletions api/v1/group_routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ import (
"net/http/httptest"
"testing"

"github.com/manyminds/api2go/jsonapi"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/loadimpact/k6/core"
"github.com/loadimpact/k6/core/local"
"github.com/loadimpact/k6/lib"
"github.com/manyminds/api2go/jsonapi"
"github.com/stretchr/testify/assert"
"github.com/loadimpact/k6/lib/testutils/minirunner"
)

func TestGetGroups(t *testing.T) {
Expand All @@ -41,8 +45,10 @@ func TestGetGroups(t *testing.T) {
g2, err := g1.Group("group 2")
assert.NoError(t, err)

engine, err := core.NewEngine(local.New(&lib.MiniRunner{Group: g0}), lib.Options{})
assert.NoError(t, err)
execScheduler, err := local.NewExecutionScheduler(&minirunner.MiniRunner{Group: g0}, logrus.StandardLogger())
require.NoError(t, err)
engine, err := core.NewEngine(execScheduler, lib.Options{}, logrus.StandardLogger())
require.NoError(t, err)

t.Run("list", func(t *testing.T) {
rw := httptest.NewRecorder()
Expand All @@ -61,34 +67,33 @@ func TestGetGroups(t *testing.T) {
}
})

// t.Run("groups", func(t *testing.T) {
// var groups []Group
// assert.NoError(t, jsonapi.Unmarshal(body, &groups))
// if assert.Len(t, groups, 3) {
// for _, g := range groups {
// switch g.ID {
// case g0.ID:
// assert.Equal(t, "", g.Name)
// assert.Nil(t, g.Parent)
// assert.Equal(t, "", g.ParentID)
// assert.Len(t, g.GroupIDs, 1)
// assert.EqualValues(t, []string{g1.ID}, g.GroupIDs)
// case g1.ID:
// assert.Equal(t, "group 1", g.Name)
// assert.Nil(t, g.Parent)
// assert.Equal(t, g0.ID, g.ParentID)
// assert.EqualValues(t, []string{g2.ID}, g.GroupIDs)
// case g2.ID:
// assert.Equal(t, "group 2", g.Name)
// assert.Nil(t, g.Parent)
// assert.Equal(t, g1.ID, g.ParentID)
// assert.EqualValues(t, []string{}, g.GroupIDs)
// default:
// assert.Fail(t, "Unknown ID: "+g.ID)
// }
// }
// }
// })
t.Run("groups", func(t *testing.T) {
var groups []Group
require.NoError(t, jsonapi.Unmarshal(body, &groups))
require.Len(t, groups, 3)
for _, g := range groups {
switch g.ID {
case g0.ID:
assert.Equal(t, "", g.Name)
assert.Nil(t, g.Parent)
assert.Equal(t, "", g.ParentID)
assert.Len(t, g.GroupIDs, 1)
assert.EqualValues(t, []string{g1.ID}, g.GroupIDs)
case g1.ID:
assert.Equal(t, "group 1", g.Name)
assert.Nil(t, g.Parent)
assert.Equal(t, g0.ID, g.ParentID)
assert.EqualValues(t, []string{g2.ID}, g.GroupIDs)
case g2.ID:
assert.Equal(t, "group 2", g.Name)
assert.Nil(t, g.Parent)
assert.Equal(t, g1.ID, g.ParentID)
assert.EqualValues(t, []string{}, g.GroupIDs)
default:
assert.Fail(t, "Unknown ID: "+g.ID)
}
}
})
})
for _, gp := range []*lib.Group{g0, g1, g2} {
t.Run(gp.Name, func(t *testing.T) {
Expand Down
Loading

0 comments on commit e16c650

Please sign in to comment.