Skip to content

Commit

Permalink
add subnetName support to ammp
Browse files Browse the repository at this point in the history
  • Loading branch information
LochanRn committed Feb 5, 2023
1 parent 83cf7f6 commit 8b84f4d
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 1 deletion.
1 change: 1 addition & 0 deletions api/v1alpha3/azuremanagedmachinepool_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
if restored.Spec.KubeletConfig != nil {
dst.Spec.KubeletConfig = restored.Spec.KubeletConfig
}
dst.Spec.SubnetName = restored.Spec.SubnetName

dst.Status.LongRunningOperationStates = restored.Status.LongRunningOperationStates
dst.Status.Conditions = restored.Status.Conditions
Expand Down
1 change: 1 addition & 0 deletions 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 api/v1alpha4/azuremanagedmachinepool_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (src *AzureManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
if restored.Spec.KubeletConfig != nil {
dst.Spec.KubeletConfig = restored.Spec.KubeletConfig
}
dst.Spec.SubnetName = restored.Spec.SubnetName

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

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

3 changes: 3 additions & 0 deletions api/v1beta1/azuremanagedmachinepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ type AzureManagedMachinePoolSpec struct {
// +kubebuilder:validation:Enum=OS;Temporary
// +optional
KubeletDiskType *KubeletDiskType `json:"kubeletDiskType,omitempty"`
// SubnetName specifies the Subnet where the MachinePool will be placed
// +optional
SubnetName string `json:"subnetName,omitempty"`
}

// ManagedMachinePoolScaling specifies scaling options.
Expand Down
19 changes: 19 additions & 0 deletions api/v1beta1/azuremanagedmachinepool_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func (m *AzureManagedMachinePool) ValidateCreate(client client.Client) error {
m.validateNodePublicIPPrefixID,
m.validateEnableNodePublicIP,
m.validateKubeletConfig,
m.validateSubnetName,
}

var errs []error
Expand Down Expand Up @@ -131,6 +132,13 @@ func (m *AzureManagedMachinePool) ValidateUpdate(oldRaw runtime.Object, client c
allErrs = append(allErrs, err)
}

if err := webhookutils.ValidateImmutable(
field.NewPath("Spec", "SubnetName"),
old.Spec.SubnetName,
m.Spec.SubnetName); err != nil {
allErrs = append(allErrs, err)
}

// custom headers are immutable
oldCustomHeaders := maps.FilterByKeyPrefix(old.ObjectMeta.Annotations, CustomHeaderPrefix)
newCustomHeaders := maps.FilterByKeyPrefix(m.ObjectMeta.Annotations, CustomHeaderPrefix)
Expand Down Expand Up @@ -343,6 +351,17 @@ func (m *AzureManagedMachinePool) validateEnableNodePublicIP() error {
return nil
}

func (m *AzureManagedMachinePool) validateSubnetName() error {
if m.Spec.SubnetName != "" {
subnetRegex := `^[-\w\._]+$`
if success, _ := regexp.Match(subnetRegex, []byte(m.Spec.SubnetName)); !success {
return field.Invalid(field.NewPath("Spec", "SubnetName"), m.Spec.SubnetName,
fmt.Sprintf("name of subnet doesn't match regex %s", subnetRegex))
}
}
return nil
}

// validateKubeletConfig enforces the AKS API configuration for KubeletConfig.
// See: https://learn.microsoft.com/en-us/azure/aks/custom-node-configuration.
func (m *AzureManagedMachinePool) validateKubeletConfig() error {
Expand Down
47 changes: 47 additions & 0 deletions api/v1beta1/azuremanagedmachinepool_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,34 @@ func TestAzureManagedMachinePoolUpdatingWebhook(t *testing.T) {
},
wantErr: true,
},
{
name: "Can't update SubnetName with error",
new: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "my-subnet",
},
},
old: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "",
},
},
wantErr: true,
},
{
name: "Can't update SubnetName without error",
new: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "my-subnet",
},
},
old: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "my-subnet",
},
},
wantErr: false,
},
}
var client client.Client
for _, tc := range tests {
Expand Down Expand Up @@ -572,6 +600,25 @@ func TestAzureManagedMachinePool_ValidateCreate(t *testing.T) {
wantErr: true,
errorLen: 1,
},
{
name: "invalid subnetname",
ammp: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "1+subnet",
},
},
wantErr: true,
errorLen: 1,
},
{
name: "valid subnetname",
ammp: &AzureManagedMachinePool{
Spec: AzureManagedMachinePoolSpec{
SubnetName: "my-subnet",
},
},
wantErr: false,
},
{
name: "too few MaxPods",
ammp: &AzureManagedMachinePool{
Expand Down
7 changes: 6 additions & 1 deletion azure/scope/managedmachinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ func buildAgentPoolSpec(managedControlPlane *infrav1.AzureManagedControlPlane,
replicas = *machinePool.Spec.Replicas
}

subnetName := managedControlPlane.Spec.VirtualNetwork.Subnet.Name
if managedMachinePool.Spec.SubnetName != "" {
subnetName = managedMachinePool.Spec.SubnetName
}

agentPoolSpec := &agentpools.AgentPoolSpec{
Name: to.String(managedMachinePool.Spec.Name),
ResourceGroup: managedControlPlane.Spec.ResourceGroupName,
Expand All @@ -166,7 +171,7 @@ func buildAgentPoolSpec(managedControlPlane *infrav1.AzureManagedControlPlane,
managedControlPlane.Spec.SubscriptionID,
managedControlPlane.Spec.VirtualNetwork.ResourceGroup,
managedControlPlane.Spec.VirtualNetwork.Name,
managedControlPlane.Spec.VirtualNetwork.Subnet.Name,
subnetName,
),
Mode: managedMachinePool.Spec.Mode,
MaxPods: managedMachinePool.Spec.MaxPods,
Expand Down
147 changes: 147 additions & 0 deletions azure/scope/managedmachinepool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,147 @@ func TestManagedMachinePoolScope_OSDiskType(t *testing.T) {
}
}

func TestManagedMachinePoolScope_SubnetName(t *testing.T) {
scheme := runtime.NewScheme()
_ = expv1.AddToScheme(scheme)
_ = infrav1.AddToScheme(scheme)

cases := []struct {
Name string
Input ManagedMachinePoolScopeParams
Expected azure.ResourceSpecGetter
}{
{
Name: "Without Vnet and SubnetName",
Input: ManagedMachinePoolScopeParams{
Cluster: &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
},
ControlPlane: &infrav1.AzureManagedControlPlane{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
Spec: infrav1.AzureManagedControlPlaneSpec{
SubscriptionID: "00000000-0000-0000-0000-000000000000",
},
},
ManagedMachinePool: ManagedMachinePool{
MachinePool: getMachinePool("pool0"),
InfraMachinePool: getAzureMachinePool("pool0", infrav1.NodePoolModeSystem),
},
},
Expected: &agentpools.AgentPoolSpec{
Name: "pool0",
SKU: "Standard_D2s_v3",
Replicas: 1,
Mode: "System",
Cluster: "cluster1",
VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/",
Headers: map[string]string{},
},
},
{
Name: "With Vnet and Without SubnetName",
Input: ManagedMachinePoolScopeParams{
Cluster: &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
},
ControlPlane: &infrav1.AzureManagedControlPlane{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
Spec: infrav1.AzureManagedControlPlaneSpec{
SubscriptionID: "00000000-0000-0000-0000-000000000000",
VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
Name: "my-vnet",
Subnet: infrav1.ManagedControlPlaneSubnet{
Name: "my-vnet-subnet",
},
ResourceGroup: "my-resource-group",
},
},
},
ManagedMachinePool: ManagedMachinePool{
MachinePool: getMachinePool("pool1"),
InfraMachinePool: getAzureMachinePool("pool1", infrav1.NodePoolModeUser),
},
},
Expected: &agentpools.AgentPoolSpec{
Name: "pool1",
SKU: "Standard_D2s_v3",
Mode: "User",
Cluster: "cluster1",
Replicas: 1,
VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/my-vnet-subnet",
Headers: map[string]string{},
},
},
{
Name: "With Vnet and With SubnetName",
Input: ManagedMachinePoolScopeParams{
Cluster: &clusterv1.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
},
ControlPlane: &infrav1.AzureManagedControlPlane{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1",
Namespace: "default",
},
Spec: infrav1.AzureManagedControlPlaneSpec{
SubscriptionID: "00000000-0000-0000-0000-000000000000",
VirtualNetwork: infrav1.ManagedControlPlaneVirtualNetwork{
Name: "my-vnet",
Subnet: infrav1.ManagedControlPlaneSubnet{
Name: "my-vnet-subnet",
},
ResourceGroup: "my-resource-group",
},
},
},
ManagedMachinePool: ManagedMachinePool{
MachinePool: getMachinePool("pool1"),
InfraMachinePool: getAzureMachinePoolWithSubnetName("pool1", "my-subnet"),
},
},
Expected: &agentpools.AgentPoolSpec{
Name: "pool1",
SKU: "Standard_D2s_v3",
Mode: "User",
Cluster: "cluster1",
Replicas: 1,
VnetSubnetID: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/my-subnet",
Headers: map[string]string{},
},
},
}

