linkerd2/cli/cmd/check_extensions_test.go

389 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"bytes"
"errors"
"path/filepath"
"reflect"
"testing"
"k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
)
func TestFindExtensions(t *testing.T) {
fakeGlob := func(path string) ([]string, error) {
dir, _ := filepath.Split(path)
return []string{
filepath.Join(dir, "linkerd-bar"),
filepath.Join(dir, "linkerd-baz"),
filepath.Join(dir, "linkerd-foo"),
}, nil
}
fcmd := fakeexec.FakeCmd{
RunScript: []fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte(`{"name":"linkerd-baz","checks":"always"}`), nil, nil
},
func() ([]byte, []byte, error) {
return []byte(`{"name":"linkerd-foo-no-match","checks":"always"}`), nil, nil
},
func() ([]byte, []byte, error) { return []byte(`{"name":"linkerd-bar","checks":"always"}`), nil, nil },
},
}
lookPathSuccess := false
fexec := &fakeexec.FakeExec{
CommandScript: []fakeexec.FakeCommandAction{
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
},
LookPathFunc: func(cmd string) (string, error) {
if lookPathSuccess {
return cmd, nil
}
lookPathSuccess = true
return "", errors.New("fake-error")
},
}
extensions, missing := findExtensions("/path1:/this/is/a/fake/path2", fakeGlob, fexec, []string{"foo", "missing-cli"})
expExtensions := []extension{
{path: "/this/is/a/fake/path2/linkerd-bar"},
{path: "/path1/linkerd-baz"},
{path: "/path1/linkerd-foo"},
}
expMissing := []string{"linkerd-missing-cli"}
if !reflect.DeepEqual(expExtensions, extensions) {
t.Errorf("Expected [%+v] Got [%+v]", expExtensions, extensions)
}
if !reflect.DeepEqual(expMissing, missing) {
t.Errorf("Expected [%+v] Got [%+v]", expMissing, missing)
}
}
func TestRunExtensionsChecks(t *testing.T) {
successJSON := `
{
"success": true,
"categories": [
{
"categoryName": "success check name",
"checks": [
{
"description": "success check desc",
"result": "success"
}
]
}
]
}
`
warningJSON := `
{
"success": true,
"categories": [
{
"categoryName": "warning check name",
"checks": [
{
"description": "warning check desc",
"hint": "https://example.com/warning",
"error": "this is the warning message",
"result": "warning"
}
]
}
]
}
`
errorJSON := `
{
"success": false,
"categories": [
{
"categoryName": "error check name",
"checks": [
{
"description": "error check desc",
"hint": "https://example.com/error",
"error": "this is the error message",
"result": "error"
}
]
}
]
}
`
multiJSON := `
{
"success": true,
"categories": [
{
"categoryName": "multi check name",
"checks": [
{
"description": "multi check desc success",
"result": "success"
},
{
"description": "multi check desc warning",
"hint": "https://example.com/multi",
"error": "this is the multi warning message",
"result": "warning"
}
]
}
]
}
`
testCases := []struct {
name string
extensions []extension
missing []string
fakeActions []fakeexec.FakeAction
expSuccess bool
expWarning bool
expOutput string
}{
{
"no checks",
nil,
nil,
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return nil, nil, nil
},
},
true,
false,
"",
},
{
"invalid JSON",
[]extension{{path: "/path/linkerd-invalid"}},
nil,
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte("bad json"), nil, nil
},
},
false,
false,
`linkerd-invalid
---------------
× Running: /path/linkerd-invalid check
invalid extension check output from "/path/linkerd-invalid check" (JSON object expected):
bad json
[invalid character 'b' looking for beginning of value]
see https://linkerd.io/2/checks/#extensions for hints
`,
},
{
"one successful check",
[]extension{{path: "/path/linkerd-success"}},
nil,
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte(successJSON), nil, nil
},
},
true,
false,
`success check name
------------------
√ success check desc
`,
},
{
"one warning check",
[]extension{{path: "/path/linkerd-warning"}},
nil,
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte(warningJSON), nil, nil
},
},
true,
true,
`warning check name
------------------
‼ warning check desc
this is the warning message
see https://example.com/warning for hints
`,
},
{
"one error check",
[]extension{{path: "/path/linkerd-error"}},
nil,
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte(errorJSON), nil, nil
},
},
false,
false,
`error check name
----------------
× error check desc
this is the error message
see https://example.com/error for hints
`,
},
{
"one missing check",
nil,
[]string{"missing"},
nil,
true,
true,
`missing
-------
‼ Linkerd extension command missing exists
exec: "missing": executable file not found in $PATH
see https://linkerd.io/2/checks/#extensions for hints
`,
},
{
"multiple checks with success, warnings, errors, and missing",
[]extension{{path: "/path/linkerd-success"}, {path: "/path/linkerd-warning"}, {path: "/path/linkerd-error"}, {path: "/path/linkerd-multi"}},
[]string{"missing1", "missing2"},
[]fakeexec.FakeAction{
func() ([]byte, []byte, error) {
return []byte(successJSON), nil, nil
},
func() ([]byte, []byte, error) {
return []byte(warningJSON), nil, nil
},
func() ([]byte, []byte, error) {
return []byte(errorJSON), nil, nil
},
func() ([]byte, []byte, error) {
return []byte(multiJSON), nil, nil
},
},
false,
true,
`success check name
------------------
√ success check desc
warning check name
------------------
‼ warning check desc
this is the warning message
see https://example.com/warning for hints
error check name
----------------
× error check desc
this is the error message
see https://example.com/error for hints
multi check name
----------------
√ multi check desc success
‼ multi check desc warning
this is the multi warning message
see https://example.com/multi for hints
missing1
--------
‼ Linkerd extension command missing1 exists
exec: "missing1": executable file not found in $PATH
see https://linkerd.io/2/checks/#extensions for hints
missing2
--------
‼ Linkerd extension command missing2 exists
exec: "missing2": executable file not found in $PATH
see https://linkerd.io/2/checks/#extensions for hints
`,
},
}
for _, tc := range testCases {
tc := tc // pin
t.Run(tc.name, func(t *testing.T) {
fcmd := fakeexec.FakeCmd{
RunScript: tc.fakeActions,
}
fakeCommandActions := make([]fakeexec.FakeCommandAction, len(tc.fakeActions))
for i := 0; i < len(tc.fakeActions); i++ {
fakeCommandActions[i] = func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }
}
fexec := &fakeexec.FakeExec{
CommandScript: fakeCommandActions,
}
var stdout, stderr bytes.Buffer
success, warning := runExtensionsChecks(&stdout, &stderr, tc.extensions, tc.missing, fexec, nil, "")
if tc.expSuccess != success {
t.Errorf("Expected success to be %t, got %t", tc.expSuccess, success)
}
if tc.expWarning != warning {
t.Errorf("Expected warning to be %t, got %t", tc.expWarning, warning)
}
output := stdout.String()
if tc.expOutput != output {
t.Errorf("Expected output to be:\n%s\nGot:\n%s", tc.expOutput, output)
}
})
}
}
func TestSuffix(t *testing.T) {
testCases := []*struct {
testName string
input string
exp string
}{
{
"empty",
"",
"",
},
{
"no path",
"linkerd-foo",
"foo",
},
{
"extra dash",
"linkerd-foo-bar",
"foo-bar",
},
{
"with path",
"/tmp/linkerd-foo",
"foo",
},
}
for _, tc := range testCases {
tc := tc // pin
t.Run(tc.testName, func(t *testing.T) {
result := suffix(tc.input)
if !reflect.DeepEqual(tc.exp, result) {
t.Fatalf("Expected [%s] Got [%s]", tc.exp, result)
}
})
}
}