Skip to content

Commit 8846555

Browse files
Merge pull request #1455 from vr4manta/SPLAT-2615
SPLAT-2615: Added AWS dynamic dedicated host support
2 parents 4610a83 + f13d585 commit 8846555

89 files changed

Lines changed: 3922 additions & 1425 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ require (
1919
github.com/onsi/ginkgo/v2 v2.27.2
2020
github.com/onsi/gomega v1.38.2
2121
github.com/openshift-eng/openshift-tests-extension v0.0.0-20251105193959-75a0be5d9bd7
22-
github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368
22+
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3
2323
github.com/openshift/client-go v0.0.0-20251202151200-fb4471581cf8
2424
github.com/openshift/cluster-api-actuator-pkg/testutils v0.0.0-20250910145856-21d03d30056d
2525
github.com/openshift/cluster-control-plane-machine-set-operator v0.0.0-20251029084908-344babe6a957

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,8 @@ github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jD
449449
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
450450
github.com/openshift-eng/openshift-tests-extension v0.0.0-20251105193959-75a0be5d9bd7 h1:Z1swlS6b3Adm6RPhjqefs3DWnNFLDxRX+WC8GMXhja4=
451451
github.com/openshift-eng/openshift-tests-extension v0.0.0-20251105193959-75a0be5d9bd7/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
452-
github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368 h1:kSr3DOlq0NCrHd65HB2o/pBsks7AfRm+fkpf9RLUPoc=
453-
github.com/openshift/api v0.0.0-20260114133223-6ab113cb7368/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
452+
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3 h1:SZ8+jxtkMvpb4HDTjSAbaOyhFsw5PiWhjBog+XLY7jc=
453+
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
454454
github.com/openshift/client-go v0.0.0-20251202151200-fb4471581cf8 h1:97rgISdT4IOmXlmEUV5Wr6d8BzzjPclzAjCARLbSlT0=
455455
github.com/openshift/client-go v0.0.0-20251202151200-fb4471581cf8/go.mod h1:WVJnsrbSO1J8x8KceOmv1d5CpoN34Uzsaz1O4MIOKJI=
456456
github.com/openshift/cluster-api-actuator-pkg/testutils v0.0.0-20250910145856-21d03d30056d h1:+sqUThLi/lmgT5/scmmjnS6+RZFtbdxRAscNfCPyLPI=

install/0000_30_machine-api-operator_00_credentials-request.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ spec:
2121
statementEntries:
2222
- effect: Allow
2323
action:
24+
- ec2:AllocateHosts
2425
- ec2:CreateTags
2526
- ec2:DescribeAvailabilityZones
2627
- ec2:DescribeDhcpOptions
@@ -32,6 +33,7 @@ spec:
3233
- ec2:DescribeRegions
3334
- ec2:DescribeSubnets
3435
- ec2:DescribeVpcs
36+
- ec2:ReleaseHosts
3537
- ec2:RunInstances
3638
- ec2:TerminateInstances
3739
- elasticloadbalancing:DescribeLoadBalancers

install/0000_30_machine-api-operator_02_machine.CustomNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,16 @@ spec:
567567
serialized/deserialized from this field.
568568
type: object
569569
x-kubernetes-preserve-unknown-fields: true
570+
synchronizedAPI:
571+
description: |-
572+
synchronizedAPI holds the last stable value of authoritativeAPI.
573+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
574+
Valid values are "MachineAPI" and "ClusterAPI".
575+
When omitted, the resource has not yet been reconciled by the migration controller.
576+
enum:
577+
- MachineAPI
578+
- ClusterAPI
579+
type: string
570580
synchronizedGeneration:
571581
description: |-
572582
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

install/0000_30_machine-api-operator_02_machine.DevPreviewNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,16 @@ spec:
567567
serialized/deserialized from this field.
568568
type: object
569569
x-kubernetes-preserve-unknown-fields: true
570+
synchronizedAPI:
571+
description: |-
572+
synchronizedAPI holds the last stable value of authoritativeAPI.
573+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
574+
Valid values are "MachineAPI" and "ClusterAPI".
575+
When omitted, the resource has not yet been reconciled by the migration controller.
576+
enum:
577+
- MachineAPI
578+
- ClusterAPI
579+
type: string
570580
synchronizedGeneration:
571581
description: |-
572582
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

install/0000_30_machine-api-operator_02_machine.TechPreviewNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,16 @@ spec:
567567
serialized/deserialized from this field.
568568
type: object
569569
x-kubernetes-preserve-unknown-fields: true
570+
synchronizedAPI:
571+
description: |-
572+
synchronizedAPI holds the last stable value of authoritativeAPI.
573+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
574+
Valid values are "MachineAPI" and "ClusterAPI".
575+
When omitted, the resource has not yet been reconciled by the migration controller.
576+
enum:
577+
- MachineAPI
578+
- ClusterAPI
579+
type: string
570580
synchronizedGeneration:
571581
description: |-
572582
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

install/0000_30_machine-api-operator_03_machineset.CustomNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,16 @@ spec:
674674
description: replicas is the most recently observed number of replicas.
675675
format: int32
676676
type: integer
677+
synchronizedAPI:
678+
description: |-
679+
synchronizedAPI holds the last stable value of authoritativeAPI.
680+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
681+
Valid values are "MachineAPI" and "ClusterAPI".
682+
When omitted, the resource has not yet been reconciled by the migration controller.
683+
enum:
684+
- MachineAPI
685+
- ClusterAPI
686+
type: string
677687
synchronizedGeneration:
678688
description: |-
679689
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

install/0000_30_machine-api-operator_03_machineset.DevPreviewNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,16 @@ spec:
674674
description: replicas is the most recently observed number of replicas.
675675
format: int32
676676
type: integer
677+
synchronizedAPI:
678+
description: |-
679+
synchronizedAPI holds the last stable value of authoritativeAPI.
680+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
681+
Valid values are "MachineAPI" and "ClusterAPI".
682+
When omitted, the resource has not yet been reconciled by the migration controller.
683+
enum:
684+
- MachineAPI
685+
- ClusterAPI
686+
type: string
677687
synchronizedGeneration:
678688
description: |-
679689
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

install/0000_30_machine-api-operator_03_machineset.TechPreviewNoUpgrade.crd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,16 @@ spec:
674674
description: replicas is the most recently observed number of replicas.
675675
format: int32
676676
type: integer
677+
synchronizedAPI:
678+
description: |-
679+
synchronizedAPI holds the last stable value of authoritativeAPI.
680+
It is used to detect migration cancellation requests and to restore the resource to its previous state.
681+
Valid values are "MachineAPI" and "ClusterAPI".
682+
When omitted, the resource has not yet been reconciled by the migration controller.
683+
enum:
684+
- MachineAPI
685+
- ClusterAPI
686+
type: string
677687
synchronizedGeneration:
678688
description: |-
679689
synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with.

pkg/webhooks/machine_webhook.go

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -949,20 +949,15 @@ func processAWSPlacementTenancy(placement machinev1beta1.Placement) field.ErrorL
949949
switch *placement.Host.Affinity {
950950
case machinev1beta1.HostAffinityAnyAvailable:
951951
// DedicatedHost is optional. If it is set, make sure it follows conventions
952-
if placement.Host.DedicatedHost != nil && !awsDedicatedHostNamePattern.MatchString(placement.Host.DedicatedHost.ID) {
953-
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.id"), placement.Host.DedicatedHost.ID, "id must start with 'h-' followed by 8 or 17 lowercase hexadecimal characters (0-9 and a-f)"))
952+
if placement.Host.DedicatedHost != nil {
953+
errs = append(errs, validateDedicatedHost(placement.Host.DedicatedHost)...)
954954
}
955955
case machinev1beta1.HostAffinityDedicatedHost:
956956
// We need to make sure DedicatedHost is set with an ID
957957
if placement.Host.DedicatedHost == nil {
958958
errs = append(errs, field.Required(field.NewPath("spec.placement.host.dedicatedHost"), "dedicatedHost is required when hostAffinity is DedicatedHost, and optional otherwise"))
959959
} else {
960-
// If not set, return required error. If it does not match pattern, return pattern failure message.
961-
if placement.Host.DedicatedHost.ID == "" {
962-
errs = append(errs, field.Required(field.NewPath("spec.placement.host.dedicatedHost.id"), "id is required and must start with 'h-' followed by 8 or 17 lowercase hexadecimal characters (0-9 and a-f)"))
963-
} else if !awsDedicatedHostNamePattern.MatchString(placement.Host.DedicatedHost.ID) {
964-
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.id"), placement.Host.DedicatedHost.ID, "id must start with 'h-' followed by 8 or 17 lowercase hexadecimal characters (0-9 and a-f)"))
965-
}
960+
errs = append(errs, validateDedicatedHost(placement.Host.DedicatedHost)...)
966961
}
967962
default:
968963
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.affinity"), placement.Host.Affinity, "hostAffinity must be either AnyAvailable or DedicatedHost"))
@@ -983,6 +978,75 @@ func processAWSPlacementTenancy(placement machinev1beta1.Placement) field.ErrorL
983978
return errs
984979
}
985980

981+
// validateDedicatedHost validates that all fields in the DedicatedHost are configured correctly.
982+
func validateDedicatedHost(host *machinev1beta1.DedicatedHost) field.ErrorList {
983+
var errs field.ErrorList
984+
985+
// If host is nil, then nothing to validate
986+
if host == nil {
987+
return errs
988+
}
989+
990+
strategy := machinev1beta1.AllocationStrategyUserProvided
991+
if host.AllocationStrategy != nil {
992+
strategy = *host.AllocationStrategy
993+
}
994+
995+
switch strategy {
996+
// Empty string is for backward compatability in case an existing config exists with the allocation strategy not set.
997+
// Default is User Provided.
998+
case machinev1beta1.AllocationStrategyUserProvided, "":
999+
// User Provided requires the ID being set of the host to use
1000+
if host.ID == "" {
1001+
errs = append(errs, field.Required(field.NewPath("spec.placement.host.dedicatedHost.id"), "id is required when allocationStrategy is UserProvided and must start with 'h-' followed by 8 or 17 lowercase hexadecimal characters (0-9 and a-f)"))
1002+
} else if !awsDedicatedHostNamePattern.MatchString(host.ID) {
1003+
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.id"), host.ID, "id must start with 'h-' followed by 8 or 17 lowercase hexadecimal characters (0-9 and a-f)"))
1004+
}
1005+
1006+
// DynamicHostAllocation is not allowed if user provided
1007+
if host.DynamicHostAllocation != nil {
1008+
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.dynamicHostAllocation"), host.ID, "dynamicHostAllocation is only allowed when allocationStrategy is Dynamic"))
1009+
}
1010+
case machinev1beta1.AllocationStrategyDynamic:
1011+
// ID must not be set
1012+
if host.ID != "" {
1013+
errs = append(errs, field.Forbidden(field.NewPath("spec.placement.host.dedicatedHost.id"), "id is only allowed when allocationStrategy is Provided"))
1014+
}
1015+
1016+
// Validate DynamicHostAllocation if present
1017+
if host.DynamicHostAllocation != nil {
1018+
// MinProperties=1: At least one property must be set
1019+
// Currently only Tags exists, so if Tags is nil, the struct is empty
1020+
if host.DynamicHostAllocation.Tags == nil {
1021+
errs = append(errs, field.Required(field.NewPath("spec.placement.host.dedicatedHost.dynamicHostAllocation.tags"), "at least one property must be specified in dynamicHostAllocation"))
1022+
} else {
1023+
tags := *host.DynamicHostAllocation.Tags
1024+
1025+
// MinItems=1: At least 1 tag must be specified
1026+
if len(tags) < 1 {
1027+
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.dynamicHostAllocation.tags"), len(tags), "at least 1 tag must be specified"))
1028+
}
1029+
1030+
// MaxItems=50: Maximum 50 tags can be specified
1031+
if len(tags) > 50 {
1032+
errs = append(errs, field.Invalid(field.NewPath("spec.placement.host.dedicatedHost.dynamicHostAllocation.tags"), len(tags), "maximum 50 tags can be specified"))
1033+
}
1034+
}
1035+
}
1036+
default:
1037+
errs = append(
1038+
errs,
1039+
field.Invalid(
1040+
field.NewPath("spec.placement.host.dedicatedHost.allocationStrategy"),
1041+
host.AllocationStrategy,
1042+
fmt.Sprintf("Invalid allocationStrategy, the only allowed options are: %s, %s", machinev1beta1.AllocationStrategyUserProvided, machinev1beta1.AllocationStrategyDynamic),
1043+
),
1044+
)
1045+
}
1046+
1047+
return errs
1048+
}
1049+
9861050
// getDuplicatedTags iterates through the AWS TagSpecifications
9871051
// to determine if any tag Name is duplicated within the list.
9881052
// A list of duplicated names will be returned.

0 commit comments

Comments
 (0)