diff --git a/api/v1alpha4/azurecluster_default.go b/api/v1alpha4/azurecluster_default.go index dad4817cae1..7f8bea61474 100644 --- a/api/v1alpha4/azurecluster_default.go +++ b/api/v1alpha4/azurecluster_default.go @@ -202,10 +202,10 @@ func (c *AzureCluster) setNodeOutboundLBDefaults() { return } - var oneSubnetWithoutNatGateway bool + var needsOutboundLB bool for _, subnet := range c.Spec.NetworkSpec.Subnets { if subnet.Role == SubnetNode && !subnet.IsNatGatewayEnabled() { - oneSubnetWithoutNatGateway = true + needsOutboundLB = true break } } @@ -213,7 +213,7 @@ func (c *AzureCluster) setNodeOutboundLBDefaults() { // If we don't default the outbound LB when there are some subnets with nat gateway, // and some without, those without wouldn't have outbound traffic. So taking the // safer route, we configure the outbound LB in that scenario. - if len(c.Spec.NetworkSpec.Subnets) > 0 && !oneSubnetWithoutNatGateway { + if !needsOutboundLB { return } diff --git a/api/v1alpha4/azurecluster_default_test.go b/api/v1alpha4/azurecluster_default_test.go index e23b7678545..cfd521ac56c 100644 --- a/api/v1alpha4/azurecluster_default_test.go +++ b/api/v1alpha4/azurecluster_default_test.go @@ -803,6 +803,154 @@ func TestNodeOutboundLBDefaults(t *testing.T) { Spec: AzureClusterSpec{ NetworkSpec: NetworkSpec{ APIServerLB: LoadBalancerSpec{Type: Public}, + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + APIServerLB: LoadBalancerSpec{ + Type: Public, + }, + NodeOutboundLB: &LoadBalancerSpec{ + Name: "cluster-test", + SKU: SKUStandard, + FrontendIPs: []FrontendIP{{ + Name: "cluster-test-frontEnd", + PublicIP: &PublicIPSpec{ + Name: "pip-cluster-test-node-outbound", + }, + }}, + Type: Public, + FrontendIPsCount: to.Int32Ptr(1), + IdleTimeoutInMinutes: to.Int32Ptr(DefaultOutboundRuleIdleTimeoutInMinutes), + }, + }, + }, + }, + }, + { + name: "NAT Gateway enabled - no LB", + cluster: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{Type: Public}, + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + }, + APIServerLB: LoadBalancerSpec{ + Type: Public, + }, + }, + }, + }, + }, + { + name: "NAT Gateway enabled on 1 of 2 node subnets", + cluster: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{Type: Public}, + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, }, }, }, @@ -812,6 +960,29 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, Spec: AzureClusterSpec{ NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, APIServerLB: LoadBalancerSpec{ Type: Public, }, @@ -832,6 +1003,191 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, }, + { + name: "multiple node subnets, NAT Gateway not enabled in any of them", + cluster: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{Type: Public}, + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet-3", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet-3", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + APIServerLB: LoadBalancerSpec{ + Type: Public, + }, + NodeOutboundLB: &LoadBalancerSpec{ + Name: "cluster-test", + SKU: SKUStandard, + FrontendIPs: []FrontendIP{{ + Name: "cluster-test-frontEnd", + PublicIP: &PublicIPSpec{ + Name: "pip-cluster-test-node-outbound", + }, + }}, + Type: Public, + FrontendIPsCount: to.Int32Ptr(1), + IdleTimeoutInMinutes: to.Int32Ptr(DefaultOutboundRuleIdleTimeoutInMinutes), + }, + }, + }, + }, + }, + { + name: "multiple node subnets, NAT Gateway enabled on all of them", + cluster: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{Type: Public}, + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway-2", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-3", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway-3", + }, + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: v1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + Role: SubnetControlPlane, + Name: "control-plane-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + Role: SubnetNode, + Name: "node-subnet", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-2", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway-2", + }, + }, + { + Role: SubnetNode, + Name: "node-subnet-3", + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + NatGateway: NatGateway{ + Name: "node-natgateway-3", + }, + }, + }, + APIServerLB: LoadBalancerSpec{ + Type: Public, + }, + }, + }, + }, + }, { name: "no lb for private clusters", cluster: &AzureCluster{ @@ -858,7 +1214,7 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, { - name: "frontendIPsCount > 1", + name: "NodeOutboundLB declared as input with non-default IdleTimeoutInMinutes and FrontendIPsCount values", cluster: &AzureCluster{ ObjectMeta: v1.ObjectMeta{ Name: "cluster-test", @@ -900,8 +1256,8 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, Type: Public, - FrontendIPsCount: to.Int32Ptr(2), - IdleTimeoutInMinutes: to.Int32Ptr(15), + FrontendIPsCount: to.Int32Ptr(2), // we expect the original value to be respected here + IdleTimeoutInMinutes: to.Int32Ptr(15), // we expect the original value to be respected here }, }, }, diff --git a/azure/services/natgateways/natgateways.go b/azure/services/natgateways/natgateways.go index 877e65db43f..925f4d84196 100644 --- a/azure/services/natgateways/natgateways.go +++ b/azure/services/natgateways/natgateways.go @@ -18,8 +18,10 @@ package natgateways import ( "context" + "fmt" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" + autorest "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/to" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -78,6 +80,8 @@ func (s *Service) Reconcile(ctx context.Context) error { natGatewaySpec.Subnet.NatGateway = *existingNatGateway s.Scope.SetSubnet(natGatewaySpec.Subnet) continue + } else { + s.Scope.V(2).Info("updating NAT gateway IP name to match the spec", "old name", existingNatGateway.NatGatewayIP.Name, "desired name", natGatewaySpec.NatGatewayIP.Name) } default: // nat gateway doesn't exist but its name was specified in the subnet, let's create it @@ -118,12 +122,27 @@ func (s *Service) getExisting(ctx context.Context, spec azure.NatGatewaySpec) (* if err != nil { return nil, err } + // We must have a non-nil, non-"empty" PublicIPAddresses + if !(existingNatGateway.PublicIPAddresses != nil && len(*existingNatGateway.PublicIPAddresses) > 0) { + return nil, errors.Wrap(err, "failed to parse PublicIPAddresses") + } + // TODO do we want to eventually handle NatGateway resources w/ more than one public IP address? + // For now we assume the first one is the significant one + publicIPAddressID := to.String((*existingNatGateway.PublicIPAddresses)[0].ID) + resource, err := autorest.ParseResourceID(publicIPAddressID) + if err != nil { + return nil, errors.Wrap(err, "failed to parse Resource ID from PublicIPAddresses ID") + } + // We depend upon a non-empty ResourceName string + if resource.ResourceName == "" { + return nil, errors.Wrap(err, fmt.Sprintf("got unexpected ResourceName value from NatGateway PublicIpAddress, ResourceName=%s", resource.ResourceName)) + } return &infrav1.NatGateway{ ID: to.String(existingNatGateway.ID), Name: to.String(existingNatGateway.Name), NatGatewayIP: infrav1.PublicIPSpec{ - Name: to.String((*existingNatGateway.PublicIPAddresses)[0].ID), + Name: resource.ResourceName, }, }, nil } diff --git a/azure/services/natgateways/natgateways_test.go b/azure/services/natgateways/natgateways_test.go index d598fa75486..d811c4a7e5a 100644 --- a/azure/services/natgateways/natgateways_test.go +++ b/azure/services/natgateways/natgateways_test.go @@ -108,7 +108,7 @@ func TestReconcileNatGateways(t *testing.T) { }, }, { - name: "update nat gateway if already exists but it's out of date", + name: "update nat gateway if actual state does not match desired state", tags: infrav1.Tags{ "Name": "my-vnet", "sigs.k8s.io_cluster-api-provider-azure_cluster_test-cluster": "owned", @@ -180,7 +180,7 @@ func TestReconcileNatGateways(t *testing.T) { Role: infrav1.SubnetNode, }, NatGatewayIP: infrav1.PublicIPSpec{ - Name: "/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/pip-my-node-natgateway-node-subnet-natgw", + Name: "pip-my-node-natgateway-node-subnet-natgw", }, }, }) @@ -191,7 +191,9 @@ func TestReconcileNatGateways(t *testing.T) { Name: to.StringPtr("my-node-natgateway"), ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/natGateways/my-node-natgateway"), NatGatewayPropertiesFormat: &network.NatGatewayPropertiesFormat{PublicIPAddresses: &[]network.SubResource{ - {ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/pip-my-node-natgateway-node-subnet-natgw")}, + { + ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/pip-my-node-natgateway-node-subnet-natgw"), + }, }}, }, nil) s.SetSubnet(infrav1.SubnetSpec{ @@ -201,7 +203,7 @@ func TestReconcileNatGateways(t *testing.T) { ID: "/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/natGateways/my-node-natgateway", Name: "my-node-natgateway", NatGatewayIP: infrav1.PublicIPSpec{ - Name: "/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/pip-my-node-natgateway-node-subnet-natgw", + Name: "pip-my-node-natgateway-node-subnet-natgw", }, }, }) diff --git a/azure/services/subnets/subnets.go b/azure/services/subnets/subnets.go index 66bb7e3b5bd..001dfc9b892 100644 --- a/azure/services/subnets/subnets.go +++ b/azure/services/subnets/subnets.go @@ -63,13 +63,8 @@ func (s *Service) Reconcile(ctx context.Context) error { return errors.Wrapf(err, "failed to get subnet %s", subnetSpec.Name) case err == nil: // subnet already exists, update the spec and skip creation - var subnet infrav1.SubnetSpec - subnet.ID = existingSubnet.ID - subnet.Name = existingSubnet.Name - subnet.Role = existingSubnet.Role - subnet.CIDRBlocks = existingSubnet.CIDRBlocks - - s.Scope.SetSubnet(subnet) + s.Scope.SetSubnet(*existingSubnet) + continue case !s.Scope.IsVnetManaged(): return fmt.Errorf("vnet was provided but subnet %s is missing", subnetSpec.Name) @@ -167,12 +162,9 @@ func (s *Service) getExisting(ctx context.Context, rgName string, spec azure.Sub addresses = to.StringSlice(subnet.SubnetPropertiesFormat.AddressPrefixes) } - subnetSpec := &infrav1.SubnetSpec{ - Role: spec.Role, - Name: to.String(subnet.Name), - ID: to.String(subnet.ID), - CIDRBlocks: addresses, - } + subnetSpec := s.Scope.Subnet(spec.Name) + subnetSpec.ID = to.String(subnet.ID) + subnetSpec.CIDRBlocks = addresses - return subnetSpec, nil + return &subnetSpec, nil } diff --git a/azure/services/subnets/subnets_test.go b/azure/services/subnets/subnets_test.go index 7aa82b0d888..ec317fa2c7e 100644 --- a/azure/services/subnets/subnets_test.go +++ b/azure/services/subnets/subnets_test.go @@ -190,6 +190,18 @@ func TestReconcileSubnets(t *testing.T) { expectedError: "", expect: func(s *mock_subnets.MockSubnetScopeMockRecorder, m *mock_subnets.MockClientMockRecorder) { s.V(gomock.AssignableToTypeOf(2)).AnyTimes().Return(klogr.New()) + s.Subnet("my-subnet").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "subnet-id", + Name: "my-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{"10.0.0.0/16"}, + }) + s.Subnet("my-subnet-1").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "subnet-id-1", + Name: "my-subnet-1", + Role: infrav1.SubnetControlPlane, + CIDRBlocks: []string{"10.2.0.0/16"}, + }) s.SubnetSpecs().AnyTimes().Return([]azure.SubnetSpec{ { Name: "my-subnet", @@ -263,6 +275,18 @@ func TestReconcileSubnets(t *testing.T) { expectedError: "", expect: func(s *mock_subnets.MockSubnetScopeMockRecorder, m *mock_subnets.MockClientMockRecorder) { s.V(gomock.AssignableToTypeOf(2)).AnyTimes().Return(klogr.New()) + s.Subnet("my-ipv6-subnet").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "subnet-id", + Name: "my-ipv6-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{"10.0.0.0/16", "2001:1234:5678:9abd::/64"}, + }) + s.Subnet("my-ipv6-subnet-cp").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "subnet-id-1", + Name: "my-ipv6-subnet-cp", + Role: infrav1.SubnetControlPlane, + CIDRBlocks: []string{"10.2.0.0/16", "2001:1234:5678:9abc::/64"}, + }) s.SubnetSpecs().AnyTimes().Return([]azure.SubnetSpec{ { Name: "my-ipv6-subnet", @@ -338,6 +362,121 @@ func TestReconcileSubnets(t *testing.T) { }).Times(1) }, }, + { + name: "doesn't overwrite existing NAT Gateway", + expectedError: "", + expect: func(s *mock_subnets.MockSubnetScopeMockRecorder, m *mock_subnets.MockClientMockRecorder) { + s.V(gomock.AssignableToTypeOf(2)).AnyTimes().Return(klogr.New()) + s.Subnet("my-subnet").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "subnet-id", + Name: "my-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{"10.0.0.0/16"}, + NatGateway: infrav1.NatGateway{ + ID: azure.NatGatewayID("123", "my-rg", "existing-natgateway"), + Name: "existing-natgateway", + NatGatewayIP: infrav1.PublicIPSpec{ + Name: "existing-natgateway-ip-name", + }, + }, + }) + s.SubnetSpecs().AnyTimes().Return([]azure.SubnetSpec{ + { + Name: "my-subnet", + CIDRs: []string{"10.0.0.0/16"}, + VNetName: "my-vnet", + RouteTableName: "my-subnet_route_table", + SecurityGroupName: "my-sg", + Role: infrav1.SubnetNode, + }, + }) + s.Vnet().AnyTimes().Return(&infrav1.VnetSpec{Name: "my-vnet"}) + s.ClusterName().AnyTimes().Return("fake-cluster") + s.SubscriptionID().AnyTimes().Return("123") + s.ResourceGroup().AnyTimes().Return("my-rg") + m.Get(gomockinternal.AContext(), "", "my-vnet", "my-subnet"). + Return(network.Subnet{ + ID: to.StringPtr("subnet-id"), + Name: to.StringPtr("my-subnet"), + SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ + AddressPrefix: to.StringPtr("10.0.0.0/16"), + RouteTable: &network.RouteTable{ + ID: to.StringPtr("rt-id"), + Name: to.StringPtr("my-subnet_route_table"), + }, + NetworkSecurityGroup: &network.SecurityGroup{ + ID: to.StringPtr("sg-id"), + Name: to.StringPtr("my-sg"), + }, + NatGateway: &network.SubResource{ + ID: to.StringPtr(azure.NatGatewayID("123", "my-rg", "existing-natgateway")), + }, + }, + }, nil) + s.SetSubnet(infrav1.SubnetSpec{ + ID: "subnet-id", + Name: "my-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{"10.0.0.0/16"}, + NatGateway: infrav1.NatGateway{ + ID: azure.NatGatewayID("123", "my-rg", "existing-natgateway"), + Name: "existing-natgateway", + NatGatewayIP: infrav1.PublicIPSpec{ + Name: "existing-natgateway-ip-name", + }, + }, + }).Times(1) + }, + }, + { + name: "spec has empty CIDR and ID data but GET from Azure has the values", + expectedError: "", + expect: func(s *mock_subnets.MockSubnetScopeMockRecorder, m *mock_subnets.MockClientMockRecorder) { + s.V(gomock.AssignableToTypeOf(2)).AnyTimes().Return(klogr.New()) + s.Subnet("my-subnet").AnyTimes().Return(infrav1.SubnetSpec{ + ID: "", + Name: "my-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{}, + }) + s.SubnetSpecs().AnyTimes().Return([]azure.SubnetSpec{ + { + Name: "my-subnet", + CIDRs: []string{}, + VNetName: "my-vnet", + RouteTableName: "my-subnet_route_table", + SecurityGroupName: "my-sg", + Role: infrav1.SubnetNode, + }, + }) + s.Vnet().AnyTimes().Return(&infrav1.VnetSpec{Name: "my-vnet"}) + s.ClusterName().AnyTimes().Return("fake-cluster") + s.SubscriptionID().AnyTimes().Return("123") + s.ResourceGroup().AnyTimes().Return("my-rg") + m.Get(gomockinternal.AContext(), "", "my-vnet", "my-subnet"). + Return(network.Subnet{ + ID: to.StringPtr("subnet-id"), + Name: to.StringPtr("my-subnet"), + SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ + AddressPrefix: to.StringPtr("10.0.0.0/16"), + RouteTable: &network.RouteTable{ + ID: to.StringPtr("rt-id"), + Name: to.StringPtr("my-subnet_route_table"), + }, + NetworkSecurityGroup: &network.SecurityGroup{ + ID: to.StringPtr("sg-id"), + Name: to.StringPtr("my-sg"), + }, + }, + }, nil) + s.SetSubnet(infrav1.SubnetSpec{ + ID: "subnet-id", + Name: "my-subnet", + Role: infrav1.SubnetNode, + CIDRBlocks: []string{"10.0.0.0/16"}, + }).Times(1) + }, + }, } for _, tc := range testcases {