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

chore: add E2E tests for sidecars #577

Merged
merged 5 commits into from
Nov 8, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/knuu_testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ jobs:
timeout: 10m
- pkg: "./e2e/basic"
timeout: 15m
- pkg: "./e2e/sidecars"
timeout: 5m
- pkg: "./e2e/system"
timeout: 15m
- pkg: "./e2e/netshaper"
Expand Down
84 changes: 0 additions & 84 deletions e2e/basic/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,13 @@ package basic

import (
"context"
"errors"
"fmt"
"io"
"time"

"github.com/celestiaorg/knuu/pkg/instance"
"github.com/celestiaorg/knuu/pkg/system"
)

const expectedLogMsg = "Hello World"

type sidecarLogsTest struct {
instance *instance.Instance
}

var _ instance.SidecarManager = (*sidecarLogsTest)(nil)

func (s *Suite) TestLogs() {
const namePrefix = "logs"
ctx := context.Background()
Expand Down Expand Up @@ -46,77 +36,3 @@ func (s *Suite) TestLogs() {
logOutput := string(logs)
s.Contains(logOutput, expectedLogMsg)
}

func (s *Suite) TestLogsWithSidecar() {
const namePrefix = "logs-sidecar"
ctx := context.Background()

// Create a new instance
target, err := s.Knuu.NewInstance(namePrefix + "-target")
s.Require().NoError(err)

sidecar := &sidecarLogsTest{}

s.Require().NoError(target.Build().SetImage(ctx, alpineImage))
s.Require().NoError(target.Build().SetStartCommand("sh", "-c", "sleep infinity"))
s.Require().NoError(target.Build().Commit(ctx))
s.Require().NoError(target.Sidecars().Add(ctx, sidecar))
s.Require().NoError(target.Execution().Start(ctx))

// Wait for a short duration to allow log generation
time.Sleep(5 * time.Second)

logStream, err := sidecar.Instance().Monitoring().Logs(ctx)
s.Require().NoError(err)
defer logStream.Close()

logs, err := io.ReadAll(logStream)
s.Require().NoError(err)

logOutput := string(logs)
s.Contains(logOutput, expectedLogMsg)
}

func (sl *sidecarLogsTest) Initialize(ctx context.Context, namePrefix string, sysDeps *system.SystemDependencies) error {
var err error
sl.instance, err = instance.New(namePrefix+"-sidecar-logs", sysDeps)
if err != nil {
return err
}
sl.instance.Sidecars().SetIsSidecar(true)

if err := sl.instance.Build().SetImage(ctx, alpineImage); err != nil {
return err
}

err = sl.instance.Build().SetStartCommand("sh", "-c", fmt.Sprintf("while true; do echo '%s'; sleep 1; done", expectedLogMsg))
if err != nil {
return err
}

if err := sl.instance.Build().Commit(ctx); err != nil {
return err
}
return nil
}

func (sl *sidecarLogsTest) PreStart(ctx context.Context) error {
if sl.instance == nil {
return errors.New("instance not initialized")
}
return nil
}

func (sl *sidecarLogsTest) Instance() *instance.Instance {
return sl.instance
}

func (sl *sidecarLogsTest) Clone(namePrefix string) (instance.SidecarManager, error) {
clone, err := sl.instance.CloneWithName(namePrefix + "-" + sl.instance.Name())
if err != nil {
return nil, err
}
return &sidecarLogsTest{
instance: clone,
}, nil
}
28 changes: 28 additions & 0 deletions e2e/sidecars/cmd_exec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package sidecars

import (
"context"
"strings"
)

MSevey marked this conversation as resolved.
Show resolved Hide resolved
func (s *Suite) TestExecuteCommandInSidecar() {
const (
namePrefix = "execute-command-in-sidecar"
cmdMsg = "Hello World!"
command = "echo " + cmdMsg
)

ctx := context.Background()

sidecar := &testSidecar{
StartCommand: []string{"sh", "-c", "sleep infinity"},
}
s.startNewInstanceWithSidecar(ctx, namePrefix, sidecar)

// Create a file in the sidecar instance
out, err := sidecar.Instance().Execution().ExecuteCommand(ctx, command)
s.Require().NoError(err, "executing command output: %v", out)

outTrimmed := strings.TrimSpace(out)
s.Assert().Equal(cmdMsg, outTrimmed)
}
mojtaba-esk marked this conversation as resolved.
Show resolved Hide resolved
28 changes: 28 additions & 0 deletions e2e/sidecars/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package sidecars

import (
"context"
)

MSevey marked this conversation as resolved.
Show resolved Hide resolved
func (s *Suite) TestDownloadFileFromRunningSidecar() {
const (
namePrefix = "download-file-running-sidecar"
fileContent = "Hello World!"
filePath = "/hello.txt"
)
ctx := context.Background()

sidecar := &testSidecar{
StartCommand: []string{"sh", "-c", "sleep infinity"},
}
s.startNewInstanceWithSidecar(ctx, namePrefix, sidecar)

// Create a file in the sidecar instance
out, err := sidecar.Instance().Execution().ExecuteCommand(ctx, "echo", "-n", fileContent, ">", filePath)
s.Require().NoError(err, "executing command output: %v", out)

gotContent, err := sidecar.Instance().Storage().GetFileBytes(ctx, filePath)
s.Require().NoError(err, "Failed to read file %s from sidecar: %v", filePath, err)

s.Assert().Equal(fileContent, string(gotContent))
}
43 changes: 43 additions & 0 deletions e2e/sidecars/logs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package sidecars

import (
"context"
"fmt"
"io"
"strings"
"time"
)

func (s *Suite) TestLogsWithSidecar() {
const (
namePrefix = "logs-sidecar"
expectedLogMsg = "Hello World"
timeout = 10 * time.Second
interval = 1 * time.Second
)
ctx := context.Background()

sidecar := &testSidecar{
StartCommand: []string{
"sh", "-c",
fmt.Sprintf("while true; do echo '%s'; sleep 1; done", expectedLogMsg),
},
}
s.startNewInstanceWithSidecar(ctx, namePrefix, sidecar)

// Wait for a short duration to allow log generation
s.Require().Eventually(func() bool {
mojtaba-esk marked this conversation as resolved.
Show resolved Hide resolved
logStream, err := sidecar.Instance().Monitoring().Logs(ctx)
if err != nil {
return false
}
defer logStream.Close()

logs, err := io.ReadAll(logStream)
if err != nil {
return false
}

return strings.Contains(string(logs), expectedLogMsg)
}, timeout, interval, "failed to get expected log message")
}
64 changes: 64 additions & 0 deletions e2e/sidecars/sidecar_def_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package sidecars

import (
"context"
"errors"

"github.com/celestiaorg/knuu/pkg/instance"
"github.com/celestiaorg/knuu/pkg/system"
)

type testSidecar struct {
instance *instance.Instance
StartCommand []string
}

var _ instance.SidecarManager = (*testSidecar)(nil)

func (s *testSidecar) Initialize(ctx context.Context, namePrefix string, sysDeps *system.SystemDependencies) error {
var err error
s.instance, err = instance.New(namePrefix+"-sidecar-logs", sysDeps)
if err != nil {
return err
}
s.instance.Sidecars().SetIsSidecar(true)

if err := s.instance.Build().SetImage(ctx, alpineImage); err != nil {
mojtaba-esk marked this conversation as resolved.
Show resolved Hide resolved
return err
}

err = s.instance.Build().SetStartCommand(s.StartCommand...)
if err != nil {
return err
}

if err := s.instance.Build().Commit(ctx); err != nil {
return err
}
return nil
}
mojtaba-esk marked this conversation as resolved.
Show resolved Hide resolved

func (s *testSidecar) PreStart(ctx context.Context) error {
if s.instance == nil {
return errors.New("instance not initialized")
}
if len(s.StartCommand) == 0 {
return errors.New("start command not configured")
}
return nil
}

func (s *testSidecar) Instance() *instance.Instance {
return s.instance
}

func (s *testSidecar) Clone(namePrefix string) (instance.SidecarManager, error) {
clone, err := s.instance.CloneWithName(namePrefix + "-" + s.instance.Name())
if err != nil {
return nil, err
}
return &testSidecar{
instance: clone,
StartCommand: append([]string{}, s.StartCommand...),
}, nil
}
59 changes: 59 additions & 0 deletions e2e/sidecars/suite_setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package sidecars

import (
"context"
"testing"
"time"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/suite"

"github.com/celestiaorg/knuu/e2e"
"github.com/celestiaorg/knuu/pkg/instance"
"github.com/celestiaorg/knuu/pkg/knuu"
)

const (
testTimeout = time.Minute * 5 // the same time that is used in the ci/cd pipeline
alpineImage = "alpine:3.20.3"
)

type Suite struct {
e2e.Suite
}

func TestRunSuite(t *testing.T) {
suite.Run(t, new(Suite))
}

func (s *Suite) SetupSuite() {
var (
ctx = context.Background()
logger = logrus.New()
err error
)

s.Knuu, err = knuu.New(ctx, knuu.Options{
Timeout: testTimeout,
Logger: logger,
})
s.Require().NoError(err)

s.T().Logf("Scope: %s", s.Knuu.Scope)
s.Knuu.HandleStopSignal(ctx)

s.Executor.Kn = s.Knuu
}

func (s *Suite) startNewInstanceWithSidecar(ctx context.Context, namePrefix string, sidecar *testSidecar) *instance.Instance {
target, err := s.Knuu.NewInstance(namePrefix + "-target")
s.Require().NoError(err)

s.Require().NoError(target.Build().SetImage(ctx, alpineImage))
s.Require().NoError(target.Build().SetStartCommand("sh", "-c", "sleep infinity"))
s.Require().NoError(target.Build().Commit(ctx))
s.Require().NoError(target.Sidecars().Add(ctx, sidecar))
s.Require().NoError(target.Execution().Start(ctx))

return target
}
Loading