Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeadm: add test to detect panics when given certain feature gates #83369

Merged
merged 1 commit into from Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/kubeadm/test/cmd/completion_test.go
Expand Up @@ -37,7 +37,7 @@ func TestCmdCompletion(t *testing.T) {

for _, rt := range tests {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "completion", rt.args)
_, _, _, actual := RunCmd(kubeadmPath, "completion", rt.args)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdCompletion running 'kubeadm completion %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down
61 changes: 55 additions & 6 deletions cmd/kubeadm/test/cmd/init_test.go
Expand Up @@ -29,7 +29,7 @@ import (
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
)

func runKubeadmInit(args ...string) (string, string, error) {
func runKubeadmInit(args ...string) (string, string, int, error) {
kubeadmPath := getKubeadmPath()
kubeadmArgs := []string{"init", "--dry-run", "--ignore-preflight-errors=all"}
kubeadmArgs = append(kubeadmArgs, args...)
Expand Down Expand Up @@ -66,7 +66,7 @@ func TestCmdInitToken(t *testing.T) {

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, err := runKubeadmInit(rt.args)
_, _, _, err := runKubeadmInit(rt.args)
if (err == nil) != rt.expected {
t.Fatalf(dedent.Dedent(`
CmdInitToken test case %q failed with an error: %v
Expand Down Expand Up @@ -110,7 +110,7 @@ func TestCmdInitKubernetesVersion(t *testing.T) {

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, err := runKubeadmInit(rt.args)
_, _, _, err := runKubeadmInit(rt.args)
if (err == nil) != rt.expected {
t.Fatalf(dedent.Dedent(`
CmdInitKubernetesVersion test case %q failed with an error: %v
Expand Down Expand Up @@ -184,7 +184,7 @@ func TestCmdInitConfig(t *testing.T) {

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, err := runKubeadmInit(rt.args)
_, _, _, err := runKubeadmInit(rt.args)
if (err == nil) != rt.expected {
t.Fatalf(dedent.Dedent(`
CmdInitConfig test case %q failed with an error: %v
Expand Down Expand Up @@ -235,7 +235,7 @@ func TestCmdInitCertPhaseCSR(t *testing.T) {
csrDir := testutil.SetupTempDir(t)
cert := &certs.KubeadmCertKubeletClient
kubeadmPath := getKubeadmPath()
_, stderr, err := RunCmd(kubeadmPath,
_, stderr, _, err := RunCmd(kubeadmPath,
"init",
"phase",
"certs",
Expand Down Expand Up @@ -303,7 +303,7 @@ func TestCmdInitAPIPort(t *testing.T) {

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, err := runKubeadmInit(rt.args)
_, _, _, err := runKubeadmInit(rt.args)
if (err == nil) != rt.expected {
t.Fatalf(dedent.Dedent(`
CmdInitAPIPort test case %q failed with an error: %v
Expand All @@ -321,3 +321,52 @@ func TestCmdInitAPIPort(t *testing.T) {
})
}
}

// TestCmdInitFeatureGates test that feature gates won't make kubeadm panic.
// When go panics it will exit with a 2 code. While we don't expect the init
// calls to succeed in these tests, we ensure that the exit code of calling
// kubeadm with different feature gates is not 2.
func TestCmdInitFeatureGates(t *testing.T) {
const PanicExitcode = 2

if *kubeadmCmdSkip {
t.Log("kubeadm cmd tests being skipped")
t.Skip()
}

initTest := []struct {
name string
args string
}{
{
name: "no feature gates passed",
args: "",
},
{
name: "feature gate CoreDNS=true",
args: "--feature-gates=CoreDNS=true",
},
{
name: "feature gate IPv6DualStack=true",
args: "--feature-gates=IPv6DualStack=true",
},
}

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, exitcode, err := runKubeadmInit(rt.args)
if exitcode == PanicExitcode {
t.Fatalf(dedent.Dedent(`
CmdInitFeatureGates test case %q failed with an error: %v
command 'kubeadm init %s'
got exit code: %t (panic); unexpected
`),
rt.name,
err,
rt.args,
PanicExitcode,
)
}
})
}
}
18 changes: 9 additions & 9 deletions cmd/kubeadm/test/cmd/join_test.go
Expand Up @@ -21,7 +21,7 @@ import "testing"
// kubeadmReset executes "kubeadm reset" and restarts kubelet.
func kubeadmReset() error {
kubeadmPath := getKubeadmPath()
_, _, err := RunCmd(kubeadmPath, "reset")
_, _, _, err := RunCmd(kubeadmPath, "reset")
return err
}

Expand All @@ -43,7 +43,7 @@ func TestCmdJoinConfig(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinConfig running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -76,7 +76,7 @@ func TestCmdJoinDiscoveryFile(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinDiscoveryFile running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -109,7 +109,7 @@ func TestCmdJoinDiscoveryToken(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinDiscoveryToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -141,7 +141,7 @@ func TestCmdJoinNodeName(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinNodeName running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -174,7 +174,7 @@ func TestCmdJoinTLSBootstrapToken(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinTLSBootstrapToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -207,7 +207,7 @@ func TestCmdJoinToken(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinToken running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -240,7 +240,7 @@ func TestCmdJoinBadArgs(t *testing.T) {

for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinBadArgs 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -272,7 +272,7 @@ func TestCmdJoinArgsMixed(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range initTest {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
_, _, _, actual := RunCmd(kubeadmPath, "join", rt.args, "--ignore-preflight-errors=all")
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdJoinArgsMixed running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down
6 changes: 3 additions & 3 deletions cmd/kubeadm/test/cmd/token_test.go
Expand Up @@ -48,7 +48,7 @@ func TestCmdTokenGenerate(t *testing.T) {
t.Log("kubeadm cmd tests being skipped")
t.Skip()
}
stdout, _, err := RunCmd(kubeadmPath, "token", "generate")
stdout, _, _, err := RunCmd(kubeadmPath, "token", "generate")
if err != nil {
t.Fatalf("'kubeadm token generate' exited uncleanly: %v", err)
}
Expand Down Expand Up @@ -78,7 +78,7 @@ func TestCmdTokenGenerateTypoError(t *testing.T) {
}

kubeadmPath := getKubeadmPath()
_, _, err := RunCmd(kubeadmPath, "token", "genorate") // subtle typo
_, _, _, err := RunCmd(kubeadmPath, "token", "genorate") // subtle typo
if err == nil {
t.Error("'kubeadm token genorate' (a deliberate typo) exited without an error when we expected non-zero exit status")
}
Expand All @@ -101,7 +101,7 @@ func TestCmdTokenDelete(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range tests {
t.Run(rt.name, func(t *testing.T) {
_, _, actual := RunCmd(kubeadmPath, "token", "delete", rt.args)
_, _, _, actual := RunCmd(kubeadmPath, "token", "delete", rt.args)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdTokenDelete running 'kubeadm token %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down
14 changes: 7 additions & 7 deletions cmd/kubeadm/test/cmd/util.go
Expand Up @@ -29,24 +29,24 @@ import (
// Forked from test/e2e/framework because the e2e framework is quite bloated
// for our purposes here, and modified to remove undesired logging.

func runCmdNoWrap(command string, args ...string) (string, string, error) {
func runCmdNoWrap(command string, args ...string) (string, string, int, error) {
var bout, berr bytes.Buffer
cmd := exec.Command(command, args...)
cmd.Stdout = &bout
cmd.Stderr = &berr
err := cmd.Run()
stdout, stderr := bout.String(), berr.String()
return stdout, stderr, err
return stdout, stderr, cmd.ProcessState.ExitCode(), err
}

// RunCmd is a utility function for kubeadm testing that executes a specified command
func RunCmd(command string, args ...string) (string, string, error) {
stdout, stderr, err := runCmdNoWrap(command, args...)
func RunCmd(command string, args ...string) (string, string, int, error) {
stdout, stderr, retcode, err := runCmdNoWrap(command, args...)
if err != nil {
return stdout, stderr, errors.Wrapf(err, "error running %s %v; \nstdout %q, \nstderr %q, \ngot error",
command, args, stdout, stderr)
return stdout, stderr, retcode, errors.Wrapf(err, "error running %s %v; \nretcode %d, \nstdout %q, \nstderr %q, \ngot error",
command, args, retcode, stdout, stderr)
}
return stdout, stderr, nil
return stdout, stderr, retcode, nil
}

// RunSubCommand is a utility function for kubeadm testing that executes a Cobra sub command
Expand Down
4 changes: 2 additions & 2 deletions cmd/kubeadm/test/cmd/version_test.go
Expand Up @@ -53,7 +53,7 @@ func TestCmdVersion(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range versionTest {
t.Run(rt.name, func(t *testing.T) {
stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args)
stdout, _, _, actual := RunCmd(kubeadmPath, "version", rt.args)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down Expand Up @@ -96,7 +96,7 @@ func TestCmdVersionOutputJsonOrYaml(t *testing.T) {
kubeadmPath := getKubeadmPath()
for _, rt := range versionTest {
t.Run(rt.name, func(t *testing.T) {
stdout, _, actual := RunCmd(kubeadmPath, "version", rt.args)
stdout, _, _, actual := RunCmd(kubeadmPath, "version", rt.args)
if (actual == nil) != rt.expected {
t.Errorf(
"failed CmdVersion running 'kubeadm version %s' with an error: %v\n\texpected: %t\n\t actual: %t",
Expand Down