Skip to content

Commit

Permalink
feat: docker agent run command
Browse files Browse the repository at this point in the history
Signed-off-by: Vladislav Sukhin <[email protected]>
  • Loading branch information
vsukhin committed Oct 10, 2024
1 parent dbb0791 commit da30393
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 62 deletions.
14 changes: 7 additions & 7 deletions build/kind/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,14 @@ send_telenetry "docker_installation_started"

# Check if agent key is provided
if [ -z "$AGENT_KEY" ]; then
log "Please provide AGENT_KEY env var"
log "Testkube installation failed. Please provide AGENT_KEY env var"
send_telenetry "docker_installation_failed" "parameter_not_found" "agent key is empty"
exit 1
fi

# Check if cloud url is provided
if [ -z "$CLOUD_URL" ]; then
log "Please provide CLOUD_URL env var"
log "Testkube installation failed. Please provide CLOUD_URL env var"
send_telenetry "docker_installation_failed" "parameter_not_found" "cloud url is empty"
exit 1
fi
Expand Down Expand Up @@ -205,7 +205,7 @@ else
log "Creating Kubernetes cluster using Kind (Kubernetes v1.31.0)..."
kind create cluster --name testkube-cluster --image kindest/node:v1.31.0 --wait 5m
if [ $? -ne 0 ]; then
log "Failed to create Kind cluster."
log "Testkube installation failed. Couldn't create Kind cluster."
send_telenetry "docker_installation_failed" "kind_error" "Kind cluster was not created"
exit 1
fi
Expand All @@ -214,7 +214,7 @@ else
log "Verifying cluster is up..."
kubectl cluster-info
if [ $? -ne 0 ]; then
log "Failed to verify cluster."
log "Testkube installation failed. Couldn't verify cluster."
send_telenetry "docker_installation_failed" "kind_error" "Kind cluster is nor accessible"
exit 1
fi
Expand Down Expand Up @@ -244,7 +244,7 @@ else

# Check if there are any pods in the Testkube namespace
if [ -z "$pod_status" ]; then
log "No pods found in testkube namespace."
log "Testkube installation failed. No pods found in testkube namespace."
send_telenetry "docker_installation_failed" "tetkube_error" "No pods found in testkube namespace"
exit 1
fi
Expand Down Expand Up @@ -293,7 +293,7 @@ else
done

if [ $counter -eq 15 ]; then
log "Testkube validation failed."
log "Testkube installation failed."
send_telenetry "docker_installation_failed" "tetkube_error" "Testkube pods are not up and running"
exit 1
fi
Expand All @@ -303,7 +303,7 @@ else
log "Creating and running Testkube k6 Test Workflow..."
kubectl apply -f /examples/k6.yaml -n testkube

