Skip to content

Commit

Permalink
Merge pull request #2664 from nojnhuh/aks-public-ip-prefix
Browse files Browse the repository at this point in the history
Add nodePublicIPPrefixID to AzureManagedMachinePool
  • Loading branch information
k8s-ci-robot authored Oct 14, 2022
2 parents 94b3d74 + fa0ec4c commit 3529056
Show file tree
Hide file tree
Showing 15 changed files with 340 additions and 66 deletions.
41 changes: 21 additions & 20 deletions azure/converters/managedagentpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ import (
func AgentPoolToManagedClusterAgentPoolProfile(pool containerservice.AgentPool) containerservice.ManagedClusterAgentPoolProfile {
properties := pool.ManagedClusterAgentPoolProfileProperties
return containerservice.ManagedClusterAgentPoolProfile{
Name: pool.Name, // Note: if converting from agentPoolSpec.Parameters(), this field will not be set
VMSize: properties.VMSize,
OsType: properties.OsType,
OsDiskSizeGB: properties.OsDiskSizeGB,
Count: properties.Count,
Type: properties.Type,
OrchestratorVersion: properties.OrchestratorVersion,
VnetSubnetID: properties.VnetSubnetID,
Mode: properties.Mode,
EnableAutoScaling: properties.EnableAutoScaling,
MaxCount: properties.MaxCount,
MinCount: properties.MinCount,
NodeTaints: properties.NodeTaints,
AvailabilityZones: properties.AvailabilityZones,
MaxPods: properties.MaxPods,
OsDiskType: properties.OsDiskType,
NodeLabels: properties.NodeLabels,
EnableUltraSSD: properties.EnableUltraSSD,
EnableNodePublicIP: properties.EnableNodePublicIP,
ScaleSetPriority: properties.ScaleSetPriority,
Name: pool.Name, // Note: if converting from agentPoolSpec.Parameters(), this field will not be set
VMSize: properties.VMSize,
OsType: properties.OsType,
OsDiskSizeGB: properties.OsDiskSizeGB,
Count: properties.Count,
Type: properties.Type,
OrchestratorVersion: properties.OrchestratorVersion,
VnetSubnetID: properties.VnetSubnetID,
Mode: properties.Mode,
EnableAutoScaling: properties.EnableAutoScaling,
MaxCount: properties.MaxCount,
MinCount: properties.MinCount,
NodeTaints: properties.NodeTaints,
AvailabilityZones: properties.AvailabilityZones,
MaxPods: properties.MaxPods,
OsDiskType: properties.OsDiskType,
NodeLabels: properties.NodeLabels,
EnableUltraSSD: properties.EnableUltraSSD,
EnableNodePublicIP: properties.EnableNodePublicIP,
NodePublicIPPrefixID: properties.NodePublicIPPrefixID,
ScaleSetPriority: properties.ScaleSetPriority,
}
}
17 changes: 9 additions & 8 deletions azure/scope/managedmachinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,15 @@ func buildAgentPoolSpec(managedControlPlane *infrav1exp.AzureManagedControlPlane
managedControlPlane.Spec.VirtualNetwork.Name,
managedControlPlane.Spec.VirtualNetwork.Subnet.Name,
),
Mode: managedMachinePool.Spec.Mode,
MaxPods: managedMachinePool.Spec.MaxPods,
AvailabilityZones: managedMachinePool.Spec.AvailabilityZones,
OsDiskType: managedMachinePool.Spec.OsDiskType,
EnableUltraSSD: managedMachinePool.Spec.EnableUltraSSD,
Headers: maps.FilterByKeyPrefix(agentPoolAnnotations, azure.CustomHeaderPrefix),
EnableNodePublicIP: managedMachinePool.Spec.EnableNodePublicIP,
ScaleSetPriority: managedMachinePool.Spec.ScaleSetPriority,
Mode: managedMachinePool.Spec.Mode,
MaxPods: managedMachinePool.Spec.MaxPods,
AvailabilityZones: managedMachinePool.Spec.AvailabilityZones,
OsDiskType: managedMachinePool.Spec.OsDiskType,
EnableUltraSSD: managedMachinePool.Spec.EnableUltraSSD,
Headers: maps.FilterByKeyPrefix(agentPoolAnnotations, azure.CustomHeaderPrefix),
EnableNodePublicIP: managedMachinePool.Spec.EnableNodePublicIP,
NodePublicIPPrefixID: managedMachinePool.Spec.NodePublicIPPrefixID,
ScaleSetPriority: managedMachinePool.Spec.ScaleSetPriority,
}

