sigs.k8s.io/cluster-api-provider-azure@v1.14.3/api/v1beta1/azureclustertemplate_default_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"testing"
    23  
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/utils/ptr"
    26  )
    27  
    28  func TestVnetTemplateDefaults(t *testing.T) {
    29  	cases := []struct {
    30  		name            string
    31  		clusterTemplate *AzureClusterTemplate
    32  		outputTemplate  *AzureClusterTemplate
    33  	}{
    34  		{
    35  			name: "vnet not specified",
    36  			clusterTemplate: &AzureClusterTemplate{
    37  				ObjectMeta: metav1.ObjectMeta{
    38  					Name: "test-cluster-template",
    39  				},
    40  				Spec: AzureClusterTemplateSpec{
    41  					Template: AzureClusterTemplateResource{},
    42  				},
    43  			},
    44  			outputTemplate: &AzureClusterTemplate{
    45  				ObjectMeta: metav1.ObjectMeta{
    46  					Name: "test-cluster-template",
    47  				},
    48  				Spec: AzureClusterTemplateSpec{
    49  					Template: AzureClusterTemplateResource{
    50  						Spec: AzureClusterTemplateResourceSpec{
    51  							NetworkSpec: NetworkTemplateSpec{
    52  								Vnet: VnetTemplateSpec{
    53  									VnetClassSpec: VnetClassSpec{
    54  										CIDRBlocks: []string{DefaultVnetCIDR},
    55  									},
    56  								},
    57  							},
    58  						},
    59  					},
    60  				},
    61  			},
    62  		},
    63  		{
    64  			name: "custom CIDR",
    65  			clusterTemplate: &AzureClusterTemplate{
    66  				ObjectMeta: metav1.ObjectMeta{
    67  					Name: "test-cluster-template",
    68  				},
    69  				Spec: AzureClusterTemplateSpec{
    70  					Template: AzureClusterTemplateResource{
    71  						Spec: AzureClusterTemplateResourceSpec{
    72  							NetworkSpec: NetworkTemplateSpec{
    73  								Vnet: VnetTemplateSpec{
    74  									VnetClassSpec: VnetClassSpec{
    75  										CIDRBlocks: []string{"10.0.0.0/16"},
    76  									},
    77  								},
    78  							},
    79  						},
    80  					},
    81  				},
    82  			},
    83  			outputTemplate: &AzureClusterTemplate{
    84  				ObjectMeta: metav1.ObjectMeta{
    85  					Name: "test-cluster-template",
    86  				},
    87  				Spec: AzureClusterTemplateSpec{
    88  					Template: AzureClusterTemplateResource{
    89  						Spec: AzureClusterTemplateResourceSpec{
    90  							NetworkSpec: NetworkTemplateSpec{
    91  								Vnet: VnetTemplateSpec{
    92  									VnetClassSpec: VnetClassSpec{
    93  										CIDRBlocks: []string{"10.0.0.0/16"},
    94  									},
    95  								},
    96  							},
    97  						},
    98  					},
    99  				},
   100  			},
   101  		},
   102  		{
   103  			name: "IPv6 enabled",
   104  			clusterTemplate: &AzureClusterTemplate{
   105  				ObjectMeta: metav1.ObjectMeta{
   106  					Name: "test-cluster-template",
   107  				},
   108  				Spec: AzureClusterTemplateSpec{
   109  					Template: AzureClusterTemplateResource{
   110  						Spec: AzureClusterTemplateResourceSpec{
   111  							NetworkSpec: NetworkTemplateSpec{
   112  								Vnet: VnetTemplateSpec{
   113  									VnetClassSpec: VnetClassSpec{
   114  										CIDRBlocks: []string{"2001:1234:5678:9a00::/56"},
   115  									},
   116  								},
   117  							},
   118  						},
   119  					},
   120  				},
   121  			},
   122  			outputTemplate: &AzureClusterTemplate{
   123  				ObjectMeta: metav1.ObjectMeta{
   124  					Name: "test-cluster-template",
   125  				},
   126  				Spec: AzureClusterTemplateSpec{
   127  					Template: AzureClusterTemplateResource{
   128  						Spec: AzureClusterTemplateResourceSpec{
   129  							NetworkSpec: NetworkTemplateSpec{
   130  								Vnet: VnetTemplateSpec{
   131  									VnetClassSpec: VnetClassSpec{
   132  										CIDRBlocks: []string{"2001:1234:5678:9a00::/56"},
   133  									},
   134  								},
   135  							},
   136  						},
   137  					},
   138  				},
   139  			},
   140  		},
   141  	}
   142  
   143  	for _, c := range cases {
   144  		tc := c
   145  		t.Run(tc.name, func(t *testing.T) {
   146  			t.Parallel()
   147  			tc.clusterTemplate.setVnetTemplateDefaults()
   148  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
   149  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
   150  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
   151  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
   152  			}
   153  		})
   154  	}
   155  }
   156  
   157  func TestSubnetsTemplateDefaults(t *testing.T) {
   158  	cases := []struct {
   159  		name            string
   160  		clusterTemplate *AzureClusterTemplate
   161  		outputTemplate  *AzureClusterTemplate
   162  	}{
   163  		{
   164  			name: "no subnets",
   165  			clusterTemplate: &AzureClusterTemplate{
   166  				ObjectMeta: metav1.ObjectMeta{
   167  					Name: "test-cluster-template",
   168  				},
   169  				Spec: AzureClusterTemplateSpec{
   170  					Template: AzureClusterTemplateResource{
   171  						Spec: AzureClusterTemplateResourceSpec{
   172  							NetworkSpec: NetworkTemplateSpec{},
   173  						},
   174  					},
   175  				},
   176  			},
   177  			outputTemplate: &AzureClusterTemplate{
   178  				ObjectMeta: metav1.ObjectMeta{
   179  					Name: "test-cluster-template",
   180  				},
   181  				Spec: AzureClusterTemplateSpec{
   182  					Template: AzureClusterTemplateResource{
   183  						Spec: AzureClusterTemplateResourceSpec{
   184  							NetworkSpec: NetworkTemplateSpec{
   185  								Subnets: SubnetTemplatesSpec{
   186  									{
   187  										SubnetClassSpec: SubnetClassSpec{
   188  											Role:       SubnetControlPlane,
   189  											CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR},
   190  										},
   191  									},
   192  									{
   193  										SubnetClassSpec: SubnetClassSpec{
   194  											Role:       SubnetNode,
   195  											CIDRBlocks: []string{DefaultNodeSubnetCIDR},
   196  										},
   197  									},
   198  								},
   199  							},
   200  						},
   201  					},
   202  				},
   203  			},
   204  		},
   205  		{
   206  			name: "subnet with custom attributes",
   207  			clusterTemplate: &AzureClusterTemplate{
   208  				ObjectMeta: metav1.ObjectMeta{
   209  					Name: "test-cluster-template",
   210  				},
   211  				Spec: AzureClusterTemplateSpec{
   212  					Template: AzureClusterTemplateResource{
   213  						Spec: AzureClusterTemplateResourceSpec{
   214  							NetworkSpec: NetworkTemplateSpec{
   215  								Subnets: SubnetTemplatesSpec{
   216  									{
   217  										SubnetClassSpec: SubnetClassSpec{
   218  											Role:       SubnetControlPlane,
   219  											CIDRBlocks: []string{"10.0.0.16/24"},
   220  										},
   221  									},
   222  									{
   223  										SubnetClassSpec: SubnetClassSpec{
   224  											Role:       SubnetNode,
   225  											CIDRBlocks: []string{"10.1.0.16/24"},
   226  										},
   227  										NatGateway: NatGatewayClassSpec{
   228  											Name: "foo-natgw",
   229  										},
   230  									},
   231  								},
   232  							},
   233  						},
   234  					},
   235  				},
   236  			},
   237  			outputTemplate: &AzureClusterTemplate{
   238  				ObjectMeta: metav1.ObjectMeta{
   239  					Name: "test-cluster-template",
   240  				},
   241  				Spec: AzureClusterTemplateSpec{
   242  					Template: AzureClusterTemplateResource{
   243  						Spec: AzureClusterTemplateResourceSpec{
   244  							NetworkSpec: NetworkTemplateSpec{
   245  								Subnets: SubnetTemplatesSpec{
   246  									{
   247  										SubnetClassSpec: SubnetClassSpec{
   248  											Role:       SubnetControlPlane,
   249  											CIDRBlocks: []string{"10.0.0.16/24"},
   250  										},
   251  									},
   252  									{
   253  										SubnetClassSpec: SubnetClassSpec{
   254  											Role:       SubnetNode,
   255  											CIDRBlocks: []string{"10.1.0.16/24"},
   256  										},
   257  										NatGateway: NatGatewayClassSpec{Name: "foo-natgw"},
   258  									},
   259  								},
   260  							},
   261  						},
   262  					},
   263  				},
   264  			},
   265  		},
   266  		{
   267  			name: "subnet with custom attributes and security groups",
   268  			clusterTemplate: &AzureClusterTemplate{
   269  				ObjectMeta: metav1.ObjectMeta{
   270  					Name: "test-cluster-template",
   271  				},
   272  				Spec: AzureClusterTemplateSpec{
   273  					Template: AzureClusterTemplateResource{
   274  						Spec: AzureClusterTemplateResourceSpec{
   275  							NetworkSpec: NetworkTemplateSpec{
   276  								Subnets: SubnetTemplatesSpec{
   277  									{
   278  										SubnetClassSpec: SubnetClassSpec{
   279  											Role:       SubnetControlPlane,
   280  											CIDRBlocks: []string{"10.0.0.16/24"},
   281  										},
   282  										SecurityGroup: SecurityGroupClass{
   283  											SecurityRules: []SecurityRule{
   284  												{
   285  													Name:             "allow_port_50000",
   286  													Description:      "allow port 50000",
   287  													Protocol:         "*",
   288  													Priority:         2202,
   289  													SourcePorts:      ptr.To("*"),
   290  													DestinationPorts: ptr.To("*"),
   291  													Source:           ptr.To("*"),
   292  													Destination:      ptr.To("*"),
   293  													Action:           SecurityRuleActionAllow,
   294  												},
   295  											},
   296  										},
   297  									},
   298  									{
   299  										SubnetClassSpec: SubnetClassSpec{
   300  											Role:       SubnetNode,
   301  											CIDRBlocks: []string{"10.1.0.16/24"},
   302  										},
   303  										NatGateway: NatGatewayClassSpec{
   304  											Name: "foo-natgw",
   305  										},
   306  										SecurityGroup: SecurityGroupClass{
   307  											SecurityRules: []SecurityRule{
   308  												{
   309  													Name:             "allow_port_50000",
   310  													Description:      "allow port 50000",
   311  													Protocol:         "*",
   312  													Priority:         2202,
   313  													SourcePorts:      ptr.To("*"),
   314  													DestinationPorts: ptr.To("*"),
   315  													Source:           ptr.To("*"),
   316  													Destination:      ptr.To("*"),
   317  													Action:           SecurityRuleActionAllow,
   318  												},
   319  											},
   320  										},
   321  									},
   322  								},
   323  							},
   324  						},
   325  					},
   326  				},
   327  			},
   328  			outputTemplate: &AzureClusterTemplate{
   329  				ObjectMeta: metav1.ObjectMeta{
   330  					Name: "test-cluster-template",
   331  				},
   332  				Spec: AzureClusterTemplateSpec{
   333  					Template: AzureClusterTemplateResource{
   334  						Spec: AzureClusterTemplateResourceSpec{
   335  							NetworkSpec: NetworkTemplateSpec{
   336  								Subnets: SubnetTemplatesSpec{
   337  									{
   338  										SubnetClassSpec: SubnetClassSpec{
   339  											Role:       SubnetControlPlane,
   340  											CIDRBlocks: []string{"10.0.0.16/24"},
   341  										},
   342  										SecurityGroup: SecurityGroupClass{
   343  											SecurityRules: SecurityRules{
   344  												{
   345  													Name:             "allow_port_50000",
   346  													Description:      "allow port 50000",
   347  													Protocol:         "*",
   348  													Priority:         2202,
   349  													SourcePorts:      ptr.To("*"),
   350  													DestinationPorts: ptr.To("*"),
   351  													Source:           ptr.To("*"),
   352  													Destination:      ptr.To("*"),
   353  													Direction:        SecurityRuleDirectionInbound,
   354  													Action:           SecurityRuleActionAllow,
   355  												},
   356  											},
   357  										},
   358  									},
   359  									{
   360  										SubnetClassSpec: SubnetClassSpec{
   361  											Role:       SubnetNode,
   362  											CIDRBlocks: []string{"10.1.0.16/24"},
   363  										},
   364  										NatGateway: NatGatewayClassSpec{Name: "foo-natgw"},
   365  										SecurityGroup: SecurityGroupClass{
   366  											SecurityRules: SecurityRules{
   367  												{
   368  													Name:             "allow_port_50000",
   369  													Description:      "allow port 50000",
   370  													Protocol:         "*",
   371  													Priority:         2202,
   372  													SourcePorts:      ptr.To("*"),
   373  													DestinationPorts: ptr.To("*"),
   374  													Source:           ptr.To("*"),
   375  													Destination:      ptr.To("*"),
   376  													Direction:        SecurityRuleDirectionInbound,
   377  													Action:           SecurityRuleActionAllow,
   378  												},
   379  											},
   380  										},
   381  									},
   382  								},
   383  							},
   384  						},
   385  					},
   386  				},
   387  			},
   388  		},
   389  		{
   390  			name: "subnets specified",
   391  			clusterTemplate: &AzureClusterTemplate{
   392  				ObjectMeta: metav1.ObjectMeta{
   393  					Name: "test-cluster-template",
   394  				},
   395  				Spec: AzureClusterTemplateSpec{
   396  					Template: AzureClusterTemplateResource{
   397  						Spec: AzureClusterTemplateResourceSpec{
   398  							NetworkSpec: NetworkTemplateSpec{
   399  								Subnets: SubnetTemplatesSpec{
   400  									{
   401  										SubnetClassSpec: SubnetClassSpec{
   402  											Role: SubnetControlPlane,
   403  										},
   404  									},
   405  									{
   406  										SubnetClassSpec: SubnetClassSpec{
   407  											Role: SubnetNode,
   408  										},
   409  									},
   410  								},
   411  							},
   412  						},
   413  					},
   414  				},
   415  			},
   416  			outputTemplate: &AzureClusterTemplate{
   417  				ObjectMeta: metav1.ObjectMeta{
   418  					Name: "test-cluster-template",
   419  				},
   420  				Spec: AzureClusterTemplateSpec{
   421  					Template: AzureClusterTemplateResource{
   422  						Spec: AzureClusterTemplateResourceSpec{
   423  							NetworkSpec: NetworkTemplateSpec{
   424  								Subnets: SubnetTemplatesSpec{
   425  									{
   426  										SubnetClassSpec: SubnetClassSpec{
   427  											Role:       SubnetControlPlane,
   428  											CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR},
   429  										},
   430  									},
   431  									{
   432  										SubnetClassSpec: SubnetClassSpec{
   433  											Role:       SubnetNode,
   434  											CIDRBlocks: []string{DefaultNodeSubnetCIDR},
   435  										},
   436  									},
   437  								},
   438  							},
   439  						},
   440  					},
   441  				},
   442  			},
   443  		},
   444  		{
   445  			name: "cluster subnet with custom attributes",
   446  			clusterTemplate: &AzureClusterTemplate{
   447  				ObjectMeta: metav1.ObjectMeta{
   448  					Name: "test-cluster-template",
   449  				},
   450  				Spec: AzureClusterTemplateSpec{
   451  					Template: AzureClusterTemplateResource{
   452  						Spec: AzureClusterTemplateResourceSpec{
   453  							NetworkSpec: NetworkTemplateSpec{
   454  								Subnets: SubnetTemplatesSpec{
   455  									{
   456  										SubnetClassSpec: SubnetClassSpec{
   457  											Role:       SubnetCluster,
   458  											CIDRBlocks: []string{"10.1.0.16/24"},
   459  										},
   460  										NatGateway: NatGatewayClassSpec{
   461  											Name: "foo-natgw",
   462  										},
   463  									},
   464  								},
   465  							},
   466  						},
   467  					},
   468  				},
   469  			},
   470  			outputTemplate: &AzureClusterTemplate{
   471  				ObjectMeta: metav1.ObjectMeta{
   472  					Name: "test-cluster-template",
   473  				},
   474  				Spec: AzureClusterTemplateSpec{
   475  					Template: AzureClusterTemplateResource{
   476  						Spec: AzureClusterTemplateResourceSpec{
   477  							NetworkSpec: NetworkTemplateSpec{
   478  								Subnets: SubnetTemplatesSpec{
   479  									{
   480  										SubnetClassSpec: SubnetClassSpec{
   481  											Role:       SubnetCluster,
   482  											CIDRBlocks: []string{"10.1.0.16/24"},
   483  										},
   484  										NatGateway: NatGatewayClassSpec{Name: "foo-natgw"},
   485  									},
   486  								},
   487  							},
   488  						},
   489  					},
   490  				},
   491  			},
   492  		},
   493  		{
   494  			name: "subnets specified",
   495  			clusterTemplate: &AzureClusterTemplate{
   496  				ObjectMeta: metav1.ObjectMeta{
   497  					Name: "test-cluster-template",
   498  				},
   499  				Spec: AzureClusterTemplateSpec{
   500  					Template: AzureClusterTemplateResource{
   501  						Spec: AzureClusterTemplateResourceSpec{
   502  							NetworkSpec: NetworkTemplateSpec{
   503  								Subnets: SubnetTemplatesSpec{
   504  									{
   505  										SubnetClassSpec: SubnetClassSpec{
   506  											Role: SubnetCluster,
   507  										},
   508  									},
   509  								},
   510  							},
   511  						},
   512  					},
   513  				},
   514  			},
   515  			outputTemplate: &AzureClusterTemplate{
   516  				ObjectMeta: metav1.ObjectMeta{
   517  					Name: "test-cluster-template",
   518  				},
   519  				Spec: AzureClusterTemplateSpec{
   520  					Template: AzureClusterTemplateResource{
   521  						Spec: AzureClusterTemplateResourceSpec{
   522  							NetworkSpec: NetworkTemplateSpec{
   523  								Subnets: SubnetTemplatesSpec{
   524  									{
   525  										SubnetClassSpec: SubnetClassSpec{
   526  											Role:       SubnetCluster,
   527  											CIDRBlocks: []string{DefaultClusterSubnetCIDR},
   528  										},
   529  									},
   530  								},
   531  							},
   532  						},
   533  					},
   534  				},
   535  			},
   536  		},
   537  		{
   538  			name: "only node subnet specified",
   539  			clusterTemplate: &AzureClusterTemplate{
   540  				ObjectMeta: metav1.ObjectMeta{
   541  					Name: "test-cluster-template",
   542  				},
   543  				Spec: AzureClusterTemplateSpec{
   544  					Template: AzureClusterTemplateResource{
   545  						Spec: AzureClusterTemplateResourceSpec{
   546  							NetworkSpec: NetworkTemplateSpec{
   547  								Subnets: SubnetTemplatesSpec{
   548  									{
   549  										SubnetClassSpec: SubnetClassSpec{
   550  											Role: SubnetNode,
   551  										},
   552  									},
   553  								},
   554  							},
   555  						},
   556  					},
   557  				},
   558  			},
   559  			outputTemplate: &AzureClusterTemplate{
   560  				ObjectMeta: metav1.ObjectMeta{
   561  					Name: "test-cluster-template",
   562  				},
   563  				Spec: AzureClusterTemplateSpec{
   564  					Template: AzureClusterTemplateResource{
   565  						Spec: AzureClusterTemplateResourceSpec{
   566  							NetworkSpec: NetworkTemplateSpec{
   567  								Subnets: SubnetTemplatesSpec{
   568  									{
   569  										SubnetClassSpec: SubnetClassSpec{
   570  											Role:       SubnetNode,
   571  											CIDRBlocks: []string{DefaultNodeSubnetCIDR},
   572  										},
   573  									},
   574  									{
   575  										SubnetClassSpec: SubnetClassSpec{
   576  											Role:       SubnetControlPlane,
   577  											CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR},
   578  										},
   579  									},
   580  								},
   581  							},
   582  						},
   583  					},
   584  				},
   585  			},
   586  		},
   587  		{
   588  			name: "subnets specified with IPv6 enabled",
   589  			clusterTemplate: &AzureClusterTemplate{
   590  				ObjectMeta: metav1.ObjectMeta{
   591  					Name: "test-cluster-template",
   592  				},
   593  				Spec: AzureClusterTemplateSpec{
   594  					Template: AzureClusterTemplateResource{
   595  						Spec: AzureClusterTemplateResourceSpec{
   596  							NetworkSpec: NetworkTemplateSpec{
   597  								Subnets: SubnetTemplatesSpec{
   598  									{
   599  										SubnetClassSpec: SubnetClassSpec{
   600  											Role:       SubnetControlPlane,
   601  											CIDRBlocks: []string{"2001:beef::1/64"},
   602  										},
   603  									},
   604  									{
   605  										SubnetClassSpec: SubnetClassSpec{
   606  											Role:       SubnetNode,
   607  											CIDRBlocks: []string{"2001:beea::1/64"},
   608  										},
   609  									},
   610  								},
   611  							},
   612  						},
   613  					},
   614  				},
   615  			},
   616  			outputTemplate: &AzureClusterTemplate{
   617  				ObjectMeta: metav1.ObjectMeta{
   618  					Name: "test-cluster-template",
   619  				},
   620  				Spec: AzureClusterTemplateSpec{
   621  					Template: AzureClusterTemplateResource{
   622  						Spec: AzureClusterTemplateResourceSpec{
   623  							NetworkSpec: NetworkTemplateSpec{
   624  								Subnets: SubnetTemplatesSpec{
   625  									{
   626  										SubnetClassSpec: SubnetClassSpec{
   627  											Role:       SubnetControlPlane,
   628  											CIDRBlocks: []string{"2001:beef::1/64"},
   629  										},
   630  									},
   631  									{
   632  										SubnetClassSpec: SubnetClassSpec{
   633  											Role:       SubnetNode,
   634  											CIDRBlocks: []string{"2001:beea::1/64"},
   635  										},
   636  									},
   637  								},
   638  							},
   639  						},
   640  					},
   641  				},
   642  			},
   643  		},
   644  	}
   645  
   646  	for _, c := range cases {
   647  		tc := c
   648  		t.Run(tc.name, func(t *testing.T) {
   649  			t.Parallel()
   650  			tc.clusterTemplate.setSubnetsTemplateDefaults()
   651  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
   652  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
   653  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
   654  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
   655  			}
   656  		})
   657  	}
   658  }
   659  
   660  func TestAPIServerLBClassDefaults(t *testing.T) {
   661  	cases := []struct {
   662  		name            string
   663  		clusterTemplate *AzureClusterTemplate
   664  		outputTemplate  *AzureClusterTemplate
   665  	}{
   666  		{
   667  			name: "no lb",
   668  			clusterTemplate: &AzureClusterTemplate{
   669  				ObjectMeta: metav1.ObjectMeta{
   670  					Name: "test-cluster-template",
   671  				},
   672  				Spec: AzureClusterTemplateSpec{
   673  					Template: AzureClusterTemplateResource{
   674  						Spec: AzureClusterTemplateResourceSpec{
   675  							NetworkSpec: NetworkTemplateSpec{},
   676  						},
   677  					},
   678  				},
   679  			},
   680  			outputTemplate: &AzureClusterTemplate{
   681  				ObjectMeta: metav1.ObjectMeta{
   682  					Name: "test-cluster-template",
   683  				},
   684  				Spec: AzureClusterTemplateSpec{
   685  					Template: AzureClusterTemplateResource{
   686  						Spec: AzureClusterTemplateResourceSpec{
   687  							NetworkSpec: NetworkTemplateSpec{
   688  								APIServerLB: LoadBalancerClassSpec{
   689  									SKU:                  SKUStandard,
   690  									Type:                 Public,
   691  									IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes),
   692  								},
   693  							},
   694  						},
   695  					},
   696  				},
   697  			},
   698  		},
   699  		{
   700  			name: "internal lb",
   701  			clusterTemplate: &AzureClusterTemplate{
   702  				ObjectMeta: metav1.ObjectMeta{
   703  					Name: "test-cluster-template",
   704  				},
   705  				Spec: AzureClusterTemplateSpec{
   706  					Template: AzureClusterTemplateResource{
   707  						Spec: AzureClusterTemplateResourceSpec{
   708  							NetworkSpec: NetworkTemplateSpec{
   709  								APIServerLB: LoadBalancerClassSpec{
   710  									Type: Internal,
   711  								},
   712  							},
   713  						},
   714  					},
   715  				},
   716  			},
   717  			outputTemplate: &AzureClusterTemplate{
   718  				ObjectMeta: metav1.ObjectMeta{
   719  					Name: "test-cluster-template",
   720  				},
   721  				Spec: AzureClusterTemplateSpec{
   722  					Template: AzureClusterTemplateResource{
   723  						Spec: AzureClusterTemplateResourceSpec{
   724  							NetworkSpec: NetworkTemplateSpec{
   725  								APIServerLB: LoadBalancerClassSpec{
   726  									SKU:                  SKUStandard,
   727  									Type:                 Internal,
   728  									IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes),
   729  								},
   730  							},
   731  						},
   732  					},
   733  				},
   734  			},
   735  		},
   736  	}
   737  
   738  	for _, c := range cases {
   739  		tc := c
   740  		t.Run(tc.name, func(t *testing.T) {
   741  			t.Parallel()
   742  			tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.APIServerLB.setAPIServerLBDefaults()
   743  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
   744  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
   745  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
   746  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
   747  			}
   748  		})
   749  	}
   750  }
   751  
   752  func TestNodeOutboundLBClassDefaults(t *testing.T) {
   753  	cases := []struct {
   754  		name            string
   755  		clusterTemplate *AzureClusterTemplate
   756  		outputTemplate  *AzureClusterTemplate
   757  	}{
   758  		{
   759  			name: "default no lb for public clusters",
   760  			clusterTemplate: &AzureClusterTemplate{
   761  				ObjectMeta: metav1.ObjectMeta{
   762  					Name: "test-cluster-template",
   763  				},
   764  				Spec: AzureClusterTemplateSpec{
   765  					Template: AzureClusterTemplateResource{
   766  						Spec: AzureClusterTemplateResourceSpec{
   767  							NetworkSpec: NetworkTemplateSpec{
   768  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   769  								Subnets: SubnetTemplatesSpec{
   770  									{
   771  										SubnetClassSpec: SubnetClassSpec{
   772  											Role: SubnetControlPlane,
   773  										},
   774  									},
   775  									{
   776  										SubnetClassSpec: SubnetClassSpec{
   777  											Role: SubnetNode,
   778  										},
   779  									},
   780  								},
   781  							},
   782  						},
   783  					},
   784  				},
   785  			},
   786  			outputTemplate: &AzureClusterTemplate{
   787  				ObjectMeta: metav1.ObjectMeta{
   788  					Name: "test-cluster-template",
   789  				},
   790  				Spec: AzureClusterTemplateSpec{
   791  					Template: AzureClusterTemplateResource{
   792  						Spec: AzureClusterTemplateResourceSpec{
   793  							NetworkSpec: NetworkTemplateSpec{
   794  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   795  								Subnets: SubnetTemplatesSpec{
   796  									{
   797  										SubnetClassSpec: SubnetClassSpec{
   798  											Role: SubnetControlPlane,
   799  										},
   800  									},
   801  									{
   802  										SubnetClassSpec: SubnetClassSpec{
   803  											Role: SubnetNode,
   804  										},
   805  									},
   806  								},
   807  							},
   808  						},
   809  					},
   810  				},
   811  			},
   812  		},
   813  		{
   814  			name: "default lb when IPv6 enabled",
   815  			clusterTemplate: &AzureClusterTemplate{
   816  				ObjectMeta: metav1.ObjectMeta{
   817  					Name: "test-cluster-template",
   818  				},
   819  				Spec: AzureClusterTemplateSpec{
   820  					Template: AzureClusterTemplateResource{
   821  						Spec: AzureClusterTemplateResourceSpec{
   822  							NetworkSpec: NetworkTemplateSpec{
   823  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   824  								Subnets: SubnetTemplatesSpec{
   825  									{
   826  										SubnetClassSpec: SubnetClassSpec{
   827  											Role: SubnetControlPlane,
   828  										},
   829  									},
   830  									{
   831  										SubnetClassSpec: SubnetClassSpec{
   832  											Role:       SubnetNode,
   833  											CIDRBlocks: []string{"2001:beea::1/64"},
   834  										},
   835  									},
   836  								},
   837  							},
   838  						},
   839  					},
   840  				},
   841  			},
   842  			outputTemplate: &AzureClusterTemplate{
   843  				ObjectMeta: metav1.ObjectMeta{
   844  					Name: "test-cluster-template",
   845  				},
   846  				Spec: AzureClusterTemplateSpec{
   847  					Template: AzureClusterTemplateResource{
   848  						Spec: AzureClusterTemplateResourceSpec{
   849  							NetworkSpec: NetworkTemplateSpec{
   850  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   851  								Subnets: SubnetTemplatesSpec{
   852  									{
   853  										SubnetClassSpec: SubnetClassSpec{
   854  											Role: SubnetControlPlane,
   855  										},
   856  									},
   857  									{
   858  										SubnetClassSpec: SubnetClassSpec{
   859  											Role:       SubnetNode,
   860  											CIDRBlocks: []string{"2001:beea::1/64"},
   861  										},
   862  									},
   863  								},
   864  								NodeOutboundLB: &LoadBalancerClassSpec{
   865  									SKU:                  SKUStandard,
   866  									Type:                 Public,
   867  									IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes),
   868  								},
   869  							},
   870  						},
   871  					},
   872  				},
   873  			},
   874  		},
   875  		{
   876  			name: "IPv6 enabled on 1 of 2 node subnets",
   877  			clusterTemplate: &AzureClusterTemplate{
   878  				ObjectMeta: metav1.ObjectMeta{
   879  					Name: "test-cluster-template",
   880  				},
   881  				Spec: AzureClusterTemplateSpec{
   882  					Template: AzureClusterTemplateResource{
   883  						Spec: AzureClusterTemplateResourceSpec{
   884  							NetworkSpec: NetworkTemplateSpec{
   885  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   886  								Subnets: SubnetTemplatesSpec{
   887  									{
   888  										SubnetClassSpec: SubnetClassSpec{
   889  											Role: SubnetControlPlane,
   890  										},
   891  									},
   892  									{
   893  										SubnetClassSpec: SubnetClassSpec{
   894  											Role:       SubnetNode,
   895  											CIDRBlocks: []string{"2001:beea::1/64"},
   896  										},
   897  									},
   898  									{
   899  										SubnetClassSpec: SubnetClassSpec{
   900  											Role: SubnetNode,
   901  										},
   902  									},
   903  								},
   904  							},
   905  						},
   906  					},
   907  				},
   908  			},
   909  			outputTemplate: &AzureClusterTemplate{
   910  				ObjectMeta: metav1.ObjectMeta{
   911  					Name: "test-cluster-template",
   912  				},
   913  				Spec: AzureClusterTemplateSpec{
   914  					Template: AzureClusterTemplateResource{
   915  						Spec: AzureClusterTemplateResourceSpec{
   916  							NetworkSpec: NetworkTemplateSpec{
   917  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   918  								Subnets: SubnetTemplatesSpec{
   919  									{
   920  										SubnetClassSpec: SubnetClassSpec{
   921  											Role: SubnetControlPlane,
   922  										},
   923  									},
   924  									{
   925  										SubnetClassSpec: SubnetClassSpec{
   926  											Role:       SubnetNode,
   927  											CIDRBlocks: []string{"2001:beea::1/64"},
   928  										},
   929  									},
   930  									{
   931  										SubnetClassSpec: SubnetClassSpec{
   932  											Role: SubnetNode,
   933  										},
   934  									},
   935  								},
   936  								NodeOutboundLB: &LoadBalancerClassSpec{
   937  									SKU:                  SKUStandard,
   938  									Type:                 Public,
   939  									IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes),
   940  								},
   941  							},
   942  						},
   943  					},
   944  				},
   945  			},
   946  		},
   947  		{
   948  			name: "multiple subnets specified with IPv6 enabled",
   949  			clusterTemplate: &AzureClusterTemplate{
   950  				ObjectMeta: metav1.ObjectMeta{
   951  					Name: "test-cluster-template",
   952  				},
   953  				Spec: AzureClusterTemplateSpec{
   954  					Template: AzureClusterTemplateResource{
   955  						Spec: AzureClusterTemplateResourceSpec{
   956  							NetworkSpec: NetworkTemplateSpec{
   957  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   958  								Subnets: SubnetTemplatesSpec{
   959  									{
   960  										SubnetClassSpec: SubnetClassSpec{
   961  											Role: SubnetControlPlane,
   962  										},
   963  									},
   964  									{
   965  										SubnetClassSpec: SubnetClassSpec{
   966  											Role:       SubnetNode,
   967  											CIDRBlocks: []string{"2001:beea::1/64"},
   968  										},
   969  									},
   970  									{
   971  										SubnetClassSpec: SubnetClassSpec{
   972  											Role:       SubnetNode,
   973  											CIDRBlocks: []string{"2002:beeb::1/64"},
   974  										},
   975  									},
   976  								},
   977  							},
   978  						},
   979  					},
   980  				},
   981  			},
   982  			outputTemplate: &AzureClusterTemplate{
   983  				ObjectMeta: metav1.ObjectMeta{
   984  					Name: "test-cluster-template",
   985  				},
   986  				Spec: AzureClusterTemplateSpec{
   987  					Template: AzureClusterTemplateResource{
   988  						Spec: AzureClusterTemplateResourceSpec{
   989  							NetworkSpec: NetworkTemplateSpec{
   990  								APIServerLB: LoadBalancerClassSpec{Type: Public},
   991  								Subnets: SubnetTemplatesSpec{
   992  									{
   993  										SubnetClassSpec: SubnetClassSpec{
   994  											Role: SubnetControlPlane,
   995  										},
   996  									},
   997  									{
   998  										SubnetClassSpec: SubnetClassSpec{
   999  											Role:       SubnetNode,
  1000  											CIDRBlocks: []string{"2001:beea::1/64"},
  1001  										},
  1002  									},
  1003  									{
  1004  										SubnetClassSpec: SubnetClassSpec{
  1005  											Role:       SubnetNode,
  1006  											CIDRBlocks: []string{"2002:beeb::1/64"},
  1007  										},
  1008  									},
  1009  								},
  1010  								NodeOutboundLB: &LoadBalancerClassSpec{
  1011  									SKU:                  SKUStandard,
  1012  									Type:                 Public,
  1013  									IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes),
  1014  								},
  1015  							},
  1016  						},
  1017  					},
  1018  				},
  1019  			},
  1020  		},
  1021  		{
  1022  			name: "multiple node subnets, Ipv6 not enabled in any of them",
  1023  			clusterTemplate: &AzureClusterTemplate{
  1024  				ObjectMeta: metav1.ObjectMeta{
  1025  					Name: "test-cluster-template",
  1026  				},
  1027  				Spec: AzureClusterTemplateSpec{
  1028  					Template: AzureClusterTemplateResource{
  1029  						Spec: AzureClusterTemplateResourceSpec{
  1030  							NetworkSpec: NetworkTemplateSpec{
  1031  								APIServerLB: LoadBalancerClassSpec{Type: Public},
  1032  								Subnets: SubnetTemplatesSpec{
  1033  									{
  1034  										SubnetClassSpec: SubnetClassSpec{
  1035  											Role: SubnetControlPlane,
  1036  										},
  1037  									},
  1038  									{
  1039  										SubnetClassSpec: SubnetClassSpec{
  1040  											Role: SubnetNode,
  1041  										},
  1042  									},
  1043  									{
  1044  										SubnetClassSpec: SubnetClassSpec{
  1045  											Role: SubnetNode,
  1046  										},
  1047  									},
  1048  								},
  1049  							},
  1050  						},
  1051  					},
  1052  				},
  1053  			},
  1054  			outputTemplate: &AzureClusterTemplate{
  1055  				ObjectMeta: metav1.ObjectMeta{
  1056  					Name: "test-cluster-template",
  1057  				},
  1058  				Spec: AzureClusterTemplateSpec{
  1059  					Template: AzureClusterTemplateResource{
  1060  						Spec: AzureClusterTemplateResourceSpec{
  1061  							NetworkSpec: NetworkTemplateSpec{
  1062  								APIServerLB: LoadBalancerClassSpec{Type: Public},
  1063  								Subnets: SubnetTemplatesSpec{
  1064  									{
  1065  										SubnetClassSpec: SubnetClassSpec{
  1066  											Role: SubnetControlPlane,
  1067  										},
  1068  									},
  1069  									{
  1070  										SubnetClassSpec: SubnetClassSpec{
  1071  											Role: SubnetNode,
  1072  										},
  1073  									},
  1074  									{
  1075  										SubnetClassSpec: SubnetClassSpec{
  1076  											Role: SubnetNode,
  1077  										},
  1078  									},
  1079  								},
  1080  							},
  1081  						},
  1082  					},
  1083  				},
  1084  			},
  1085  		},
  1086  		{
  1087  			name: "no LB for private clusters",
  1088  			clusterTemplate: &AzureClusterTemplate{
  1089  				ObjectMeta: metav1.ObjectMeta{
  1090  					Name: "test-cluster-template",
  1091  				},
  1092  				Spec: AzureClusterTemplateSpec{
  1093  					Template: AzureClusterTemplateResource{
  1094  						Spec: AzureClusterTemplateResourceSpec{
  1095  							NetworkSpec: NetworkTemplateSpec{
  1096  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1097  							},
  1098  						},
  1099  					},
  1100  				},
  1101  			},
  1102  			outputTemplate: &AzureClusterTemplate{
  1103  				ObjectMeta: metav1.ObjectMeta{
  1104  					Name: "test-cluster-template",
  1105  				},
  1106  				Spec: AzureClusterTemplateSpec{
  1107  					Template: AzureClusterTemplateResource{
  1108  						Spec: AzureClusterTemplateResourceSpec{
  1109  							NetworkSpec: NetworkTemplateSpec{
  1110  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1111  							},
  1112  						},
  1113  					},
  1114  				},
  1115  			},
  1116  		},
  1117  		{
  1118  			name: "NodeOutboundLB declared as input with non-default IdleTimeoutInMinutes",
  1119  			clusterTemplate: &AzureClusterTemplate{
  1120  				ObjectMeta: metav1.ObjectMeta{
  1121  					Name: "test-cluster-template",
  1122  				},
  1123  				Spec: AzureClusterTemplateSpec{
  1124  					Template: AzureClusterTemplateResource{
  1125  						Spec: AzureClusterTemplateResourceSpec{
  1126  							NetworkSpec: NetworkTemplateSpec{
  1127  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1128  								NodeOutboundLB: &LoadBalancerClassSpec{
  1129  									IdleTimeoutInMinutes: ptr.To[int32](15),
  1130  								},
  1131  							},
  1132  						},
  1133  					},
  1134  				},
  1135  			},
  1136  			outputTemplate: &AzureClusterTemplate{
  1137  				ObjectMeta: metav1.ObjectMeta{
  1138  					Name: "test-cluster-template",
  1139  				},
  1140  				Spec: AzureClusterTemplateSpec{
  1141  					Template: AzureClusterTemplateResource{
  1142  						Spec: AzureClusterTemplateResourceSpec{
  1143  							NetworkSpec: NetworkTemplateSpec{
  1144  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1145  								NodeOutboundLB: &LoadBalancerClassSpec{
  1146  									IdleTimeoutInMinutes: ptr.To[int32](15),
  1147  									SKU:                  SKUStandard,
  1148  									Type:                 Public,
  1149  								},
  1150  							},
  1151  						},
  1152  					},
  1153  				},
  1154  			},
  1155  		},
  1156  	}
  1157  
  1158  	for _, c := range cases {
  1159  		tc := c
  1160  		t.Run(tc.name, func(t *testing.T) {
  1161  			t.Parallel()
  1162  			tc.clusterTemplate.setNodeOutboundLBDefaults()
  1163  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
  1164  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
  1165  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
  1166  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
  1167  			}
  1168  		})
  1169  	}
  1170  }
  1171  
  1172  func TestControlPlaneOutboundLBTemplateDefaults(t *testing.T) {
  1173  	cases := []struct {
  1174  		name            string
  1175  		clusterTemplate *AzureClusterTemplate
  1176  		outputTemplate  *AzureClusterTemplate
  1177  	}{
  1178  		{
  1179  			name: "no cp lb for public clusters",
  1180  			clusterTemplate: &AzureClusterTemplate{
  1181  				ObjectMeta: metav1.ObjectMeta{
  1182  					Name: "test-cluster-template",
  1183  				},
  1184  				Spec: AzureClusterTemplateSpec{
  1185  					Template: AzureClusterTemplateResource{
  1186  						Spec: AzureClusterTemplateResourceSpec{
  1187  							NetworkSpec: NetworkTemplateSpec{
  1188  								APIServerLB: LoadBalancerClassSpec{Type: Public},
  1189  							},
  1190  						},
  1191  					},
  1192  				},
  1193  			},
  1194  			outputTemplate: &AzureClusterTemplate{
  1195  				ObjectMeta: metav1.ObjectMeta{
  1196  					Name: "test-cluster-template",
  1197  				},
  1198  				Spec: AzureClusterTemplateSpec{
  1199  					Template: AzureClusterTemplateResource{
  1200  						Spec: AzureClusterTemplateResourceSpec{
  1201  							NetworkSpec: NetworkTemplateSpec{
  1202  								APIServerLB: LoadBalancerClassSpec{Type: Public},
  1203  							},
  1204  						},
  1205  					},
  1206  				},
  1207  			},
  1208  		},
  1209  		{
  1210  			name: "no cp lb for private clusters",
  1211  			clusterTemplate: &AzureClusterTemplate{
  1212  				ObjectMeta: metav1.ObjectMeta{
  1213  					Name: "test-cluster-template",
  1214  				},
  1215  				Spec: AzureClusterTemplateSpec{
  1216  					Template: AzureClusterTemplateResource{
  1217  						Spec: AzureClusterTemplateResourceSpec{
  1218  							NetworkSpec: NetworkTemplateSpec{
  1219  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1220  							},
  1221  						},
  1222  					},
  1223  				},
  1224  			},
  1225  			outputTemplate: &AzureClusterTemplate{
  1226  				ObjectMeta: metav1.ObjectMeta{
  1227  					Name: "test-cluster-template",
  1228  				},
  1229  				Spec: AzureClusterTemplateSpec{
  1230  					Template: AzureClusterTemplateResource{
  1231  						Spec: AzureClusterTemplateResourceSpec{
  1232  							NetworkSpec: NetworkTemplateSpec{
  1233  								APIServerLB: LoadBalancerClassSpec{Type: Internal},
  1234  							},
  1235  						},
  1236  					},
  1237  				},
  1238  			},
  1239  		},
  1240  	}
  1241  
  1242  	for _, c := range cases {
  1243  		tc := c
  1244  		t.Run(tc.name, func(t *testing.T) {
  1245  			t.Parallel()
  1246  			setControlPlaneOutboundLBDefaults(
  1247  				tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.ControlPlaneOutboundLB,
  1248  				tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.APIServerLB.Type,
  1249  			)
  1250  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
  1251  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
  1252  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
  1253  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
  1254  			}
  1255  		})
  1256  	}
  1257  }
  1258  
  1259  func TestBastionTemplateDefaults(t *testing.T) {
  1260  	cases := []struct {
  1261  		name            string
  1262  		clusterTemplate *AzureClusterTemplate
  1263  		outputTemplate  *AzureClusterTemplate
  1264  	}{
  1265  		{
  1266  			name: "no bastion set",
  1267  			clusterTemplate: &AzureClusterTemplate{
  1268  				ObjectMeta: metav1.ObjectMeta{
  1269  					Name: "test-cluster-template",
  1270  				},
  1271  				Spec: AzureClusterTemplateSpec{
  1272  					Template: AzureClusterTemplateResource{
  1273  						Spec: AzureClusterTemplateResourceSpec{},
  1274  					},
  1275  				},
  1276  			},
  1277  			outputTemplate: &AzureClusterTemplate{
  1278  				ObjectMeta: metav1.ObjectMeta{
  1279  					Name: "test-cluster-template",
  1280  				},
  1281  				Spec: AzureClusterTemplateSpec{
  1282  					Template: AzureClusterTemplateResource{
  1283  						Spec: AzureClusterTemplateResourceSpec{},
  1284  					},
  1285  				},
  1286  			},
  1287  		},
  1288  		{
  1289  			name: "azure bastion enabled with no settings",
  1290  			clusterTemplate: &AzureClusterTemplate{
  1291  				ObjectMeta: metav1.ObjectMeta{
  1292  					Name: "test-cluster-template",
  1293  				},
  1294  				Spec: AzureClusterTemplateSpec{
  1295  					Template: AzureClusterTemplateResource{
  1296  						Spec: AzureClusterTemplateResourceSpec{
  1297  							BastionSpec: BastionTemplateSpec{
  1298  								AzureBastion: &AzureBastionTemplateSpec{},
  1299  							},
  1300  						},
  1301  					},
  1302  				},
  1303  			},
  1304  			outputTemplate: &AzureClusterTemplate{
  1305  				ObjectMeta: metav1.ObjectMeta{
  1306  					Name: "test-cluster-template",
  1307  				},
  1308  				Spec: AzureClusterTemplateSpec{
  1309  					Template: AzureClusterTemplateResource{
  1310  						Spec: AzureClusterTemplateResourceSpec{
  1311  							BastionSpec: BastionTemplateSpec{
  1312  								AzureBastion: &AzureBastionTemplateSpec{
  1313  									Subnet: SubnetTemplateSpec{
  1314  										SubnetClassSpec: SubnetClassSpec{
  1315  											Role:       DefaultAzureBastionSubnetRole,
  1316  											CIDRBlocks: []string{DefaultAzureBastionSubnetCIDR},
  1317  										},
  1318  									},
  1319  								},
  1320  							},
  1321  						},
  1322  					},
  1323  				},
  1324  			},
  1325  		},
  1326  		{
  1327  			name: "azure bastion enabled with subnet partially set",
  1328  			clusterTemplate: &AzureClusterTemplate{
  1329  				ObjectMeta: metav1.ObjectMeta{
  1330  					Name: "test-cluster-template",
  1331  				},
  1332  				Spec: AzureClusterTemplateSpec{
  1333  					Template: AzureClusterTemplateResource{
  1334  						Spec: AzureClusterTemplateResourceSpec{
  1335  							BastionSpec: BastionTemplateSpec{
  1336  								AzureBastion: &AzureBastionTemplateSpec{
  1337  									Subnet: SubnetTemplateSpec{
  1338  										SubnetClassSpec: SubnetClassSpec{},
  1339  									},
  1340  								},
  1341  							},
  1342  						},
  1343  					},
  1344  				},
  1345  			},
  1346  			outputTemplate: &AzureClusterTemplate{
  1347  				ObjectMeta: metav1.ObjectMeta{
  1348  					Name: "test-cluster-template",
  1349  				},
  1350  				Spec: AzureClusterTemplateSpec{
  1351  					Template: AzureClusterTemplateResource{
  1352  						Spec: AzureClusterTemplateResourceSpec{
  1353  							BastionSpec: BastionTemplateSpec{
  1354  								AzureBastion: &AzureBastionTemplateSpec{
  1355  									Subnet: SubnetTemplateSpec{
  1356  										SubnetClassSpec: SubnetClassSpec{
  1357  											Role:       DefaultAzureBastionSubnetRole,
  1358  											CIDRBlocks: []string{DefaultAzureBastionSubnetCIDR},
  1359  										},
  1360  									},
  1361  								},
  1362  							},
  1363  						},
  1364  					},
  1365  				},
  1366  			},
  1367  		},
  1368  		{
  1369  			name: "azure bastion enabled with subnet fully set",
  1370  			clusterTemplate: &AzureClusterTemplate{
  1371  				ObjectMeta: metav1.ObjectMeta{
  1372  					Name: "test-cluster-template",
  1373  				},
  1374  				Spec: AzureClusterTemplateSpec{
  1375  					Template: AzureClusterTemplateResource{
  1376  						Spec: AzureClusterTemplateResourceSpec{
  1377  							BastionSpec: BastionTemplateSpec{
  1378  								AzureBastion: &AzureBastionTemplateSpec{
  1379  									Subnet: SubnetTemplateSpec{
  1380  										SubnetClassSpec: SubnetClassSpec{
  1381  											Role:       DefaultAzureBastionSubnetRole,
  1382  											CIDRBlocks: []string{"10.10.0.0/16"},
  1383  										},
  1384  									},
  1385  								},
  1386  							},
  1387  						},
  1388  					},
  1389  				},
  1390  			},
  1391  			outputTemplate: &AzureClusterTemplate{
  1392  				ObjectMeta: metav1.ObjectMeta{
  1393  					Name: "test-cluster-template",
  1394  				},
  1395  				Spec: AzureClusterTemplateSpec{
  1396  					Template: AzureClusterTemplateResource{
  1397  						Spec: AzureClusterTemplateResourceSpec{
  1398  							BastionSpec: BastionTemplateSpec{
  1399  								AzureBastion: &AzureBastionTemplateSpec{
  1400  									Subnet: SubnetTemplateSpec{
  1401  										SubnetClassSpec: SubnetClassSpec{
  1402  											Role:       DefaultAzureBastionSubnetRole,
  1403  											CIDRBlocks: []string{"10.10.0.0/16"},
  1404  										},
  1405  									},
  1406  								},
  1407  							},
  1408  						},
  1409  					},
  1410  				},
  1411  			},
  1412  		},
  1413  	}
  1414  
  1415  	for _, c := range cases {
  1416  		tc := c
  1417  		t.Run(tc.name, func(t *testing.T) {
  1418  			t.Parallel()
  1419  			tc.clusterTemplate.setBastionTemplateDefaults()
  1420  			if !reflect.DeepEqual(tc.clusterTemplate, tc.outputTemplate) {
  1421  				expected, _ := json.MarshalIndent(tc.outputTemplate, "", "\t")
  1422  				actual, _ := json.MarshalIndent(tc.clusterTemplate, "", "\t")
  1423  				t.Errorf("Expected %s, got %s", string(expected), string(actual))
  1424  			}
  1425  		})
  1426  	}
  1427  }