func()

in ec2config/validate-defaults.go [290:431]


func (cfg *Config) validateASGs() error {
	n := len(cfg.ASGs)
	if n == 0 {
		return errors.New("empty ASGs")
	}
	if n > ASGsMaxLimit {
		return fmt.Errorf("ASGs %d exceeds maximum number of ASGs which is %d", n, ASGsMaxLimit)
	}
	names, processed := make(map[string]struct{}), make(map[string]ASG)
	total := int32(0)
	for k, cur := range cfg.ASGs {
		k = strings.ReplaceAll(k, "GetRef.Name", cfg.Name)
		cur.Name = strings.ReplaceAll(cur.Name, "GetRef.Name", cfg.Name)

		if cur.Name == "" {
			return fmt.Errorf("ASGs[%q].Name is empty", k)
		}
		if k != cur.Name {
			return fmt.Errorf("ASGs[%q].Name has different Name field %q", k, cur.Name)
		}
		_, ok := names[cur.Name]
		if !ok {
			names[cur.Name] = struct{}{}
		} else {
			return fmt.Errorf("ASGs[%q].Name %q is redundant", k, cur.Name)
		}

		if cur.VolumeSize == 0 {
			cur.VolumeSize = DefaultNodeVolumeSize
		}
		if cur.RemoteAccessUserName == "" {
			cur.RemoteAccessUserName = "ec2-user"
		}

		if cur.ImageID == "" && cur.ImageIDSSMParameter == "" {
			return fmt.Errorf("%q both ImageID and ImageIDSSMParameter are empty", cur.Name)
		}
		// prefer "ImageIDSSMParameter"
		if cur.ImageID != "" && cur.ImageIDSSMParameter != "" {
			cur.ImageID = ""
		}
		if cur.LaunchTemplateName == "" {
			cur.LaunchTemplateName = cur.Name + "-launch-template"
		}

		switch cur.AMIType {
		case AMITypeAL2ARM64:
			if cur.RemoteAccessUserName != "ec2-user" {
				return fmt.Errorf("AMIType %q but unexpected RemoteAccessUserName %q", cur.AMIType, cur.RemoteAccessUserName)
			}
		case AMITypeBottleRocketCPU:
			if cur.RemoteAccessUserName != "ec2-user" {
				return fmt.Errorf("AMIType %q but unexpected RemoteAccessUserName %q", cur.AMIType, cur.RemoteAccessUserName)
			}
		case AMITypeAL2X8664:
			if cur.RemoteAccessUserName != "ec2-user" {
				return fmt.Errorf("AMIType %q but unexpected RemoteAccessUserName %q", cur.AMIType, cur.RemoteAccessUserName)
			}
		case AMITypeAL2X8664GPU:
			if cur.RemoteAccessUserName != "ec2-user" {
				return fmt.Errorf("AMIType %q but unexpected RemoteAccessUserName %q", cur.AMIType, cur.RemoteAccessUserName)
			}
		case AMITypeOther:
		default:
			return fmt.Errorf("unknown ASGs[%q].AMIType %q", k, cur.AMIType)
		}

		switch cur.AMIType {
		case AMITypeAL2ARM64:
			if cur.InstanceType == "" {
				cur.InstanceType = DefaultNodeInstanceTypeCPUARM
			}
		case AMITypeBottleRocketCPU:
			if cur.InstanceType == "" {
				cur.InstanceType = DefaultNodeInstanceTypeCPU
			}
		case AMITypeAL2X8664:
			if cur.InstanceType == "" {
				cur.InstanceType = DefaultNodeInstanceTypeCPU
			}
		case AMITypeAL2X8664GPU:
			if cur.InstanceType == "" {
				cur.InstanceType = DefaultNodeInstanceTypeGPU
			}
		case AMITypeOther:
		default:
			return fmt.Errorf("unknown ASGs[%q].AMIType %q", k, cur.AMIType)
		}

		if cur.ASGMinSize == 0 {
			return fmt.Errorf("ASGs[%q].ASGMinSize must be >0", k)
		}
		if cur.ASGDesiredCapacity == 0 {
			return fmt.Errorf("ASGs[%q].ASGDesiredCapacity must be >0", k)
		}
		if cur.ASGMaxSize == 0 {
			return fmt.Errorf("ASGs[%q].ASGMaxSize must be >0", k)
		}
		if cur.ASGMinSize > cur.ASGMaxSize {
			return fmt.Errorf("ASGs[%q].ASGMinSize %d > ASGMaxSize %d", k, cur.ASGMinSize, cur.ASGMaxSize)
		}
		if cur.ASGDesiredCapacity > cur.ASGMaxSize {
			return fmt.Errorf("ASGs[%q].ASGDesiredCapacity %d > ASGMaxSize %d", k, cur.ASGDesiredCapacity, cur.ASGMaxSize)
		}
		if cur.ASGMaxSize > ASGMaxLimit {
			return fmt.Errorf("ASGs[%q].ASGMaxSize %d > ASGMaxLimit %d", k, cur.ASGMaxSize, ASGMaxLimit)
		}
		if cur.ASGDesiredCapacity > ASGMaxLimit {
			return fmt.Errorf("ASGs[%q].ASGDesiredCapacity %d > ASGMaxLimit %d", k, cur.ASGDesiredCapacity, ASGMaxLimit)
		}

		if cur.SSM != nil {
			switch cur.SSM.DocumentCreate {
			case true: // need create one, or already created
				if cur.SSM.DocumentName == "" {
					cur.SSM.DocumentName = cur.Name + "SSMDocument"
				}
				cur.SSM.DocumentName = strings.ReplaceAll(cur.SSM.DocumentName, "GetRef.Name", cfg.Name)
				cur.SSM.DocumentName = ssmDocNameRegex.ReplaceAllString(cur.SSM.DocumentName, "")
				if cur.SSM.DocumentExecutionTimeoutSeconds == 0 {
					cur.SSM.DocumentExecutionTimeoutSeconds = 3600
				}
				if cur.SSM.DocumentCommands == "" {
					return errors.New("empty SSM.DocumentCommands")
				}

			case false: // use existing one, or don't run any SSM
			}
		}

		expectedN := cur.ASGDesiredCapacity
		if expectedN == 0 {
			expectedN = cur.ASGMinSize
		}
		total += expectedN
		processed[k] = cur
	}

	cfg.ASGs = processed
	cfg.TotalNodes = total
	return nil
}