if managedMachinePool.Spec.OSDiskSizeGB != nil {
Expand Down
42 changes: 23 additions & 19 deletions azure/services/agentpools/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ type AgentPoolSpec struct {
// EnableNodePublicIP controls whether or not nodes in the agent pool each have a public IP address.
EnableNodePublicIP *bool `json:"enableNodePublicIP,omitempty"`

// NodePublicIPPrefixID specifies the public IP prefix resource ID which VM nodes should use IPs from.
NodePublicIPPrefixID *string `json:"nodePublicIPPrefixID,omitempty"`

// ScaleSetPriority specifies the ScaleSetPriority for the node pool. Allowed values are 'Spot' and 'Regular'
ScaleSetPriority *string `json:"scaleSetPriority,omitempty"`
}
Expand Down Expand Up @@ -205,25 +208,26 @@ func (s *AgentPoolSpec) Parameters(existing interface{}) (params interface{}, er

return containerservice.AgentPool{
ManagedClusterAgentPoolProfileProperties: &containerservice.ManagedClusterAgentPoolProfileProperties{
AvailabilityZones: availabilityZones,
Count: replicas,
EnableAutoScaling: s.EnableAutoScaling,
EnableUltraSSD: s.EnableUltraSSD,
MaxCount: s.MaxCount,
MaxPods: s.MaxPods,
MinCount: s.MinCount,
Mode: containerservice.AgentPoolMode(s.Mode),
NodeLabels: nodeLabels,
NodeTaints: nodeTaints,
OrchestratorVersion: s.Version,
OsDiskSizeGB: &s.OSDiskSizeGB,
OsDiskType: containerservice.OSDiskType(to.String(s.OsDiskType)),
OsType: containerservice.OSType(to.String(s.OSType)),
ScaleSetPriority: containerservice.ScaleSetPriority(to.String(s.ScaleSetPriority)),
Type: containerservice.AgentPoolTypeVirtualMachineScaleSets,
VMSize: sku,
VnetSubnetID: vnetSubnetID,
EnableNodePublicIP: s.EnableNodePublicIP,
AvailabilityZones: availabilityZones,
Count: replicas,
EnableAutoScaling: s.EnableAutoScaling,
EnableUltraSSD: s.EnableUltraSSD,
MaxCount: s.MaxCount,
MaxPods: s.MaxPods,
MinCount: s.MinCount,
Mode: containerservice.AgentPoolMode(s.Mode),
NodeLabels: nodeLabels,
NodeTaints: nodeTaints,
OrchestratorVersion: s.Version,
OsDiskSizeGB: &s.OSDiskSizeGB,
OsDiskType: containerservice.OSDiskType(to.String(s.OsDiskType)),
OsType: containerservice.OSType(to.String(s.OSType)),
ScaleSetPriority: containerservice.ScaleSetPriority(to.String(s.ScaleSetPriority)),
Type: containerservice.AgentPoolTypeVirtualMachineScaleSets,
VMSize: sku,
VnetSubnetID: vnetSubnetID,
EnableNodePublicIP: s.EnableNodePublicIP,
NodePublicIPPrefixID: s.NodePublicIPPrefixID,
},
}, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ spec:
description: Node labels - labels for all of the nodes present in
node pool
type: object
nodePublicIPPrefixID:
description: NodePublicIPPrefixID specifies the public IP prefix resource
ID which VM nodes should use IPs from.
type: string
osDiskSizeGB:
description: OSDiskSizeGB is the disk size for every machine in this
agent pool. If you specify 0, it will apply the default osDisk size
Expand Down
2 changes: 2 additions & 0 deletions docs/book/src/topics/managedcluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ Following is the list of immutable fields for managed clusters:
| AzureManagedMachinePool | .spec.availabilityZones | |
| AzureManagedMachinePool | .spec.maxPods | |
| AzureManagedMachinePool | .spec.osType | |
| AzureManagedMachinePool | .spec.enableNodePublicIP | |
| AzureManagedMachinePool | .spec.nodePublicIPPrefixID | |
## Features
Expand Down
1 change: 1 addition & 0 deletions exp/api/v1alpha3/azuremanagedmachinepool_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.NodeLabels = restored.Spec.NodeLabels
dst.Spec.EnableUltraSSD = restored.Spec.EnableUltraSSD
dst.Spec.EnableNodePublicIP = restored.Spec.EnableNodePublicIP
dst.Spec.NodePublicIPPrefixID = restored.Spec.NodePublicIPPrefixID
dst.Spec.ScaleSetPriority = restored.Spec.ScaleSetPriority

dst.Status.LongRunningOperationStates = restored.Status.LongRunningOperationStates
Expand Down
1 change: 1 addition & 0 deletions exp/api/v1alpha3/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions exp/api/v1alpha4/azuremanagedmachinepool_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.NodeLabels = restored.Spec.NodeLabels
dst.Spec.EnableUltraSSD = restored.Spec.EnableUltraSSD
dst.Spec.EnableNodePublicIP = restored.Spec.EnableNodePublicIP
dst.Spec.NodePublicIPPrefixID = restored.Spec.NodePublicIPPrefixID
dst.Spec.ScaleSetPriority = restored.Spec.ScaleSetPriority

dst.Status.LongRunningOperationStates = restored.Status.LongRunningOperationStates
Expand Down
1 change: 1 addition & 0 deletions exp/api/v1alpha4/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions exp/api/v1beta1/azuremanagedmachinepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ type AzureManagedMachinePoolSpec struct {
// +optional
EnableNodePublicIP *bool `json:"enableNodePublicIP,omitempty"`

// NodePublicIPPrefixID specifies the public IP prefix resource ID which VM nodes should use IPs from.
// +optional
NodePublicIPPrefixID *string `json:"nodePublicIPPrefixID,omitempty"`

// ScaleSetPriority specifies the ScaleSetPriority value. Default to Regular. Possible values include: 'Regular', 'Spot'
// +kubebuilder:validation:Enum=Regular;Spot
// +optional
Expand Down
72 changes: 55 additions & 17 deletions exp/api/v1beta1/azuremanagedmachinepool_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"reflect"
"regexp"

"github.com/Azure/go-autorest/autorest/to"
"github.com/pkg/errors"
Expand All @@ -34,6 +35,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

var validNodePublicPrefixID = regexp.MustCompile(`(?i)^/?subscriptions/[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}/resourcegroups/[^/]+/providers/microsoft\.network/publicipprefixes/[^/]+$`)

//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-azuremanagedmachinepool,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=azuremanagedmachinepools,verbs=create;update,versions=v1beta1,name=default.azuremanagedmachinepools.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1

// Default implements webhook.Defaulter so a webhook will be registered for the type.
Expand Down Expand Up @@ -61,6 +64,8 @@ func (m *AzureManagedMachinePool) ValidateCreate(client client.Client) error {
m.validateOSType,
m.validateName,
m.validateNodeLabels,
m.validateNodePublicIPPrefixID,
m.validateEnableNodePublicIP,
}

var errs []error
Expand All @@ -86,23 +91,11 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c
err.Error()))
}

