diff --git a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml index 7f4260fee5..66638b0963 100644 --- a/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml +++ b/config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml @@ -723,11 +723,10 @@ spec: - resource-name type: string secondaryCidrBlocks: - description: SecondaryCidrBlocks are additional CIDR blocks - to be associated when the provider creates a managed VPC. - Defaults to none. Mutually exclusive with IPAMPool. This - makes sense to use if, for example, you want to use a separate - IP range for pods (e.g. Cilium ENI mode). + description: |- + SecondaryCidrBlocks are additional CIDR blocks to be associated when the provider creates a managed VPC. + Defaults to none. Mutually exclusive with IPAMPool. This makes sense to use if, for example, you want to use + a separate IP range for pods (e.g. Cilium ENI mode). items: description: VpcCidrBlock defines the CIDR block and settings to associate with the managed VPC. Currently, only IPv4 @@ -2693,11 +2692,10 @@ spec: - resource-name type: string secondaryCidrBlocks: - description: SecondaryCidrBlocks are additional CIDR blocks - to be associated when the provider creates a managed VPC. - Defaults to none. Mutually exclusive with IPAMPool. This - makes sense to use if, for example, you want to use a separate - IP range for pods (e.g. Cilium ENI mode). + description: |- + SecondaryCidrBlocks are additional CIDR blocks to be associated when the provider creates a managed VPC. + Defaults to none. Mutually exclusive with IPAMPool. This makes sense to use if, for example, you want to use + a separate IP range for pods (e.g. Cilium ENI mode). items: description: VpcCidrBlock defines the CIDR block and settings to associate with the managed VPC. Currently, only IPv4 diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml index a63d28c2f1..80def3366d 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml @@ -1659,11 +1659,10 @@ spec: - resource-name type: string secondaryCidrBlocks: - description: SecondaryCidrBlocks are additional CIDR blocks - to be associated when the provider creates a managed VPC. - Defaults to none. Mutually exclusive with IPAMPool. This - makes sense to use if, for example, you want to use a separate - IP range for pods (e.g. Cilium ENI mode). + description: |- + SecondaryCidrBlocks are additional CIDR blocks to be associated when the provider creates a managed VPC. + Defaults to none. Mutually exclusive with IPAMPool. This makes sense to use if, for example, you want to use + a separate IP range for pods (e.g. Cilium ENI mode). items: description: VpcCidrBlock defines the CIDR block and settings to associate with the managed VPC. Currently, only IPv4 diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml index f5ce74c7a7..56d649262c 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsclustertemplates.yaml @@ -1258,12 +1258,10 @@ spec: - resource-name type: string secondaryCidrBlocks: - description: SecondaryCidrBlocks are additional CIDR - blocks to be associated when the provider creates - a managed VPC. Defaults to none. Mutually exclusive - with IPAMPool. This makes sense to use if, for example, - you want to use a separate IP range for pods (e.g. - Cilium ENI mode). + description: |- + SecondaryCidrBlocks are additional CIDR blocks to be associated when the provider creates a managed VPC. + Defaults to none. Mutually exclusive with IPAMPool. This makes sense to use if, for example, you want to use + a separate IP range for pods (e.g. Cilium ENI mode). items: description: VpcCidrBlock defines the CIDR block and settings to associate with the managed VPC. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml index ae1d6e3b83..778030c456 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml @@ -738,26 +738,6 @@ spec: name: description: The name of the launch template. type: string - privateDnsName: - description: PrivateDNSName is the options for the instance hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - AAAA records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object nonRootVolumes: description: Configuration options for the non root storage volumes. items: @@ -772,11 +752,10 @@ spec: or not. type: boolean encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. + description: |- + EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. + If Encrypted is set and this is omitted, the default AWS key will be used. + The key must already exist and be accessible by the controller. type: string iops: description: IOPS is the number of IOPS requested for the @@ -784,9 +763,9 @@ spec: format: int64 type: integer size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). + description: |- + Size specifies size (in Gi) of the storage device. + Must be greater than the image snapshot size or 8 (whichever is greater). format: int64 minimum: 8 type: integer @@ -803,6 +782,26 @@ spec: - size type: object type: array + privateDnsName: + description: PrivateDNSName is the options for the instance hostname. + properties: + enableResourceNameDnsAAAARecord: + description: EnableResourceNameDNSAAAARecord indicates whether + to respond to DNS queries for instance hostnames with DNS + AAAA records. + type: boolean + enableResourceNameDnsARecord: + description: EnableResourceNameDNSARecord indicates whether + to respond to DNS queries for instance hostnames with DNS + A records. + type: boolean + hostnameType: + description: The type of hostname to assign to an instance. + enum: + - ip-name + - resource-name + type: string + type: object rootVolume: description: RootVolume encapsulates the configuration options for the root volume @@ -888,6 +887,89 @@ spec: description: Ignition defined options related to the bootstrapping systems where Ignition is used. properties: + proxy: + description: |- + Proxy defines proxy settings for Ignition. + Only valid for Ignition versions 3.1 and above. + properties: + httpProxy: + description: |- + HTTPProxy is the HTTP proxy to use for Ignition. + A single URL that specifies the proxy server to use for HTTP and HTTPS requests, + unless overridden by the HTTPSProxy or NoProxy options. + type: string + httpsProxy: + description: |- + HTTPSProxy is the HTTPS proxy to use for Ignition. + A single URL that specifies the proxy server to use for HTTPS requests, + unless overridden by the NoProxy option. + type: string + noProxy: + description: |- + NoProxy is the list of domains to not proxy for Ignition. + Specifies a list of strings to hosts that should be excluded from proxying. + + + Each value is represented by: + - An IP address prefix (1.2.3.4) + - An IP address prefix in CIDR notation (1.2.3.4/8) + - A domain name + - A domain name matches that name and all subdomains + - A domain name with a leading . matches subdomains only + - A special DNS label (*), indicates that no proxying should be done + + + An IP address prefix and domain name can also include a literal port number (1.2.3.4:80). + items: + description: IgnitionNoProxy defines the list of domains + to not proxy for Ignition. + maxLength: 2048 + type: string + maxItems: 64 + type: array + type: object + storageType: + default: ClusterObjectStore + description: |- + StorageType defines how to store the boostrap user data for Ignition. + This can be used to instruct Ignition from where to fetch the user data to bootstrap an instance. + + + When omitted, the storage option will default to ClusterObjectStore. + + + When set to "ClusterObjectStore", if the capability is available and a Cluster ObjectStore configuration + is correctly provided in the Cluster object (under .spec.s3Bucket), + an object store will be used to store bootstrap user data. + + + When set to "UnencryptedUserData", EC2 Instance User Data will be used to store the machine bootstrap user data, unencrypted. + This option is considered less secure than others as user data may contain sensitive informations (keys, certificates, etc.) + and users with ec2:DescribeInstances permission or users running pods + that can access the ec2 metadata service have access to this sensitive information. + So this is only to be used at ones own risk, and only when other more secure options are not viable. + enum: + - ClusterObjectStore + - UnencryptedUserData + type: string + tls: + description: |- + TLS defines TLS settings for Ignition. + Only valid for Ignition versions 3.1 and above. + properties: + certificateAuthorities: + description: |- + CASources defines the list of certificate authorities to use for Ignition. + The value is the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. + Supported schemes are http, https, tftp, s3, arn, gs, and `data` (RFC 2397) URL scheme. + items: + description: IgnitionCASource defines the source of the + certificate authority to use for Ignition. + maxLength: 65536 + type: string + maxItems: 64 + type: array + type: object version: default: "2.3" description: Version defines which version of Ignition will be @@ -987,6 +1069,18 @@ spec: The default is to use the value for the health check grace period defined for the group. format: int64 type: integer + maxHealthyPercentage: + description: |- + The amount of capacity as a percentage in ASG that can be in service and healthy, or pending, + to support your workload when replacing instances. + The value is expressed as a percentage of the desired capacity of the ASG. Value range is 100 to 200. + If you specify MaxHealthyPercentage , you must also specify MinHealthyPercentage , and the difference between + them cannot be greater than 100. + A larger range increases the number of instances that can be replaced at the same time. + format: int64 + maximum: 200 + minimum: 100 + type: integer minHealthyPercentage: description: |- The amount of capacity as a percentage in ASG that must remain healthy diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml index 01f722f849..008bfd9d2e 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml @@ -734,26 +734,6 @@ spec: name: description: The name of the launch template. type: string - privateDnsName: - description: PrivateDNSName is the options for the instance hostname. - properties: - enableResourceNameDnsAAAARecord: - description: EnableResourceNameDNSAAAARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - AAAA records. - type: boolean - enableResourceNameDnsARecord: - description: EnableResourceNameDNSARecord indicates whether - to respond to DNS queries for instance hostnames with DNS - A records. - type: boolean - hostnameType: - description: The type of hostname to assign to an instance. - enum: - - ip-name - - resource-name - type: string - type: object nonRootVolumes: description: Configuration options for the non root storage volumes. items: @@ -768,11 +748,10 @@ spec: or not. type: boolean encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. + description: |- + EncryptionKey is the KMS key to use to encrypt the volume. Can be either a KMS key ID or ARN. + If Encrypted is set and this is omitted, the default AWS key will be used. + The key must already exist and be accessible by the controller. type: string iops: description: IOPS is the number of IOPS requested for the @@ -780,9 +759,9 @@ spec: format: int64 type: integer size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). + description: |- + Size specifies size (in Gi) of the storage device. + Must be greater than the image snapshot size or 8 (whichever is greater). format: int64 minimum: 8 type: integer @@ -799,6 +778,26 @@ spec: - size type: object type: array + privateDnsName: + description: PrivateDNSName is the options for the instance hostname. + properties: + enableResourceNameDnsAAAARecord: + description: EnableResourceNameDNSAAAARecord indicates whether + to respond to DNS queries for instance hostnames with DNS + AAAA records. + type: boolean + enableResourceNameDnsARecord: + description: EnableResourceNameDNSARecord indicates whether + to respond to DNS queries for instance hostnames with DNS + A records. + type: boolean + hostnameType: + description: The type of hostname to assign to an instance. + enum: + - ip-name + - resource-name + type: string + type: object rootVolume: description: RootVolume encapsulates the configuration options for the root volume diff --git a/exp/api/v1beta1/conversion.go b/exp/api/v1beta1/conversion.go index 603131a2e4..fd086db786 100644 --- a/exp/api/v1beta1/conversion.go +++ b/exp/api/v1beta1/conversion.go @@ -41,8 +41,9 @@ func (src *AWSMachinePool) ConvertTo(dstRaw conversion.Hub) error { if restored.Spec.SuspendProcesses != nil { dst.Spec.SuspendProcesses = restored.Spec.SuspendProcesses } - if dst.Spec.RefreshPreferences != nil && restored.Spec.RefreshPreferences != nil { + if restored.Spec.RefreshPreferences != nil { dst.Spec.RefreshPreferences.Disable = restored.Spec.RefreshPreferences.Disable + dst.Spec.RefreshPreferences.MaxHealthyPercentage = restored.Spec.RefreshPreferences.MaxHealthyPercentage } if restored.Spec.AWSLaunchTemplate.InstanceMetadataOptions != nil { dst.Spec.AWSLaunchTemplate.InstanceMetadataOptions = restored.Spec.AWSLaunchTemplate.InstanceMetadataOptions diff --git a/exp/api/v1beta1/zz_generated.conversion.go b/exp/api/v1beta1/zz_generated.conversion.go index 3c88285772..2b9783c0e9 100644 --- a/exp/api/v1beta1/zz_generated.conversion.go +++ b/exp/api/v1beta1/zz_generated.conversion.go @@ -1067,6 +1067,7 @@ func autoConvert_v1beta2_RefreshPreferences_To_v1beta1_RefreshPreferences(in *v1 out.Strategy = (*string)(unsafe.Pointer(in.Strategy)) out.InstanceWarmup = (*int64)(unsafe.Pointer(in.InstanceWarmup)) out.MinHealthyPercentage = (*int64)(unsafe.Pointer(in.MinHealthyPercentage)) + // WARNING: in.MaxHealthyPercentage requires manual conversion: does not exist in peer-type return nil } diff --git a/exp/api/v1beta2/awsmachinepool_types.go b/exp/api/v1beta2/awsmachinepool_types.go index d29ce0676b..62e81e7c7a 100644 --- a/exp/api/v1beta2/awsmachinepool_types.go +++ b/exp/api/v1beta2/awsmachinepool_types.go @@ -176,6 +176,17 @@ type RefreshPreferences struct { // during an instance refresh. The default is 90. // +optional MinHealthyPercentage *int64 `json:"minHealthyPercentage,omitempty"` + + // The amount of capacity as a percentage in ASG that can be in service and healthy, or pending, + // to support your workload when replacing instances. + // The value is expressed as a percentage of the desired capacity of the ASG. Value range is 100 to 200. + // If you specify MaxHealthyPercentage , you must also specify MinHealthyPercentage , and the difference between + // them cannot be greater than 100. + // A larger range increases the number of instances that can be replaced at the same time. + // +optional + // +kubebuilder:validation:Minimum=100 + // +kubebuilder:validation:Maximum=200 + MaxHealthyPercentage *int64 `json:"maxHealthyPercentage,omitempty"` } // AWSMachinePoolStatus defines the observed state of AWSMachinePool. diff --git a/exp/api/v1beta2/awsmachinepool_webhook.go b/exp/api/v1beta2/awsmachinepool_webhook.go index f392e8670b..a2e408caf4 100644 --- a/exp/api/v1beta2/awsmachinepool_webhook.go +++ b/exp/api/v1beta2/awsmachinepool_webhook.go @@ -109,6 +109,7 @@ func (r *AWSMachinePool) validateAdditionalSecurityGroups() field.ErrorList { } return allErrs } + func (r *AWSMachinePool) validateSpotInstances() field.ErrorList { var allErrs field.ErrorList if r.Spec.AWSLaunchTemplate.SpotMarketOptions != nil && r.Spec.MixedInstancesPolicy != nil { @@ -133,6 +134,26 @@ func (r *AWSMachinePool) validateIgnition() field.ErrorList { return allErrs } +func (r *AWSMachinePool) validateRefreshPreferences() field.ErrorList { + var allErrs field.ErrorList + + if r.Spec.RefreshPreferences == nil { + return allErrs + } + + if r.Spec.RefreshPreferences.MaxHealthyPercentage != nil && r.Spec.RefreshPreferences.MinHealthyPercentage == nil { + allErrs = append(allErrs, field.Forbidden(field.NewPath("spec.refreshPreferences.maxHealthyPercentage"), "If you specify spec.refreshPreferences.maxHealthyPercentage, you must also specify spec.refreshPreferences.minHealthyPercentage")) + } + + if r.Spec.RefreshPreferences.MaxHealthyPercentage != nil && r.Spec.RefreshPreferences.MinHealthyPercentage != nil { + if *r.Spec.RefreshPreferences.MaxHealthyPercentage-*r.Spec.RefreshPreferences.MinHealthyPercentage > 100 { + allErrs = append(allErrs, field.Forbidden(field.NewPath("spec.refreshPreferences.maxHealthyPercentage"), "the difference between spec.refreshPreferences.maxHealthyPercentage and spec.refreshPreferences.minHealthyPercentage cannot be greater than 100")) + } + } + + return allErrs +} + // ValidateCreate will do any extra validation when creating a AWSMachinePool. func (r *AWSMachinePool) ValidateCreate() (admission.Warnings, error) { log.Info("AWSMachinePool validate create", "machine-pool", klog.KObj(r)) @@ -146,6 +167,7 @@ func (r *AWSMachinePool) ValidateCreate() (admission.Warnings, error) { allErrs = append(allErrs, r.validateAdditionalSecurityGroups()...) allErrs = append(allErrs, r.validateSpotInstances()...) allErrs = append(allErrs, r.validateIgnition()...) + allErrs = append(allErrs, r.validateRefreshPreferences()...) if len(allErrs) == 0 { return nil, nil @@ -167,6 +189,7 @@ func (r *AWSMachinePool) ValidateUpdate(_ runtime.Object) (admission.Warnings, e allErrs = append(allErrs, r.validateSubnets()...) allErrs = append(allErrs, r.validateAdditionalSecurityGroups()...) allErrs = append(allErrs, r.validateSpotInstances()...) + allErrs = append(allErrs, r.validateRefreshPreferences()...) if len(allErrs) == 0 { return nil, nil diff --git a/exp/api/v1beta2/awsmachinepool_webhook_test.go b/exp/api/v1beta2/awsmachinepool_webhook_test.go index 3f7f30a101..0f14ad1c0a 100644 --- a/exp/api/v1beta2/awsmachinepool_webhook_test.go +++ b/exp/api/v1beta2/awsmachinepool_webhook_test.go @@ -153,6 +153,27 @@ func TestAWSMachinePoolValidateCreate(t *testing.T) { }, wantErr: true, }, + { + name: "Should fail if MaxHealthyPercentage is set, but MinHealthyPercentage is not set", + pool: &AWSMachinePool{ + Spec: AWSMachinePoolSpec{ + RefreshPreferences: &RefreshPreferences{MaxHealthyPercentage: aws.Int64(100)}, + }, + }, + wantErr: true, + }, + { + name: "Should fail if the difference between MaxHealthyPercentage and MinHealthyPercentage is greater than 100", + pool: &AWSMachinePool{ + Spec: AWSMachinePoolSpec{ + RefreshPreferences: &RefreshPreferences{ + MaxHealthyPercentage: aws.Int64(150), + MinHealthyPercentage: aws.Int64(25), + }, + }, + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -287,6 +308,27 @@ func TestAWSMachinePoolValidateUpdate(t *testing.T) { }, wantErr: true, }, + { + name: "Should fail if MaxHealthyPercentage is set, but MinHealthyPercentage is not set", + new: &AWSMachinePool{ + Spec: AWSMachinePoolSpec{ + RefreshPreferences: &RefreshPreferences{MaxHealthyPercentage: aws.Int64(100)}, + }, + }, + wantErr: true, + }, + { + name: "Should fail if the difference between MaxHealthyPercentage and MinHealthyPercentage is greater than 100", + new: &AWSMachinePool{ + Spec: AWSMachinePoolSpec{ + RefreshPreferences: &RefreshPreferences{ + MaxHealthyPercentage: aws.Int64(150), + MinHealthyPercentage: aws.Int64(25), + }, + }, + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/exp/api/v1beta2/zz_generated.deepcopy.go b/exp/api/v1beta2/zz_generated.deepcopy.go index e4a9c0988c..eb43428077 100644 --- a/exp/api/v1beta2/zz_generated.deepcopy.go +++ b/exp/api/v1beta2/zz_generated.deepcopy.go @@ -279,7 +279,7 @@ func (in *AWSMachinePoolSpec) DeepCopyInto(out *AWSMachinePoolSpec) { if in.Ignition != nil { in, out := &in.Ignition, &out.Ignition *out = new(apiv1beta2.Ignition) - **out = **in + (*in).DeepCopyInto(*out) } } @@ -1066,6 +1066,11 @@ func (in *RefreshPreferences) DeepCopyInto(out *RefreshPreferences) { *out = new(int64) **out = **in } + if in.MaxHealthyPercentage != nil { + in, out := &in.MaxHealthyPercentage, &out.MaxHealthyPercentage + *out = new(int64) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefreshPreferences. diff --git a/pkg/cloud/services/autoscaling/autoscalinggroup.go b/pkg/cloud/services/autoscaling/autoscalinggroup.go index fc0e523bc6..c3cf215075 100644 --- a/pkg/cloud/services/autoscaling/autoscalinggroup.go +++ b/pkg/cloud/services/autoscaling/autoscalinggroup.go @@ -373,7 +373,7 @@ func (s *Service) CancelASGInstanceRefresh(scope *scope.MachinePoolScope) error // StartASGInstanceRefresh will start an ASG instance refresh. func (s *Service) StartASGInstanceRefresh(scope *scope.MachinePoolScope) error { strategy := ptr.To[string](autoscaling.RefreshStrategyRolling) - var minHealthyPercentage, instanceWarmup *int64 + var minHealthyPercentage, maxHealthyPercentage, instanceWarmup *int64 if scope.AWSMachinePool.Spec.RefreshPreferences != nil { if scope.AWSMachinePool.Spec.RefreshPreferences.Strategy != nil { strategy = scope.AWSMachinePool.Spec.RefreshPreferences.Strategy @@ -384,6 +384,9 @@ func (s *Service) StartASGInstanceRefresh(scope *scope.MachinePoolScope) error { if scope.AWSMachinePool.Spec.RefreshPreferences.MinHealthyPercentage != nil { minHealthyPercentage = scope.AWSMachinePool.Spec.RefreshPreferences.MinHealthyPercentage } + if scope.AWSMachinePool.Spec.RefreshPreferences.MaxHealthyPercentage != nil { + maxHealthyPercentage = scope.AWSMachinePool.Spec.RefreshPreferences.MaxHealthyPercentage + } } input := &autoscaling.StartInstanceRefreshInput{ @@ -392,6 +395,7 @@ func (s *Service) StartASGInstanceRefresh(scope *scope.MachinePoolScope) error { Preferences: &autoscaling.RefreshPreferences{ InstanceWarmup: instanceWarmup, MinHealthyPercentage: minHealthyPercentage, + MaxHealthyPercentage: maxHealthyPercentage, }, } diff --git a/pkg/cloud/services/autoscaling/autoscalinggroup_test.go b/pkg/cloud/services/autoscaling/autoscalinggroup_test.go index d64ed15c29..5a83aa8088 100644 --- a/pkg/cloud/services/autoscaling/autoscalinggroup_test.go +++ b/pkg/cloud/services/autoscaling/autoscalinggroup_test.go @@ -1207,6 +1207,7 @@ func TestServiceStartASGInstanceRefresh(t *testing.T) { Preferences: &autoscaling.RefreshPreferences{ InstanceWarmup: aws.Int64(100), MinHealthyPercentage: aws.Int64(80), + MaxHealthyPercentage: aws.Int64(100), }, })). Return(nil, awserrors.NewNotFound("not found")) @@ -1222,6 +1223,7 @@ func TestServiceStartASGInstanceRefresh(t *testing.T) { Preferences: &autoscaling.RefreshPreferences{ InstanceWarmup: aws.Int64(100), MinHealthyPercentage: aws.Int64(80), + MaxHealthyPercentage: aws.Int64(100), }, })). Return(&autoscaling.StartInstanceRefreshOutput{}, nil) @@ -1316,6 +1318,7 @@ func getMachinePoolScope(client client.Client, clusterScope *scope.ClusterScope) Strategy: aws.String("Rolling"), InstanceWarmup: aws.Int64(100), MinHealthyPercentage: aws.Int64(80), + MaxHealthyPercentage: aws.Int64(100), }, MixedInstancesPolicy: &expinfrav1.MixedInstancesPolicy{ InstancesDistribution: &expinfrav1.InstancesDistribution{