2017-11-21 19:25:08 +00:00
package cluster
import (
2019-03-01 18:09:45 +00:00
"context"
2020-03-03 11:05:59 +00:00
"errors"
2017-11-21 19:25:08 +00:00
"fmt"
"strings"
2017-11-28 17:45:24 +00:00
2019-03-01 18:09:45 +00:00
"github.com/rancher/rke/log"
2020-02-04 19:27:52 +00:00
"github.com/rancher/rke/metadata"
2019-06-11 22:31:01 +00:00
"github.com/rancher/rke/pki"
2017-11-28 17:45:24 +00:00
"github.com/rancher/rke/services"
2019-03-01 18:09:45 +00:00
"github.com/rancher/rke/util"
2020-02-04 19:27:52 +00:00
"k8s.io/api/core/v1"
2018-08-25 20:03:34 +00:00
"k8s.io/apimachinery/pkg/util/validation"
2017-11-21 19:25:08 +00:00
)
2019-03-01 18:09:45 +00:00
func ( c * Cluster ) ValidateCluster ( ctx context . Context ) error {
// validate kubernetes version
// Version Check
if err := validateVersion ( ctx , c ) ; err != nil {
return err
}
2018-02-12 17:52:12 +00:00
// validate duplicate nodes
if err := validateDuplicateNodes ( c ) ; err != nil {
return err
}
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 {
2018-12-28 16:41:37 +00:00
for strategy , enabled := range c . AuthnStrategies {
if ! enabled {
continue
}
strategy = strings . ToLower ( strategy )
if strategy != AuthnX509Provider && strategy != AuthnWebhookProvider {
return fmt . Errorf ( "Authentication strategy [%s] is not supported" , strategy )
}
}
if ! c . AuthnStrategies [ AuthnX509Provider ] {
return fmt . Errorf ( "Authentication strategy must contain [%s]" , AuthnX509Provider )
2017-11-28 17:45:24 +00:00
}
return nil
}
2020-06-26 07:35:32 +00:00
func transformAciNetworkOption ( option string ) ( string , string ) {
var description string
switch option {
case AciSystemIdentifier :
option = "system_id"
description = "unique suffix for all cluster related objects in aci"
case AciServiceGraphSubnet :
option = "node_svc_subnet"
description = "Subnet to use for service graph endpoints on aci"
case AciStaticExternalSubnet :
option = "extern_static"
description = "Subnet to use for static external IPs on aci"
case AciDynamicExternalSubnet :
option = "extern_dynamic"
description = "Subnet to use for dynamic external IPs on aci"
case AciToken :
description = "UUID for this version of the input configuration"
case AciApicUserName :
description = "User name for aci apic"
case AciApicUserKey :
description = "Base64 encoded private key for aci apic user"
case AciApicUserCrt :
description = "Base64 encoded certificate for aci apic user"
case AciEncapType :
description = "One of the supported encap types for aci(vlan/vxlan)"
case AciMcastRangeStart :
description = "Mcast range start address for endpoint groups on aci"
case AciMcastRangeEnd :
description = "Mcast range end address for endpoint groups on aci"
case AciNodeSubnet :
description = "Kubernetes node address subnet"
case AciAEP :
description = "Attachment entity profile name on aci"
case AciVRFName :
description = "VRF Name on aci"
case AciVRFTenant :
description = "Tenant for VRF on aci"
case AciL3Out :
description = "L3Out on aci"
case AciKubeAPIVlan :
description = "Vlan for node network on aci"
case AciServiceVlan :
description = "Vlan for service graph nodes on aci"
case AciInfraVlan :
description = "Vlan for infra network on aci"
}
return option , description
}
func validateAciCloudOptionsDisabled ( option string , value string ) ( string , string , bool ) {
var description string
ok := false
switch option {
case AciUseOpflexServerVolume :
if value == DefaultAciUseOpflexServerVolume {
ok = true
}
description = "Use mounted volume for opflex server"
case AciUseHostNetnsVolume :
if value == DefaultAciUseHostNetnsVolume {
ok = true
}
description = "Mount host netns for opflex server"
case AciCApic :
if value == DefaultAciCApic {
ok = true
}
description = "Provision cloud apic"
case AciUseAciAnywhereCRD :
if value == DefaultAciUseAciAnywhereCRD {
ok = true
}
description = "Use Aci anywhere CRD"
case AciRunGbpContainer :
if value == DefaultAciRunGbpContainer {
ok = true
}
description = "Run Gbp Server"
case AciRunOpflexServerContainer :
if value == DefaultAciRunOpflexServerContainer {
ok = true
}
description = "Run Opflex Server"
case AciEpRegistry :
if value == "" {
ok = true
}
description = "Registry for Ep whether CRD or MODB"
case AciOpflexMode :
if value == "" {
ok = true
}
description = "Opflex overlay mode or on-prem"
case AciSubnetDomainName :
if value == "" {
ok = true
}
description = "Subnet domain name"
case AciKafkaClientCrt :
if value == "" {
ok = true
}
description = "CApic Kafka client certificate"
case AciKafkaClientKey :
if value == "" {
ok = true
}
description = "CApic Kafka client key"
case AciOverlayVRFName :
if value == "" {
ok = true
}
description = "Overlay VRF name"
case AciGbpPodSubnet :
if value == "" {
ok = true
}
description = "Gbp pod subnet"
case AciOpflexServerPort :
if value == "" {
ok = true
}
description = "Opflex server port"
}
return option , description , ok
}
2017-11-28 17:45:24 +00:00
func validateNetworkOptions ( c * Cluster ) error {
2020-06-26 07:35:32 +00:00
if c . Network . Plugin != NoNetworkPlugin && c . Network . Plugin != FlannelNetworkPlugin && c . Network . Plugin != CalicoNetworkPlugin && c . Network . Plugin != CanalNetworkPlugin && c . Network . Plugin != WeaveNetworkPlugin && c . Network . Plugin != AciNetworkPlugin {
2017-11-28 17:45:24 +00:00
return fmt . Errorf ( "Network plugin [%s] is not supported" , c . Network . Plugin )
}
2019-12-23 00:22:13 +00:00
if c . Network . Plugin == FlannelNetworkPlugin && c . Network . MTU != 0 {
2019-12-06 16:59:15 +00:00
return fmt . Errorf ( "Network plugin [%s] does not support configuring MTU" , FlannelNetworkPlugin )
}
2020-06-26 07:35:32 +00:00
if c . Network . Plugin == AciNetworkPlugin {
//Skip cloud options and throw an error.
cloudOptionsList := [ ] string { AciEpRegistry , AciOpflexMode , AciUseHostNetnsVolume , AciUseOpflexServerVolume ,
AciSubnetDomainName , AciKafkaClientCrt , AciKafkaClientKey , AciCApic , UseAciAnywhereCRD ,
AciOverlayVRFName , AciGbpPodSubnet , AciRunGbpContainer , AciRunOpflexServerContainer , AciOpflexServerPort }
for _ , v := range cloudOptionsList {
val , ok := c . Network . Options [ v ]
_ , _ , disabled := validateAciCloudOptionsDisabled ( v , val )
if ok && ! disabled {
return fmt . Errorf ( "Network plugin aci: %s = %s is provided,but cloud options are not allowed in this release" , v , val )
}
}
networkOptionsList := [ ] string { AciSystemIdentifier , AciToken , AciApicUserName , AciApicUserKey ,
AciApicUserCrt , AciEncapType , AciMcastRangeStart , AciMcastRangeEnd ,
AciNodeSubnet , AciAEP , AciVRFName , AciVRFTenant , AciL3Out , AciDynamicExternalSubnet ,
AciStaticExternalSubnet , AciServiceGraphSubnet , AciKubeAPIVlan , AciServiceVlan , AciInfraVlan ,
AciNodeSubnet }
for _ , v := range networkOptionsList {
val , ok := c . Network . Options [ v ]
if ! ok || val == "" {
var description string
v , description = transformAciNetworkOption ( v )
return fmt . Errorf ( "Network plugin aci: %s(%s) under aci_network_provider is not provided" , strings . TrimPrefix ( v , "aci_" ) , description )
}
}
if c . Network . AciNetworkProvider != nil {
if c . Network . AciNetworkProvider . ApicHosts == nil {
return fmt . Errorf ( "Network plugin aci: %s(address of aci apic hosts) under aci_network_provider is not provided" , "apic_hosts" )
}
if c . Network . AciNetworkProvider . L3OutExternalNetworks == nil {
return fmt . Errorf ( "Network plugin aci: %s(external network name/s on aci) under aci_network_provider is not provided" , "l3out_external_networks" )
}
} else {
var requiredArgs [ ] string
for _ , v := range networkOptionsList {
v , _ = transformAciNetworkOption ( v )
requiredArgs = append ( requiredArgs , fmt . Sprintf ( " %s" , strings . TrimPrefix ( "aci_" , v ) ) )
}
requiredArgs = append ( requiredArgs , fmt . Sprintf ( " %s" , ApicHosts ) )
requiredArgs = append ( requiredArgs , fmt . Sprintf ( " %s" , L3OutExternalNetworks ) )
return fmt . Errorf ( "Network plugin aci: multiple parameters under aci_network_provider are not provided: %s" , requiredArgs )
}
}
2017-11-28 17:45:24 +00:00
return nil
}
func validateHostsOptions ( c * Cluster ) error {
for i , host := range c . Nodes {
if len ( host . Address ) == 0 {
2018-02-26 23:27:18 +00:00
return fmt . Errorf ( "Address for host (%d) is not provided" , i + 1 )
2017-11-28 17:45:24 +00:00
}
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 )
}
2018-08-25 20:03:34 +00:00
if errs := validation . IsDNS1123Subdomain ( host . HostnameOverride ) ; len ( errs ) > 0 {
return fmt . Errorf ( "Hostname_override [%s] for host (%d) is not valid: %v" , host . HostnameOverride , i + 1 , errs )
}
2017-11-28 17:45:24 +00:00
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 {
2020-03-03 11:05:59 +00:00
return errors . New ( "External CA Certificate for etcd can't be empty" )
2018-02-14 20:58:35 +00:00
}
if len ( c . Services . Etcd . Cert ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "External Client Certificate for etcd can't be empty" )
2018-02-14 20:58:35 +00:00
}
if len ( c . Services . Etcd . Key ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "External Client Key for etcd can't be empty" )
2018-02-14 20:58:35 +00:00
}
if len ( c . Services . Etcd . Path ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "External etcd path can't be empty" )
2018-02-14 20:58:35 +00:00
}
}
2018-12-13 08:46:47 +00:00
// validate etcd s3 backup backend configurations
if err := validateEtcdBackupOptions ( c ) ; err != nil {
return err
}
return nil
}
func validateEtcdBackupOptions ( c * Cluster ) error {
2019-03-11 23:04:08 +00:00
if c . Services . Etcd . BackupConfig != nil {
2019-01-14 20:20:10 +00:00
if c . Services . Etcd . BackupConfig . S3BackupConfig != nil {
if len ( c . Services . Etcd . BackupConfig . S3BackupConfig . Endpoint ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "etcd s3 backup backend endpoint can't be empty" )
2019-01-14 20:20:10 +00:00
}
if len ( c . Services . Etcd . BackupConfig . S3BackupConfig . BucketName ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "etcd s3 backup backend bucketName can't be empty" )
2019-01-14 20:20:10 +00:00
}
2019-06-25 20:12:17 +00:00
if len ( c . Services . Etcd . BackupConfig . S3BackupConfig . CustomCA ) != 0 {
if isValid , err := pki . IsValidCertStr ( c . Services . Etcd . BackupConfig . S3BackupConfig . CustomCA ) ; ! isValid {
2019-06-11 22:31:01 +00:00
return fmt . Errorf ( "invalid S3 endpoint CA certificate: %v" , err )
}
}
2018-12-13 08:46:47 +00:00
}
}
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
}
2019-08-23 22:52:31 +00:00
if c . Ingress . DNSPolicy != "" &&
! ( c . Ingress . DNSPolicy == string ( v1 . DNSClusterFirst ) ||
c . Ingress . DNSPolicy == string ( v1 . DNSClusterFirstWithHostNet ) ||
c . Ingress . DNSPolicy == string ( v1 . DNSNone ) ||
c . Ingress . DNSPolicy == string ( v1 . DNSDefault ) ) {
return fmt . Errorf ( "DNSPolicy %s was not a valid DNS Policy" , c . Ingress . DNSPolicy )
}
2020-02-13 05:27:12 +00:00
if c . Ingress . NetworkMode == "hostPort" {
if ! ( c . Ingress . HTTPPort >= 0 && c . Ingress . HTTPPort <= 65535 ) {
return fmt . Errorf ( "https port is invalid. Needs to be within 0 to 65535" )
}
if ! ( c . Ingress . HTTPPort >= 0 && c . Ingress . HTTPPort <= 65535 ) {
return fmt . Errorf ( "http port is invalid. Needs to be within 0 to 65535" )
}
if c . Ingress . HTTPPort != 0 && c . Ingress . HTTPSPort != 0 &&
( c . Ingress . HTTPPort == c . Ingress . HTTPSPort ) {
return fmt . Errorf ( "http and https ports need to be different" )
}
}
if ! ( c . Ingress . NetworkMode == "" ||
c . Ingress . NetworkMode == "hostNetwork" || c . Ingress . NetworkMode == "hostPort" ||
c . Ingress . NetworkMode == "none" ) {
return fmt . Errorf ( "NetworkMode %s was not a valid network mode" , c . Ingress . NetworkMode )
}
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 {
2019-08-07 15:35:19 +00:00
failedEtcdHosts := [ ] string { }
for _ , host := range c . InactiveHosts {
if host . IsEtcd {
failedEtcdHosts = append ( failedEtcdHosts , host . Address )
2018-08-29 21:49:01 +00:00
}
return fmt . Errorf ( "Cluster must have at least one etcd plane host: failed to connect to the following etcd host(s) %v" , failedEtcdHosts )
}
2020-03-03 11:05:59 +00:00
return errors . New ( "Cluster must have at least one etcd plane host: please specify one or more etcd in cluster config" )
2018-02-21 23:13:08 +00:00
}
if len ( c . EtcdHosts ) > 0 && len ( c . Services . Etcd . ExternalURLs ) > 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "Cluster can't have both internal and external etcd" )
2018-02-21 23:13:08 +00:00
}
return nil
}
2018-02-12 17:52:12 +00:00
func validateDuplicateNodes ( c * Cluster ) error {
2020-03-06 15:47:03 +00:00
addresses := make ( map [ string ] struct { } , len ( c . Nodes ) )
hostnames := make ( map [ string ] struct { } , len ( c . Nodes ) )
2018-02-12 17:52:12 +00:00
for i := range c . Nodes {
2020-03-06 15:47:03 +00:00
if _ , ok := addresses [ c . Nodes [ i ] . Address ] ; ok {
return fmt . Errorf ( "Cluster can't have duplicate node: %s" , c . Nodes [ i ] . Address )
}
addresses [ c . Nodes [ i ] . Address ] = struct { } { }
if _ , ok := hostnames [ c . Nodes [ i ] . HostnameOverride ] ; ok {
return fmt . Errorf ( "Cluster can't have duplicate node: %s" , c . Nodes [ i ] . HostnameOverride )
2018-02-12 17:52:12 +00:00
}
2020-03-06 15:47:03 +00:00
hostnames [ c . Nodes [ i ] . HostnameOverride ] = struct { } { }
2018-02-12 17:52:12 +00:00
}
return nil
}
2019-03-01 18:09:45 +00:00
func validateVersion ( ctx context . Context , c * Cluster ) error {
_ , err := util . StrToSemVer ( c . Version )
if err != nil {
return fmt . Errorf ( "%s is not valid semver" , c . Version )
}
2019-05-28 18:51:53 +00:00
_ , ok := metadata . K8sVersionToRKESystemImages [ c . Version ]
2019-03-01 18:09:45 +00:00
if ! ok {
if err := validateSystemImages ( c ) ; err != nil {
return fmt . Errorf ( "%s is an unsupported Kubernetes version and system images are not populated: %v" , c . Version , err )
}
return nil
}
2019-05-28 18:51:53 +00:00
if _ , ok := metadata . K8sBadVersions [ c . Version ] ; ok {
2019-03-01 18:09:45 +00:00
log . Warnf ( ctx , "%s version exists but its recommended to install this version - see 'rke config --system-images --all' for versions supported with this release" , c . Version )
2019-05-28 18:51:53 +00:00
return fmt . Errorf ( "%s is an unsupported Kubernetes version and system images are not populated: %v" , c . Version , err )
2019-03-01 18:09:45 +00:00
}
return nil
}
func validateSystemImages ( c * Cluster ) error {
if err := validateKubernetesImages ( c ) ; err != nil {
return err
}
if err := validateNetworkImages ( c ) ; err != nil {
return err
}
if err := validateDNSImages ( c ) ; err != nil {
return err
}
if err := validateMetricsImages ( c ) ; err != nil {
return err
}
if err := validateIngressImages ( c ) ; err != nil {
return err
}
return nil
}
func validateKubernetesImages ( c * Cluster ) error {
if len ( c . SystemImages . Etcd ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "etcd image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . Kubernetes ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "kubernetes image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . PodInfraContainer ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "pod infrastructure container image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . Alpine ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "alpine image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . NginxProxy ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "nginx proxy image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CertDownloader ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "certificate downloader image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . KubernetesServicesSidecar ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "kubernetes sidecar image is not populated" )
2019-03-01 18:09:45 +00:00
}
return nil
}
func validateNetworkImages ( c * Cluster ) error {
// check network provider images
if c . Network . Plugin == FlannelNetworkPlugin {
if len ( c . SystemImages . Flannel ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "flannel image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . FlannelCNI ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "flannel cni image is not populated" )
2019-03-01 18:09:45 +00:00
}
} else if c . Network . Plugin == CanalNetworkPlugin {
if len ( c . SystemImages . CanalNode ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "canal image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CanalCNI ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "canal cni image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CanalFlannel ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "flannel image is not populated" )
2019-03-01 18:09:45 +00:00
}
} else if c . Network . Plugin == CalicoNetworkPlugin {
if len ( c . SystemImages . CalicoCNI ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "calico cni image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CalicoCtl ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "calico ctl image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CalicoNode ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "calico image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CalicoControllers ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "calico controllers image is not populated" )
2019-03-01 18:09:45 +00:00
}
} else if c . Network . Plugin == WeaveNetworkPlugin {
if len ( c . SystemImages . WeaveCNI ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "weave cni image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . WeaveNode ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "weave image is not populated" )
2019-03-01 18:09:45 +00:00
}
2020-06-26 07:35:32 +00:00
} else if c . Network . Plugin == AciNetworkPlugin {
if len ( c . SystemImages . AciCniDeployContainer ) == 0 {
return errors . New ( "aci cnideploy image is not populated" )
}
if len ( c . SystemImages . AciHostContainer ) == 0 {
return errors . New ( "aci host container image is not populated" )
}
if len ( c . SystemImages . AciOpflexContainer ) == 0 {
return errors . New ( "aci opflex agent image is not populated" )
}
if len ( c . SystemImages . AciMcastContainer ) == 0 {
return errors . New ( "aci mcast container image is not populated" )
}
if len ( c . SystemImages . AciOpenvSwitchContainer ) == 0 {
return errors . New ( "aci openvswitch image is not populated" )
}
if len ( c . SystemImages . AciControllerContainer ) == 0 {
return errors . New ( "aci controller image is not populated" )
}
//Skipping Cloud image validation.
//c.SystemImages.AciOpflexServerContainer
//c.SystemImages.AciGbpServerContainer
2019-03-01 18:09:45 +00:00
}
return nil
}
func validateDNSImages ( c * Cluster ) error {
// check dns provider images
if c . DNS . Provider == "kube-dns" {
if len ( c . SystemImages . KubeDNS ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "kubedns image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . DNSmasq ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "dnsmasq image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . KubeDNSSidecar ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "kubedns sidecar image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . KubeDNSAutoscaler ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "kubedns autoscaler image is not populated" )
2019-03-01 18:09:45 +00:00
}
} else if c . DNS . Provider == "coredns" {
if len ( c . SystemImages . CoreDNS ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "coredns image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . CoreDNSAutoscaler ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "coredns autoscaler image is not populated" )
2019-03-01 18:09:45 +00:00
}
}
2020-03-03 11:05:59 +00:00
if c . DNS . Nodelocal != nil && len ( c . SystemImages . Nodelocal ) == 0 {
return errors . New ( "nodelocal image is not populated" )
}
2019-03-01 18:09:45 +00:00
return nil
}
func validateMetricsImages ( c * Cluster ) error {
// checl metrics server image
if c . Monitoring . Provider != "none" {
if len ( c . SystemImages . MetricsServer ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "metrics server images is not populated" )
2019-03-01 18:09:45 +00:00
}
}
return nil
}
func validateIngressImages ( c * Cluster ) error {
// check ingress images
if c . Ingress . Provider != "none" {
if len ( c . SystemImages . Ingress ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "ingress image is not populated" )
2019-03-01 18:09:45 +00:00
}
if len ( c . SystemImages . IngressBackend ) == 0 {
2020-03-03 11:05:59 +00:00
return errors . New ( "ingress backend image is not populated" )
2019-03-01 18:09:45 +00:00
}
}
return nil
}