if old.Spec.OSType != nil {
// Prevent OSType modification if it was already set to some value
if m.Spec.OSType == nil {
// unsetting the field is not allowed
allErrs = append(allErrs,
field.Invalid(
field.NewPath("Spec", "OSType"),
m.Spec.OSType,
"field is immutable, unsetting is not allowed"))
} else if *m.Spec.OSType != *old.Spec.OSType {
// changing the field is not allowed
allErrs = append(allErrs,
field.Invalid(
field.NewPath("Spec", "OSType"),
*m.Spec.OSType,
"field is immutable"))
}
if err := validateStringPtrImmutable(
field.NewPath("Spec", "OSType"),
old.Spec.OSType,
m.Spec.OSType); err != nil {
allErrs = append(allErrs, err)
}

if m.Spec.SKU != old.Spec.SKU {
Expand Down Expand Up @@ -217,6 +210,12 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c
m.Spec.EnableNodePublicIP); err != nil {
allErrs = append(allErrs, err)
}
if err := validateStringPtrImmutable(
field.NewPath("Spec", "NodePublicIPPrefixID"),
old.Spec.NodePublicIPPrefixID,
m.Spec.NodePublicIPPrefixID); err != nil {
allErrs = append(allErrs, err)
}

if len(allErrs) != 0 {
return apierrors.NewInvalid(GroupVersion.WithKind("AzureManagedMachinePool").GroupKind(), m.Name, allErrs)
Expand Down Expand Up @@ -327,6 +326,27 @@ func (m *AzureManagedMachinePool) validateNodeLabels() error {
return nil
}

func (m *AzureManagedMachinePool) validateNodePublicIPPrefixID() error {
if m.Spec.NodePublicIPPrefixID != nil && !validNodePublicPrefixID.MatchString(*m.Spec.NodePublicIPPrefixID) {
return field.Invalid(
field.NewPath("Spec", "NodePublicIPPrefixID"),
m.Spec.NodePublicIPPrefixID,
fmt.Sprintf("resource ID must match %q", validNodePublicPrefixID.String()))
}
return nil
}

func (m *AzureManagedMachinePool) validateEnableNodePublicIP() error {
if (m.Spec.EnableNodePublicIP == nil || !*m.Spec.EnableNodePublicIP) &&
m.Spec.NodePublicIPPrefixID != nil {
return field.Invalid(
field.NewPath("Spec", "EnableNodePublicIP"),
m.Spec.EnableNodePublicIP,
"must be set to true when NodePublicIPPrefixID is set")
}
return nil
}

func ensureStringSlicesAreEqual(a []string, b []string) bool {
if len(a) != len(b) {
return false
Expand Down Expand Up @@ -362,3 +382,21 @@ func validateBoolPtrImmutable(path *field.Path, oldVal, newVal *bool) *field.Err

return nil
}

func validateStringPtrImmutable(path *field.Path, oldVal, newVal *string) *field.Error {
if oldVal != nil {
// Prevent modification if it was already set to some value
if newVal == nil {
// unsetting the field is not allowed
return field.Invalid(path, newVal, "field is immutable, unsetting is not allowed")
}
if *newVal != *oldVal {
// changing the field is not allowed
return field.Invalid(path, newVal, "field is immutable")
}
} else if newVal != nil {
return field.Invalid(path, newVal, "field is immutable, setting is not allowed")
}

return nil
}
Loading

0 comments on commit 3529056

Please sign in to comment.