Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(k6):Add remote test scripts #2350

Merged
merged 10 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
86 changes: 82 additions & 4 deletions modules/k6/k6.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package k6
import (
"context"
"fmt"
"io"
"net/http"
"os"
"path"
"path/filepath"
"time"

"github.com/docker/docker/api/types/mount"

Expand All @@ -17,17 +21,78 @@ type K6Container struct {
testcontainers.Container
}

type RemoteTestFileDescription struct{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Uri string
bearrito marked this conversation as resolved.
Show resolved Hide resolved
DownloadDir string
User string
Password string
}

func ( d *RemoteTestFileDescription) getDownloadPath() string{
bearrito marked this conversation as resolved.
Show resolved Hide resolved
baseName := path.Base(d.Uri)
return path.Join(d.DownloadDir,baseName)

bearrito marked this conversation as resolved.
Show resolved Hide resolved
}

func downloadFileFromDescription(d RemoteTestFileDescription) error{

bearrito marked this conversation as resolved.
Show resolved Hide resolved
client := http.Client{Timeout: time.Second*60}
// Set up HTTPS request with basic authorization.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

req, err := http.NewRequest(http.MethodGet, d.Uri, nil)
if err != nil {
return err
}

req.Header.Set("Content-Type", "text/javascript")
if d.User != "" && d.Password != ""{
req.SetBasicAuth(d.User, d.Password)
}

resp, err := client.Do(req)
if err != nil {
return err
}

bearrito marked this conversation as resolved.
Show resolved Hide resolved

out, err := os.Create(d.getDownloadPath())
if err != nil {
return err
}
defer out.Close()

// Write the body to file
bearrito marked this conversation as resolved.
Show resolved Hide resolved
_, err = io.Copy(out, resp.Body)
return err



mdelapenya marked this conversation as resolved.
Show resolved Hide resolved
}


// WithTestScript mounts the given script into the ./test directory in the container
// and passes it to k6 as the test to run.
// The path to the script must be an absolute path
func WithTestScript(scriptPath string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) {
script := filepath.Base(scriptPath)
target := "/home/k6x/" + script

bearrito marked this conversation as resolved.
Show resolved Hide resolved
scriptBaseName := filepath.Base(scriptPath)
f, err := os.Open(scriptPath)
if err != nil {
panic("Cannot create reader for test file ")
}
return WithTestScriptReader(f,scriptBaseName)

bearrito marked this conversation as resolved.
Show resolved Hide resolved
}

// Copies files into the Container using the Reader API
bearrito marked this conversation as resolved.
Show resolved Hide resolved
func WithTestScriptReader(reader io.Reader, scriptBaseName string) testcontainers.CustomizeRequestOption {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must include these options in the docs (root-dir/docs/modules/k6.md). Let's include that it will only accept Javascript files and the configuration of the http client (timeout=60s, context type, etc) https://github.com/testcontainers/testcontainers-go/pull/2350/files#diff-19a4c472d6cc0154e74ab208f0a048d900eb0e6006b4365b853d56218d73cd5fR40-R50

The users of the module would like to know this option exists and how to use it, from our docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

opt := func(req *testcontainers.GenericContainerRequest) {
target := "/home/k6x/" + scriptBaseName
req.Files = append(
req.Files,
testcontainers.ContainerFile{
HostFilePath: scriptPath,
HostFilePath: "",
bearrito marked this conversation as resolved.
Show resolved Hide resolved
Reader: reader,
ContainerFilePath: target,
FileMode: 0o644,
},
Expand All @@ -36,6 +101,19 @@ func WithTestScript(scriptPath string) testcontainers.CustomizeRequestOption {
// add script to the k6 run command
req.Cmd = append(req.Cmd, target)
}
return opt
}

func WithRemoteTestScript(d RemoteTestFileDescription) testcontainers.CustomizeRequestOption {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add function comments here too. I'd think about if we need to validate the URL here 🤔 Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll use net/URL. I'll assume if the URL parses it's valid for the user's use case. I guess we could also verify on the extension? But I'm not sure what types are allowed for K6




mdelapenya marked this conversation as resolved.
Show resolved Hide resolved
err := downloadFileFromDescription(d)
if err != nil {
panic("Not able to download required test script")
}

return WithTestScript(d.getDownloadPath())
}

// WithCmdOptions pass the given options to the k6 run command
Expand Down
27 changes: 23 additions & 4 deletions modules/k6/k6_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package k6_test
import (
"context"
"path/filepath"
"strings"
"testing"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/k6"
)


func TestK6(t *testing.T) {
testCases := []struct {
title string
Expand All @@ -24,19 +27,35 @@ func TestK6(t *testing.T) {
script: "fail.js",
expect: 108,
},
{
title: "Passing remote test",
script: "https://raw.githubusercontent.com/testcontainers/testcontainers-go/main/modules/k6/scripts/pass.js",
expect: 0,
},

}

for _, tc := range testCases {
tc := tc
t.Run(tc.title, func(t *testing.T) {
ctx := context.Background()

absPath, err := filepath.Abs(filepath.Join("scripts", tc.script))
if err != nil {
t.Fatal(err)
var options testcontainers.CustomizeRequestOption
if !strings.HasPrefix(tc.script, "http"){
absPath, err := filepath.Abs(filepath.Join("scripts", tc.script))
if err != nil {
t.Fatal(err)
}
options = k6.WithTestScript(absPath)
}else{
bearrito marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

desc := k6.RemoteTestFileDescription{Uri : tc.script,DownloadDir:t.TempDir() }
options = k6.WithRemoteTestScript(desc)
}

container, err := k6.RunContainer(ctx, k6.WithCache(), k6.WithTestScript(absPath))

bearrito marked this conversation as resolved.
Show resolved Hide resolved

container, err := k6.RunContainer(ctx, k6.WithCache(),options )
if err != nil {
t.Fatal(err)
}
Expand Down
Loading