Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

View File

@ -10,60 +10,28 @@ go_library(
name = "go_default_library",
srcs = [
"checks.go",
"checks_unix.go",
"checks_windows.go",
"utils.go",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"checks_unix.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"checks_windows.go",
],
"//conditions:default": [],
}),
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/preflight",
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/util/runtime:go_default_library",
"//cmd/kubeadm/app/util/system:go_default_library",
"//pkg/registry/core/service/ipallocator:go_default_library",
"//pkg/util/initsystem:go_default_library",
"//pkg/util/ipvs:go_default_library",
"//pkg/util/version:go_default_library",
"//pkg/version:go_default_library",
"//test/e2e_node/system:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//vendor/github.com/PuerkitoBio/purell:go_default_library",
"//vendor/github.com/blang/semver:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
)
@ -77,8 +45,11 @@ go_test(
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/renstrom/dedent:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",
],

View File

@ -22,7 +22,6 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@ -37,20 +36,20 @@ import (
"github.com/PuerkitoBio/purell"
"github.com/blang/semver"
"github.com/golang/glog"
"github.com/pkg/errors"
netutil "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/sets"
versionutil "k8s.io/apimachinery/pkg/util/version"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmdefaults "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/util/system"
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
"k8s.io/kubernetes/pkg/util/initsystem"
ipvsutil "k8s.io/kubernetes/pkg/util/ipvs"
versionutil "k8s.io/kubernetes/pkg/util/version"
kubeadmversion "k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/test/e2e_node/system"
utilsexec "k8s.io/utils/exec"
)
@ -86,34 +85,27 @@ func (e *Error) Preflight() bool {
// Checker validates the state of the system to ensure kubeadm will be
// successful as often as possible.
type Checker interface {
Check() (warnings, errors []error)
Check() (warnings, errorList []error)
Name() string
}
// CRICheck verifies the container runtime through the CRI.
type CRICheck struct {
socket string
exec utilsexec.Interface
// ContainerRuntimeCheck verifies the container runtime.
type ContainerRuntimeCheck struct {
runtime utilruntime.ContainerRuntime
}
// Name returns label for CRICheck.
func (CRICheck) Name() string {
// Name returns label for RuntimeCheck.
func (ContainerRuntimeCheck) Name() string {
return "CRI"
}
// Check validates the container runtime through the CRI.
func (criCheck CRICheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating the container runtime through the CRI")
crictlPath, err := criCheck.exec.LookPath("crictl")
if err != nil {
errors = append(errors, fmt.Errorf("unable to find command crictl: %s", err))
return warnings, errors
// Check validates the container runtime
func (crc ContainerRuntimeCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating the container runtime")
if err := crc.runtime.IsRunning(); err != nil {
errorList = append(errorList, err)
}
if err := criCheck.exec.Command(crictlPath, "-r", criCheck.socket, "info").Run(); err != nil {
errors = append(errors, fmt.Errorf("unable to check if the container runtime at %q is running: %s", criCheck.socket, err))
return warnings, errors
}
return warnings, errors
return warnings, errorList
}
// ServiceCheck verifies that the given service is enabled and active. If we do not
@ -134,8 +126,8 @@ func (sc ServiceCheck) Name() string {
}
// Check validates if the service is enabled and active.
func (sc ServiceCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating if the service is enabled and active")
func (sc ServiceCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating if the service is enabled and active")
initSystem, err := initsystem.GetInitSystem()
if err != nil {
return []error{err}, nil
@ -144,23 +136,23 @@ func (sc ServiceCheck) Check() (warnings, errors []error) {
warnings = []error{}
if !initSystem.ServiceExists(sc.Service) {
warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.Service))
warnings = append(warnings, errors.Errorf("%s service does not exist", sc.Service))
return warnings, nil
}
if !initSystem.ServiceIsEnabled(sc.Service) {
warnings = append(warnings,
fmt.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'",
errors.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'",
sc.Service, sc.Service))
}
if sc.CheckIfActive && !initSystem.ServiceIsActive(sc.Service) {
errors = append(errors,
fmt.Errorf("%s service is not active, please run 'systemctl start %s.service'",
errorList = append(errorList,
errors.Errorf("%s service is not active, please run 'systemctl start %s.service'",
sc.Service, sc.Service))
}
return warnings, errors
return warnings, errorList
}
// FirewalldCheck checks if firewalld is enabled or active. If it is, warn the user that there may be problems
@ -175,8 +167,8 @@ func (FirewalldCheck) Name() string {
}
// Check validates if the firewall is enabled and active.
func (fc FirewalldCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating if the firewall is enabled and active")
func (fc FirewalldCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating if the firewall is enabled and active")
initSystem, err := initsystem.GetInitSystem()
if err != nil {
return []error{err}, nil
@ -190,11 +182,11 @@ func (fc FirewalldCheck) Check() (warnings, errors []error) {
if initSystem.ServiceIsActive("firewalld") {
warnings = append(warnings,
fmt.Errorf("firewalld is active, please ensure ports %v are open or your cluster may not function correctly",
errors.Errorf("firewalld is active, please ensure ports %v are open or your cluster may not function correctly",
fc.ports))
}
return warnings, errors
return warnings, errorList
}
// PortOpenCheck ensures the given port is available for use.
@ -212,18 +204,18 @@ func (poc PortOpenCheck) Name() string {
}
// Check validates if the particular port is available.
func (poc PortOpenCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating availability of port %d", poc.port)
errors = []error{}
func (poc PortOpenCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating availability of port %d", poc.port)
errorList = []error{}
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", poc.port))
if err != nil {
errors = append(errors, fmt.Errorf("Port %d is in use", poc.port))
errorList = append(errorList, errors.Errorf("Port %d is in use", poc.port))
}
if ln != nil {
ln.Close()
}
return nil, errors
return nil, errorList
}
// IsPrivilegedUserCheck verifies user is privileged (linux - root, windows - Administrator)
@ -249,9 +241,9 @@ func (dac DirAvailableCheck) Name() string {
}
// Check validates if a directory does not exist or empty.
func (dac DirAvailableCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating the existence and emptiness of directory %s", dac.Path)
errors = []error{}
func (dac DirAvailableCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating the existence and emptiness of directory %s", dac.Path)
errorList = []error{}
// If it doesn't exist we are good:
if _, err := os.Stat(dac.Path); os.IsNotExist(err) {
return nil, nil
@ -259,17 +251,17 @@ func (dac DirAvailableCheck) Check() (warnings, errors []error) {
f, err := os.Open(dac.Path)
if err != nil {
errors = append(errors, fmt.Errorf("unable to check if %s is empty: %s", dac.Path, err))
return nil, errors
errorList = append(errorList, errors.Wrapf(err, "unable to check if %s is empty", dac.Path))
return nil, errorList
}
defer f.Close()
_, err = f.Readdirnames(1)
if err != io.EOF {
errors = append(errors, fmt.Errorf("%s is not empty", dac.Path))
errorList = append(errorList, errors.Errorf("%s is not empty", dac.Path))
}
return nil, errors
return nil, errorList
}
// FileAvailableCheck checks that the given file does not already exist.
@ -287,13 +279,13 @@ func (fac FileAvailableCheck) Name() string {
}
// Check validates if the given file does not already exist.
func (fac FileAvailableCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating the existence of file %s", fac.Path)
errors = []error{}
func (fac FileAvailableCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating the existence of file %s", fac.Path)
errorList = []error{}
if _, err := os.Stat(fac.Path); err == nil {
errors = append(errors, fmt.Errorf("%s already exists", fac.Path))
errorList = append(errorList, errors.Errorf("%s already exists", fac.Path))
}
return nil, errors
return nil, errorList
}
// FileExistingCheck checks that the given file does not already exist.
@ -311,13 +303,13 @@ func (fac FileExistingCheck) Name() string {
}
// Check validates if the given file already exists.
func (fac FileExistingCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating the existence of file %s", fac.Path)
errors = []error{}
func (fac FileExistingCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating the existence of file %s", fac.Path)
errorList = []error{}
if _, err := os.Stat(fac.Path); err != nil {
errors = append(errors, fmt.Errorf("%s doesn't exist", fac.Path))
errorList = append(errorList, errors.Errorf("%s doesn't exist", fac.Path))
}
return nil, errors
return nil, errorList
}
// FileContentCheck checks that the given file contains the string Content.
@ -336,11 +328,11 @@ func (fcc FileContentCheck) Name() string {
}
// Check validates if the given file contains the given content.
func (fcc FileContentCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating the contents of file %s", fcc.Path)
func (fcc FileContentCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating the contents of file %s", fcc.Path)
f, err := os.Open(fcc.Path)
if err != nil {
return nil, []error{fmt.Errorf("%s does not exist", fcc.Path)}
return nil, []error{errors.Errorf("%s does not exist", fcc.Path)}
}
lr := io.LimitReader(f, int64(len(fcc.Content)))
@ -349,11 +341,11 @@ func (fcc FileContentCheck) Check() (warnings, errors []error) {
buf := &bytes.Buffer{}
_, err = io.Copy(buf, lr)
if err != nil {
return nil, []error{fmt.Errorf("%s could not be read", fcc.Path)}
return nil, []error{errors.Errorf("%s could not be read", fcc.Path)}
}
if !bytes.Equal(buf.Bytes(), fcc.Content) {
return nil, []error{fmt.Errorf("%s contents are not set to %s", fcc.Path, fcc.Content)}
return nil, []error{errors.Errorf("%s contents are not set to %s", fcc.Path, fcc.Content)}
}
return nil, []error{}
@ -378,12 +370,12 @@ func (ipc InPathCheck) Name() string {
// Check validates if the given executable is present in the path.
func (ipc InPathCheck) Check() (warnings, errs []error) {
glog.V(1).Infof("validating the presence of executable %s", ipc.executable)
klog.V(1).Infof("validating the presence of executable %s", ipc.executable)
_, err := ipc.exec.LookPath(ipc.executable)
if err != nil {
if ipc.mandatory {
// Return as an error:
return nil, []error{fmt.Errorf("%s not found in system path", ipc.executable)}
return nil, []error{errors.Errorf("%s not found in system path", ipc.executable)}
}
// Return as a warning:
warningMessage := fmt.Sprintf("%s not found in system path", ipc.executable)
@ -407,18 +399,18 @@ func (HostnameCheck) Name() string {
}
// Check validates if hostname match dns sub domain regex.
func (hc HostnameCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("checking whether the given node name is reachable using net.LookupHost")
errors = []error{}
func (hc HostnameCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("checking whether the given node name is reachable using net.LookupHost")
errorList = []error{}
warnings = []error{}
addr, err := net.LookupHost(hc.nodeName)
if addr == nil {
warnings = append(warnings, fmt.Errorf("hostname \"%s\" could not be reached", hc.nodeName))
warnings = append(warnings, errors.Errorf("hostname \"%s\" could not be reached", hc.nodeName))
}
if err != nil {
warnings = append(warnings, fmt.Errorf("hostname \"%s\" %s", hc.nodeName, err))
warnings = append(warnings, errors.Wrapf(err, "hostname \"%s\"", hc.nodeName))
}
return warnings, errors
return warnings, errorList
}
// HTTPProxyCheck checks if https connection to specific host is going
@ -434,8 +426,8 @@ func (hst HTTPProxyCheck) Name() string {
}
// Check validates http connectivity type, direct or via proxy.
func (hst HTTPProxyCheck) Check() (warnings, errors []error) {
glog.V(1).Infof("validating if the connectivity type is via proxy or direct")
func (hst HTTPProxyCheck) Check() (warnings, errorList []error) {
klog.V(1).Infof("validating if the connectivity type is via proxy or direct")
u := (&url.URL{Scheme: hst.Proto, Host: hst.Host}).String()
req, err := http.NewRequest("GET", u, nil)
@ -448,7 +440,7 @@ func (hst HTTPProxyCheck) Check() (warnings, errors []error) {
return nil, []error{err}
}
if proxy != nil {
return []error{fmt.Errorf("Connection to %q uses proxy %q. If that is not intended, adjust your proxy settings", u, proxy)}, nil
return []error{errors.Errorf("Connection to %q uses proxy %q. If that is not intended, adjust your proxy settings", u, proxy)}, nil
}
return nil, nil
}
@ -470,20 +462,20 @@ func (HTTPProxyCIDRCheck) Name() string {
// Check validates http connectivity to first IP address in the CIDR.
// If it is not directly connected and goes via proxy it will produce warning.
func (subnet HTTPProxyCIDRCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating http connectivity to first IP address in the CIDR")
func (subnet HTTPProxyCIDRCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating http connectivity to first IP address in the CIDR")
if len(subnet.CIDR) == 0 {
return nil, nil
}
_, cidr, err := net.ParseCIDR(subnet.CIDR)
if err != nil {
return nil, []error{fmt.Errorf("error parsing CIDR %q: %v", subnet.CIDR, err)}
return nil, []error{errors.Wrapf(err, "error parsing CIDR %q", subnet.CIDR)}
}
testIP, err := ipallocator.GetIndexedIP(cidr, 1)
if err != nil {
return nil, []error{fmt.Errorf("unable to get first IP address from the given CIDR (%s): %v", cidr.String(), err)}
return nil, []error{errors.Wrapf(err, "unable to get first IP address from the given CIDR (%s)", cidr.String())}
}
testIPstring := testIP.String()
@ -503,14 +495,14 @@ func (subnet HTTPProxyCIDRCheck) Check() (warnings, errors []error) {
return nil, []error{err}
}
if proxy != nil {
return []error{fmt.Errorf("connection to %q uses proxy %q. This may lead to malfunctional cluster setup. Make sure that Pod and Services IP ranges specified correctly as exceptions in proxy configuration", subnet.CIDR, proxy)}, nil
return []error{errors.Errorf("connection to %q uses proxy %q. This may lead to malfunctional cluster setup. Make sure that Pod and Services IP ranges specified correctly as exceptions in proxy configuration", subnet.CIDR, proxy)}, nil
}
return nil, nil
}
// SystemVerificationCheck defines struct used for for running the system verification node check in test/e2e_node/system
// SystemVerificationCheck defines struct used for running the system verification node check in test/e2e_node/system
type SystemVerificationCheck struct {
CRISocket string
IsDocker bool
}
// Name will return SystemVerification as name for SystemVerificationCheck
@ -519,8 +511,8 @@ func (SystemVerificationCheck) Name() string {
}
// Check runs all individual checks
func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("running all checks")
func (sysver SystemVerificationCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("running all checks")
// Create a buffered writer and choose a quite large value (1M) and suppose the output from the system verification test won't exceed the limit
// Run the system verification check, but write to out buffered writer instead of stdout
bufw := bufio.NewWriterSize(os.Stdout, 1*1024*1024)
@ -532,9 +524,8 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
var validators = []system.Validator{
&system.KernelValidator{Reporter: reporter}}
// run the docker validator only with dockershim
if sysver.CRISocket == kubeadmdefaults.DefaultCRISocket {
// https://github.com/kubernetes/kubeadm/issues/533
// run the docker validator only with docker runtime
if sysver.IsDocker {
validators = append(validators, &system.DockerValidator{Reporter: reporter})
}
@ -565,7 +556,7 @@ func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
return warns, nil
}
// KubernetesVersionCheck validates kubernetes and kubeadm versions
// KubernetesVersionCheck validates Kubernetes and kubeadm versions
type KubernetesVersionCheck struct {
KubeadmVersion string
KubernetesVersion string
@ -576,9 +567,9 @@ func (KubernetesVersionCheck) Name() string {
return "KubernetesVersion"
}
// Check validates kubernetes and kubeadm versions
func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating kubernetes and kubeadm version")
// Check validates Kubernetes and kubeadm versions
func (kubever KubernetesVersionCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating Kubernetes and kubeadm version")
// Skip this check for "super-custom builds", where apimachinery/the overall codebase version is not set.
if strings.HasPrefix(kubever.KubeadmVersion, "v0.0.0") {
return nil, nil
@ -586,12 +577,12 @@ func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
kadmVersion, err := versionutil.ParseSemantic(kubever.KubeadmVersion)
if err != nil {
return nil, []error{fmt.Errorf("couldn't parse kubeadm version %q: %v", kubever.KubeadmVersion, err)}
return nil, []error{errors.Wrapf(err, "couldn't parse kubeadm version %q", kubever.KubeadmVersion)}
}
k8sVersion, err := versionutil.ParseSemantic(kubever.KubernetesVersion)
if err != nil {
return nil, []error{fmt.Errorf("couldn't parse kubernetes version %q: %v", kubever.KubernetesVersion, err)}
return nil, []error{errors.Wrapf(err, "couldn't parse Kubernetes version %q", kubever.KubernetesVersion)}
}
// Checks if k8sVersion greater or equal than the first unsupported versions by current version of kubeadm,
@ -600,7 +591,7 @@ func (kubever KubernetesVersionCheck) Check() (warnings, errors []error) {
// thus setting the value to x.y.0-0 we are defining the very first patch - prereleases within x.y minor release.
firstUnsupportedVersion := versionutil.MustParseSemantic(fmt.Sprintf("%d.%d.%s", kadmVersion.Major(), kadmVersion.Minor()+1, "0-0"))
if k8sVersion.AtLeast(firstUnsupportedVersion) {
return []error{fmt.Errorf("kubernetes version is greater than kubeadm version. Please consider to upgrade kubeadm. kubernetes version: %s. Kubeadm version: %d.%d.x", k8sVersion, kadmVersion.Components()[0], kadmVersion.Components()[1])}, nil
return []error{errors.Errorf("Kubernetes version is greater than kubeadm version. Please consider to upgrade kubeadm. Kubernetes version: %s. Kubeadm version: %d.%d.x", k8sVersion, kadmVersion.Components()[0], kadmVersion.Components()[1])}, nil
}
return nil, nil
@ -618,23 +609,23 @@ func (KubeletVersionCheck) Name() string {
}
// Check validates kubelet version. It should be not less than minimal supported version
func (kubever KubeletVersionCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating kubelet version")
func (kubever KubeletVersionCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating kubelet version")
kubeletVersion, err := GetKubeletVersion(kubever.exec)
if err != nil {
return nil, []error{fmt.Errorf("couldn't get kubelet version: %v", err)}
return nil, []error{errors.Wrap(err, "couldn't get kubelet version")}
}
if kubeletVersion.LessThan(kubeadmconstants.MinimumKubeletVersion) {
return nil, []error{fmt.Errorf("Kubelet version %q is lower than kubadm can support. Please upgrade kubelet", kubeletVersion)}
return nil, []error{errors.Errorf("Kubelet version %q is lower than kubadm can support. Please upgrade kubelet", kubeletVersion)}
}
if kubever.KubernetesVersion != "" {
k8sVersion, err := versionutil.ParseSemantic(kubever.KubernetesVersion)
if err != nil {
return nil, []error{fmt.Errorf("couldn't parse kubernetes version %q: %v", kubever.KubernetesVersion, err)}
return nil, []error{errors.Wrapf(err, "couldn't parse Kubernetes version %q", kubever.KubernetesVersion)}
}
if kubeletVersion.Major() > k8sVersion.Major() || kubeletVersion.Minor() > k8sVersion.Minor() {
return nil, []error{fmt.Errorf("the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: %q Control plane version: %q", kubeletVersion, k8sVersion)}
return nil, []error{errors.Errorf("the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: %q Control plane version: %q", kubeletVersion, k8sVersion)}
}
}
return nil, nil
@ -649,8 +640,8 @@ func (SwapCheck) Name() string {
}
// Check validates whether swap is enabled or not
func (swc SwapCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating whether swap is enabled or not")
func (swc SwapCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating whether swap is enabled or not")
f, err := os.Open("/proc/swaps")
if err != nil {
// /proc/swaps not available, thus no reasons to warn
@ -663,11 +654,11 @@ func (swc SwapCheck) Check() (warnings, errors []error) {
buf = append(buf, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, []error{fmt.Errorf("error parsing /proc/swaps: %v", err)}
return nil, []error{errors.Wrap(err, "error parsing /proc/swaps")}
}
if len(buf) > 1 {
return nil, []error{fmt.Errorf("running with swap on is not supported. Please disable swap")}
return nil, []error{errors.New("running with swap on is not supported. Please disable swap")}
}
return nil, nil
@ -690,8 +681,8 @@ func (ExternalEtcdVersionCheck) Name() string {
// Check validates external etcd version
// TODO: Use the official etcd Golang client for this instead?
func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) {
glog.V(1).Infoln("validating the external etcd version")
func (evc ExternalEtcdVersionCheck) Check() (warnings, errorList []error) {
klog.V(1).Infoln("validating the external etcd version")
// Return quickly if the user isn't using external etcd
if evc.Etcd.External.Endpoints == nil {
@ -701,46 +692,46 @@ func (evc ExternalEtcdVersionCheck) Check() (warnings, errors []error) {
var config *tls.Config
var err error
if config, err = evc.configRootCAs(config); err != nil {
errors = append(errors, err)
return nil, errors
errorList = append(errorList, err)
return nil, errorList
}
if config, err = evc.configCertAndKey(config); err != nil {
errors = append(errors, err)
return nil, errors
errorList = append(errorList, err)
return nil, errorList
}
client := evc.getHTTPClient(config)
for _, endpoint := range evc.Etcd.External.Endpoints {
if _, err := url.Parse(endpoint); err != nil {
errors = append(errors, fmt.Errorf("failed to parse external etcd endpoint %s : %v", endpoint, err))
errorList = append(errorList, errors.Wrapf(err, "failed to parse external etcd endpoint %s", endpoint))
continue
}
resp := etcdVersionResponse{}
var err error
versionURL := fmt.Sprintf("%s/%s", endpoint, "version")
if tmpVersionURL, err := purell.NormalizeURLString(versionURL, purell.FlagRemoveDuplicateSlashes); err != nil {
errors = append(errors, fmt.Errorf("failed to normalize external etcd version url %s : %v", versionURL, err))
errorList = append(errorList, errors.Wrapf(err, "failed to normalize external etcd version url %s", versionURL))
continue
} else {
versionURL = tmpVersionURL
}
if err = getEtcdVersionResponse(client, versionURL, &resp); err != nil {
errors = append(errors, err)
errorList = append(errorList, err)
continue
}
etcdVersion, err := semver.Parse(resp.Etcdserver)
if err != nil {
errors = append(errors, fmt.Errorf("couldn't parse external etcd version %q: %v", resp.Etcdserver, err))
errorList = append(errorList, errors.Wrapf(err, "couldn't parse external etcd version %q", resp.Etcdserver))
continue
}
if etcdVersion.LT(minExternalEtcdVersion) {
errors = append(errors, fmt.Errorf("this version of kubeadm only supports external etcd version >= %s. Current version: %s", kubeadmconstants.MinExternalEtcdVersion, resp.Etcdserver))
errorList = append(errorList, errors.Errorf("this version of kubeadm only supports external etcd version >= %s. Current version: %s", kubeadmconstants.MinExternalEtcdVersion, resp.Etcdserver))
continue
}
}
return nil, errors
return nil, errorList
}
// configRootCAs configures and returns a reference to tls.Config instance if CAFile is provided
@ -749,7 +740,7 @@ func (evc ExternalEtcdVersionCheck) configRootCAs(config *tls.Config) (*tls.Conf
if evc.Etcd.External.CAFile != "" {
CACert, err := ioutil.ReadFile(evc.Etcd.External.CAFile)
if err != nil {
return nil, fmt.Errorf("couldn't load external etcd's server certificate %s: %v", evc.Etcd.External.CAFile, err)
return nil, errors.Wrapf(err, "couldn't load external etcd's server certificate %s", evc.Etcd.External.CAFile)
}
CACertPool = x509.NewCertPool()
CACertPool.AppendCertsFromPEM(CACert)
@ -770,7 +761,7 @@ func (evc ExternalEtcdVersionCheck) configCertAndKey(config *tls.Config) (*tls.C
var err error
cert, err = tls.LoadX509KeyPair(evc.Etcd.External.CertFile, evc.Etcd.External.KeyFile)
if err != nil {
return nil, fmt.Errorf("couldn't load external etcd's certificate and key pair %s, %s: %v", evc.Etcd.External.CertFile, evc.Etcd.External.KeyFile, err)
return nil, errors.Wrapf(err, "couldn't load external etcd's certificate and key pair %s, %s", evc.Etcd.External.CertFile, evc.Etcd.External.KeyFile)
}
if config == nil {
config = &tls.Config{}
@ -811,7 +802,7 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{})
if r != nil && r.StatusCode >= 500 && r.StatusCode <= 599 {
loopCount--
return false, fmt.Errorf("server responded with non-successful status: %s", r.Status)
return false, errors.Errorf("server responded with non-successful status: %s", r.Status)
}
return true, json.NewDecoder(r.Body).Decode(target)
@ -825,8 +816,8 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{})
// ImagePullCheck will pull container images used by kubeadm
type ImagePullCheck struct {
Images images.Images
ImageList []string
runtime utilruntime.ContainerRuntime
imageList []string
}
// Name returns the label for ImagePullCheck
@ -835,21 +826,45 @@ func (ImagePullCheck) Name() string {
}
// Check pulls images required by kubeadm. This is a mutating check
func (i ImagePullCheck) Check() (warnings, errors []error) {
for _, image := range i.ImageList {
glog.V(1).Infoln("pulling ", image)
if err := i.Images.Exists(image); err == nil {
func (ipc ImagePullCheck) Check() (warnings, errorList []error) {
for _, image := range ipc.imageList {
ret, err := ipc.runtime.ImageExists(image)
if ret && err == nil {
klog.V(1).Infof("image exists: %s", image)
continue
}
if err := i.Images.Pull(image); err != nil {
errors = append(errors, fmt.Errorf("failed to pull image [%s]: %v", image, err))
if err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to check if image %s exists", image))
}
klog.V(1).Infof("pulling %s", image)
if err := ipc.runtime.PullImage(image); err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to pull image %s", image))
}
}
return warnings, errors
return warnings, errorList
}
// NumCPUCheck checks if current number of CPUs is not less than required
type NumCPUCheck struct {
NumCPU int
}
// Name returns the label for NumCPUCheck
func (NumCPUCheck) Name() string {
return "NumCPU"
}
// Check number of CPUs required by kubeadm
func (ncc NumCPUCheck) Check() (warnings, errorList []error) {
numCPU := runtime.NumCPU()
if numCPU < ncc.NumCPU {
errorList = append(errorList, errors.Errorf("the number of available CPUs %d is less than the required %d", numCPU, ncc.NumCPU))
}
return warnings, errorList
}
// RunInitMasterChecks executes all individual, applicable to Master node checks.
func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String) error {
func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.InitConfiguration, ignorePreflightErrors sets.String) error {
// First, check if we're root separately from the other preflight checks and fail fast
if err := RunRootCheckOnly(ignorePreflightErrors); err != nil {
return err
@ -857,23 +872,24 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi
manifestsDir := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)
checks := []Checker{
NumCPUCheck{NumCPU: kubeadmconstants.MasterNumCPU},
KubernetesVersionCheck{KubernetesVersion: cfg.KubernetesVersion, KubeadmVersion: kubeadmversion.Get().GitVersion},
FirewalldCheck{ports: []int{int(cfg.API.BindPort), 10250}},
PortOpenCheck{port: int(cfg.API.BindPort)},
FirewalldCheck{ports: []int{int(cfg.LocalAPIEndpoint.BindPort), 10250}},
PortOpenCheck{port: int(cfg.LocalAPIEndpoint.BindPort)},
PortOpenCheck{port: 10251},
PortOpenCheck{port: 10252},
FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, manifestsDir)},
FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeControllerManager, manifestsDir)},
FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeScheduler, manifestsDir)},
FileAvailableCheck{Path: kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.Etcd, manifestsDir)},
HTTPProxyCheck{Proto: "https", Host: cfg.API.AdvertiseAddress},
HTTPProxyCheck{Proto: "https", Host: cfg.LocalAPIEndpoint.AdvertiseAddress},
HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.ServiceSubnet},
HTTPProxyCIDRCheck{Proto: "https", CIDR: cfg.Networking.PodSubnet},
}
checks = addCommonChecks(execer, cfg, checks)
// Check ipvs required kernel module once we use ipvs kube-proxy mode
if cfg.KubeProxy.Config != nil && cfg.KubeProxy.Config.Mode == ipvsutil.IPVSProxyMode {
if cfg.ComponentConfigs.KubeProxy != nil && cfg.ComponentConfigs.KubeProxy.Mode == ipvsutil.IPVSProxyMode {
checks = append(checks,
ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer},
)
@ -882,7 +898,8 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi
if cfg.Etcd.Local != nil {
// Only do etcd related checks when no external endpoints were specified
checks = append(checks,
PortOpenCheck{port: 2379},
PortOpenCheck{port: kubeadmconstants.EtcdListenClientPort},
PortOpenCheck{port: kubeadmconstants.EtcdListenPeerPort},
DirAvailableCheck{Path: cfg.Etcd.Local.DataDir},
)
}
@ -901,7 +918,7 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi
checks = append(checks, ExternalEtcdVersionCheck{Etcd: cfg.Etcd})
}
if ip := net.ParseIP(cfg.API.AdvertiseAddress); ip != nil {
if ip := net.ParseIP(cfg.LocalAPIEndpoint.AdvertiseAddress); ip != nil {
if ip.To4() == nil && ip.To16() != nil {
checks = append(checks,
FileContentCheck{Path: bridgenf6, Content: []byte{'1'}},
@ -913,7 +930,7 @@ func RunInitMasterChecks(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfi
}
// RunJoinNodeChecks executes all individual, applicable to node checks.
func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfiguration, ignorePreflightErrors sets.String) error {
func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.JoinConfiguration, ignorePreflightErrors sets.String) error {
// First, check if we're root separately from the other preflight checks and fail fast
if err := RunRootCheckOnly(ignorePreflightErrors); err != nil {
return err
@ -921,16 +938,17 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura
checks := []Checker{
DirAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName)},
FileAvailableCheck{Path: cfg.CACertPath},
FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)},
FileAvailableCheck{Path: filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName)},
ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer},
}
checks = addCommonChecks(execer, cfg, checks)
if cfg.ControlPlane == nil {
checks = append(checks, FileAvailableCheck{Path: cfg.CACertPath})
}
addIPv6Checks := false
for _, server := range cfg.DiscoveryTokenAPIServers {
ipstr, _, err := net.SplitHostPort(server)
if cfg.Discovery.BootstrapToken != nil {
ipstr, _, err := net.SplitHostPort(cfg.Discovery.BootstrapToken.APIServerEndpoint)
if err == nil {
checks = append(checks,
HTTPProxyCheck{Proto: "https", Host: ipstr},
@ -954,23 +972,44 @@ func RunJoinNodeChecks(execer utilsexec.Interface, cfg *kubeadmapi.NodeConfigura
return RunChecks(checks, os.Stderr, ignorePreflightErrors)
}
// RunOptionalJoinNodeChecks executes all individual, applicable to node configuration dependant checks
func RunOptionalJoinNodeChecks(execer utilsexec.Interface, initCfg *kubeadmapi.InitConfiguration, ignorePreflightErrors sets.String) error {
checks := []Checker{}
// Check ipvs required kernel module if we use ipvs kube-proxy mode
if initCfg.ComponentConfigs.KubeProxy != nil && initCfg.ComponentConfigs.KubeProxy.Mode == ipvsutil.IPVSProxyMode {
checks = append(checks,
ipvsutil.RequiredIPVSKernelModulesAvailableCheck{Executor: execer},
)
}
return RunChecks(checks, os.Stderr, ignorePreflightErrors)
}
// addCommonChecks is a helper function to deplicate checks that are common between both the
// kubeadm init and join commands
func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfiguration, checks []Checker) []Checker {
// Check whether or not the CRI socket defined is the default
if cfg.GetCRISocket() != kubeadmdefaults.DefaultCRISocket {
checks = append(checks, CRICheck{socket: cfg.GetCRISocket(), exec: execer})
containerRuntime, err := utilruntime.NewContainerRuntime(execer, cfg.GetCRISocket())
isDocker := false
if err != nil {
fmt.Printf("[preflight] WARNING: Couldn't create the interface used for talking to the container runtime: %v\n", err)
} else {
checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true})
checks = append(checks, ContainerRuntimeCheck{runtime: containerRuntime})
if containerRuntime.IsDocker() {
isDocker = true
checks = append(checks, ServiceCheck{Service: "docker", CheckIfActive: true})
}
}
// non-windows checks
if runtime.GOOS == "linux" {
if !isDocker {
checks = append(checks, InPathCheck{executable: "crictl", mandatory: true, exec: execer})
}
checks = append(checks,
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
FileContentCheck{Path: ipv4Forward, Content: []byte{'1'}},
SwapCheck{},
InPathCheck{executable: "crictl", mandatory: true, exec: execer},
InPathCheck{executable: "ip", mandatory: true, exec: execer},
InPathCheck{executable: "iptables", mandatory: true, exec: execer},
InPathCheck{executable: "mount", mandatory: true, exec: execer},
@ -982,8 +1021,7 @@ func addCommonChecks(execer utilsexec.Interface, cfg kubeadmapi.CommonConfigurat
InPathCheck{executable: "touch", mandatory: false, exec: execer})
}
checks = append(checks,
SystemVerificationCheck{CRISocket: cfg.GetCRISocket()},
IsPrivilegedUserCheck{},
SystemVerificationCheck{IsDocker: isDocker},
HostnameCheck{nodeName: cfg.GetNodeName()},
KubeletVersionCheck{KubernetesVersion: cfg.GetKubernetesVersion(), exec: execer},
ServiceCheck{Service: "kubelet", CheckIfActive: false},
@ -1000,15 +1038,15 @@ func RunRootCheckOnly(ignorePreflightErrors sets.String) error {
return RunChecks(checks, os.Stderr, ignorePreflightErrors)
}
// RunPullImagesCheck will pull images kubeadm needs if the are not found on the system
func RunPullImagesCheck(execer utilsexec.Interface, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String) error {
criInterfacer, err := images.NewCRInterfacer(execer, cfg.GetCRISocket())
// RunPullImagesCheck will pull images kubeadm needs if they are not found on the system
func RunPullImagesCheck(execer utilsexec.Interface, cfg *kubeadmapi.InitConfiguration, ignorePreflightErrors sets.String) error {
containerRuntime, err := utilruntime.NewContainerRuntime(utilsexec.New(), cfg.GetCRISocket())
if err != nil {
return err
}
checks := []Checker{
ImagePullCheck{Images: criInterfacer, ImageList: images.GetAllImages(cfg)},
ImagePullCheck{runtime: containerRuntime, imageList: images.GetAllImages(&cfg.ClusterConfiguration)},
}
return RunChecks(checks, os.Stderr, ignorePreflightErrors)
}
@ -1051,47 +1089,6 @@ func RunChecks(checks []Checker, ww io.Writer, ignorePreflightErrors sets.String
return nil
}
// TryStartKubelet attempts to bring up kubelet service
// TODO: Move these kubelet start/stop functions to some other place, e.g. phases/kubelet
func TryStartKubelet() {
// If we notice that the kubelet service is inactive, try to start it
initSystem, err := initsystem.GetInitSystem()
if err != nil {
fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet is running properly.")
return
}
if !initSystem.ServiceExists("kubelet") {
fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet is running properly.")
}
fmt.Println("[preflight] Activating the kubelet service")
// This runs "systemctl daemon-reload && systemctl restart kubelet"
if err := initSystem.ServiceRestart("kubelet"); err != nil {
fmt.Printf("[preflight] WARNING: unable to start the kubelet service: [%v]\n", err)
fmt.Printf("[preflight] please ensure kubelet is reloaded and running manually.\n")
}
}
// TryStopKubelet attempts to bring down the kubelet service momentarily
func TryStopKubelet() {
// If we notice that the kubelet service is inactive, try to start it
initSystem, err := initsystem.GetInitSystem()
if err != nil {
fmt.Println("[preflight] no supported init system detected, won't make sure the kubelet not running for a short period of time while setting up configuration for it.")
return
}
if !initSystem.ServiceExists("kubelet") {
fmt.Println("[preflight] couldn't detect a kubelet service, can't make sure the kubelet not running for a short period of time while setting up configuration for it.")
}
// This runs "systemctl daemon-reload && systemctl stop kubelet"
if err := initSystem.ServiceStop("kubelet"); err != nil {
fmt.Printf("[preflight] WARNING: unable to stop the kubelet service momentarily: [%v]\n", err)
}
}
// setHasItemOrAll is helper function that return true if item is present in the set (case insensitive) or special key 'all' is present
func setHasItemOrAll(s sets.String, item string) bool {
if s.Has("all") || s.Has(strings.ToLower(item)) {

View File

@ -18,12 +18,11 @@ package preflight
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"strings"
"testing"
"github.com/pkg/errors"
"github.com/renstrom/dedent"
"net/http"
@ -31,6 +30,8 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
"k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
)
@ -172,12 +173,12 @@ func (pfct preflightCheckTest) Name() string {
return "preflightCheckTest"
}
func (pfct preflightCheckTest) Check() (warning, errors []error) {
func (pfct preflightCheckTest) Check() (warning, errorList []error) {
if pfct.msg == "warning" {
return []error{fmt.Errorf("warning")}, nil
return []error{errors.New("warning")}, nil
}
if pfct.msg != "" {
return nil, []error{fmt.Errorf("fake error")}
return nil, []error{errors.New("fake error")}
}
return
}
@ -185,45 +186,51 @@ func (pfct preflightCheckTest) Check() (warning, errors []error) {
func TestRunInitMasterChecks(t *testing.T) {
var tests = []struct {
name string
cfg *kubeadmapi.MasterConfiguration
cfg *kubeadmapi.InitConfiguration
expected bool
}{
{name: "Test valid advertised address",
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{AdvertiseAddress: "foo"},
cfg: &kubeadmapi.InitConfiguration{
LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "foo"},
},
expected: false,
},
{
name: "Test CA file exists if specfied",
cfg: &kubeadmapi.MasterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: "/foo"}},
cfg: &kubeadmapi.InitConfiguration{
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: "/foo"}},
},
},
expected: false,
},
{
name: "Test Cert file exists if specfied",
cfg: &kubeadmapi.MasterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}},
cfg: &kubeadmapi.InitConfiguration{
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}},
},
},
expected: false,
},
{
name: "Test Key file exists if specfied",
cfg: &kubeadmapi.MasterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}},
cfg: &kubeadmapi.InitConfiguration{
ClusterConfiguration: kubeadmapi.ClusterConfiguration{
Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}},
},
},
expected: false,
},
{
cfg: &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{AdvertiseAddress: "2001:1234::1:15"},
cfg: &kubeadmapi.InitConfiguration{
LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "2001:1234::1:15"},
},
expected: false,
},
}
for _, rt := range tests {
// TODO: Make RunInitMasterChecks accept a ClusterConfiguration object instead of InitConfiguration
actual := RunInitMasterChecks(exec.New(), rt.cfg, sets.NewString())
if (actual == nil) != rt.expected {
t.Errorf(
@ -238,22 +245,30 @@ func TestRunInitMasterChecks(t *testing.T) {
func TestRunJoinNodeChecks(t *testing.T) {
var tests = []struct {
cfg *kubeadmapi.NodeConfiguration
cfg *kubeadmapi.JoinConfiguration
expected bool
}{
{
cfg: &kubeadmapi.NodeConfiguration{},
cfg: &kubeadmapi.JoinConfiguration{},
expected: false,
},
{
cfg: &kubeadmapi.NodeConfiguration{
DiscoveryTokenAPIServers: []string{"192.168.1.15"},
cfg: &kubeadmapi.JoinConfiguration{
Discovery: kubeadmapi.Discovery{
BootstrapToken: &kubeadmapi.BootstrapTokenDiscovery{
APIServerEndpoint: "192.168.1.15",
},
},
},
expected: false,
},
{
cfg: &kubeadmapi.NodeConfiguration{
DiscoveryTokenAPIServers: []string{"2001:1234::1:15"},
cfg: &kubeadmapi.JoinConfiguration{
Discovery: kubeadmapi.Discovery{
BootstrapToken: &kubeadmapi.BootstrapTokenDiscovery{
APIServerEndpoint: "2001:1234::1:15",
},
},
},
expected: false,
},
@ -632,13 +647,13 @@ func TestKubeletVersionCheck(t *testing.T) {
expectErrors bool
expectWarnings bool
}{
{"v1.11.2", "", false, false}, // check minimally supported version when there is no information about control plane
{"v1.8.3", "v1.8.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail.
{"v1.10.0", "v1.10.5", false, false}, // kubelet within same major.minor as control plane
{"v1.10.5", "v1.10.1", false, false}, // kubelet is newer, but still within same major.minor as control plane
{"v1.10.0", "v1.11.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported
{"v1.11.0-alpha.1", "v1.10.1", true, false}, // kubelet is newer (development build) than control plane, should fail.
{"v1.11.0", "v1.10.5", true, false}, // kubelet is newer (release) than control plane, should fail.
{"v1.13.2", "", false, false}, // check minimally supported version when there is no information about control plane
{"v1.11.3", "v1.11.8", true, false}, // too old kubelet (older than kubeadmconstants.MinimumKubeletVersion), should fail.
{"v1.12.0", "v1.12.5", false, false}, // kubelet within same major.minor as control plane
{"v1.12.5", "v1.12.1", false, false}, // kubelet is newer, but still within same major.minor as control plane
{"v1.12.0", "v1.13.1", false, false}, // kubelet is lower than control plane, but newer than minimally supported
{"v1.13.0-alpha.1", "v1.12.1", true, false}, // kubelet is newer (development build) than control plane, should fail.
{"v1.13.0", "v1.12.5", true, false}, // kubelet is newer (release) than control plane, should fail.
}
for _, tc := range cases {
@ -658,13 +673,13 @@ func TestKubeletVersionCheck(t *testing.T) {
switch {
case warnings != nil && !tc.expectWarnings:
t.Errorf("KubeletVersionCheck: unexpected warnings for kubelet version %q and kubernetes version %q. Warnings: %v", tc.kubeletVersion, tc.k8sVersion, warnings)
t.Errorf("KubeletVersionCheck: unexpected warnings for kubelet version %q and Kubernetes version %q. Warnings: %v", tc.kubeletVersion, tc.k8sVersion, warnings)
case warnings == nil && tc.expectWarnings:
t.Errorf("KubeletVersionCheck: expected warnings for kubelet version %q and kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
t.Errorf("KubeletVersionCheck: expected warnings for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
case errors != nil && !tc.expectErrors:
t.Errorf("KubeletVersionCheck: unexpected errors for kubelet version %q and kubernetes version %q. errors: %v", tc.kubeletVersion, tc.k8sVersion, errors)
t.Errorf("KubeletVersionCheck: unexpected errors for kubelet version %q and Kubernetes version %q. errors: %v", tc.kubeletVersion, tc.k8sVersion, errors)
case errors == nil && tc.expectErrors:
t.Errorf("KubeletVersionCheck: expected errors for kubelet version %q and kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
t.Errorf("KubeletVersionCheck: expected errors for kubelet version %q and Kubernetes version %q but got nothing", tc.kubeletVersion, tc.k8sVersion)
}
}
@ -698,31 +713,88 @@ func TestSetHasItemOrAll(t *testing.T) {
}
}
type imgs struct{}
func (i *imgs) Pull(image string) error {
if image == "bad pull" {
return errors.New("pull error")
}
return nil
}
func (i *imgs) Exists(image string) error {
if image == "found" {
return nil
}
return errors.New("error")
}
func TestImagePullCheck(t *testing.T) {
i := ImagePullCheck{
Images: &imgs{},
ImageList: []string{"found", "not found", "bad pull"},
fcmd := fakeexec.FakeCmd{
RunScript: []fakeexec.FakeRunAction{
// Test case 1: img1 and img2 exist, img3 doesn't exist
func() ([]byte, []byte, error) { return nil, nil, nil },
func() ([]byte, []byte, error) { return nil, nil, nil },
func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
// Test case 2: images don't exist
func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} },
},
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
// Test case1: pull only img3
func() ([]byte, error) { return nil, nil },
// Test case 2: fail to pull image2 and image3
func() ([]byte, error) { return nil, nil },
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} },
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} },
},
}
warnings, errors := i.Check()
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...) },
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...) },
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...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
},
LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil },
}
containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, kubeadmapiv1beta1.DefaultCRISocket)
if err != nil {
t.Errorf("unexpected NewContainerRuntime error: %v", err)
}
check := ImagePullCheck{
runtime: containerRuntime,
imageList: []string{"img1", "img2", "img3"},
}
warnings, errors := check.Check()
if len(warnings) != 0 {
t.Fatalf("did not expect any warnings but got %q", warnings)
}
if len(errors) != 1 {
if len(errors) != 0 {
t.Fatalf("expected 1 errors but got %d: %q", len(errors), errors)
}
warnings, errors = check.Check()
if len(warnings) != 0 {
t.Fatalf("did not expect any warnings but got %q", warnings)
}
if len(errors) != 2 {
t.Fatalf("expected 2 errors but got %d: %q", len(errors), errors)
}
}
func TestNumCPUCheck(t *testing.T) {
var tests = []struct {
numCPU int
numErrors int
numWarnings int
}{
{0, 0, 0},
{999999999, 1, 0},
}
for _, rt := range tests {
warnings, errors := NumCPUCheck{NumCPU: rt.numCPU}.Check()
if len(warnings) != rt.numWarnings {
t.Errorf("expected %d warning(s) but got %d: %q", rt.numWarnings, len(warnings), warnings)
}
if len(errors) != rt.numErrors {
t.Errorf("expected %d warning(s) but got %d: %q", rt.numErrors, len(errors), errors)
}
}
}

View File

@ -19,16 +19,17 @@ limitations under the License.
package preflight
import (
"fmt"
"os"
"github.com/pkg/errors"
)
// Check validates if an user has elevated (root) privileges.
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errors []error) {
errors = []error{}
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errorList []error) {
errorList = []error{}
if os.Getuid() != 0 {
errors = append(errors, fmt.Errorf("user is not running as root"))
errorList = append(errorList, errors.New("user is not running as root"))
}
return nil, errors
return nil, errorList
}

View File

@ -19,14 +19,15 @@ limitations under the License.
package preflight
import (
"fmt"
"os/exec"
"strings"
"github.com/pkg/errors"
)
// Check validates if an user has elevated (administrator) privileges.
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errors []error) {
errors = []error{}
func (ipuc IsPrivilegedUserCheck) Check() (warnings, errorList []error) {
errorList = []error{}
// The "Well-known SID" of Administrator group is S-1-5-32-544
// The following powershell will return "True" if run as an administrator, "False" otherwise
@ -35,10 +36,10 @@ func (ipuc IsPrivilegedUserCheck) Check() (warnings, errors []error) {
isAdmin, err := exec.Command("powershell", args...).Output()
if err != nil {
errors = append(errors, fmt.Errorf("unable to determine if user is running as administrator: %s", err))
errorList = append(errorList, errors.Wrap(err, "unable to determine if user is running as administrator"))
} else if strings.EqualFold(strings.TrimSpace(string(isAdmin)), "false") {
errors = append(errors, fmt.Errorf("user is not running as administrator"))
errorList = append(errorList, errors.New("user is not running as administrator"))
}
return nil, errors
return nil, errorList
}

View File

@ -17,11 +17,12 @@ limitations under the License.
package preflight
import (
"fmt"
"regexp"
"strings"
"k8s.io/kubernetes/pkg/util/version"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/version"
utilsexec "k8s.io/utils/exec"
)
@ -38,7 +39,7 @@ func GetKubeletVersion(execer utilsexec.Interface) (*version.Version, error) {
cleanOutput := strings.TrimSpace(string(out))
subs := kubeletVersionRegex.FindAllStringSubmatch(cleanOutput, -1)
if len(subs) != 1 || len(subs[0]) < 2 {
return nil, fmt.Errorf("Unable to parse output from Kubelet: %q", cleanOutput)
return nil, errors.Errorf("Unable to parse output from Kubelet: %q", cleanOutput)
}
return version.ParseSemantic(subs[0][1])
}

View File

@ -17,9 +17,10 @@ limitations under the License.
package preflight
import (
"fmt"
"testing"
"github.com/pkg/errors"
utilsexec "k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
)
@ -34,7 +35,7 @@ func TestGetKubeletVersion(t *testing.T) {
{"Kubernetes v1.7.0", "1.7.0", nil, true},
{"Kubernetes v1.8.0-alpha.2.1231+afabd012389d53a", "1.8.0-alpha.2.1231+afabd012389d53a", nil, true},
{"something-invalid", "", nil, false},
{"command not found", "", fmt.Errorf("kubelet not found"), false},
{"command not found", "", errors.New("kubelet not found"), false},
{"", "", nil, false},
}