diff --git a/cluster/hosts.go b/cluster/hosts.go index b763744f..f0b628a3 100644 --- a/cluster/hosts.go +++ b/cluster/hosts.go @@ -12,18 +12,18 @@ import ( func (c *Cluster) TunnelHosts() error { for i := range c.EtcdHosts { if err := c.EtcdHosts[i].TunnelUp(); err != nil { - return fmt.Errorf("Failed to set up SSH tunneling for Etcd hosts: %v", err) + return fmt.Errorf("Failed to set up SSH tunneling for Etcd host [%s]: %v", c.EtcdHosts[i].Address, err) } } for i := range c.ControlPlaneHosts { err := c.ControlPlaneHosts[i].TunnelUp() if err != nil { - return fmt.Errorf("Failed to set up SSH tunneling for Control hosts: %v", err) + return fmt.Errorf("Failed to set up SSH tunneling for Control host [%s]: %v", c.ControlPlaneHosts[i].Address, err) } } for i := range c.WorkerHosts { if err := c.WorkerHosts[i].TunnelUp(); err != nil { - return fmt.Errorf("Failed to set up SSH tunneling for Worker hosts: %v", err) + return fmt.Errorf("Failed to set up SSH tunneling for Worker host [%s]: %v", c.WorkerHosts[i].Address, err) } } return nil diff --git a/cluster/validation.go b/cluster/validation.go index 5995cfd4..e0870107 100644 --- a/cluster/validation.go +++ b/cluster/validation.go @@ -35,10 +35,7 @@ func (c *Cluster) ValidateCluster() error { } // validate services options - if err := validateServicesOptions(c); err != nil { - return err - } - return nil + return validateServicesOptions(c) } func validateAuthOptions(c *Cluster) error { diff --git a/docker/docker.go b/docker/docker.go index f6288350..53c9363c 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "reflect" + "regexp" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -14,6 +15,10 @@ import ( "github.com/sirupsen/logrus" ) +var K8sDockerVersions = map[string][]string{ + "1.8": {"1.12.6", "1.13.1", "17.03.2"}, +} + func DoRunContainer(dClient *client.Client, imageCfg *container.Config, hostCfg *container.HostConfig, containerName string, hostname string, plane string) error { isRunning, err := IsContainerRunning(dClient, hostname, containerName) if err != nil { @@ -225,3 +230,15 @@ func IsContainerUpgradable(dClient *client.Client, imageCfg *container.Config, c logrus.Debugf("[%s] Container [%s] is not eligible for updgrade on host [%s]", plane, containerName, hostname) return false, nil } + +func IsSupportedDockerVersion(info types.Info, K8sVersion string) (bool, error) { + // Docker versions are not semver compliant since stable/edge version (17.03 and higher) so we need to check if the reported ServerVersion starts with a compatible version + for _, DockerVersion := range K8sDockerVersions[K8sVersion] { + DockerVersionRegexp := regexp.MustCompile("^" + DockerVersion) + if DockerVersionRegexp.MatchString(info.ServerVersion) { + return true, nil + } + + } + return false, nil +} diff --git a/hosts/dialer.go b/hosts/dialer.go index cde330ee..22769ed1 100644 --- a/hosts/dialer.go +++ b/hosts/dialer.go @@ -11,9 +11,11 @@ import ( "syscall" "github.com/docker/docker/client" + "github.com/rancher/rke/docker" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/terminal" + "golang.org/x/net/context" ) type dialer struct { @@ -23,6 +25,7 @@ type dialer struct { const ( DockerAPIVersion = "1.24" + K8sVersion = "1.8" ) func (d *dialer) Dial(network, addr string) (net.Conn, error) { @@ -35,24 +38,25 @@ func (d *dialer) Dial(network, addr string) (net.Conn, error) { // Establish connection with SSH server conn, err := ssh.Dial("tcp", sshAddr, cfg) if err != nil { - return nil, fmt.Errorf("Error establishing SSH connection: %v", err) + return nil, fmt.Errorf("Failed to dial ssh using address [%s]: %v", sshAddr, err) } if len(d.host.DockerSocket) == 0 { d.host.DockerSocket = "/var/run/docker.sock" } remote, err := conn.Dial("unix", d.host.DockerSocket) if err != nil { - return nil, fmt.Errorf("Error connecting to Docker socket on host [%s]: %v", d.host.Address, err) + return nil, fmt.Errorf("Failed to dial to Docker socket: %v", err) } return remote, err } func (h *Host) TunnelUp() error { - logrus.Infof("[ssh] Start tunnel for host [%s]", h.Address) + logrus.Infof("[ssh] Setup tunnel for host [%s]", h.Address) key, err := checkEncryptedKey(h.SSHKey, h.SSHKeyPath) if err != nil { return fmt.Errorf("Failed to parse the private key: %v", err) } + dialer := &dialer{ host: h, signer: key, @@ -67,8 +71,22 @@ func (h *Host) TunnelUp() error { logrus.Debugf("Connecting to Docker API for host [%s]", h.Address) h.DClient, err = client.NewClient("unix:///var/run/docker.sock", DockerAPIVersion, httpClient, nil) if err != nil { - return fmt.Errorf("Can't connect to Docker for host [%s]: %v", h.Address, err) + return fmt.Errorf("Can't initiate NewClient: %v", err) } + info, err := h.DClient.Info(context.Background()) + if err != nil { + return fmt.Errorf("Can't retrieve Docker Info: %v", err) + } + logrus.Debugf("Docker Info found: %#v", info) + isvalid, err := docker.IsSupportedDockerVersion(info, K8sVersion) + if err != nil { + return fmt.Errorf("Error while determining supported Docker version [%s]: %v", info.ServerVersion, err) + } + + if !isvalid { + return fmt.Errorf("Unsupported Docker version found [%s], supported versions are %v", info.ServerVersion, docker.K8sDockerVersions[K8sVersion]) + } + return nil }