Merge pull request #61601 from neolit123/test-join

Automatic merge from submit-queue (batch tested with PRs 61601, 62881, 63159). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

kubeadm: add test coverage to join.go

**What this PR does / why we need it**:
Add test coverage to `join.go`.

A separate commit exports the function `ValidateJoinCommandLine()` from `join.go` so that testing this file is more flexible.

Test coverage is at 76%. One untested part is successfully running `Join.Run()` without errors, but that requires a valid HTTPS API server running and a valid config. i got this partially working but gave up because i faced some cert / config blockers. suggestions on how to get that to work easily are welcome.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:

NONE

**Special notes for your reviewer**:

NONE

**Release note**:

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue
2018-04-25 14:03:18 -07:00
committed by GitHub
3 changed files with 212 additions and 15 deletions

View File

@@ -81,16 +81,19 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"join_test.go",
"reset_test.go",
"token_test.go",
"version_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//pkg/api/legacyscheme:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",

View File

@@ -115,21 +115,7 @@ func NewCmdJoin(out io.Writer) *cobra.Command {
Short: "Run this on any machine you wish to join an existing cluster",
Long: joinLongDescription,
Run: func(cmd *cobra.Command, args []string) {
cfg.DiscoveryTokenAPIServers = args
var err error
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
legacyscheme.Scheme.Default(cfg)
internalcfg := &kubeadmapi.NodeConfiguration{}
legacyscheme.Scheme.Convert(cfg, internalcfg, nil)
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
kubeadmutil.CheckErr(err)
j, err := NewJoin(cfgPath, args, internalcfg, ignorePreflightErrorsSet)
j, err := NewValidJoin(cfg, args, skipPreFlight, cfgPath, featureGatesString, ignorePreflightErrors)
kubeadmutil.CheckErr(err)
kubeadmutil.CheckErr(j.Validate(cmd))
kubeadmutil.CheckErr(j.Run(out))
@@ -142,6 +128,27 @@ func NewCmdJoin(out io.Writer) *cobra.Command {
return cmd
}
// NewValidJoin validates the command line that are passed to the cobra command
func NewValidJoin(cfg *kubeadmapiext.NodeConfiguration, args []string, skipPreFlight bool, cfgPath, featureGatesString string, ignorePreflightErrors []string) (*Join, error) {
cfg.DiscoveryTokenAPIServers = args
var err error
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
return nil, err
}
legacyscheme.Scheme.Default(cfg)
internalcfg := &kubeadmapi.NodeConfiguration{}
legacyscheme.Scheme.Convert(cfg, internalcfg, nil)
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
if err != nil {
return nil, err
}
return NewJoin(cfgPath, args, internalcfg, ignorePreflightErrorsSet)
}
// AddJoinConfigFlags adds join flags bound to the config to the specified flagset
func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.NodeConfiguration, featureGatesString *string) {
flagSet.StringVar(

View File

@@ -0,0 +1,187 @@
/*
Copyright 2018 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 cmd
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/pkg/api/legacyscheme"
)
const (
testConfig = `apiVersion: v1
clusters:
- cluster:
certificate-authority-data:
server: localhost:9008
name: prod
contexts:
- context:
cluster: prod
namespace: default
user: default-service-account
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data:
client-key-data:
`
)
func TestNewValidJoin(t *testing.T) {
// create temp directory
tmpDir, err := ioutil.TempDir("", "kubeadm-join-test")
if err != nil {
t.Errorf("Unable to create temporary directory: %v", err)
}
defer os.RemoveAll(tmpDir)
// create config file
configFilePath := filepath.Join(tmpDir, "test-config-file")
cfgFile, err := os.Create(configFilePath)
if err != nil {
t.Errorf("Unable to create file %q: %v", configFilePath, err)
}
defer cfgFile.Close()
testCases := []struct {
name string
args []string
skipPreFlight bool
cfgPath string
configToWrite string
featureGatesString string
ignorePreflightErrors []string
testJoinValidate bool
testJoinRun bool
cmdPersistentFlags map[string]string
nodeConfig *kubeadm.NodeConfiguration
expectedError bool
}{
{
name: "invalid: missing config file",
skipPreFlight: true,
cfgPath: "missing-path-to-a-config",
expectedError: true,
},
{
name: "invalid: incorrect config file",
skipPreFlight: true,
cfgPath: configFilePath,
configToWrite: "bad-config-contents",
expectedError: true,
},
{
name: "invalid: fail at preflight.RunJoinNodeChecks()",
skipPreFlight: false,
cfgPath: configFilePath,
configToWrite: testConfig,
expectedError: true,
},
{
name: "invalid: incorrect ignorePreflight argument",
skipPreFlight: true,
cfgPath: configFilePath,
configToWrite: testConfig,
ignorePreflightErrors: []string{"some-unsupported-preflight-arg"},
expectedError: true,
},
{
name: "invalid: incorrect featureGatesString",
featureGatesString: "bad-feature-gate-string",
expectedError: true,
},
{
name: "invalid: fail Join.Validate() with wrong flags",
skipPreFlight: true,
cfgPath: configFilePath,
configToWrite: testConfig,
testJoinValidate: true,
cmdPersistentFlags: map[string]string{
"config": "some-config",
"node-name": "some-node-name",
},
expectedError: true,
},
{
name: "invalid: fail Join.Validate() with wrong node configuration",
skipPreFlight: true,
cfgPath: configFilePath,
configToWrite: testConfig,
testJoinValidate: true,
expectedError: true,
},
{
name: "invalid: fail Join.Run() with invalid node config",
skipPreFlight: true,
cfgPath: configFilePath,
configToWrite: testConfig,
testJoinRun: true,
expectedError: true,
},
}
var out bytes.Buffer
cfg := &kubeadmapiext.NodeConfiguration{}
legacyscheme.Scheme.Default(cfg)
errorFormat := "Test case %q: NewValidJoin expected error: %v, saw: %v, error: %v"
for _, tc := range testCases {
if _, err = cfgFile.WriteString(tc.configToWrite); err != nil {
t.Fatalf("Unable to write file %q: %v", tc.cfgPath, err)
}
join, err := NewValidJoin(cfg, tc.args, tc.skipPreFlight, tc.cfgPath, tc.featureGatesString, tc.ignorePreflightErrors)
cmd := NewCmdJoin(&out)
if tc.cmdPersistentFlags != nil {
for key, value := range tc.cmdPersistentFlags {
cmd.PersistentFlags().Set(key, value)
}
}
if tc.nodeConfig != nil {
join.cfg = tc.nodeConfig
}
// test Join.Run()
if err == nil && tc.testJoinRun {
err = join.Run(&out)
if (err != nil) != tc.expectedError {
t.Fatalf(errorFormat, tc.name, tc.expectedError, (err != nil), err)
}
// test Join.Validate()
} else if err == nil && tc.testJoinValidate {
if err = join.Validate(cmd); (err != nil) != tc.expectedError {
t.Fatalf(errorFormat, tc.name, tc.expectedError, (err != nil), err)
}
// check error for NewValidJoin()
} else if (err != nil) != tc.expectedError {
t.Fatalf(errorFormat, tc.name, tc.expectedError, (err != nil), err)
}
}
}