in eksconfig/config.go [1167:1446]
func (cfg *Config) validateConfig() error {
if len(cfg.Name) == 0 {
return errors.New("name is empty")
}
if cfg.Name != strings.ToLower(cfg.Name) {
return fmt.Errorf("name %q must be in lower-case", cfg.Name)
}
if cfg.LogColorOverride == "" {
_, cerr := terminal.IsColor()
if cfg.LogColor && cerr != nil {
cfg.LogColor = false
fmt.Fprintf(os.Stderr, "[WARN] LogColor is set to 'false' due to error %+v", cerr)
}
} else {
// non-empty override, don't even run "terminal.IsColor"
ov, perr := strconv.ParseBool(cfg.LogColorOverride)
if perr != nil {
return fmt.Errorf("failed to parse LogColorOverride %q (%v)", cfg.LogColorOverride, perr)
}
cfg.LogColor = ov
fmt.Fprintf(os.Stderr, "[WARN] LogColor is overwritten with %q", cfg.LogColorOverride)
}
if len(cfg.LogOutputs) == 0 {
return errors.New("LogOutputs is not empty")
}
if cfg.Clients == 0 {
cfg.Clients = DefaultClients
}
if cfg.ClientQPS == 0 {
cfg.ClientQPS = DefaultClientQPS
}
if cfg.ClientBurst == 0 {
cfg.ClientBurst = DefaultClientBurst
}
if cfg.ClientTimeout == time.Duration(0) {
cfg.ClientTimeout = DefaultClientTimeout
}
cfg.ClientTimeoutString = cfg.ClientTimeout.String()
if cfg.ConfigPath == "" {
rootDir, err := os.Getwd()
if err != nil {
rootDir = filepath.Join(os.TempDir(), cfg.Name)
if err := os.MkdirAll(rootDir, 0700); err != nil {
return err
}
}
cfg.ConfigPath = filepath.Join(rootDir, cfg.Name+".yaml")
var p string
p, err = filepath.Abs(cfg.ConfigPath)
if err != nil {
panic(err)
}
cfg.ConfigPath = p
}
if err := os.MkdirAll(filepath.Dir(cfg.ConfigPath), 0700); err != nil {
return err
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.ConfigPath)); err != nil {
return err
}
if len(cfg.LogOutputs) == 1 && (cfg.LogOutputs[0] == "stderr" || cfg.LogOutputs[0] == "stdout") {
cfg.LogOutputs = append(cfg.LogOutputs, strings.ReplaceAll(cfg.ConfigPath, ".yaml", "")+".log")
}
logFilePath := ""
for _, fpath := range cfg.LogOutputs {
if filepath.Ext(fpath) == ".log" {
logFilePath = fpath
break
}
}
if logFilePath == "" {
return fmt.Errorf("*.log file not found in %q", cfg.LogOutputs)
}
if cfg.Version == "" {
return errors.New("empty Parameters.Version")
}
var err error
cfg.VersionValue, err = strconv.ParseFloat(cfg.Version, 64)
if err != nil {
return fmt.Errorf("cannot parse Parameters.Version %q (%v)", cfg.Version, err)
}
if len(cfg.Role.ServicePrincipals) == 0 {
return errors.New("empty Role.ServicePrincipals")
}
if len(cfg.Role.ManagedPolicyARNs) == 0 {
return errors.New("empty Role.ManagedPolicyARNs")
}
// e.g.,
// "api error LimitExceeded: Cannot exceed quota for PoliciesPerRole: 10"
if len(cfg.Role.ManagedPolicyARNs) > 9 {
return fmt.Errorf("too many ManagedPolicyARNs %q", cfg.Role.ManagedPolicyARNs)
}
found := false
for _, v := range cfg.Role.ServicePrincipals {
if v == "eks.amazonaws.com" {
found = true
break
}
}
if !found {
return fmt.Errorf("Role.ServicePrincipals missing 'eks.amazonaws.com' (%q)", cfg.Role.ServicePrincipals)
}
found = false
for _, v := range cfg.Role.ManagedPolicyARNs {
if v == "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" {
found = true
break
}
}
if !found {
return fmt.Errorf("Role.ManagedPolicyARNs missing 'arn:aws:iam::aws:policy/AmazonEKSClusterPolicy' (%q)", cfg.Role.ManagedPolicyARNs)
}
switch cfg.Role.Create {
case true: // need create one, or already created
if cfg.Role.Name == "" {
cfg.Role.Name = cfg.Name + "-role"
}
case false: // use existing one
if cfg.Role.ARN == "" {
return fmt.Errorf("Role.Create false; expect non-empty RoleARN but got %q", cfg.Role.ARN)
}
if cfg.Role.Name == "" {
cfg.Role.Name = getNameFromARN(cfg.Role.ARN)
}
}
if cfg.Role.PolicyName == "" {
cfg.Role.PolicyName = cfg.Name + "-policy"
}
switch cfg.VPC.Create {
case true: // need create one, or already created
// just ignore...
// could be populated from previous run
// do not error, so long as VPCCreate false, VPC won't be deleted
case false: // use existing one
if cfg.VPC.ID == "" {
return fmt.Errorf("RoleCreate false; expect non-empty VPCID but got %q", cfg.VPC.ID)
}
}
if cfg.VPC.NodeGroupSecurityGroupName == "" {
cfg.VPC.NodeGroupSecurityGroupName = cfg.Name + "-node-group-security-group"
}
if len(cfg.VPC.PublicSubnetCIDRs) < 2 {
return fmt.Errorf("unexpected number of VPC.PublicSubnetCIDRs %v (expected at least 2)", cfg.VPC.PublicSubnetCIDRs)
}
switch cfg.Encryption.CMKCreate {
case true: // need create one, or already created
// just ignore...
// could be populated from previous run
// do not error, so long as EncryptionCMKCreate false, CMK won't be deleted
case false: // use existing one
}
switch cfg.RemoteAccessKeyCreate {
case true: // need create one, or already created
if cfg.RemoteAccessKeyName == "" {
cfg.RemoteAccessKeyName = cfg.Name + "-remote-access-key"
}
if cfg.RemoteAccessPrivateKeyPath == "" {
cfg.RemoteAccessPrivateKeyPath = filepath.Join(os.TempDir(), randutil.String(10)+".insecure.key")
}
case false: // use existing one
if cfg.RemoteAccessKeyName == "" {
return fmt.Errorf("RemoteAccessKeyCreate false; expect non-empty RemoteAccessKeyName but got %q", cfg.RemoteAccessKeyName)
}
if cfg.RemoteAccessPrivateKeyPath == "" {
return fmt.Errorf("RemoteAccessKeyCreate false; expect non-empty RemoteAccessPrivateKeyPath but got %q", cfg.RemoteAccessPrivateKeyPath)
}
if !fileutil.Exist(cfg.RemoteAccessPrivateKeyPath) {
return fmt.Errorf("RemoteAccessPrivateKeyPath %q does not exist", cfg.RemoteAccessPrivateKeyPath)
}
}
keyDir := filepath.Dir(cfg.RemoteAccessPrivateKeyPath)
if err := fileutil.IsDirWriteable(keyDir); err != nil {
return err
}
if cfg.KubectlCommandsOutputPath == "" {
cfg.KubectlCommandsOutputPath = strings.ReplaceAll(cfg.ConfigPath, ".yaml", "") + ".kubectl.sh"
}
if filepath.Ext(cfg.KubectlCommandsOutputPath) != ".sh" {
cfg.KubectlCommandsOutputPath = cfg.KubectlCommandsOutputPath + ".sh"
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.KubectlCommandsOutputPath)); err != nil {
return err
}
if cfg.RemoteAccessCommandsOutputPath == "" {
cfg.RemoteAccessCommandsOutputPath = strings.ReplaceAll(cfg.ConfigPath, ".yaml", "") + ".ssh.sh"
}
if filepath.Ext(cfg.RemoteAccessCommandsOutputPath) != ".sh" {
cfg.RemoteAccessCommandsOutputPath = cfg.RemoteAccessCommandsOutputPath + ".sh"
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.RemoteAccessCommandsOutputPath)); err != nil {
return err
}
if cfg.CommandAfterCreateClusterOutputPath == "" {
cfg.CommandAfterCreateClusterOutputPath = strings.ReplaceAll(cfg.ConfigPath, ".yaml", "") + ".after-create-cluster.out.log"
}
if filepath.Ext(cfg.CommandAfterCreateClusterOutputPath) != ".log" {
cfg.CommandAfterCreateClusterOutputPath = cfg.CommandAfterCreateClusterOutputPath + ".log"
}
if cfg.CommandAfterCreateClusterTimeout == time.Duration(0) {
cfg.CommandAfterCreateClusterTimeout = DefaultCommandAfterCreateClusterTimeout
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.CommandAfterCreateClusterOutputPath)); err != nil {
return err
}
cfg.CommandAfterCreateClusterTimeoutString = cfg.CommandAfterCreateClusterTimeout.String()
if cfg.CommandAfterCreateAddOnsOutputPath == "" {
cfg.CommandAfterCreateAddOnsOutputPath = strings.ReplaceAll(cfg.ConfigPath, ".yaml", "") + ".after-create-add-ons.out.log"
}
if filepath.Ext(cfg.CommandAfterCreateAddOnsOutputPath) != ".log" {
cfg.CommandAfterCreateAddOnsOutputPath = cfg.CommandAfterCreateAddOnsOutputPath + ".log"
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.CommandAfterCreateAddOnsOutputPath)); err != nil {
return err
}
if cfg.CommandAfterCreateAddOnsTimeout == time.Duration(0) {
cfg.CommandAfterCreateAddOnsTimeout = DefaultCommandAfterCreateAddOnsTimeout
}
cfg.CommandAfterCreateAddOnsTimeoutString = cfg.CommandAfterCreateAddOnsTimeout.String()
if cfg.KubeConfigPath == "" {
cfg.KubeConfigPath = strings.ReplaceAll(cfg.ConfigPath, ".yaml", "") + ".kubeconfig.yaml"
}
if err := fileutil.IsDirWriteable(filepath.Dir(cfg.KubeConfigPath)); err != nil {
return err
}
if cfg.KubectlPath == "" && cfg.KubectlDownloadURL == "" {
return errors.New("empty KubectlPath and KubectlDownloadURL")
}
if !strings.ContainsAny(cfg.KubectlDownloadURL, runtime.GOOS) {
return fmt.Errorf("kubectl-download-url %q build OS mismatch, expected %q", cfg.KubectlDownloadURL, runtime.GOOS)
}
if err := cfg.evaluateCommandRefs(); err != nil {
return err
}
switch cfg.S3.BucketCreate {
case true: // need create one, or already created
if cfg.S3.BucketName == "" {
cfg.S3.BucketName = cfg.Name + "-s3-bucket"
}
if cfg.S3.BucketLifecycleExpirationDays > 0 && cfg.S3.BucketLifecycleExpirationDays < 3 {
cfg.S3.BucketLifecycleExpirationDays = 3
}
case false: // use existing one
if cfg.S3.BucketName == "" {
return errors.New("empty S3BucketName")
}
}
if cfg.CWNamespace == "" {
cfg.CWNamespace = "aws-k8s-tester-eks"
}
if cfg.Status == nil {
cfg.Status = &Status{
Up: false,
PrivateDNSToNodeInfo: make(map[string]NodeInfo),
}
}
return nil
}