Skip to content

Commit

Permalink
feat: detect namespace of enterprise installation (#6058)
Browse files Browse the repository at this point in the history
* fix: allow to use just key override

* feat allow to choose enterprise namespace from drop down

* fix: labels for select

* fix: use selector
  • Loading branch information
exu authored Nov 28, 2024
1 parent 8266e56 commit f1fd9b6
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 8 deletions.
54 changes: 53 additions & 1 deletion cmd/kubectl-testkube/commands/common/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,58 @@ func KubectlDescribeIngresses(namespace string) error {
return process.ExecuteAndStreamOutput(kubectl, args...)
}

func KubectlGetNamespacesHavingSecrets(secretName string) ([]string, error) {
kubectl, clierr := lookupKubectlPath()
if clierr != nil {
return nil, clierr.ActualError
}

args := []string{
"get",
"secret",
"-A",
}

if ui.IsVerbose() {
ui.ShellCommand(kubectl, args...)
ui.NL()
}

out, err := process.Execute(kubectl, args...)
if err != nil {
return nil, err
}

nss := extractUniqueNamespaces(string(out), secretName)
return nss, nil
}

func extractUniqueNamespaces(data string, secretName string) []string {
// Split the data into lines
lines := strings.Split(data, "\n")

// Map to store unique namespaces
uniq := make(map[string]bool)

for _, line := range lines {
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
if parts[1] == secretName {
uniq[parts[0]] = true
}
}

// Convert map keys (namespaces) to a slice of strings
list := make([]string, 0, len(uniq))
for namespace := range uniq {
list = append(list, namespace)
}

return list
}

func KubectlGetPodEnvs(selector, namespace string) (map[string]string, error) {
kubectl, clierr := lookupKubectlPath()
if clierr != nil {
Expand All @@ -821,7 +873,7 @@ func KubectlGetPodEnvs(selector, namespace string) (map[string]string, error) {

args := []string{
"get",
"pod",
"secret",
selector,
"-n", namespace,
"-o", `jsonpath='{range .items[*].spec.containers[*]}{"\nContainer: "}{.name}{"\n"}{range .env[*]}{.name}={.value}{"\n"}{end}{end}'`,
Expand Down
1 change: 1 addition & 0 deletions cmd/kubectl-testkube/commands/diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func NewDiagnosticsCmd() *cobra.Command {
Run: NewRunDiagnosticsCmdFunc(),
}

cmd.Flags().Bool("offline-override", false, "Pass License key manually (we will not try to locate it automatically)")
cmd.Flags().StringP("key-override", "k", "", "Pass License key manually (we will not try to locate it automatically)")
cmd.Flags().StringP("file-override", "f", "", "Pass License file manually (we will not try to locate it automatically)")

Expand Down
3 changes: 0 additions & 3 deletions cmd/kubectl-testkube/commands/diagnostics/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ func NewInstallCheckCmd() *cobra.Command {
Run: RunInstallCheckFunc(),
}

cmd.Flags().StringP("key-override", "k", "", "Pass License key manually (we will not try to locate it automatically)")
cmd.Flags().StringP("file-override", "f", "", "Pass License file manually (we will not try to locate it automatically)")

return cmd
}

Expand Down
32 changes: 30 additions & 2 deletions cmd/kubectl-testkube/commands/diagnostics/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package diagnostics
import (
"github.com/spf13/cobra"

"github.com/kubeshop/testkube/cmd/kubectl-testkube/commands/common"
"github.com/kubeshop/testkube/pkg/diagnostics"
"github.com/kubeshop/testkube/pkg/diagnostics/loader"
"github.com/kubeshop/testkube/pkg/diagnostics/validators/license"
Expand All @@ -14,6 +15,26 @@ func RegisterLicenseValidators(cmd *cobra.Command, d diagnostics.Diagnostics) {
namespace := cmd.Flag("namespace").Value.String()
keyOverride := cmd.Flag("key-override").Value.String()
fileOverride := cmd.Flag("file-override").Value.String()
isOfflineOverride := cmd.Flag("offline-override").Changed && cmd.Flag("offline-override").Value.String() == "true"

// if not namespace provided load all namespaces having license file secret
if !cmd.Flag("namespace").Changed {
namespaces, err := common.KubectlGetNamespacesHavingSecrets("testkube-enterprise-license")
if err != nil {
ui.Errf("Can't check for namespaces, make sure you have valid access rights to list resources in Kubernetes")
ui.ExitOnError("error:", err)
return
}

switch true {
case len(namespaces) == 0:
ui.Failf("Can't locate any Testkube installations please pass `--namespace` parameter")
case len(namespaces) == 1:
namespace = namespaces[0]
case len(namespaces) > 1:
namespace = ui.Select("Choose namespace to check license", namespaces)
}
}

var err error
l := loader.License{}
Expand All @@ -28,19 +49,23 @@ func RegisterLicenseValidators(cmd *cobra.Command, d diagnostics.Diagnostics) {
if fileOverride != "" && keyOverride != "" {
l.EnterpriseOfflineActivation = true
}
if isOfflineOverride {
l.EnterpriseOfflineActivation = isOfflineOverride
}

if fileOverride == "" || keyOverride == "" {
if keyOverride == "" || (l.EnterpriseOfflineActivation && fileOverride == "") {
l, err = loader.GetLicenseConfig(namespace, "")
ui.ExitOnError("loading license data", err)
}

// License validator
licenseGroup := d.AddValidatorGroup("license.validation", l.EnterpriseLicenseKey)
if l.EnterpriseOfflineActivation {
licenseGroup := d.AddValidatorGroup("offline.license.validation", l.EnterpriseLicenseKey)
licenseGroup.AddValidator(license.NewFileValidator())
licenseGroup.AddValidator(license.NewOfflineLicenseKeyValidator())
licenseGroup.AddValidator(license.NewOfflineLicenseValidator(l.EnterpriseLicenseKey, l.EnterpriseLicenseFile))
} else {
licenseGroup := d.AddValidatorGroup("online.license.validation", l.EnterpriseLicenseKey)
licenseGroup.AddValidator(license.NewOnlineLicenseKeyValidator())
licenseGroup.AddValidator(license.NewKeygenShValidator())
}
Expand All @@ -54,6 +79,7 @@ func NewLicenseCheckCmd() *cobra.Command {
Run: RunLicenseCheckFunc(),
}

cmd.Flags().Bool("offline-override", false, "Pass License key manually (we will not try to locate it automatically)")
cmd.Flags().StringP("key-override", "k", "", "Pass License key manually (we will not try to locate it automatically)")
cmd.Flags().StringP("file-override", "f", "", "Pass License file manually (we will not try to locate it automatically)")

Expand All @@ -62,6 +88,8 @@ func NewLicenseCheckCmd() *cobra.Command {

func RunLicenseCheckFunc() func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
ui.H1("Check licensing issues")

d := diagnostics.New()
RegisterLicenseValidators(cmd, d)

Expand Down
4 changes: 2 additions & 2 deletions pkg/diagnostics/validators/license/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var (
ErrLicenseKeyInvalidFormat = v.Err("license key invalid format", v.ErrorKindInvalidKeyContent)

ErrOnlineLicenseKeyInvalidLength = v.Err("license key invalid length", v.ErrorKindInvalidKeyContent).
WithDetails("License key should be in form XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX-XX - 37 chars in length").
WithSuggestion("License key should be in form XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX-XX - 37 chars in length").
WithSuggestion("Make sure license key is in valid format").
WithSuggestion("Make sure there is no whitespaces on the begining and the end of the key")

Expand All @@ -34,7 +34,7 @@ var (
ErrOfflineLicenseKeyInvalidPrefix = v.Err("license key has invalid prefix", v.ErrorKindInvalidKeyContent).
WithDetails("License key should start with 'key/' string").
WithSuggestion("Make sure license key is in valid format").
WithSuggestion("Make sure you're NOT using offline keys for air-gapped (offline) installations").
WithSuggestion("Make sure you're NOT using 'online' keys for air-gapped ('offline') installations").
WithSuggestion("Make sure there is no whitespaces on the begining and the end of the key")

ErrOfflineLicensePublicKeyMissing = v.Err("public key is missing", v.ErrorKindLicenseInvalid)
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "github.com/pterm/pterm"
func (ui *UI) Select(label string, options []string) string {
val, _ := pterm.DefaultInteractiveSelect.
WithOptions(options).
WithDefaultText(label).
Show()

ui.NL()
Expand Down

0 comments on commit f1fd9b6

Please sign in to comment.