diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index ead55d590d7..367d8f68108 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -323,6 +323,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { reporter := &system.StreamReporter{WriteStream: bufw} var errs []error + var warns []error // All the validators we'd like to run: var validators = []system.Validator{ &system.OSValidator{Reporter: reporter}, @@ -333,7 +334,9 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { // Run all validators for _, v := range validators { - errs = append(errs, v.Validate(system.DefaultSysSpec)) + warn, err := v.Validate(system.DefaultSysSpec) + errs = append(errs, err) + warns = append(warns, warn) } err := utilerrors.NewAggregate(errs) @@ -341,9 +344,9 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { // Only print the output from the system verification check if the check failed fmt.Println("[preflight] The system verification failed. Printing the output from the verification:") bufw.Flush() - return nil, []error{err} + return warns, []error{err} } - return nil, nil + return warns, nil } type etcdVersionResponse struct { diff --git a/test/e2e_node/e2e_node_suite_test.go b/test/e2e_node/e2e_node_suite_test.go index 9368a5fe0b7..39b10a52307 100644 --- a/test/e2e_node/e2e_node_suite_test.go +++ b/test/e2e_node/e2e_node_suite_test.go @@ -98,7 +98,7 @@ func TestE2eNode(t *testing.T) { glog.Exitf("chroot %q failed: %v", rootfs, err) } } - if err := system.ValidateDefault(framework.TestContext.ContainerRuntime); err != nil { + if _, err := system.ValidateDefault(framework.TestContext.ContainerRuntime); err != nil { glog.Exitf("system validation failed: %v", err) } return diff --git a/test/e2e_node/system/cgroup_validator.go b/test/e2e_node/system/cgroup_validator.go index 86119a36032..dec67e8492d 100644 --- a/test/e2e_node/system/cgroup_validator.go +++ b/test/e2e_node/system/cgroup_validator.go @@ -37,12 +37,12 @@ const ( cgroupsConfigPrefix = "CGROUPS_" ) -func (c *CgroupsValidator) Validate(spec SysSpec) error { +func (c *CgroupsValidator) Validate(spec SysSpec) (error, error) { subsystems, err := c.getCgroupSubsystems() if err != nil { - return fmt.Errorf("failed to get cgroup subsystems: %v", err) + return nil, fmt.Errorf("failed to get cgroup subsystems: %v", err) } - return c.validateCgroupSubsystems(spec.Cgroups, subsystems) + return nil, c.validateCgroupSubsystems(spec.Cgroups, subsystems) } func (c *CgroupsValidator) validateCgroupSubsystems(cgroupSpec, subsystems []string) error { diff --git a/test/e2e_node/system/docker_validator.go b/test/e2e_node/system/docker_validator.go index aa045b4adf1..3799b04f0f9 100644 --- a/test/e2e_node/system/docker_validator.go +++ b/test/e2e_node/system/docker_validator.go @@ -37,29 +37,30 @@ func (d *DockerValidator) Name() string { } const ( - dockerEndpoint = "unix:///var/run/docker.sock" - dockerConfigPrefix = "DOCKER_" + dockerEndpoint = "unix:///var/run/docker.sock" + dockerConfigPrefix = "DOCKER_" + maxDockerValidatedVersion = "1.12" ) // TODO(random-liu): Add more validating items. -func (d *DockerValidator) Validate(spec SysSpec) error { +func (d *DockerValidator) Validate(spec SysSpec) (error, error) { if spec.RuntimeSpec.DockerSpec == nil { // If DockerSpec is not specified, assume current runtime is not // docker, skip the docker configuration validation. - return nil + return nil, nil } c, err := client.NewClient(dockerEndpoint, "", nil, nil) if err != nil { - return fmt.Errorf("failed to create docker client: %v", err) + return nil, fmt.Errorf("failed to create docker client: %v", err) } info, err := c.Info(context.Background()) if err != nil { - return fmt.Errorf("failed to get docker info: %v", err) + return nil, fmt.Errorf("failed to get docker info: %v", err) } return d.validateDockerInfo(spec.RuntimeSpec.DockerSpec, info) } -func (d *DockerValidator) validateDockerInfo(spec *DockerSpec, info types.Info) error { +func (d *DockerValidator) validateDockerInfo(spec *DockerSpec, info types.Info) (error, error) { // Validate docker version. matched := false for _, v := range spec.Version { @@ -70,17 +71,29 @@ func (d *DockerValidator) validateDockerInfo(spec *DockerSpec, info types.Info) } } if !matched { + // catch if docker is 1.13+ + ver := `1\.(1[3-9])\..*|\d{2}\.\d+\.\d+-[a-z]{2}` + r := regexp.MustCompile(ver) + if r.MatchString(info.ServerVersion) { + d.Reporter.Report(dockerConfigPrefix+"VERSION", info.ServerVersion, good) + w := fmt.Errorf( + "docker version is greater than the most recently validated version. Docker version: %s. Max validated version: %s", + info.ServerVersion, + maxDockerValidatedVersion, + ) + return w, nil + } d.Reporter.Report(dockerConfigPrefix+"VERSION", info.ServerVersion, bad) - return fmt.Errorf("unsupported docker version: %s", info.ServerVersion) + return nil, fmt.Errorf("unsupported docker version: %s", info.ServerVersion) } // Validate graph driver. item := dockerConfigPrefix + "GRAPH_DRIVER" for _, gd := range spec.GraphDriver { if info.Driver == gd { d.Reporter.Report(item, info.Driver, good) - return nil + return nil, nil } } d.Reporter.Report(item, info.Driver, bad) - return fmt.Errorf("unsupported graph driver: %s", info.Driver) + return nil, fmt.Errorf("unsupported graph driver: %s", info.Driver) } diff --git a/test/e2e_node/system/docker_validator_test.go b/test/e2e_node/system/docker_validator_test.go index de250c43347..bff47ce1138 100644 --- a/test/e2e_node/system/docker_validator_test.go +++ b/test/e2e_node/system/docker_validator_test.go @@ -28,42 +28,53 @@ func TestValidateDockerInfo(t *testing.T) { Reporter: DefaultReporter, } spec := &DockerSpec{ - Version: []string{`1\.(9|\d?[0-2]{2,})\..*`}, // Requires 1.9+ + Version: []string{`1\.(9|1[0-2])\..*`}, // Requires 1.9+ GraphDriver: []string{"driver_1", "driver_2"}, } for _, test := range []struct { info types.Info err bool + warn bool }{ { info: types.Info{Driver: "driver_1", ServerVersion: "1.10.1"}, err: false, + warn: false, }, { info: types.Info{Driver: "bad_driver", ServerVersion: "1.9.1"}, err: true, + warn: false, }, { info: types.Info{Driver: "driver_2", ServerVersion: "1.8.1"}, err: true, + warn: false, }, - // TODO remove once sig-node supports 1.13 + // TODO remove/change warn value once sig-node supports 1.13 { info: types.Info{Driver: "driver_2", ServerVersion: "1.13.1"}, - err: true, + err: false, + warn: true, }, - // TODO remove once sig-node supports 17.03-0-ce + // TODO remove/change warn value once sig-node supports 17.03-0-ce { info: types.Info{Driver: "driver_2", ServerVersion: "17.03.0-ce"}, - err: true, + err: false, + warn: true, }, } { - err := v.validateDockerInfo(spec, test.info) + warn, err := v.validateDockerInfo(spec, test.info) if !test.err { assert.Nil(t, err, "Expect error not to occur with docker info %+v", test.info) } else { assert.NotNil(t, err, "Expect error to occur with docker info %+v", test.info) } + if !test.warn { + assert.Nil(t, warn, "Expect error not to occur with docker info %+v", test.info) + } else { + assert.NotNil(t, warn, "Expect error to occur with docker info %+v", test.info) + } } } diff --git a/test/e2e_node/system/kernel_validator.go b/test/e2e_node/system/kernel_validator.go index 000eaee4117..295706dca14 100644 --- a/test/e2e_node/system/kernel_validator.go +++ b/test/e2e_node/system/kernel_validator.go @@ -60,16 +60,16 @@ const ( kConfigPrefix = "CONFIG_" ) -func (k *KernelValidator) Validate(spec SysSpec) error { +func (k *KernelValidator) Validate(spec SysSpec) (error, error) { release, err := exec.Command("uname", "-r").CombinedOutput() if err != nil { - return fmt.Errorf("failed to get kernel release: %v", err) + return nil, fmt.Errorf("failed to get kernel release: %v", err) } k.kernelRelease = strings.TrimSpace(string(release)) var errs []error errs = append(errs, k.validateKernelVersion(spec.KernelSpec)) errs = append(errs, k.validateKernelConfig(spec.KernelSpec)) - return errors.NewAggregate(errs) + return nil, errors.NewAggregate(errs) } // validateKernelVersion validates the kernel version. diff --git a/test/e2e_node/system/os_validator.go b/test/e2e_node/system/os_validator.go index b5cd34c4694..76326559daa 100644 --- a/test/e2e_node/system/os_validator.go +++ b/test/e2e_node/system/os_validator.go @@ -32,12 +32,12 @@ func (o *OSValidator) Name() string { return "os" } -func (o *OSValidator) Validate(spec SysSpec) error { +func (o *OSValidator) Validate(spec SysSpec) (error, error) { os, err := exec.Command("uname").CombinedOutput() if err != nil { - return fmt.Errorf("failed to get os name: %v", err) + return nil, fmt.Errorf("failed to get os name: %v", err) } - return o.validateOS(strings.TrimSpace(string(os)), spec.OS) + return nil, o.validateOS(strings.TrimSpace(string(os)), spec.OS) } func (o *OSValidator) validateOS(os, specOS string) error { diff --git a/test/e2e_node/system/validators.go b/test/e2e_node/system/validators.go index 395413c1992..369aefa71b6 100644 --- a/test/e2e_node/system/validators.go +++ b/test/e2e_node/system/validators.go @@ -26,7 +26,7 @@ type Validator interface { // Name is the name of the validator. Name() string // Validate is the validate function. - Validate(SysSpec) error + Validate(SysSpec) (error, error) } // Reporter is the interface for the reporters for the validators. @@ -35,19 +35,22 @@ type Reporter interface { Report(string, string, ValidationResultType) error } -// Validate uses validators to validate the system. -func Validate(spec SysSpec, validators []Validator) error { +// Validate uses validators to validate the system and returns a warning or error. +func Validate(spec SysSpec, validators []Validator) (error, error) { var errs []error + var warns []error for _, v := range validators { glog.Infof("Validating %s...", v.Name()) - errs = append(errs, v.Validate(spec)) + warn, err := v.Validate(spec) + errs = append(errs, err) + warns = append(warns, warn) } - return errors.NewAggregate(errs) + return errors.NewAggregate(warns), errors.NewAggregate(errs) } // ValidateDefault uses all default validators to validate the system and writes to stdout. -func ValidateDefault(runtime string) error { +func ValidateDefault(runtime string) (error, error) { // OS-level validators. var osValidators = []Validator{ &OSValidator{Reporter: DefaultReporter},