Skip to content

Commit ff1da65

Browse files
committed
🐛 fix(loadbalancer): use subnet in different subregion as a fallback
1 parent b94d123 commit ff1da65

3 files changed

Lines changed: 48 additions & 3 deletions

File tree

ccm/cloud/loadbalancer.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,13 +623,22 @@ func (c *Cloud) ensureSubnet(ctx context.Context, l *LoadBalancer) error {
623623

624624
l.SubnetID = make([]string, l.Instances)
625625
ensureByTag := func(key, subregion string, i int) bool {
626+
// right tag, right subregion
626627
for _, subnet := range *resp.Subnets {
627628
if tags.Has(subnet.Tags, key) && subnet.SubregionName == subregion {
628629
l.SubnetID[i] = subnet.SubnetId
629630
l.NetID = subnet.NetId
630631
return true
631632
}
632633
}
634+
// fallback: right tag, other subregion
635+
for _, subnet := range *resp.Subnets {
636+
if tags.Has(subnet.Tags, key) {
637+
l.SubnetID[i] = subnet.SubnetId
638+
l.NetID = subnet.NetId
639+
return true
640+
}
641+
}
633642
return false
634643
}
635644

ccm/helpers_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,19 @@ func expectFindLBSubnetWithRole(mock *mocks_osc.MockClient) {
341341
}}, nil)
342342
}
343343

344+
func expectFindLBSubnetWithRoleButAnotherSubregion(mock *mocks_osc.MockClient) {
345+
mock.EXPECT().
346+
ReadSubnets(gomock.Any(), gomock.Eq(osc.ReadSubnetsRequest{
347+
Filters: &osc.FiltersSubnet{
348+
TagKeys: &[]string{"OscK8sClusterID/foo"},
349+
},
350+
})).
351+
Return(&osc.ReadSubnetsResponse{Subnets: &[]osc.Subnet{
352+
{SubnetId: "subnet-service", NetId: "net-foo", SubregionName: "eu-west-2b", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.Service)}}},
353+
{SubnetId: "subnet-service.internal", NetId: "net-foo", SubregionName: "eu-west-2b", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.InternalService)}}},
354+
}}, nil)
355+
}
356+
344357
func expectFindLBSubnetWithRoleWithNetFallback(mock *mocks_osc.MockClient) {
345358
mock.EXPECT().
346359
ReadSubnets(gomock.Any(), gomock.Eq(osc.ReadSubnetsRequest{
@@ -491,12 +504,14 @@ func expectFindExistingWorkerSG(mock *mocks_osc.MockClient) {
491504
},
492505
})).
493506
Return(&osc.ReadSecurityGroupsResponse{SecurityGroups: &[]osc.SecurityGroup{
494-
{SecurityGroupId: "sg-worker", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.Worker)}},
507+
{
508+
SecurityGroupId: "sg-worker", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.Worker)}},
495509
InboundRules: []osc.SecurityGroupRule{
496510
{IpProtocol: "tcp", FromPortRange: 8080, ToPortRange: 8080, SecurityGroupsMembers: []osc.SecurityGroupsMember{{
497511
SecurityGroupId: "sg-foo",
498512
}}},
499-
}},
513+
},
514+
},
500515
{SecurityGroupId: "sg-controlplane", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.ControlPlane)}}},
501516
{SecurityGroupId: "sg-node", Tags: []osc.ResourceTag{{Key: tags.RoleKey(role.Worker)}, {Key: tags.RoleKey(role.ControlPlane)}}},
502517
}}, nil)

ccm/loadbalancer_test.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,28 @@ func TestEnsureLoadBalancer_Create(t *testing.T) {
231231
_, err := p.EnsureLoadBalancer(t.Context(), "foo", svc, []*corev1.Node{&vmNode})
232232
require.ErrorIs(t, err, cloud.ErrLoadBalancerIsNotReady)
233233
})
234-
t.Run("A subnet is found, event if subnets are not tagged by owner", func(t *testing.T) {
234+
t.Run("A subnet is found, even if no subnet exists in the right subregion", func(t *testing.T) {
235+
svc := testSvc()
236+
c, oapimock, lbmock := newAPI(t, self, []string{"foo"})
237+
expectVMs(oapimock, sdkSelf, sdkVM)
238+
expectNoLoadbalancer(oapimock)
239+
expectFindLBSubnetWithRoleButAnotherSubregion(oapimock)
240+
expectSGAlreadyExists(oapimock)
241+
expectFindWorkerSGByRole(oapimock)
242+
expectAddIngressSGRule(oapimock, []string{"0.0.0.0/0"}, "sg-foo")
243+
expectAddInternalSGRule(oapimock, "sg-foo", "sg-worker")
244+
expectCreateLoadBalancer(oapimock, func(clbr *osc.CreateLoadBalancerRequest) {
245+
clbr.Subnets = &[]string{"subnet-service"}
246+
})
247+
expectConfigureHealthCheck(oapimock)
248+
expectDescribeProxyProtocol(lbmock, false)
249+
expectDescribeLoadBalancerAttributes(lbmock)
250+
expectRegisterInstances(oapimock, sdkVM.VmId)
251+
p := ccm.NewProviderWith(c, staticDNSResolver{}, ccm.Options{})
252+
_, err := p.EnsureLoadBalancer(t.Context(), "foo", svc, []*corev1.Node{&vmNode})
253+
require.Error(t, err)
254+
})
255+
t.Run("A subnet is found, even if subnets are not tagged by owner", func(t *testing.T) {
235256
svc := testSvc()
236257
c, oapimock, lbmock := newAPI(t, self, []string{"foo"})
237258
expectVMs(oapimock, sdkSelf, sdkVM)

0 commit comments

Comments
 (0)