diff --git a/Makefile b/Makefile index f4485c362c5..f682c194ca4 100644 --- a/Makefile +++ b/Makefile @@ -185,6 +185,7 @@ test-e2e-node: ginkgo generated_files # make test-cmd .PHONY: test-cmd test-cmd: generated_files + hack/make-rules/test-kubeadm-cmd.sh hack/make-rules/test-cmd.sh # Remove all build artifacts. diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index 2edf2c923e4..925020a3907 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -17,6 +17,7 @@ go_library( "init.go", "join.go", "reset.go", + "token.go", "version.go", ], tags = ["automanaged"], @@ -42,7 +43,10 @@ go_library( go_test( name = "go_default_test", - srcs = ["reset_test.go"], + srcs = [ + "reset_test.go", + "token_test.go", + ], library = "go_default_library", tags = ["automanaged"], deps = ["//cmd/kubeadm/app/preflight:go_default_library"], diff --git a/cmd/kubeadm/test/BUILD b/cmd/kubeadm/test/BUILD new file mode 100644 index 00000000000..f6609ba4222 --- /dev/null +++ b/cmd/kubeadm/test/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_binary", + "go_library", + "go_test", + "cgo_library", +) + +go_library( + name = "go_default_library", + srcs = ["util.go"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["token_test.go"], + library = "go_default_library", + tags = ["automanaged"], + deps = [], +) diff --git a/cmd/kubeadm/test/token_test.go b/cmd/kubeadm/test/token_test.go new file mode 100644 index 00000000000..b9bda37d8e0 --- /dev/null +++ b/cmd/kubeadm/test/token_test.go @@ -0,0 +1,65 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeadm + +import ( + "flag" + "regexp" + "testing" +) + +const ( + TokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$" +) + +var kubeadmPath string + +func init() { + flag.StringVar(&kubeadmPath, "kubeadm-path", "cluster/kubeadm.sh", "Location of kubeadm") +} + +func TestCmdTokenGenerate(t *testing.T) { + stdout, _, err := RunCmd(kubeadmPath, "token", "generate") + if err != nil { + t.Errorf("'kubeadm token generate' exited uncleanly: %v", err) + } + + matched, err := regexp.MatchString(TokenExpectedRegex, stdout) + if err != nil { + t.Fatalf("encountered an error while trying to match 'kubeadm token generate' stdout: %v", err) + } + if !matched { + t.Errorf("'kubeadm token generate' stdout did not match expected regex; wanted: [%s], got: [%s]", TokenExpectedRegex, stdout) + } +} + +func TestCmdTokenGenerateTypoError(t *testing.T) { + /* + Since we expect users to do things like this: + + $ TOKEN=$(kubeadm token generate) + + we want to make sure that if they have a typo in their command, we exit + with a non-zero status code after showing the command's usage, so that + the usage itself isn't captured as a token without the user noticing. + */ + + _, _, 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") + } +} diff --git a/cmd/kubeadm/test/util.go b/cmd/kubeadm/test/util.go new file mode 100644 index 00000000000..d17836f3c68 --- /dev/null +++ b/cmd/kubeadm/test/util.go @@ -0,0 +1,41 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubeadm + +import ( + "bytes" + "fmt" + "io" + "os" + "os/exec" +) + +// Forked from test/e2e/framework because the e2e framework is quite bloated +// for our purposes here, and modified to remove undesired logging. +func RunCmd(command string, args ...string) (string, string, error) { + var bout, berr bytes.Buffer + cmd := exec.Command(command, args...) + cmd.Stdout = io.MultiWriter(os.Stdout, &bout) + cmd.Stderr = io.MultiWriter(os.Stderr, &berr) + err := cmd.Run() + stdout, stderr := bout.String(), berr.String() + if err != nil { + return "", "", fmt.Errorf("error running %s %v; got error %v, stdout %q, stderr %q", + command, args, err, stdout, stderr) + } + return stdout, stderr, nil +} diff --git a/hack/make-rules/test-kubeadm-cmd.sh b/hack/make-rules/test-kubeadm-cmd.sh new file mode 100755 index 00000000000..c28d7d00e51 --- /dev/null +++ b/hack/make-rules/test-kubeadm-cmd.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Copyright 2016 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. +source "${KUBE_ROOT}/hack/lib/init.sh" + +KUBEADM_PATH="${KUBEADM_PATH:=$(kube::realpath "${KUBE_ROOT}")/cluster/kubeadm.sh}" + +# If testing a different version of kubeadm than the current build, you can +# comment this out to save yourself from needlessly building here. +make -C "${KUBE_ROOT}" WHAT=cmd/kubeadm + +make -C "${KUBE_ROOT}" test \ + WHAT=cmd/kubeadm/test \ + KUBE_TEST_ARGS="--kubeadm-path '${KUBEADM_PATH}'" diff --git a/hack/make-rules/test.sh b/hack/make-rules/test.sh index db6a3998496..93946fa3447 100755 --- a/hack/make-rules/test.sh +++ b/hack/make-rules/test.sh @@ -35,6 +35,7 @@ kube::test::find_dirs() { -path './_artifacts/*' \ -o -path './_output/*' \ -o -path './_gopath/*' \ + -o -path './cmd/kubeadm/test/*' \ -o -path './contrib/podex/*' \ -o -path './output/*' \ -o -path './release/*' \ diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index e73dec1d75b..668244b3b08 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -295,6 +295,7 @@ kube-master kube-master kube-master-url kube-reserved +kubeadm-path kubecfg-file kubectl-path kubelet-address diff --git a/test/test_owners.csv b/test/test_owners.csv index abaa63625b1..115a32bfda2 100644 --- a/test/test_owners.csv +++ b/test/test_owners.csv @@ -457,6 +457,7 @@ k8s.io/kubernetes/cmd/kubeadm/app/cmd,caesarxuchao,1 k8s.io/kubernetes/cmd/kubeadm/app/images,davidopp,1 k8s.io/kubernetes/cmd/kubeadm/app/preflight,apprenda,0 k8s.io/kubernetes/cmd/kubeadm/app/util,krousey,1 +k8s.io/kubernetes/cmd/kubeadm/test,pipejakob,0 k8s.io/kubernetes/cmd/kubelet/app,hurf,1 k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types,caesarxuchao,0 k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf,smarterclayton,0