Skip to content

Commit

Permalink
feat: docker upgrade 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 11, 2024
1 parent 7c81531 commit 2b8afd4
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 38 deletions.
69 changes: 62 additions & 7 deletions cmd/kubectl-testkube/commands/common/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion cmd/kubectl-testkube/commands/pro/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
17 changes: 9 additions & 8 deletions cmd/kubectl-testkube/commands/pro/docker.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pro

import (
"errors"
"os"

"github.com/pterm/pterm"
Expand All @@ -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{
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
}
Expand All @@ -69,15 +70,15 @@ 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()
}
sendErrTelemetry(cmd, cfg, "docker_run", cliErr)
common.HandleCLIError(cliErr)
}

if cliErr := common.StreamDockerLogs(containerName); cliErr != nil {
if cliErr := common.StreamDockerLogs(dockerContainerName); cliErr != nil {
if spinner != nil {
spinner.Fail()
}
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
2 changes: 1 addition & 1 deletion cmd/kubectl-testkube/commands/pro/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubectl-testkube/commands/pro/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
38 changes: 30 additions & 8 deletions cmd/kubectl-testkube/commands/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

func NewUpgradeCmd() *cobra.Command {
var options common.HelmOptions
var dockerContainerName string

cmd := &cobra.Command{
Use: "upgrade",
Expand All @@ -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")
Expand All @@ -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)
Expand All @@ -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
}
25 changes: 13 additions & 12 deletions cmd/kubectl-testkube/config/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 2b8afd4

Please sign in to comment.