for _, c := range cases {
c := c
t.Run(c.Name, func(t *testing.T) {
g := NewWithT(t)
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(c.Input.MachinePool, c.Input.InfraMachinePool, c.Input.ControlPlane).Build()
c.Input.Client = fakeClient
s, err := NewManagedMachinePoolScope(context.TODO(), c.Input)
g.Expect(err).To(Succeed())
agentPool := s.AgentPoolSpec()
if !reflect.DeepEqual(c.Expected, agentPool) {
t.Errorf("Got difference between expected result and result:\n%s", cmp.Diff(c.Expected, agentPool))
}
})
}
}

func TestManagedMachinePoolScope_KubeletDiskType(t *testing.T) {
scheme := runtime.NewScheme()
_ = expv1.AddToScheme(scheme)
Expand Down Expand Up @@ -763,6 +904,12 @@ func getAzureMachinePoolWithTaints(name string, taints infrav1.Taints) *infrav1.
return managedPool
}

func getAzureMachinePoolWithSubnetName(name, subnetName string) *infrav1.AzureManagedMachinePool {
managedPool := getAzureMachinePool(name, infrav1.NodePoolModeUser)
managedPool.Spec.SubnetName = subnetName
return managedPool
}

func getAzureMachinePoolWithOsDiskType(name string, osDiskType string) *infrav1.AzureManagedMachinePool {
managedPool := getAzureMachinePool(name, infrav1.NodePoolModeUser)
managedPool.Spec.OsDiskType = to.StringPtr(osDiskType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ spec:
sku:
description: SKU is the size of the VMs in the node pool.
type: string
subnetName:
description: SubnetName specifies the Subnet where the MachinePool
will be placed
type: string
taints:
description: Taints specifies the taints for nodes present in this
agent pool.
Expand Down

0 comments on commit 8b84f4d

Please sign in to comment.