From 0067c1d8da915c912cd1ea2d124f1604c4f1cbcf Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Wed, 14 Jun 2023 14:27:27 +0200 Subject: [PATCH 1/9] feat: validate cloud context on root cmd --- .../commands/common/validator/cloudcontext.go | 37 +++++++++++++++++++ cmd/kubectl-testkube/commands/context/set.go | 13 +++++++ cmd/kubectl-testkube/commands/root.go | 19 ++++++++++ 3 files changed, 69 insertions(+) create mode 100644 cmd/kubectl-testkube/commands/common/validator/cloudcontext.go diff --git a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go new file mode 100644 index 00000000000..eda625c21a1 --- /dev/null +++ b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go @@ -0,0 +1,37 @@ +package validator + +import ( + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" +) + +type ContextErr struct { + Msg string +} + +func (e ContextErr) Error() string { + return e.Msg +} + +func ValidateCloudContext(cfg config.Data) error { + if cfg.ContextType != config.ContextTypeCloud { + return nil + } + + if cfg.CloudContext.ApiUri == "" { + return ContextErr{"please provide Testkube Cloud URI"} + } + + if cfg.CloudContext.ApiKey == "" { + return ContextErr{"please provide Testkube Cloud API token"} + } + + if cfg.CloudContext.Environment == "" { + return ContextErr{"please provide environment"} + } + + if cfg.CloudContext.Organization == "" { + return ContextErr{"please provide organization"} + } + + return nil +} diff --git a/cmd/kubectl-testkube/commands/context/set.go b/cmd/kubectl-testkube/commands/context/set.go index 940e17a6063..2ffa5ba6086 100644 --- a/cmd/kubectl-testkube/commands/context/set.go +++ b/cmd/kubectl-testkube/commands/context/set.go @@ -1,9 +1,12 @@ package context import ( + "os" + "github.com/spf13/cobra" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -74,6 +77,16 @@ func NewSetContextCmd() *cobra.Command { ui.Success("Your config was updated with new values") ui.NL() common.UiPrintContext(cfg) + + if err = validator.ValidateCloudContext(cfg); err != nil { + ui.Errf("Validating cloud context failed: %s", err.Error()) + ui.NL() + ui.Info("Please set valid cloud context using `testkube set context` with valid values") + ui.NL() + ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") + ui.NL() + os.Exit(1) + } }, } diff --git a/cmd/kubectl-testkube/commands/root.go b/cmd/kubectl-testkube/commands/root.go index b5527e13866..ad3d7e0b7ee 100644 --- a/cmd/kubectl-testkube/commands/root.go +++ b/cmd/kubectl-testkube/commands/root.go @@ -8,6 +8,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/cloud" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/telemetry" "github.com/kubeshop/testkube/pkg/ui" @@ -62,6 +63,24 @@ var RootCmd = &cobra.Command{ Short: "Testkube entrypoint for kubectl plugin", PersistentPreRun: func(cmd *cobra.Command, args []string) { ui.SetVerbose(verbose) + + if cmd.Name() == "context" { + return + } + + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + + if err = validator.ValidateCloudContext(cfg); err != nil { + ui.NL() + ui.Errf("Validating cloud context failed: %s", err) + ui.NL() + ui.Info("Please set valid cloud context using `testkube set context` with valid values") + ui.NL() + ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") + ui.NL() + os.Exit(1) + } }, PersistentPostRun: func(cmd *cobra.Command, args []string) { From 21176d08b60a570b49ff8a54a2ee20671b0fddd3 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Wed, 14 Jun 2023 14:30:10 +0200 Subject: [PATCH 2/9] chore: organize --- cmd/kubectl-testkube/commands/common/cloudcontext.go | 11 +++++++++++ cmd/kubectl-testkube/commands/context/set.go | 10 +--------- cmd/kubectl-testkube/commands/root.go | 9 +-------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/cloudcontext.go b/cmd/kubectl-testkube/commands/common/cloudcontext.go index c929a579ef4..4d719f16a12 100644 --- a/cmd/kubectl-testkube/commands/common/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/cloudcontext.go @@ -2,6 +2,7 @@ package common import ( "fmt" + "os" "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" @@ -35,3 +36,13 @@ func UiPrintContext(cfg config.Data) { }) } } + +func UiCloudContextValidationError(err error) { + ui.Errf("Validating cloud context failed: %s", err.Error()) + ui.NL() + ui.Info("Please set valid cloud context using `testkube set context` with valid values") + ui.NL() + ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") + ui.NL() + os.Exit(1) +} diff --git a/cmd/kubectl-testkube/commands/context/set.go b/cmd/kubectl-testkube/commands/context/set.go index 2ffa5ba6086..dbf8beda574 100644 --- a/cmd/kubectl-testkube/commands/context/set.go +++ b/cmd/kubectl-testkube/commands/context/set.go @@ -1,8 +1,6 @@ package context import ( - "os" - "github.com/spf13/cobra" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" @@ -79,13 +77,7 @@ func NewSetContextCmd() *cobra.Command { common.UiPrintContext(cfg) if err = validator.ValidateCloudContext(cfg); err != nil { - ui.Errf("Validating cloud context failed: %s", err.Error()) - ui.NL() - ui.Info("Please set valid cloud context using `testkube set context` with valid values") - ui.NL() - ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") - ui.NL() - os.Exit(1) + common.UiCloudContextValidationError(err) } }, } diff --git a/cmd/kubectl-testkube/commands/root.go b/cmd/kubectl-testkube/commands/root.go index ad3d7e0b7ee..5060cf376bf 100644 --- a/cmd/kubectl-testkube/commands/root.go +++ b/cmd/kubectl-testkube/commands/root.go @@ -72,14 +72,7 @@ var RootCmd = &cobra.Command{ ui.ExitOnError("loading config", err) if err = validator.ValidateCloudContext(cfg); err != nil { - ui.NL() - ui.Errf("Validating cloud context failed: %s", err) - ui.NL() - ui.Info("Please set valid cloud context using `testkube set context` with valid values") - ui.NL() - ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") - ui.NL() - os.Exit(1) + common.UiCloudContextValidationError(err) } }, From 0b0014905f8d46e794ef207a59834503c694da33 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Wed, 14 Jun 2023 14:36:25 +0200 Subject: [PATCH 3/9] chore: organize --- .../commands/common/validator/cloudcontext.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go index eda625c21a1..daa784b9d33 100644 --- a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go @@ -1,36 +1,30 @@ package validator import ( + "errors" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" ) -type ContextErr struct { - Msg string -} - -func (e ContextErr) Error() string { - return e.Msg -} - func ValidateCloudContext(cfg config.Data) error { if cfg.ContextType != config.ContextTypeCloud { return nil } if cfg.CloudContext.ApiUri == "" { - return ContextErr{"please provide Testkube Cloud URI"} + return errors.New("please provide Testkube Cloud URI") } if cfg.CloudContext.ApiKey == "" { - return ContextErr{"please provide Testkube Cloud API token"} + return errors.New("please provide Testkube Cloud API token") } if cfg.CloudContext.Environment == "" { - return ContextErr{"please provide environment"} + return errors.New("please provide environment") } if cfg.CloudContext.Organization == "" { - return ContextErr{"please provide organization"} + return errors.New("please provide organization") } return nil From 462b14c6707ecb0f8e454e0732f930fa6a4d4ce7 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Wed, 14 Jun 2023 14:47:37 +0200 Subject: [PATCH 4/9] chore: organize --- .../commands/common/validator/cloudcontext.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go index daa784b9d33..f6369a5b4b5 100644 --- a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go @@ -20,11 +20,11 @@ func ValidateCloudContext(cfg config.Data) error { } if cfg.CloudContext.Environment == "" { - return errors.New("please provide environment") + return errors.New("please provide Environment") } if cfg.CloudContext.Organization == "" { - return errors.New("please provide organization") + return errors.New("please provide Organization") } return nil From 5debe027a48d8952dc5382a1b8cfbe1da8ae012a Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Thu, 15 Jun 2023 10:12:49 +0200 Subject: [PATCH 5/9] feat: added org-env names to context on set context --- cmd/kubectl-testkube/commands/abort.go | 5 +++ cmd/kubectl-testkube/commands/agent.go | 2 - cmd/kubectl-testkube/commands/cloud/login.go | 4 +- .../commands/common/client.go | 6 +-- .../commands/common/cloudcontext.go | 41 ++++++++++++++++++- .../commands/common/helper.go | 4 +- .../commands/common/validator/cloudcontext.go | 4 +- cmd/kubectl-testkube/commands/context/set.go | 30 +++++++++++--- cmd/kubectl-testkube/commands/create.go | 5 +++ cmd/kubectl-testkube/commands/debug.go | 5 +++ cmd/kubectl-testkube/commands/delete.go | 5 +++ cmd/kubectl-testkube/commands/download.go | 5 +++ cmd/kubectl-testkube/commands/get.go | 6 +++ cmd/kubectl-testkube/commands/root.go | 10 +++-- cmd/kubectl-testkube/commands/run.go | 5 +++ cmd/kubectl-testkube/commands/update.go | 5 +++ cmd/kubectl-testkube/commands/version.go | 5 +++ cmd/kubectl-testkube/commands/watch.go | 5 +++ cmd/kubectl-testkube/config/data.go | 20 +++++---- pkg/cloud/client/rest.go | 23 +++++++++++ pkg/telemetry/telemetry.go | 4 +- 21 files changed, 166 insertions(+), 33 deletions(-) diff --git a/cmd/kubectl-testkube/commands/abort.go b/cmd/kubectl-testkube/commands/abort.go index b10631b7235..57156e36ddb 100644 --- a/cmd/kubectl-testkube/commands/abort.go +++ b/cmd/kubectl-testkube/commands/abort.go @@ -7,6 +7,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -20,6 +21,10 @@ func NewAbortCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/agent.go b/cmd/kubectl-testkube/commands/agent.go index 490806240ee..6d991f7a50f 100644 --- a/cmd/kubectl-testkube/commands/agent.go +++ b/cmd/kubectl-testkube/commands/agent.go @@ -29,8 +29,6 @@ func NewAgentCmd() *cobra.Command { ui.Info("Build date", common.Date) }, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - }, } cmd.AddCommand(agent.NewAgentDebugCmd()) diff --git a/cmd/kubectl-testkube/commands/cloud/login.go b/cmd/kubectl-testkube/commands/cloud/login.go index 14ef7080bc5..e8e7dac2839 100644 --- a/cmd/kubectl-testkube/commands/cloud/login.go +++ b/cmd/kubectl-testkube/commands/cloud/login.go @@ -55,8 +55,8 @@ func NewLoginCmd() *cobra.Command { ui.ExitOnError("loading config file", err) cfg.ContextType = config.ContextTypeCloud - cfg.CloudContext.Organization = orgID - cfg.CloudContext.Environment = envID + cfg.CloudContext.OrganizationId = orgID + cfg.CloudContext.EnvironmentId = envID uris := opts.CloudUris cfg.CloudContext.ApiUri = uris.Api diff --git a/cmd/kubectl-testkube/commands/common/client.go b/cmd/kubectl-testkube/commands/common/client.go index a9878c333f4..4d40f867f0e 100644 --- a/cmd/kubectl-testkube/commands/common/client.go +++ b/cmd/kubectl-testkube/commands/common/client.go @@ -70,10 +70,10 @@ func GetClient(cmd *cobra.Command) (client.Client, string, error) { } case config.ContextTypeCloud: clientType = string(client.ClientCloud) - options.CloudApiPathPrefix = fmt.Sprintf("/organizations/%s/environments/%s/agent", cfg.CloudContext.Organization, cfg.CloudContext.Environment) + options.CloudApiPathPrefix = fmt.Sprintf("/organizations/%s/environments/%s/agent", cfg.CloudContext.OrganizationId, cfg.CloudContext.EnvironmentId) options.CloudApiKey = cfg.CloudContext.ApiKey - options.CloudEnvironment = cfg.CloudContext.Environment - options.CloudOrganization = cfg.CloudContext.Organization + options.CloudEnvironment = cfg.CloudContext.EnvironmentId + options.CloudOrganization = cfg.CloudContext.OrganizationId options.ApiUri = cfg.CloudContext.ApiUri } diff --git a/cmd/kubectl-testkube/commands/common/cloudcontext.go b/cmd/kubectl-testkube/commands/common/cloudcontext.go index 4d719f16a12..71d38ff397c 100644 --- a/cmd/kubectl-testkube/commands/common/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/cloudcontext.go @@ -3,10 +3,13 @@ package common import ( "fmt" "os" + "regexp" + "strings" "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" "github.com/kubeshop/testkube/pkg/utils/text" + "github.com/spf13/cobra" ) func UiPrintContext(cfg config.Data) { @@ -15,8 +18,8 @@ func UiPrintContext(cfg config.Data) { if cfg.ContextType == config.ContextTypeCloud { contextData := map[string]string{ - "Organization ID": cfg.CloudContext.Organization, - "Environment ID ": cfg.CloudContext.Environment, + "Organization": cfg.CloudContext.OrganizationName + ui.DarkGray(" ("+cfg.CloudContext.OrganizationId+")"), + "Environment": cfg.CloudContext.EnvironmentName + ui.DarkGray(" ("+cfg.CloudContext.EnvironmentId+")"), "API Key ": text.Obfuscate(cfg.CloudContext.ApiKey), "API URI ": cfg.CloudContext.ApiUri, "Namespace ": cfg.Namespace, @@ -38,6 +41,7 @@ func UiPrintContext(cfg config.Data) { } func UiCloudContextValidationError(err error) { + ui.NL() ui.Errf("Validating cloud context failed: %s", err.Error()) ui.NL() ui.Info("Please set valid cloud context using `testkube set context` with valid values") @@ -46,3 +50,36 @@ func UiCloudContextValidationError(err error) { ui.NL() os.Exit(1) } + +func UiContextHeader(cmd *cobra.Command, cfg config.Data) { + // only show header when output is pretty + if cmd.Flag("output") != nil && cmd.Flag("output").Value.String() != "pretty" { + return + } + + header := "\n" + separator := " " + + if cfg.ContextType == config.ContextTypeCloud { + header += ui.DarkGray("Context: ") + ui.White(cfg.ContextType) + ui.DarkGray(" ("+Version+")") + separator + header += ui.DarkGray("Namespace: ") + ui.White(cfg.Namespace) + separator + header += ui.DarkGray("Org: ") + ui.White(cfg.CloudContext.OrganizationName) + separator + header += ui.DarkGray("Env: ") + ui.White(cfg.CloudContext.EnvironmentName) + } else { + header += ui.DarkGray("Context: ") + ui.White(cfg.ContextType) + ui.DarkGray(" ("+Version+")") + separator + header += ui.DarkGray("Namespace: ") + ui.White(cfg.Namespace) + } + + fmt.Println(header) + fmt.Println(strings.Repeat("-", calculateStringSize(header))) +} + +// calculateStringSize calculates the length of a string, excluding shell color codes. +func calculateStringSize(s string) int { + // Regular expression to match ANSI escape codes. + re := regexp.MustCompile(`\x1b[^m]*m`) + // Remove the escape codes from the string. + s = re.ReplaceAllString(s, "") + // Return the length of the string. + return len(s) - 1 +} diff --git a/cmd/kubectl-testkube/commands/common/helper.go b/cmd/kubectl-testkube/commands/common/helper.go index a54f729b2e1..446765427c0 100644 --- a/cmd/kubectl-testkube/commands/common/helper.go +++ b/cmd/kubectl-testkube/commands/common/helper.go @@ -183,8 +183,8 @@ func PopulateLoginDataToContext(orgID, envID, token string, options HelmOptions, cfg.CloudContext.ApiUri = options.CloudUris.Api } cfg.ContextType = config.ContextTypeCloud - cfg.CloudContext.Organization = orgID - cfg.CloudContext.Environment = envID + cfg.CloudContext.OrganizationId = orgID + cfg.CloudContext.EnvironmentId = envID cfg.CloudContext.ApiKey = token return config.Save(cfg) diff --git a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go index f6369a5b4b5..558cba14230 100644 --- a/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/validator/cloudcontext.go @@ -19,11 +19,11 @@ func ValidateCloudContext(cfg config.Data) error { return errors.New("please provide Testkube Cloud API token") } - if cfg.CloudContext.Environment == "" { + if cfg.CloudContext.EnvironmentId == "" { return errors.New("please provide Environment") } - if cfg.CloudContext.Organization == "" { + if cfg.CloudContext.OrganizationId == "" { return errors.New("please provide Organization") } diff --git a/cmd/kubectl-testkube/commands/context/set.go b/cmd/kubectl-testkube/commands/context/set.go index dbf8beda574..7ec7bf3cb37 100644 --- a/cmd/kubectl-testkube/commands/context/set.go +++ b/cmd/kubectl-testkube/commands/context/set.go @@ -1,11 +1,14 @@ package context import ( + "fmt" + "github.com/spf13/cobra" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" + cloudclient "github.com/kubeshop/testkube/pkg/cloud/client" "github.com/kubeshop/testkube/pkg/ui" ) @@ -39,14 +42,14 @@ func NewSetContextCmd() *cobra.Command { } if org != "" { - cfg.CloudContext.Organization = org + cfg.CloudContext.OrganizationId = org // reset env when the org is changed if env == "" { - cfg.CloudContext.Environment = "" + cfg.CloudContext.EnvironmentId = "" } } if env != "" { - cfg.CloudContext.Environment = env + cfg.CloudContext.EnvironmentId = env } if apiKey != "" { cfg.CloudContext.ApiKey = apiKey @@ -58,6 +61,20 @@ func NewSetContextCmd() *cobra.Command { cfg.CloudContext.UiUri = uris.Ui cfg.CloudContext.AgentUri = uris.Agent + orgClient := cloudclient.NewOrganizationsClient(rootDomain, cfg.CloudContext.ApiKey) + ui.ExitOnError("getting client", err) + org, err := orgClient.Get(cfg.CloudContext.OrganizationId) + ui.ExitOnError("getting organization", err) + + envsClient := cloudclient.NewEnvironmentsClient(rootDomain, cfg.CloudContext.ApiKey, cfg.CloudContext.OrganizationId) + env, err := envsClient.Get(cfg.CloudContext.EnvironmentId) + ui.ExitOnError("getting environment", err) + + cfg.CloudContext.OrganizationName = org.Name + cfg.CloudContext.EnvironmentName = env.Name + + fmt.Printf("%+v\n", cfg.CloudContext) + case config.ContextTypeKubeconfig: // kubeconfig special use cases @@ -72,13 +89,14 @@ func NewSetContextCmd() *cobra.Command { err = config.Save(cfg) ui.ExitOnError("saving config file", err) + if err = validator.ValidateCloudContext(cfg); err != nil { + common.UiCloudContextValidationError(err) + } + ui.Success("Your config was updated with new values") ui.NL() common.UiPrintContext(cfg) - if err = validator.ValidateCloudContext(cfg); err != nil { - common.UiCloudContextValidationError(err) - } }, } diff --git a/cmd/kubectl-testkube/commands/create.go b/cmd/kubectl-testkube/commands/create.go index 5e22be433d5..4e5e344afa0 100644 --- a/cmd/kubectl-testkube/commands/create.go +++ b/cmd/kubectl-testkube/commands/create.go @@ -10,6 +10,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsources" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/webhooks" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -26,6 +27,10 @@ func NewCreateCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + if !crdOnly { validator.PersistentPreRunVersionCheck(cmd, common.Version) } diff --git a/cmd/kubectl-testkube/commands/debug.go b/cmd/kubectl-testkube/commands/debug.go index 67642fcacad..d16722c1e32 100644 --- a/cmd/kubectl-testkube/commands/debug.go +++ b/cmd/kubectl-testkube/commands/debug.go @@ -6,6 +6,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/debug" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -19,6 +20,10 @@ func NewDebugCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/delete.go b/cmd/kubectl-testkube/commands/delete.go index 9f08a991aab..cb6385dec90 100644 --- a/cmd/kubectl-testkube/commands/delete.go +++ b/cmd/kubectl-testkube/commands/delete.go @@ -10,6 +10,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsources" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/webhooks" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -24,6 +25,10 @@ func NewDeleteCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/download.go b/cmd/kubectl-testkube/commands/download.go index 56b36ebb0ed..e15e531a69d 100644 --- a/cmd/kubectl-testkube/commands/download.go +++ b/cmd/kubectl-testkube/commands/download.go @@ -9,6 +9,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -32,6 +33,10 @@ func NewDownloadCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/get.go b/cmd/kubectl-testkube/commands/get.go index 064f4d6eb77..3cde0dcc96f 100644 --- a/cmd/kubectl-testkube/commands/get.go +++ b/cmd/kubectl-testkube/commands/get.go @@ -12,6 +12,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsources" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/webhooks" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -27,7 +28,12 @@ func NewGetCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) + }} cmd.AddCommand(tests.NewGetTestsCmd()) diff --git a/cmd/kubectl-testkube/commands/root.go b/cmd/kubectl-testkube/commands/root.go index 5060cf376bf..c8a2090ef78 100644 --- a/cmd/kubectl-testkube/commands/root.go +++ b/cmd/kubectl-testkube/commands/root.go @@ -64,13 +64,16 @@ var RootCmd = &cobra.Command{ PersistentPreRun: func(cmd *cobra.Command, args []string) { ui.SetVerbose(verbose) + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + + common.UiContextHeader(cmd, cfg) + + // don't validate context before set if cmd.Name() == "context" { return } - cfg, err := config.Load() - ui.ExitOnError("loading config", err) - if err = validator.ValidateCloudContext(cfg); err != nil { common.UiCloudContextValidationError(err) } @@ -160,6 +163,7 @@ func Execute() { RootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "", false, "show additional debug messages") RootCmd.PersistentFlags().StringVarP(&apiURI, "api-uri", "a", apiURI, "api uri, default value read from config if set") RootCmd.PersistentFlags().BoolVarP(&oauthEnabled, "oauth-enabled", "", cfg.OAuth2Data.Enabled, "enable oauth") + if err := RootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/cmd/kubectl-testkube/commands/run.go b/cmd/kubectl-testkube/commands/run.go index 2e5b628c92a..5321340b922 100644 --- a/cmd/kubectl-testkube/commands/run.go +++ b/cmd/kubectl-testkube/commands/run.go @@ -7,6 +7,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -21,6 +22,10 @@ func NewRunCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/update.go b/cmd/kubectl-testkube/commands/update.go index 2d8fcb14040..73ad55f3fe0 100644 --- a/cmd/kubectl-testkube/commands/update.go +++ b/cmd/kubectl-testkube/commands/update.go @@ -9,6 +9,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsources" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -23,6 +24,10 @@ func NewUpdateCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/commands/version.go b/cmd/kubectl-testkube/commands/version.go index 1040e90e515..25bb74d47a7 100644 --- a/cmd/kubectl-testkube/commands/version.go +++ b/cmd/kubectl-testkube/commands/version.go @@ -5,6 +5,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -32,6 +33,10 @@ func NewVersionCmd() *cobra.Command { }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }, } diff --git a/cmd/kubectl-testkube/commands/watch.go b/cmd/kubectl-testkube/commands/watch.go index a99a2e1ad77..db02ff293db 100644 --- a/cmd/kubectl-testkube/commands/watch.go +++ b/cmd/kubectl-testkube/commands/watch.go @@ -7,6 +7,7 @@ import ( "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common/validator" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/tests" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/testsuites" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" ) @@ -21,6 +22,10 @@ func NewWatchCmd() *cobra.Command { ui.PrintOnError("Displaying help", err) }, PersistentPreRun: func(cmd *cobra.Command, args []string) { + cfg, err := config.Load() + ui.ExitOnError("loading config", err) + common.UiContextHeader(cmd, cfg) + validator.PersistentPreRunVersionCheck(cmd, common.Version) }} diff --git a/cmd/kubectl-testkube/config/data.go b/cmd/kubectl-testkube/config/data.go index 905a3193426..904b61d3722 100644 --- a/cmd/kubectl-testkube/config/data.go +++ b/cmd/kubectl-testkube/config/data.go @@ -17,15 +17,17 @@ const ( ) type CloudContext struct { - Environment string `json:"environment,omitempty"` - Organization string `json:"organization,omitempty"` - ApiKey string `json:"apiKey,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"` + 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"` } type Data struct { diff --git a/pkg/cloud/client/rest.go b/pkg/cloud/client/rest.go index 3f7b080abb9..c4eec96ec5f 100644 --- a/pkg/cloud/client/rest.go +++ b/pkg/cloud/client/rest.go @@ -41,6 +41,29 @@ func (c RESTClient[T]) List() ([]T, error) { return orgsResponse.Elements, err } +func (c RESTClient[T]) Get(id string) (e T, err error) { + req, err := nethttp.NewRequest("GET", c.BaseUrl+c.Path+"/"+id, nil) + req.Header.Add("Authorization", "Bearer "+c.Token) + if err != nil { + return e, err + } + resp, err := c.Client.Do(req) + if err != nil { + return e, err + } + + if resp.StatusCode > 299 { + d, err := io.ReadAll(resp.Body) + if err != nil { + return e, fmt.Errorf("error creating %s: can't read response: %s", c.Path, err) + } + return e, fmt.Errorf("error creating %s: %s", c.Path, d) + } + + err = json.NewDecoder(resp.Body).Decode(&e) + return +} + func (c RESTClient[T]) Create(entity T, overridePath ...string) (e T, err error) { d, err := json.Marshal(entity) if err != nil { diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 418fee619a8..89f38b3b672 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -99,8 +99,8 @@ func getCurrentContext() RunContext { } return RunContext{ Type: string(data.ContextType), - OrganizationId: data.CloudContext.Organization, - EnvironmentId: data.CloudContext.Environment, + OrganizationId: data.CloudContext.OrganizationId, + EnvironmentId: data.CloudContext.EnvironmentId, } } From 3bbe3d0acf3c910f47a16dfe368da25c12f28ed6 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Thu, 15 Jun 2023 10:23:47 +0200 Subject: [PATCH 6/9] feat: added org-env names fallback --- .../commands/common/cloudcontext.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/cloudcontext.go b/cmd/kubectl-testkube/commands/common/cloudcontext.go index 71d38ff397c..3563575d5a0 100644 --- a/cmd/kubectl-testkube/commands/common/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/cloudcontext.go @@ -60,18 +60,27 @@ func UiContextHeader(cmd *cobra.Command, cfg config.Data) { header := "\n" separator := " " + orgName := cfg.CloudContext.OrganizationName + if orgName == "" { + orgName = cfg.CloudContext.OrganizationId + } + envName := cfg.CloudContext.EnvironmentName + if envName == "" { + envName = cfg.CloudContext.EnvironmentId + } + if cfg.ContextType == config.ContextTypeCloud { header += ui.DarkGray("Context: ") + ui.White(cfg.ContextType) + ui.DarkGray(" ("+Version+")") + separator header += ui.DarkGray("Namespace: ") + ui.White(cfg.Namespace) + separator - header += ui.DarkGray("Org: ") + ui.White(cfg.CloudContext.OrganizationName) + separator - header += ui.DarkGray("Env: ") + ui.White(cfg.CloudContext.EnvironmentName) + header += ui.DarkGray("Org: ") + ui.White(orgName) + separator + header += ui.DarkGray("Env: ") + ui.White(envName) } else { header += ui.DarkGray("Context: ") + ui.White(cfg.ContextType) + ui.DarkGray(" ("+Version+")") + separator header += ui.DarkGray("Namespace: ") + ui.White(cfg.Namespace) } fmt.Println(header) - fmt.Println(strings.Repeat("-", calculateStringSize(header))) + fmt.Println(strings.Repeat("─", calculateStringSize(header))) } // calculateStringSize calculates the length of a string, excluding shell color codes. From 57a94933bad766f5b2d1725a1e6d7ae19a975766 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Thu, 15 Jun 2023 10:25:49 +0200 Subject: [PATCH 7/9] fix: golangci lint --- cmd/kubectl-testkube/commands/common/cloudcontext.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/kubectl-testkube/commands/common/cloudcontext.go b/cmd/kubectl-testkube/commands/common/cloudcontext.go index 3563575d5a0..573356c14c3 100644 --- a/cmd/kubectl-testkube/commands/common/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/cloudcontext.go @@ -2,14 +2,14 @@ package common import ( "fmt" - "os" "regexp" "strings" + "github.com/spf13/cobra" + "github.com/kubeshop/testkube/cmd/kubectl-testkube/config" "github.com/kubeshop/testkube/pkg/ui" "github.com/kubeshop/testkube/pkg/utils/text" - "github.com/spf13/cobra" ) func UiPrintContext(cfg config.Data) { @@ -48,7 +48,6 @@ func UiCloudContextValidationError(err error) { ui.NL() ui.ShellCommand(" testkube set context -c cloud -e tkcenv_XXX -o tkcorg_XXX -k tkcapi_XXX") ui.NL() - os.Exit(1) } func UiContextHeader(cmd *cobra.Command, cfg config.Data) { From dd80ea47ba62f376f3b7e7175abe8954dbf57c2d Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Thu, 15 Jun 2023 10:50:31 +0200 Subject: [PATCH 8/9] fix: codeql alert --- cmd/kubectl-testkube/commands/context/set.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/kubectl-testkube/commands/context/set.go b/cmd/kubectl-testkube/commands/context/set.go index 7ec7bf3cb37..5b444dba588 100644 --- a/cmd/kubectl-testkube/commands/context/set.go +++ b/cmd/kubectl-testkube/commands/context/set.go @@ -1,8 +1,6 @@ package context import ( - "fmt" - "github.com/spf13/cobra" "github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common" @@ -73,8 +71,6 @@ func NewSetContextCmd() *cobra.Command { cfg.CloudContext.OrganizationName = org.Name cfg.CloudContext.EnvironmentName = env.Name - fmt.Printf("%+v\n", cfg.CloudContext) - case config.ContextTypeKubeconfig: // kubeconfig special use cases From ad868ec2068cfa5fc30b28da8132075dab0d5954 Mon Sep 17 00:00:00 2001 From: Jacek Wysocki Date: Thu, 15 Jun 2023 11:49:49 +0200 Subject: [PATCH 9/9] fix: utf character fails build --- cmd/kubectl-testkube/commands/common/cloudcontext.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kubectl-testkube/commands/common/cloudcontext.go b/cmd/kubectl-testkube/commands/common/cloudcontext.go index 573356c14c3..2f89f3d6aec 100644 --- a/cmd/kubectl-testkube/commands/common/cloudcontext.go +++ b/cmd/kubectl-testkube/commands/common/cloudcontext.go @@ -79,7 +79,7 @@ func UiContextHeader(cmd *cobra.Command, cfg config.Data) { } fmt.Println(header) - fmt.Println(strings.Repeat("─", calculateStringSize(header))) + fmt.Println(strings.Repeat("-", calculateStringSize(header))) } // calculateStringSize calculates the length of a string, excluding shell color codes.