2017-11-21 19:25:08 +00:00
|
|
|
package cluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2017-11-28 17:45:24 +00:00
|
|
|
|
|
|
|
"github.com/rancher/rke/services"
|
2017-11-21 19:25:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (c *Cluster) ValidateCluster() error {
|
|
|
|
// make sure cluster has at least one controlplane/etcd host
|
2018-02-21 23:13:08 +00:00
|
|
|
if err := ValidateHostCount(c); err != nil {
|
|
|
|
return err
|
2018-02-14 20:58:35 +00:00
|
|
|
}
|
2017-11-28 17:45:24 +00:00
|
|
|
|
|
|
|
// validate hosts options
|
|
|
|
if err := validateHostsOptions(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// validate Auth options
|
|
|
|
if err := validateAuthOptions(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// validate Network options
|
|
|
|
if err := validateNetworkOptions(c); err != nil {
|
|
|
|
return err
|
2017-11-21 19:25:08 +00:00
|
|
|
}
|
|
|
|
|
2018-02-01 21:28:31 +00:00
|
|
|
// validate Ingress options
|
|
|
|
if err := validateIngressOptions(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-11-21 19:25:08 +00:00
|
|
|
// validate services options
|
2017-12-01 21:06:13 +00:00
|
|
|
return validateServicesOptions(c)
|
2017-11-21 19:25:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 17:45:24 +00:00
|
|
|
func validateAuthOptions(c *Cluster) error {
|
|
|
|
if c.Authentication.Strategy != DefaultAuthStrategy {
|
|
|
|
return fmt.Errorf("Authentication strategy [%s] is not supported", c.Authentication.Strategy)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateNetworkOptions(c *Cluster) error {
|
2017-11-30 11:35:31 +00:00
|
|
|
if c.Network.Plugin != FlannelNetworkPlugin && c.Network.Plugin != CalicoNetworkPlugin && c.Network.Plugin != CanalNetworkPlugin && c.Network.Plugin != WeaveNetworkPlugin {
|
2017-11-28 17:45:24 +00:00
|
|
|
return fmt.Errorf("Network plugin [%s] is not supported", c.Network.Plugin)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateHostsOptions(c *Cluster) error {
|
|
|
|
for i, host := range c.Nodes {
|
|
|
|
if len(host.Address) == 0 {
|
|
|
|
return fmt.Errorf("User for host (%d) is not provided", i+1)
|
|
|
|
}
|
|
|
|
if len(host.User) == 0 {
|
|
|
|
return fmt.Errorf("User for host (%d) is not provided", i+1)
|
|
|
|
}
|
|
|
|
if len(host.Role) == 0 {
|
|
|
|
return fmt.Errorf("Role for host (%d) is not provided", i+1)
|
|
|
|
}
|
|
|
|
for _, role := range host.Role {
|
|
|
|
if role != services.ETCDRole && role != services.ControlRole && role != services.WorkerRole {
|
|
|
|
return fmt.Errorf("Role [%s] for host (%d) is not recognized", role, i+1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateServicesOptions(c *Cluster) error {
|
2017-11-21 19:25:08 +00:00
|
|
|
servicesOptions := map[string]string{
|
|
|
|
"etcd_image": c.Services.Etcd.Image,
|
|
|
|
"kube_api_image": c.Services.KubeAPI.Image,
|
|
|
|
"kube_api_service_cluster_ip_range": c.Services.KubeAPI.ServiceClusterIPRange,
|
|
|
|
"kube_controller_image": c.Services.KubeController.Image,
|
|
|
|
"kube_controller_service_cluster_ip_range": c.Services.KubeController.ServiceClusterIPRange,
|
|
|
|
"kube_controller_cluster_cidr": c.Services.KubeController.ClusterCIDR,
|
|
|
|
"scheduler_image": c.Services.Scheduler.Image,
|
|
|
|
"kubelet_image": c.Services.Kubelet.Image,
|
|
|
|
"kubelet_cluster_dns_service": c.Services.Kubelet.ClusterDNSServer,
|
|
|
|
"kubelet_cluster_domain": c.Services.Kubelet.ClusterDomain,
|
|
|
|
"kubelet_infra_container_image": c.Services.Kubelet.InfraContainerImage,
|
|
|
|
"kubeproxy_image": c.Services.Kubeproxy.Image,
|
|
|
|
}
|
|
|
|
for optionName, OptionValue := range servicesOptions {
|
|
|
|
if len(OptionValue) == 0 {
|
|
|
|
return fmt.Errorf("%s can't be empty", strings.Join(strings.Split(optionName, "_"), " "))
|
|
|
|
}
|
|
|
|
}
|
2018-02-14 20:58:35 +00:00
|
|
|
// Validate external etcd information
|
|
|
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
|
|
|
if len(c.Services.Etcd.CACert) == 0 {
|
|
|
|
return fmt.Errorf("External CA Certificate for etcd can't be empty")
|
|
|
|
}
|
|
|
|
if len(c.Services.Etcd.Cert) == 0 {
|
|
|
|
return fmt.Errorf("External Client Certificate for etcd can't be empty")
|
|
|
|
}
|
|
|
|
if len(c.Services.Etcd.Key) == 0 {
|
|
|
|
return fmt.Errorf("External Client Key for etcd can't be empty")
|
|
|
|
}
|
|
|
|
if len(c.Services.Etcd.Path) == 0 {
|
|
|
|
return fmt.Errorf("External etcd path can't be empty")
|
|
|
|
}
|
|
|
|
}
|
2017-11-21 19:25:08 +00:00
|
|
|
return nil
|
|
|
|
}
|
2018-02-01 21:28:31 +00:00
|
|
|
|
|
|
|
func validateIngressOptions(c *Cluster) error {
|
|
|
|
// Should be changed when adding more ingress types
|
2018-02-07 00:30:25 +00:00
|
|
|
if c.Ingress.Provider != DefaultIngressController && c.Ingress.Provider != "none" {
|
|
|
|
return fmt.Errorf("Ingress controller %s is incorrect", c.Ingress.Provider)
|
2018-02-01 21:28:31 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2018-02-21 23:13:08 +00:00
|
|
|
|
|
|
|
func ValidateHostCount(c *Cluster) error {
|
|
|
|
if len(c.EtcdHosts) == 0 && len(c.Services.Etcd.ExternalURLs) == 0 {
|
|
|
|
return fmt.Errorf("Cluster must have at least one etcd plane host")
|
|
|
|
}
|
|
|
|
if len(c.EtcdHosts) > 0 && len(c.Services.Etcd.ExternalURLs) > 0 {
|
|
|
|
return fmt.Errorf("Cluster can't have both internal and external etcd")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|