From e5f155536d72c3bce0e29a1618899f746592196a Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 10 Oct 2024 15:46:24 +0300 Subject: [PATCH 01/10] feat: run docker agent command Signed-off-by: Vladislav Sukhin --- .../commands/common/errors.go | 4 +- .../commands/common/helper.go | 56 +++++++++ cmd/kubectl-testkube/commands/pro.go | 1 + cmd/kubectl-testkube/commands/pro/docker.go | 106 ++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 cmd/kubectl-testkube/commands/pro/docker.go diff --git a/cmd/kubectl-testkube/commands/common/errors.go b/cmd/kubectl-testkube/commands/common/errors.go index 92015d9fba7..1a89bce4eda 100644 --- a/cmd/kubectl-testkube/commands/common/errors.go +++ b/cmd/kubectl-testkube/commands/common/errors.go @@ -32,8 +32,10 @@ const ( // TKErrHelmCommandFailed is returned when a helm command fails. TKErrHelmCommandFailed ErrorCode = "TKERR-1301" - // TKErrKubectlCommandFailed is returned when a kubectl command fail. + // TKErrKubectlCommandFailed is returned when a kubectl command fails. TKErrKubectlCommandFailed ErrorCode = "TKERR-1302" + // TKErrDockerCommandFailed is returned when a docker command fails. + TKErrDockerCommandFailed ErrorCode = "TKERR-1303" // TKErrCleanOldMigrationJobFailed is returned in case of issues with old migration jobs. TKErrCleanOldMigrationJobFailed ErrorCode = "TKERR-1401" diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index a42486e35a1..1d60a1f45c4 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -759,3 +759,59 @@ func UiGetNamespace(cmd *cobra.Command, defaultNamespace string) string { return namespace } + +func RunDockerCommand(args []string) (output string, cliErr *CLIError) { + out, err := process.Execute("docker", args...) + if err != nil { + return "", NewCLIError( + TKErrDockerCommandFailed, + "docker command failed", + "Check is the Docker service installed and running on your computer by executing 'docker info' ", + err, + ) + } + return string(out), nil +} + +func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName string) *CLIError { + // use config if set + if cfg.CloudContext.AgentKey != "" && options.Master.AgentToken == "" { + options.Master.AgentToken = cfg.CloudContext.AgentKey + } + + if options.Master.AgentToken == "" { + return NewCLIError( + TKErrInvalidInstallConfig, + "Invalid install config", + "Provide the agent token by setting the '--agent-token' flag", + errors.New("agent key is required")) + } + + args := prepareTestkubeProDockerArgs(options, containerName) + output, err := RunDockerCommand(args) + if err != nil { + return err + } + + ui.Debug("Docker command output:") + ui.Debug("Arguments", args...) + + ui.Debug("Docker run testkube output", output) + + return nil +} + +// prepareTestkubeProDockerArgs prepares docker arguments for Testkube Pro running. +func prepareTestkubeProDockerArgs(options HelmOptions, containerName string) []string { + args := []string{ + "run", + "--name", containerName, + "--privileged", + "-d", + "-e", "CLOUD_URL=" + options.Master.URIs.Agent, + "-e", "AGENT_KEY=" + options.Master.AgentToken, + "kubeshop/testkube-agent", + } + + return args +} diff --git a/cmd/kubectl-testkube/commands/pro.go b/cmd/kubectl-testkube/commands/pro.go index 09986b4c757..4fae70e3bc4 100644 --- a/cmd/kubectl-testkube/commands/pro.go +++ b/cmd/kubectl-testkube/commands/pro.go @@ -19,6 +19,7 @@ func NewProCmd() *cobra.Command { cmd.AddCommand(pro.NewDisconnectCmd()) cmd.AddCommand(pro.NewInitCmd()) cmd.AddCommand(pro.NewLoginCmd()) + cmd.AddCommand(pro.NewDockerCmd()) return cmd } diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go new file mode 100644 index 00000000000..df713018d87 --- /dev/null +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -0,0 +1,106 @@ +package pro + +import ( + "os" + + "github.com/spf13/cobra" + + "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" + "github.com/kubeshop/testkube/pkg/ui" +) + +func NewDockerCmd() *cobra.Command { + var noLogin bool // ignore ask for login + var containerName string + var options common.HelmOptions + + cmd := &cobra.Command{ + Use: "docker", + Short: "Run Testkube Docker Agent and connect to Testkube Pro environment", + Aliases: []string{"da", "docker-agent"}, + Run: func(cmd *cobra.Command, args []string) { + ui.Info("WELCOME TO") + ui.Logo() + + cfg, err := config.Load() + if err != nil { + cliErr := common.NewCLIError( + common.TKErrConfigInitFailed, + "Error loading testkube config file", + "Check is the Testkube config file (~/.testkube/config.json) accessible and has right permissions", + err, + ) + cliErr.Print() + os.Exit(1) + } + ui.NL() + + common.ProcessMasterFlags(cmd, &options, &cfg) + + 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.NL() + + dockerInfo, cliErr := common.RunDockerCommand([]string{"info"}) + if cliErr != nil { + sendErrTelemetry(cmd, cfg, "docker_info", err) + common.HandleCLIError(cliErr) + } + ui.Alert("Current docker info:", dockerInfo) + ui.NL() + + ok := ui.Confirm("Do you want to continue?") + if !ok { + ui.Errf("Testkube Docker Agent running cancelled") + sendErrTelemetry(cmd, cfg, "user_cancel", err) + return + } + } + + spinner := ui.NewSpinner("Running Testkube Docker Agent") + if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName); cliErr != nil { + spinner.Fail() + sendErrTelemetry(cmd, cfg, "docker_run", cliErr) + common.HandleCLIError(cliErr) + } + + spinner.Success() + + ui.NL() + + if noLogin { + ui.Alert("Saving Testkube CLI Pro context, you need to authorize CLI through `testkube set context` later") + common.PopulateCloudConfig(cfg, "", &options) + ui.Info(" Happy Testing! 🚀") + ui.NL() + return + } + + ui.H2("Saving Testkube CLI Pro context") + var token, refreshToken string + if !common.IsUserLoggedIn(cfg, options) { + token, refreshToken, err = common.LoginUser(options.Master.URIs.Auth) + sendErrTelemetry(cmd, cfg, "login", err) + ui.ExitOnError("user login", err) + } + err = common.PopulateLoginDataToContext(options.Master.OrgId, options.Master.EnvId, token, refreshToken, options, cfg) + if err != nil { + sendErrTelemetry(cmd, cfg, "setting_context", err) + ui.ExitOnError("Setting Pro environment context", err) + } + ui.Info(" Happy Testing! 🚀") + ui.NL() + }, + } + + common.PopulateMasterFlags(cmd, &options) + + 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") + + return cmd +} From dbb0791be9d8b873d7ca219e6f592efa1de1c7f2 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 10 Oct 2024 16:38:36 +0300 Subject: [PATCH 02/10] fix: docker image parameter Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/common/helper.go | 8 ++++---- cmd/kubectl-testkube/commands/pro/docker.go | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 1d60a1f45c4..682eb672270 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -773,7 +773,7 @@ func RunDockerCommand(args []string) (output string, cliErr *CLIError) { return string(out), nil } -func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName string) *CLIError { +func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName, dockerImage string) *CLIError { // use config if set if cfg.CloudContext.AgentKey != "" && options.Master.AgentToken == "" { options.Master.AgentToken = cfg.CloudContext.AgentKey @@ -787,7 +787,7 @@ func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName errors.New("agent key is required")) } - args := prepareTestkubeProDockerArgs(options, containerName) + args := prepareTestkubeProDockerArgs(options, containerName, dockerImage) output, err := RunDockerCommand(args) if err != nil { return err @@ -802,7 +802,7 @@ func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName } // prepareTestkubeProDockerArgs prepares docker arguments for Testkube Pro running. -func prepareTestkubeProDockerArgs(options HelmOptions, containerName string) []string { +func prepareTestkubeProDockerArgs(options HelmOptions, containerName, dockerImage string) []string { args := []string{ "run", "--name", containerName, @@ -810,7 +810,7 @@ func prepareTestkubeProDockerArgs(options HelmOptions, containerName string) []s "-d", "-e", "CLOUD_URL=" + options.Master.URIs.Agent, "-e", "AGENT_KEY=" + options.Master.AgentToken, - "kubeshop/testkube-agent", + dockerImage, } return args diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index df713018d87..a3f676ac418 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -12,7 +12,7 @@ import ( func NewDockerCmd() *cobra.Command { var noLogin bool // ignore ask for login - var containerName string + var containerName, dockerImage string var options common.HelmOptions cmd := &cobra.Command{ @@ -62,7 +62,7 @@ func NewDockerCmd() *cobra.Command { } spinner := ui.NewSpinner("Running Testkube Docker Agent") - if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName); cliErr != nil { + if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName, dockerImage); cliErr != nil { spinner.Fail() sendErrTelemetry(cmd, cfg, "docker_run", cliErr) common.HandleCLIError(cliErr) @@ -101,6 +101,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") return cmd } From da30393020a81691c88a977a1db41a4846a72f58 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 10 Oct 2024 21:25:31 +0300 Subject: [PATCH 03/10] feat: docker agent run command Signed-off-by: Vladislav Sukhin --- build/kind/entrypoint.sh | 14 +-- .../commands/common/errors.go | 8 ++ .../commands/common/helper.go | 74 +++++++++++- cmd/kubectl-testkube/commands/pro/docker.go | 15 ++- go.mod | 45 +++++--- go.sum | 105 +++++++++++++----- 6 files changed, 199 insertions(+), 62 deletions(-) diff --git a/build/kind/entrypoint.sh b/build/kind/entrypoint.sh index de2ee74779b..65ab7a270a7 100644 --- a/build/kind/entrypoint.sh +++ b/build/kind/entrypoint.sh @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/cmd/kubectl-testkube/commands/common/errors.go b/cmd/kubectl-testkube/commands/common/errors.go index 1a89bce4eda..8279f2f49a2 100644 --- a/cmd/kubectl-testkube/commands/common/errors.go +++ b/cmd/kubectl-testkube/commands/common/errors.go @@ -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. @@ -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" diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 682eb672270..0a8b3b52a2e 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -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" @@ -38,8 +41,9 @@ type HelmOptions struct { } const ( - github = "GitHub" - gitlab = "GitLab" + github = "GitHub" + gitlab = "GitLab" + dockerDaemonPrefixLen = 8 ) func (o HelmOptions) GetApiURI() string { @@ -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, ) @@ -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 +} diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index a3f676ac418..77f68c3169e 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -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"}) @@ -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") @@ -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 } diff --git a/go.mod b/go.mod index 15da31b15ad..9bc0985e7c7 100644 --- a/go.mod +++ b/go.mod @@ -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 @@ -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 @@ -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 @@ -81,6 +82,7 @@ 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 @@ -88,28 +90,33 @@ require ( 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 @@ -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 diff --git a/go.sum b/go.sum index fb97ba77b01..bdae9af276b 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,8 @@ github.com/99designs/gqlgen v0.17.27 h1:XPsaZiWY1lL2qqVYtBt37GzkyX7bBiVvda7k1buC github.com/99designs/gqlgen v0.17.27/go.mod h1:i4rEatMrzzu6RXaHydq1nmEPZkb3bKQsnxNRHS4DQB4= github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw= github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -64,6 +66,8 @@ github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s= github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/adhocore/gronx v1.6.3 h1:bnm5vieTrY3QQPpsfB0hrAaeaHDpuZTUC2LLCVMLe9c= @@ -95,9 +99,11 @@ github.com/briandowns/spinner v1.18.1 h1:yhQmQtM1zsqFsouh09Bk/jCjd50pC3EOGsh28gL github.com/briandowns/spinner v1.18.1/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= github.com/cdevents/sdk-go v0.3.0 h1:YHb47qIVi3qV+HmkyW3e0gqCQaqKW0rnL4EejSDuMFs= github.com/cdevents/sdk-go v0.3.0/go.mod h1:8EFl9VDZkxEmO/sr06Phzr501OiU6B5d04+eYpf1tF0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/glamour v0.5.1-0.20220727184942-e70ff2d969da h1:FGz53GWQRiKQ/5xUsoCCkewSQIC7u81Scaxx2nUy3nM= github.com/charmbracelet/glamour v0.5.1-0.20220727184942-e70ff2d969da/go.mod h1:HXz79SMFnF9arKxqeoHWxmo1BhplAH7wehlRhKQIL94= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -121,6 +127,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= @@ -140,6 +148,8 @@ github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMS github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM= @@ -150,6 +160,10 @@ github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1b github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0 h1:90Ly+6UfUypEF6vvvW5rQIv9opIL8CbmW9FT20LDQoY= @@ -171,6 +185,8 @@ github.com/fasthttp/websocket v1.5.0/go.mod h1:n0BlOQvJdPbTuBkZT0O5+jk/sp/1/VCzq github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluxcd/pkg/apis/event v0.2.0 h1:cmAtkZfoEaNVYegI4SFM8XstdRAil3O9AoP+8fpbR34= github.com/fluxcd/pkg/apis/event v0.2.0/go.mod h1:OyzKqs90J+MK7rQaEOFMMCkALpPkfmxlkabgyY2wSFQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -183,8 +199,11 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -297,8 +316,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -311,6 +330,9 @@ github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= @@ -420,6 +442,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -432,6 +456,8 @@ github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v6 github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/moogar0880/problems v0.1.1 h1:bktLhq8NDG/czU2ZziYNigBFksx13RaYe5AVdNmHDT4= github.com/moogar0880/problems v0.1.1/go.mod h1:5Dxrk2sD7BfBAgnOzQ1yaTiuCYdGPUh49L8Vhfky62c= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.11.0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= @@ -623,6 +649,22 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= +go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -641,8 +683,8 @@ golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -681,8 +723,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -723,8 +765,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -734,8 +776,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -749,8 +791,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -817,16 +859,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -838,8 +880,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -897,8 +939,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -969,8 +1011,11 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 h1:9NWlQfY2ePejTmfwUH1OWwmznFa+0kKcHGPDvcPza9M= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -987,8 +1032,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= +google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1001,8 +1046,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 7c815312971fd0bbfd5cd794c0348c767830e94f Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 11 Oct 2024 17:18:42 +0300 Subject: [PATCH 04/10] fix: use verbose flag Signed-off-by: Vladislav Sukhin --- .../commands/common/helper.go | 5 ++++- cmd/kubectl-testkube/commands/pro/docker.go | 21 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 0a8b3b52a2e..2d8835a1ca9 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -859,7 +859,10 @@ func StreamDockerLogs(containerName string) *CLIError { line = line[dockerDaemonPrefixLen:] } - fmt.Println(string(line)) // Optional: print logs to console + if ui.IsVerbose() { + fmt.Println(string(line)) // Optional: print logs to console + } + if strings.Contains(string(line), "Testkube installation succeed") { break } diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index 77f68c3169e..a3829dc1c29 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -3,6 +3,7 @@ package pro import ( "os" + "github.com/pterm/pterm" "github.com/spf13/cobra" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" @@ -61,19 +62,35 @@ func NewDockerCmd() *cobra.Command { } } - ui.H2("Running Testkube Docker Agent") + var spinner *pterm.SpinnerPrinter + if ui.IsVerbose() { + ui.H2("Running Testkube Docker Agent") + } else { + spinner = ui.NewSpinner("Running Testkube Docker Agent") + } + if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName, dockerImage); cliErr != nil { + if spinner != nil { + spinner.Fail() + } sendErrTelemetry(cmd, cfg, "docker_run", cliErr) common.HandleCLIError(cliErr) } if cliErr := common.StreamDockerLogs(containerName); cliErr != nil { + if spinner != nil { + spinner.Fail() + } sendErrTelemetry(cmd, cfg, "docker_logs", cliErr) common.HandleCLIError(cliErr) } ui.NL() - ui.Success("Testkube Docker Agent is up and running") + if spinner != nil { + spinner.Success() + } else { + 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") From 2b8afd4437a02e5a078c3a61a9ade7e634ef4d6b Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 11 Oct 2024 23:01:30 +0300 Subject: [PATCH 05/10] feat: docker upgrade command Signed-off-by: Vladislav Sukhin --- .../commands/common/helper.go | 69 +++++++++++++++++-- cmd/kubectl-testkube/commands/pro/connect.go | 2 +- cmd/kubectl-testkube/commands/pro/docker.go | 17 ++--- cmd/kubectl-testkube/commands/pro/init.go | 2 +- cmd/kubectl-testkube/commands/pro/login.go | 2 +- cmd/kubectl-testkube/commands/upgrade.go | 38 +++++++--- cmd/kubectl-testkube/config/data.go | 25 +++---- 7 files changed, 117 insertions(+), 38 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 2d8835a1ca9..e1a7b7e863a 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -296,7 +296,7 @@ func PopulateHelmFlags(cmd *cobra.Command, options *HelmOptions) { cmd.Flags().BoolVar(&options.EmbeddedNATS, "embedded-nats", false, "embedded NATS server in agent") } -func PopulateLoginDataToContext(orgID, envID, token, refreshToken string, options HelmOptions, cfg config.Data) error { +func PopulateLoginDataToContext(orgID, envID, token, refreshToken, dockerContainerName string, options HelmOptions, cfg config.Data) error { if options.Master.AgentToken != "" { cfg.CloudContext.AgentKey = options.Master.AgentToken } @@ -319,6 +319,7 @@ func PopulateLoginDataToContext(orgID, envID, token, refreshToken string, option if refreshToken != "" { cfg.CloudContext.RefreshToken = refreshToken } + cfg.CloudContext.DockerContainerName = dockerContainerName cfg, err := PopulateOrgAndEnvNames(cfg, orgID, envID, options.Master.URIs.Api) if err != nil { @@ -777,7 +778,7 @@ func RunDockerCommand(args []string) (output string, cliErr *CLIError) { return string(out), nil } -func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName, dockerImage string) *CLIError { +func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, dockerContainerName, dockerImage string) *CLIError { // use config if set if cfg.CloudContext.AgentKey != "" && options.Master.AgentToken == "" { options.Master.AgentToken = cfg.CloudContext.AgentKey @@ -791,7 +792,7 @@ func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName, errors.New("agent key is required")) } - args := prepareTestkubeProDockerArgs(options, containerName, dockerImage) + args := prepareTestkubeProDockerArgs(options, dockerContainerName, dockerImage) output, err := RunDockerCommand(args) if err != nil { return err @@ -806,10 +807,10 @@ func DockerRunTestkubeAgent(options HelmOptions, cfg config.Data, containerName, } // prepareTestkubeProDockerArgs prepares docker arguments for Testkube Pro running. -func prepareTestkubeProDockerArgs(options HelmOptions, containerName, dockerImage string) []string { +func prepareTestkubeProDockerArgs(options HelmOptions, dockerContainerName, dockerImage string) []string { args := []string{ "run", - "--name", containerName, + "--name", dockerContainerName, "--privileged", "-d", "-e", "CLOUD_URL=" + options.Master.URIs.Agent, @@ -820,7 +821,33 @@ func prepareTestkubeProDockerArgs(options HelmOptions, containerName, dockerImag return args } -func StreamDockerLogs(containerName string) *CLIError { +// prepareTestkubeUpgradeDockerArgs prepares docker arguments for Testkube Upgrade running. +func prepareTestkubeUpgradeDockerArgs(options HelmOptions, dockerContainerName string) []string { + args := []string{ + "exec", + dockerContainerName, + "helm", + "upgrade", + "testkube", + "testkube/testkube", + "--namespace", + "testkube", + "--set", + "testkube-api.minio.enabled=false", + "--set", + "mongodb.enabled=false", + "--set", + "testkube-dashboard.enabled=false", + "--set", + "testkube-api.cloud.key=" + options.Master.AgentToken, + "--set", + "testkube-api.cloud.url=" + options.Master.URIs.Agent, + } + + return args +} + +func StreamDockerLogs(dockerContainerName string) *CLIError { // Create a Docker client cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { @@ -841,7 +868,7 @@ func StreamDockerLogs(containerName string) *CLIError { } // Fetch logs from the container - logs, err := cli.ContainerLogs(ctx, containerName, opts) + logs, err := cli.ContainerLogs(ctx, dockerContainerName, opts) if err != nil { return NewCLIError( TKErrDockerLogStreamingFailed, @@ -886,3 +913,31 @@ func StreamDockerLogs(containerName string) *CLIError { return nil } + +func DockerUpgradeTestkubeAgent(options HelmOptions, cfg config.Data) *CLIError { + // use config if set + if cfg.CloudContext.AgentKey != "" && options.Master.AgentToken == "" { + options.Master.AgentToken = cfg.CloudContext.AgentKey + } + + if options.Master.AgentToken == "" { + return NewCLIError( + TKErrInvalidInstallConfig, + "Invalid install config", + "Provide the agent token by setting the '--agent-token' flag", + errors.New("agent key is required")) + } + + args := prepareTestkubeUpgradeDockerArgs(options, cfg.CloudContext.DockerContainerName) + output, err := RunDockerCommand(args) + if err != nil { + return err + } + + ui.Debug("Docker command output:") + ui.Debug("Arguments", args...) + + ui.Debug("Docker run testkube output", output) + + return nil +} diff --git a/cmd/kubectl-testkube/commands/pro/connect.go b/cmd/kubectl-testkube/commands/pro/connect.go index 6826dd11073..b3c15d4f9ed 100644 --- a/cmd/kubectl-testkube/commands/pro/connect.go +++ b/cmd/kubectl-testkube/commands/pro/connect.go @@ -165,7 +165,7 @@ func NewConnectCmd() *cobra.Command { token, refreshToken, err = common.LoginUser(opts.Master.URIs.Auth) ui.ExitOnError("user login", err) } - err = common.PopulateLoginDataToContext(opts.Master.OrgId, opts.Master.EnvId, token, refreshToken, opts, cfg) + err = common.PopulateLoginDataToContext(opts.Master.OrgId, opts.Master.EnvId, token, refreshToken, "", opts, cfg) ui.ExitOnError("Setting Pro environment context", err) diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index a3829dc1c29..ea5da009d54 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -1,6 +1,7 @@ package pro import ( + "errors" "os" "github.com/pterm/pterm" @@ -13,7 +14,7 @@ import ( func NewDockerCmd() *cobra.Command { var noLogin bool // ignore ask for login - var containerName, dockerImage string + var dockerContainerName, dockerImage string var options common.HelmOptions cmd := &cobra.Command{ @@ -48,7 +49,7 @@ func NewDockerCmd() *cobra.Command { dockerInfo, cliErr := common.RunDockerCommand([]string{"info"}) if cliErr != nil { - sendErrTelemetry(cmd, cfg, "docker_info", err) + sendErrTelemetry(cmd, cfg, "docker_info", cliErr) common.HandleCLIError(cliErr) } ui.Alert("Current docker info:", dockerInfo) @@ -57,7 +58,7 @@ func NewDockerCmd() *cobra.Command { ok := ui.Confirm("Do you want to continue?") if !ok { ui.Errf("Testkube Docker Agent running cancelled") - sendErrTelemetry(cmd, cfg, "user_cancel", err) + sendErrTelemetry(cmd, cfg, "user_cancel", errors.New("user cancelled agent running")) return } } @@ -69,7 +70,7 @@ func NewDockerCmd() *cobra.Command { spinner = ui.NewSpinner("Running Testkube Docker Agent") } - if cliErr := common.DockerRunTestkubeAgent(options, cfg, containerName, dockerImage); cliErr != nil { + if cliErr := common.DockerRunTestkubeAgent(options, cfg, dockerContainerName, dockerImage); cliErr != nil { if spinner != nil { spinner.Fail() } @@ -77,7 +78,7 @@ func NewDockerCmd() *cobra.Command { common.HandleCLIError(cliErr) } - if cliErr := common.StreamDockerLogs(containerName); cliErr != nil { + if cliErr := common.StreamDockerLogs(dockerContainerName); cliErr != nil { if spinner != nil { spinner.Fail() } @@ -107,7 +108,7 @@ func NewDockerCmd() *cobra.Command { sendErrTelemetry(cmd, cfg, "login", err) ui.ExitOnError("user login", err) } - err = common.PopulateLoginDataToContext(options.Master.OrgId, options.Master.EnvId, token, refreshToken, options, cfg) + err = common.PopulateLoginDataToContext(options.Master.OrgId, options.Master.EnvId, token, refreshToken, dockerContainerName, options, cfg) if err != nil { sendErrTelemetry(cmd, cfg, "setting_context", err) ui.ExitOnError("Setting Pro environment context", err) @@ -120,8 +121,8 @@ func NewDockerCmd() *cobra.Command { common.PopulateMasterFlags(cmd, &options) 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:latest", "docker image for Testkube Docker Agent") + cmd.Flags().StringVar(&dockerContainerName, "docker-container", "testkube-agent", "Docker container name for Testkube Docker Agent") + cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent:latest", "Docker image for Testkube Docker Agent") return cmd } diff --git a/cmd/kubectl-testkube/commands/pro/init.go b/cmd/kubectl-testkube/commands/pro/init.go index 6d437666386..ad7e7673036 100644 --- a/cmd/kubectl-testkube/commands/pro/init.go +++ b/cmd/kubectl-testkube/commands/pro/init.go @@ -97,7 +97,7 @@ func NewInitCmd() *cobra.Command { sendErrTelemetry(cmd, cfg, "login", err) ui.ExitOnError("user login", err) } - err = common.PopulateLoginDataToContext(options.Master.OrgId, options.Master.EnvId, token, refreshToken, options, cfg) + err = common.PopulateLoginDataToContext(options.Master.OrgId, options.Master.EnvId, token, refreshToken, "", options, cfg) if err != nil { sendErrTelemetry(cmd, cfg, "setting_context", err) ui.ExitOnError("Setting Pro environment context", err) diff --git a/cmd/kubectl-testkube/commands/pro/login.go b/cmd/kubectl-testkube/commands/pro/login.go index d928ef02f06..7119bfd94ec 100644 --- a/cmd/kubectl-testkube/commands/pro/login.go +++ b/cmd/kubectl-testkube/commands/pro/login.go @@ -36,7 +36,7 @@ func NewLoginCmd() *cobra.Command { ui.ExitOnError("getting environment", err) } - err = common.PopulateLoginDataToContext(orgID, envID, token, refreshToken, opts, cfg) + err = common.PopulateLoginDataToContext(orgID, envID, token, refreshToken, "", opts, cfg) ui.ExitOnError("saving config file", err) ui.Success("Your config was updated with new values") diff --git a/cmd/kubectl-testkube/commands/upgrade.go b/cmd/kubectl-testkube/commands/upgrade.go index 3fd55221986..bf233b9cf00 100644 --- a/cmd/kubectl-testkube/commands/upgrade.go +++ b/cmd/kubectl-testkube/commands/upgrade.go @@ -13,6 +13,7 @@ import ( func NewUpgradeCmd() *cobra.Command { var options common.HelmOptions + var dockerContainerName string cmd := &cobra.Command{ Use: "upgrade", @@ -32,17 +33,32 @@ func NewUpgradeCmd() *cobra.Command { cfg.ContextType = config.ContextTypeCloud } + if cmd.Flags().Changed("docker-container") { + cfg.CloudContext.DockerContainerName = dockerContainerName + } + if !options.NoConfirm { ui.Warn("This will upgrade Testkube to the latest version. This may take a few minutes.") - ui.Warn("Please be sure you're on valid kubectl context before continuing!") - ui.NL() + if cfg.CloudContext.DockerContainerName != "" { + ui.Warn("Please be sure you have Docker service running before continuing and can run containers in privileged mode!") - currentContext, cliErr := common.GetCurrentKubernetesContext() - common.HandleCLIError(cliErr) + dockerInfo, cliErr := common.RunDockerCommand([]string{"info"}) + if cliErr != nil { + common.HandleCLIError(cliErr) + } - ui.ExitOnError("getting current context", err) - ui.Alert("Current kubectl context:", currentContext) - ui.NL() + ui.Alert("Current docker info:", dockerInfo) + ui.NL() + } else { + ui.Warn("Please be sure you're on valid kubectl context before continuing!") + + currentContext, cliErr := common.GetCurrentKubernetesContext() + common.HandleCLIError(cliErr) + + ui.ExitOnError("getting current context", err) + ui.Alert("Current kubectl context:", currentContext) + ui.NL() + } if ui.IsVerbose() && cfg.ContextType == config.ContextTypeCloud { ui.Info("Your Testkube is in 'cloud' mode with following context") @@ -62,7 +78,11 @@ func NewUpgradeCmd() *cobra.Command { if cfg.ContextType == config.ContextTypeCloud { ui.Info("Testkube Pro agent upgrade started") - err = common.HelmUpgradeOrInstallTestkubeAgent(options, cfg, false) + if cfg.CloudContext.DockerContainerName != "" { + err = common.DockerUpgradeTestkubeAgent(options, cfg) + } else { + err = common.HelmUpgradeOrInstallTestkubeAgent(options, cfg, false) + } ui.ExitOnError("Upgrading Testkube Pro Agent", err) err = common.PopulateAgentDataToContext(options, cfg) ui.ExitOnError("Storing agent data in context", err) @@ -86,5 +106,7 @@ func NewUpgradeCmd() *cobra.Command { common.PopulateHelmFlags(cmd, &options) common.PopulateMasterFlags(cmd, &options) + cmd.Flags().StringVar(&dockerContainerName, "docker-container", "testkube-agent", "Docker container name for Testkube Docker Agent") + return cmd } diff --git a/cmd/kubectl-testkube/config/data.go b/cmd/kubectl-testkube/config/data.go index 7a6b9c31aee..7e67f91dd0a 100644 --- a/cmd/kubectl-testkube/config/data.go +++ b/cmd/kubectl-testkube/config/data.go @@ -17,18 +17,19 @@ const ( ) type CloudContext struct { - EnvironmentId string `json:"environment,omitempty"` - EnvironmentName string `json:"environmentName,omitempty"` - OrganizationId string `json:"organization,omitempty"` - OrganizationName string `json:"organizationName,omitempty"` - ApiKey string `json:"apiKey,omitempty"` - RefreshToken string `json:"refreshToken,omitempty"` - ApiUri string `json:"apiUri,omitempty"` - AgentKey string `json:"agentKey,omitempty"` - AgentUri string `json:"agentUri,omitempty"` - RootDomain string `json:"rootDomain,omitempty"` - UiUri string `json:"uiUri,omitempty"` - TokenType string `json:"tokenType,omitempty"` + EnvironmentId string `json:"environment,omitempty"` + EnvironmentName string `json:"environmentName,omitempty"` + OrganizationId string `json:"organization,omitempty"` + OrganizationName string `json:"organizationName,omitempty"` + ApiKey string `json:"apiKey,omitempty"` + RefreshToken string `json:"refreshToken,omitempty"` + ApiUri string `json:"apiUri,omitempty"` + AgentKey string `json:"agentKey,omitempty"` + AgentUri string `json:"agentUri,omitempty"` + RootDomain string `json:"rootDomain,omitempty"` + UiUri string `json:"uiUri,omitempty"` + TokenType string `json:"tokenType,omitempty"` + DockerContainerName string `json:"dockerContainerName,omitempty"` } type Data struct { From 4f764acb788a1e99bac2608f066892fd4ee4ed6b Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 14 Oct 2024 14:46:14 +0300 Subject: [PATCH 06/10] fix: pass docker image version Signed-off-by: Vladislav Sukhin --- .../commands/common/helper.go | 37 +++++++++++++++++-- cmd/kubectl-testkube/commands/upgrade.go | 4 +- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index e1a7b7e863a..89b3aed66a2 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -3,7 +3,10 @@ package common import ( "bufio" "context" + "encoding/json" "fmt" + "io" + "net/http" "os/exec" "strings" "time" @@ -44,6 +47,7 @@ const ( github = "GitHub" gitlab = "GitLab" dockerDaemonPrefixLen = 8 + latestReleaseUrl = "https://api.github.com/repos/kubeshop/testkube/releases/latest" ) func (o HelmOptions) GetApiURI() string { @@ -822,12 +826,13 @@ func prepareTestkubeProDockerArgs(options HelmOptions, dockerContainerName, dock } // prepareTestkubeUpgradeDockerArgs prepares docker arguments for Testkube Upgrade running. -func prepareTestkubeUpgradeDockerArgs(options HelmOptions, dockerContainerName string) []string { +func prepareTestkubeUpgradeDockerArgs(options HelmOptions, dockerContainerName, latestVersion string) []string { args := []string{ "exec", dockerContainerName, "helm", "upgrade", + // These arguments are similar to Docker entrypoint script "testkube", "testkube/testkube", "--namespace", @@ -842,6 +847,8 @@ func prepareTestkubeUpgradeDockerArgs(options HelmOptions, dockerContainerName s "testkube-api.cloud.key=" + options.Master.AgentToken, "--set", "testkube-api.cloud.url=" + options.Master.URIs.Agent, + "--set", + "testkube-api.dockerImageVersion" + latestVersion, } return args @@ -914,7 +921,7 @@ func StreamDockerLogs(dockerContainerName string) *CLIError { return nil } -func DockerUpgradeTestkubeAgent(options HelmOptions, cfg config.Data) *CLIError { +func DockerUpgradeTestkubeAgent(options HelmOptions, latestVersion string, cfg config.Data) *CLIError { // use config if set if cfg.CloudContext.AgentKey != "" && options.Master.AgentToken == "" { options.Master.AgentToken = cfg.CloudContext.AgentKey @@ -928,7 +935,7 @@ func DockerUpgradeTestkubeAgent(options HelmOptions, cfg config.Data) *CLIError errors.New("agent key is required")) } - args := prepareTestkubeUpgradeDockerArgs(options, cfg.CloudContext.DockerContainerName) + args := prepareTestkubeUpgradeDockerArgs(options, cfg.CloudContext.DockerContainerName, latestVersion) output, err := RunDockerCommand(args) if err != nil { return err @@ -941,3 +948,27 @@ func DockerUpgradeTestkubeAgent(options HelmOptions, cfg config.Data) *CLIError return nil } + +type releaseMetadata struct { + TagName string `json:"tag_name"` +} + +func GetLatestVersion() (string, error) { + resp, err := http.Get(latestReleaseUrl) + if err != nil { + return "", nil + } + defer resp.Body.Close() + + data, err := io.ReadAll(resp.Body) + if err != nil { + return "", nil + } + + var metadata releaseMetadata + if err := json.Unmarshal(data, &metadata); err != nil { + return "", err + } + + return metadata.TagName, nil +} diff --git a/cmd/kubectl-testkube/commands/upgrade.go b/cmd/kubectl-testkube/commands/upgrade.go index bf233b9cf00..5fbd4abe5af 100644 --- a/cmd/kubectl-testkube/commands/upgrade.go +++ b/cmd/kubectl-testkube/commands/upgrade.go @@ -79,7 +79,9 @@ func NewUpgradeCmd() *cobra.Command { if cfg.ContextType == config.ContextTypeCloud { ui.Info("Testkube Pro agent upgrade started") if cfg.CloudContext.DockerContainerName != "" { - err = common.DockerUpgradeTestkubeAgent(options, cfg) + latestVersion, err := common.GetLatestVersion() + ui.ExitOnError("Getting latest version", err) + err = common.DockerUpgradeTestkubeAgent(options, latestVersion, cfg) } else { err = common.HelmUpgradeOrInstallTestkubeAgent(options, cfg, false) } From afc2e3f5e2c2b6e84f9e923f6859d573cb597e7c Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 14 Oct 2024 14:53:02 +0300 Subject: [PATCH 07/10] fix: missed operand Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/common/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 89b3aed66a2..210d2302627 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -848,7 +848,7 @@ func prepareTestkubeUpgradeDockerArgs(options HelmOptions, dockerContainerName, "--set", "testkube-api.cloud.url=" + options.Master.URIs.Agent, "--set", - "testkube-api.dockerImageVersion" + latestVersion, + "testkube-api.dockerImageVersion=" + latestVersion, } return args From 02da565c5889cd1f2c0f572643efc4f7ad35b8cb Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 14 Oct 2024 15:59:08 +0300 Subject: [PATCH 08/10] fix: remove tag prefix Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/common/helper.go | 2 +- cmd/kubectl-testkube/commands/pro/docker.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 210d2302627..28154595578 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -970,5 +970,5 @@ func GetLatestVersion() (string, error) { return "", err } - return metadata.TagName, nil + return strings.TrimPrefix(metadata.TagName, "v"), nil } diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index ea5da009d54..ecb5290451d 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -17,6 +17,9 @@ func NewDockerCmd() *cobra.Command { var dockerContainerName, dockerImage string var options common.HelmOptions + latestVersion, err := common.GetLatestVersion() + ui.ExitOnError("Gettong latest version", err) + cmd := &cobra.Command{ Use: "docker", Short: "Run Testkube Docker Agent and connect to Testkube Pro environment", @@ -122,7 +125,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(&dockerContainerName, "docker-container", "testkube-agent", "Docker container name for Testkube Docker Agent") - cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent:latest", "Docker image for Testkube Docker Agent") + cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent:"+latestVersion, "Docker image for Testkube Docker Agent") return cmd } From 29c88d6a92d897d7932df5f50cbfd17479c4aa7e Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 14 Oct 2024 16:07:55 +0300 Subject: [PATCH 09/10] fix: return errors Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/common/helper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index 28154595578..722e596b1ea 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -956,13 +956,13 @@ type releaseMetadata struct { func GetLatestVersion() (string, error) { resp, err := http.Get(latestReleaseUrl) if err != nil { - return "", nil + return "", err } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { - return "", nil + return "", err } var metadata releaseMetadata From 6b2e3fa68c2b5ad459f06b9bda017201ab62f361 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 14 Oct 2024 16:22:07 +0300 Subject: [PATCH 10/10] fix: prepare latest version tag Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/pro/docker.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/kubectl-testkube/commands/pro/docker.go b/cmd/kubectl-testkube/commands/pro/docker.go index ecb5290451d..263b49dbf58 100644 --- a/cmd/kubectl-testkube/commands/pro/docker.go +++ b/cmd/kubectl-testkube/commands/pro/docker.go @@ -20,6 +20,10 @@ func NewDockerCmd() *cobra.Command { latestVersion, err := common.GetLatestVersion() ui.ExitOnError("Gettong latest version", err) + if latestVersion != "" { + latestVersion = ":" + latestVersion + } + cmd := &cobra.Command{ Use: "docker", Short: "Run Testkube Docker Agent and connect to Testkube Pro environment", @@ -125,7 +129,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(&dockerContainerName, "docker-container", "testkube-agent", "Docker container name for Testkube Docker Agent") - cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent:"+latestVersion, "Docker image for Testkube Docker Agent") + cmd.Flags().StringVar(&dockerImage, "docker-image", "kubeshop/testkube-agent"+latestVersion, "Docker image for Testkube Docker Agent") return cmd }