log "Testkube installation successful!"
log "Testkube installation succeed!"
log "You can now use Testkube in your Kind Kubernetes cluster."
send_telenetry "docker_installation_succeed"
fi
Expand Down
8 changes: 8 additions & 0 deletions cmd/kubectl-testkube/commands/common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const (
TKErrConfigInitFailed ErrorCode = "TKERR-1201"
// TKErrInvalidInstallConfig is returned when invalid configuration is supplied when installing or upgrading.
TKErrInvalidInstallConfig ErrorCode = "TKERR-1202"
// TKErrInvalidDockerConfig is returned when docker client configuration is invalid.
TKErrInvalidDockerConfig ErrorCode = "TKERR-1203"

// TKERR-13xx errors are related to install operations.

Expand All @@ -36,6 +38,12 @@ const (
TKErrKubectlCommandFailed ErrorCode = "TKERR-1302"
// TKErrDockerCommandFailed is returned when a docker command fails.
TKErrDockerCommandFailed ErrorCode = "TKERR-1303"
// TKErrDockerLogStreamingFailed is returned when a docker log streaming fails.
TKErrDockerLogStreamingFailed ErrorCode = "TKERR-1304"
// TKErrDockerLogReadingFailed is returned when a docker log reading fails.
TKErrDockerLogReadingFailed ErrorCode = "TKERR-1305"
// TKErrDockerInstallationFailed is returned when a docker installation fails.
TKErrDockerInstallationFailed ErrorCode = "TKERR-1306"

// TKErrCleanOldMigrationJobFailed is returned in case of issues with old migration jobs.
TKErrCleanOldMigrationJobFailed ErrorCode = "TKERR-1401"
Expand Down
74 changes: 71 additions & 3 deletions cmd/kubectl-testkube/commands/common/helper.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package common

import (
"bufio"
"context"
"fmt"
"os/exec"
"strings"
"time"

"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/skratchdot/open-golang/open"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -38,8 +41,9 @@ type HelmOptions struct {
}

const (
github = "GitHub"
gitlab = "GitLab"
github = "GitHub"
gitlab = "GitLab"
dockerDaemonPrefixLen = 8
)

func (o HelmOptions) GetApiURI() string {
Expand Down Expand Up @@ -765,7 +769,7 @@ func RunDockerCommand(args []string) (output string, cliErr *CLIError) {
if err != nil {
return "", NewCLIError(
TKErrDockerCommandFailed,
"docker command failed",
"Docker command failed",
"Check is the Docker service installed and running on your computer by executing 'docker info' ",
err,
)
Expand Down Expand Up @@ -815,3 +819,67 @@ func prepareTestkubeProDockerArgs(options HelmOptions, containerName, dockerImag

return args
}

func StreamDockerLogs(containerName string) *CLIError {
// Create a Docker client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return NewCLIError(
TKErrInvalidDockerConfig,
"Invalid docker config",
"Check your environment variables used to connect to Docker daemon",
err)
}

ctx := context.Background()
// Set options to stream logs and show both stdout and stderr logs
opts := container.LogsOptions{
ShowStdout: true,
ShowStderr: true,
Follow: true, // Follow logs in real-time
Timestamps: false,
}

// Fetch logs from the container
logs, err := cli.ContainerLogs(ctx, containerName, opts)
if err != nil {
return NewCLIError(
TKErrDockerLogStreamingFailed,
"Docker log streaming failed",
"Check that your Testkube Docker Agent container is up and runnning",
err)
}
defer logs.Close()

// Use a buffered scanner to read the logs line by line
scanner := bufio.NewScanner(logs)
for scanner.Scan() {
line := scanner.Bytes()
if len(line) > dockerDaemonPrefixLen {
line = line[dockerDaemonPrefixLen:]
}

fmt.Println(string(line)) // Optional: print logs to console
if strings.Contains(string(line), "Testkube installation succeed") {
break
}

if strings.Contains(string(line), "Testkube installation failed") {
return NewCLIError(
TKErrDockerInstallationFailed,
"Docker installation failed",
"Check logs of your Testkube Docker Agent container",
errors.New(string(line)))
}
}

if err := scanner.Err(); err != nil {
return NewCLIError(
TKErrDockerLogReadingFailed,
"Docker log reading failed",
"Check logs of your Testkube Docker Agent container",
err)
}

return nil
}
15 changes: 9 additions & 6 deletions cmd/kubectl-testkube/commands/pro/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func NewDockerCmd() *cobra.Command {
sendAttemptTelemetry(cmd, cfg)

if !options.NoConfirm {
ui.Warn("This will run Testkube Docker Agent latest version. This may take a few minutes.")
ui.Warn("Please be sure you have Docker service running before continuing!")
ui.Warn("This will run Testkube Docker Agent latest version. This will take a few minutes.")
ui.Warn("Please be sure you have Docker service running before continuing and can run containers in privileged mode!")
ui.NL()

dockerInfo, cliErr := common.RunDockerCommand([]string{"info"})
Expand All @@ -61,16 +61,19 @@ func NewDockerCmd() *cobra.Command {
}
}

spinner := ui.NewSpinner("Running Testkube Docker Agent")
ui.H2("Running Testkube Docker Agent")
if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName, dockerImage); cliErr != nil {
spinner.Fail()
sendErrTelemetry(cmd, cfg, "docker_run", cliErr)
common.HandleCLIError(cliErr)
}

spinner.Success()
if cliErr := common.StreamDockerLogs(containerName); cliErr != nil {
sendErrTelemetry(cmd, cfg, "docker_logs", cliErr)
common.HandleCLIError(cliErr)
}

ui.NL()
ui.Success("Testkube Docker Agent is up and running")

if noLogin {
ui.Alert("Saving Testkube CLI Pro context, you need to authorize CLI through `testkube set context` later")
Expand Down Expand Up @@ -101,7 +104,7 @@ func NewDockerCmd() *cobra.Command {

cmd.Flags().BoolVarP(&noLogin, "no-login", "", false, "Ignore login prompt, set existing token later by `testkube set context`")
cmd.Flags().StringVar(&containerName, "container-name", "testkube-agent", "container name for Testkube Docker Agent")
cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent", "docker image for Testkube Docker Agent")
cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent:latest", "docker image for Testkube Docker Agent")

return cmd
}
45 changes: 29 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/creasty/defaults v1.7.0
github.com/denisbrodbeck/machineid v1.0.1
github.com/docker/docker v25.0.6+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0
github.com/fasthttp/websocket v1.5.0
Expand All @@ -25,7 +26,7 @@ require (
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.6.0
github.com/google/go-containerregistry v0.20.1
github.com/google/uuid v1.5.0
github.com/google/uuid v1.6.0
github.com/gookit/color v1.5.4
github.com/gorilla/websocket v1.5.0
github.com/h2non/filetype v1.1.3
Expand Down Expand Up @@ -61,12 +62,12 @@ require (
go.mongodb.org/mongo-driver v1.11.3
go.uber.org/zap v1.26.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/oauth2 v0.13.0
golang.org/x/sync v0.5.0
golang.org/x/text v0.15.0
golang.org/x/oauth2 v0.21.0
golang.org/x/sync v0.8.0
golang.org/x/text v0.18.0
google.golang.org/appengine v1.6.8
google.golang.org/grpc v1.60.0
google.golang.org/protobuf v1.31.0
google.golang.org/grpc v1.66.1
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.28.4
Expand All @@ -81,35 +82,41 @@ require (
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/briandowns/spinner v1.18.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/glamour v0.5.1-0.20220727184942-e70ff2d969da // indirect
github.com/cli/browser v1.1.0 // indirect
github.com/cli/go-gh v0.1.3-0.20221102170023-e3ec45fb1d1b // indirect
github.com/cli/safeexec v1.0.0 // indirect
github.com/cli/shurcooL-graphql v0.0.2 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/docker/cli v24.0.0+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v25.0.6+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.7.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
Expand Down Expand Up @@ -196,16 +203,22 @@ require (
github.com/yuin/goldmark v1.4.13 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
go.opentelemetry.io/otel v1.30.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
go.opentelemetry.io/otel/sdk v1.30.0 // indirect
go.opentelemetry.io/otel/trace v1.30.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/term v0.24.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.16.1 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
Expand Down
Loading

0 comments on commit da30393

Please sign in to comment.