mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-12-28 04:19:41 -08:00
fix(kubectl): validate array length before indexing values
relates to #1439
This commit is contained in:
parent
210a38575b
commit
31d088d56a
|
@ -121,6 +121,9 @@ func (k *kubectl) doCallKubectl() bool {
|
|||
}
|
||||
|
||||
values := strings.Split(result, ",")
|
||||
if len(values) < 4 {
|
||||
return false
|
||||
}
|
||||
k.Context = values[0]
|
||||
k.Namespace = values[1]
|
||||
k.User = values[2]
|
||||
|
|
|
@ -7,53 +7,8 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type kubectlArgs struct {
|
||||
kubectlExists bool
|
||||
kubectlErr bool
|
||||
kubeconfig string
|
||||
parseKubeConfig bool
|
||||
template string
|
||||
displayError bool
|
||||
kubectlOutContext string
|
||||
kubectlOutNamespace string
|
||||
kubectlOutUser string
|
||||
kubectlOutCluster string
|
||||
files map[string]string
|
||||
}
|
||||
|
||||
const testKubectlAllInfoTemplate = "{{.Context}} :: {{.Namespace}} :: {{.User}} :: {{.Cluster}}"
|
||||
|
||||
func bootStrapKubectlTest(args *kubectlArgs) *kubectl {
|
||||
env := new(MockedEnvironment)
|
||||
env.On("hasCommand", "kubectl").Return(args.kubectlExists)
|
||||
kubectlOut := args.kubectlOutContext + "," + args.kubectlOutNamespace + "," + args.kubectlOutUser + "," + args.kubectlOutCluster
|
||||
var kubectlErr error
|
||||
if args.kubectlErr {
|
||||
kubectlErr = &commandError{
|
||||
err: "oops",
|
||||
exitCode: 1,
|
||||
}
|
||||
}
|
||||
env.On("runCommand", "kubectl",
|
||||
[]string{"config", "view", "--minify", "--output", "jsonpath={..current-context},{..namespace},{..context.user},{..context.cluster}"}).Return(kubectlOut, kubectlErr)
|
||||
|
||||
env.On("getenv", "KUBECONFIG").Return(args.kubeconfig)
|
||||
for path, content := range args.files {
|
||||
env.On("getFileContent", path).Return(content)
|
||||
}
|
||||
env.On("homeDir", nil).Return("testhome")
|
||||
|
||||
k := &kubectl{
|
||||
env: env,
|
||||
props: map[Property]interface{}{
|
||||
SegmentTemplate: args.template,
|
||||
DisplayError: args.displayError,
|
||||
ParseKubeConfig: args.parseKubeConfig,
|
||||
},
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
func TestKubectlSegment(t *testing.T) {
|
||||
standardTemplate := "{{.Context}}{{if .Namespace}} :: {{.Namespace}}{{end}}"
|
||||
lsep := string(filepath.ListSeparator)
|
||||
|
@ -75,48 +30,127 @@ func TestKubectlSegment(t *testing.T) {
|
|||
Files map[string]string
|
||||
}{
|
||||
{Case: "disabled", Template: standardTemplate, KubectlExists: false, Context: "aaa", Namespace: "bbb", ExpectedString: "", ExpectedEnabled: false},
|
||||
{Case: "normal", Template: standardTemplate, KubectlExists: true, Context: "aaa", Namespace: "bbb", ExpectedString: "aaa :: bbb", ExpectedEnabled: true},
|
||||
{Case: "all information", Template: testKubectlAllInfoTemplate, KubectlExists: true, Context: "aaa", Namespace: "bbb", User: "ccc", Cluster: "ddd",
|
||||
ExpectedString: "aaa :: bbb :: ccc :: ddd", ExpectedEnabled: true},
|
||||
{Case: "no namespace", Template: standardTemplate, KubectlExists: true, Context: "aaa", Namespace: "", ExpectedString: "aaa", ExpectedEnabled: true},
|
||||
{Case: "kubectl error", Template: standardTemplate, DisplayError: true, KubectlExists: true, Context: "aaa", Namespace: "bbb", KubectlErr: true,
|
||||
ExpectedString: "KUBECTL ERR :: KUBECTL ERR", ExpectedEnabled: true},
|
||||
{
|
||||
Case: "not enough arguments",
|
||||
Template: standardTemplate,
|
||||
KubectlExists: true,
|
||||
Context: "aaa",
|
||||
Namespace: "bbb",
|
||||
ExpectedString: "",
|
||||
ExpectedEnabled: false,
|
||||
},
|
||||
{
|
||||
Case: "all information",
|
||||
Template: testKubectlAllInfoTemplate,
|
||||
KubectlExists: true,
|
||||
Context: "aaa",
|
||||
Namespace: "bbb",
|
||||
User: "ccc",
|
||||
Cluster: "ddd",
|
||||
ExpectedString: "aaa :: bbb :: ccc :: ddd",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{Case: "no namespace", Template: standardTemplate, KubectlExists: true, Context: "aaa", Namespace: "", ExpectedString: "", ExpectedEnabled: false},
|
||||
{
|
||||
Case: "kubectl error",
|
||||
Template: standardTemplate,
|
||||
DisplayError: true,
|
||||
KubectlExists: true,
|
||||
Context: "aaa",
|
||||
Namespace: "bbb",
|
||||
KubectlErr: true,
|
||||
ExpectedString: "KUBECTL ERR :: KUBECTL ERR",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{Case: "kubectl error hidden", Template: standardTemplate, DisplayError: false, KubectlExists: true, Context: "aaa", Namespace: "bbb", KubectlErr: true, ExpectedEnabled: false},
|
||||
{Case: "kubeconfig home", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true, Files: testKubeConfigFiles, ExpectedString: "aaa :: bbb :: ccc :: ddd",
|
||||
ExpectedEnabled: true},
|
||||
{Case: "kubeconfig multiple current marker first", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true,
|
||||
Kubeconfig: "" + lsep + "currentcontextmarker" + lsep + "contextdefinition" + lsep + "contextredefinition",
|
||||
Files: testKubeConfigFiles, ExpectedString: "ctx :: ns :: usr :: cl", ExpectedEnabled: true},
|
||||
{Case: "kubeconfig multiple context first", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true,
|
||||
Kubeconfig: "contextdefinition" + lsep + "contextredefinition" + lsep + "currentcontextmarker" + lsep,
|
||||
Files: testKubeConfigFiles, ExpectedString: "ctx :: ns :: usr :: cl", ExpectedEnabled: true},
|
||||
{Case: "kubeconfig error hidden", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true, Kubeconfig: "invalid", Files: testKubeConfigFiles, ExpectedEnabled: false},
|
||||
{Case: "kubeconfig error", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true,
|
||||
Kubeconfig: "invalid", Files: testKubeConfigFiles, DisplayError: true,
|
||||
ExpectedString: "KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR", ExpectedEnabled: true},
|
||||
{Case: "kubeconfig incomplete", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true,
|
||||
Kubeconfig: "currentcontextmarker" + lsep + "contextdefinitionincomplete",
|
||||
Files: testKubeConfigFiles, ExpectedString: "ctx :: :: :: ", ExpectedEnabled: true},
|
||||
{
|
||||
Case: "kubeconfig home",
|
||||
Template: testKubectlAllInfoTemplate,
|
||||
ParseKubeConfig: true,
|
||||
Files: testKubeConfigFiles,
|
||||
ExpectedString: "aaa :: bbb :: ccc :: ddd",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{
|
||||
Case: "kubeconfig multiple current marker first",
|
||||
Template: testKubectlAllInfoTemplate,
|
||||
ParseKubeConfig: true,
|
||||
Kubeconfig: "" + lsep + "currentcontextmarker" + lsep + "contextdefinition" + lsep + "contextredefinition",
|
||||
Files: testKubeConfigFiles,
|
||||
ExpectedString: "ctx :: ns :: usr :: cl",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{
|
||||
Case: "kubeconfig multiple context first",
|
||||
Template: testKubectlAllInfoTemplate, ParseKubeConfig: true,
|
||||
Kubeconfig: "contextdefinition" + lsep + "contextredefinition" + lsep + "currentcontextmarker" + lsep,
|
||||
Files: testKubeConfigFiles,
|
||||
ExpectedString: "ctx :: ns :: usr :: cl",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{
|
||||
Case: "kubeconfig error hidden", Template: testKubectlAllInfoTemplate, ParseKubeConfig: true, Kubeconfig: "invalid", Files: testKubeConfigFiles, ExpectedEnabled: false},
|
||||
{
|
||||
Case: "kubeconfig error",
|
||||
Template: testKubectlAllInfoTemplate,
|
||||
ParseKubeConfig: true,
|
||||
Kubeconfig: "invalid",
|
||||
Files: testKubeConfigFiles,
|
||||
DisplayError: true,
|
||||
ExpectedString: "KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR :: KUBECONFIG ERR",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{
|
||||
Case: "kubeconfig incomplete",
|
||||
Template: testKubectlAllInfoTemplate,
|
||||
ParseKubeConfig: true,
|
||||
Kubeconfig: "currentcontextmarker" + lsep + "contextdefinitionincomplete",
|
||||
Files: testKubeConfigFiles,
|
||||
ExpectedString: "ctx :: :: :: ",
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
args := &kubectlArgs{
|
||||
kubectlExists: tc.KubectlExists,
|
||||
template: tc.Template,
|
||||
displayError: tc.DisplayError,
|
||||
kubectlOutContext: tc.Context,
|
||||
kubectlOutNamespace: tc.Namespace,
|
||||
kubectlOutUser: tc.User,
|
||||
kubectlOutCluster: tc.Cluster,
|
||||
kubectlErr: tc.KubectlErr,
|
||||
parseKubeConfig: tc.ParseKubeConfig,
|
||||
files: tc.Files,
|
||||
kubeconfig: tc.Kubeconfig,
|
||||
env := new(MockedEnvironment)
|
||||
env.On("hasCommand", "kubectl").Return(tc.KubectlExists)
|
||||
addCommaAndvalue := func(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return "," + s
|
||||
}
|
||||
kubectl := bootStrapKubectlTest(args)
|
||||
assert.Equal(t, tc.ExpectedEnabled, kubectl.enabled(), tc.Case)
|
||||
kubectlOut := tc.Context
|
||||
kubectlOut += addCommaAndvalue(tc.Namespace)
|
||||
kubectlOut += addCommaAndvalue(tc.User)
|
||||
kubectlOut += addCommaAndvalue(tc.Cluster)
|
||||
var kubectlErr error
|
||||
if tc.KubectlErr {
|
||||
kubectlErr = &commandError{
|
||||
err: "oops",
|
||||
exitCode: 1,
|
||||
}
|
||||
}
|
||||
env.On("runCommand", "kubectl",
|
||||
[]string{"config", "view", "--minify", "--output", "jsonpath={..current-context},{..namespace},{..context.user},{..context.cluster}"}).Return(kubectlOut, kubectlErr)
|
||||
|
||||
env.On("getenv", "KUBECONFIG").Return(tc.Kubeconfig)
|
||||
for path, content := range tc.Files {
|
||||
env.On("getFileContent", path).Return(content)
|
||||
}
|
||||
env.On("homeDir", nil).Return("testhome")
|
||||
|
||||
k := &kubectl{
|
||||
env: env,
|
||||
props: map[Property]interface{}{
|
||||
SegmentTemplate: tc.Template,
|
||||
DisplayError: tc.DisplayError,
|
||||
ParseKubeConfig: tc.ParseKubeConfig,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, tc.ExpectedEnabled, k.enabled(), tc.Case)
|
||||
if tc.ExpectedEnabled {
|
||||
assert.Equal(t, tc.ExpectedString, kubectl.string(), tc.Case)
|
||||
assert.Equal(t, tc.ExpectedString, k.string(), tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue