Skip to content

Commit f4d6c0f

Browse files
hrakclaude
andcommitted
fix: Filter LB rules by name prefix in getLoadBalancerByID
getLoadBalancerByID queries by publicipid+networkid, which returns all LB rules on that IP — including rules belonging to other services. The cleanup loop in EnsureLoadBalancer then deletes these foreign rules. Apply filterRulesByPrefix (already used in getLoadBalancerByName) to keep only rules matching the current service's name prefix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5e06350 commit f4d6c0f

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

cloudstack/cloudstack_loadbalancer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,8 @@ func (cs *CSCloud) getLoadBalancerByID(name, ipAddrID, networkID string) (*loadB
667667
return nil, fmt.Errorf("error retrieving load balancer rules by IP ID %v: %w", ipAddrID, err)
668668
}
669669

670-
for _, lbRule := range l.LoadBalancerRules {
670+
filtered := filterRulesByPrefix(l.LoadBalancerRules, lb.name+"-")
671+
for _, lbRule := range filtered {
671672
lb.rules[lbRule.Name] = lbRule
672673

673674
if lb.ipAddr != "" && lb.ipAddr != lbRule.Publicip {

cloudstack/cloudstack_loadbalancer_test.go

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,8 +4172,8 @@ func TestGetLoadBalancerByID(t *testing.T) {
41724172
listResp := &cloudstack.ListLoadBalancerRulesResponse{
41734173
Count: 2,
41744174
LoadBalancerRules: []*cloudstack.LoadBalancerRule{
4175-
{Name: "lb-tcp-80", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4176-
{Name: "lb-tcp-443", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4175+
{Name: "my-lb-tcp-80", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4176+
{Name: "my-lb-tcp-443", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
41774177
},
41784178
}
41794179

@@ -4204,6 +4204,51 @@ func TestGetLoadBalancerByID(t *testing.T) {
42044204
}
42054205
})
42064206

4207+
t.Run("filters out rules not matching LB name prefix", func(t *testing.T) {
4208+
ctrl := gomock.NewController(t)
4209+
t.Cleanup(ctrl.Finish)
4210+
4211+
mockLB := cloudstack.NewMockLoadBalancerServiceIface(ctrl)
4212+
listParams := &cloudstack.ListLoadBalancerRulesParams{}
4213+
4214+
// API returns rules from multiple services sharing the same IP
4215+
listResp := &cloudstack.ListLoadBalancerRulesResponse{
4216+
Count: 4,
4217+
LoadBalancerRules: []*cloudstack.LoadBalancerRule{
4218+
{Name: "my-lb-tcp-80", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4219+
{Name: "my-lb-tcp-443", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4220+
{Name: "other-svc-tcp-8080", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4221+
{Name: "another-svc-tcp-9090", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4222+
},
4223+
}
4224+
4225+
mockLB.EXPECT().NewListLoadBalancerRulesParams().Return(listParams)
4226+
mockLB.EXPECT().ListLoadBalancerRules(gomock.Any()).Return(listResp, nil)
4227+
4228+
cs := &CSCloud{
4229+
client: &cloudstack.CloudStackClient{
4230+
LoadBalancer: mockLB,
4231+
},
4232+
}
4233+
4234+
lb, err := cs.getLoadBalancerByID("my-lb", "ip-1", "net-1")
4235+
if err != nil {
4236+
t.Fatalf("unexpected error: %v", err)
4237+
}
4238+
if len(lb.rules) != 2 {
4239+
t.Fatalf("expected 2 rules (only my-lb- prefix), got %d", len(lb.rules))
4240+
}
4241+
if _, ok := lb.rules["my-lb-tcp-80"]; !ok {
4242+
t.Error("expected rule my-lb-tcp-80 to be present")
4243+
}
4244+
if _, ok := lb.rules["my-lb-tcp-443"]; !ok {
4245+
t.Error("expected rule my-lb-tcp-443 to be present")
4246+
}
4247+
if _, ok := lb.rules["other-svc-tcp-8080"]; ok {
4248+
t.Error("rule other-svc-tcp-8080 should have been filtered out")
4249+
}
4250+
})
4251+
42074252
t.Run("no rules found", func(t *testing.T) {
42084253
ctrl := gomock.NewController(t)
42094254
t.Cleanup(ctrl.Finish)
@@ -4341,7 +4386,7 @@ func TestGetLoadBalancerOrchestrator(t *testing.T) {
43414386
idResp := &cloudstack.ListLoadBalancerRulesResponse{
43424387
Count: 1,
43434388
LoadBalancerRules: []*cloudstack.LoadBalancerRule{
4344-
{Name: "lb-tcp-80", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
4389+
{Name: "my-lb-tcp-80", Publicip: "1.2.3.4", Publicipid: "ip-1", Networkid: "net-1"},
43454390
},
43464391
}
43474392

0 commit comments

Comments
 (0)