Skip to content

Commit 73564da

Browse files
authored
Fix Merge Shmoo (#241)
1 parent b430d68 commit 73564da

File tree

2 files changed

+45
-26
lines changed

2 files changed

+45
-26
lines changed

pkg/lbmanager/lbmanager.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,23 @@ func (m *LBManager) CreateSvcLBIfNone(ctx context.Context, in *api.Postgres) err
3939
return fmt.Errorf("failed to fetch Service of type LoadBalancer: %w", err)
4040
}
4141

42-
nextFreePort, err := m.nextFreePort(ctx)
42+
existingLBIP, nextFreePort, err := m.nextFreeSocket(ctx)
4343
if err != nil {
44-
return fmt.Errorf("failed to get the next free port: %w", err)
44+
return fmt.Errorf("failed to get a free port for creating Service of type LoadBalancer: %w", err)
45+
}
46+
var lbIPToUse string
47+
if m.LBIP != "" {
48+
// a specific IP was configured in the config, so use that one
49+
lbIPToUse = m.LBIP
50+
} else if existingLBIP != "" {
51+
// no ip was configured, but one is already in use, so use the existing one
52+
lbIPToUse = existingLBIP
53+
} else {
54+
// nothing was configured, nothing exists yet, so use an empty address so a new loadbalancer will be created and assigned
55+
lbIPToUse = ""
4556
}
4657

47-
if err := m.Create(ctx, in.ToSvcLB(m.LBIP, nextFreePort)); err != nil {
58+
if err := m.Create(ctx, in.ToSvcLB(lbIPToUse, nextFreePort)); err != nil {
4859
return fmt.Errorf("failed to create Service of type LoadBalancer: %w", err)
4960
}
5061
return nil
@@ -64,27 +75,35 @@ func (m *LBManager) DeleteSvcLB(ctx context.Context, in *api.Postgres) error {
6475
}
6576

6677
// nextFreeSocket finds any existing LoadBalancerIP and the next free port out of the configure port range.
67-
func (m *LBManager) nextFreePort(ctx context.Context) (int32, error) {
78+
func (m *LBManager) nextFreeSocket(ctx context.Context) (string, int32, error) {
6879
// TODO prevent concurrency issues when calculating port / ip.
6980

81+
anyExistingLBIP := ""
82+
7083
// Fetch all services managed by this postgreslet
7184
lbs := &corev1.ServiceList{}
7285
if err := m.List(ctx, lbs, client.MatchingLabels(api.SvcLoadBalancerLabel)); err != nil {
73-
return 0, fmt.Errorf("failed to fetch the list of services of type LoadBalancer: %w", err)
86+
return anyExistingLBIP, 0, fmt.Errorf("failed to fetch the list of services of type LoadBalancer: %w", err)
7487
}
7588

7689
// If there are none, this will be the first (managed) service we create, so start with PortRangeStart and return
7790
if len(lbs.Items) == 0 {
78-
return m.PortRangeStart, nil
91+
return anyExistingLBIP, m.PortRangeStart, nil
7992
}
8093

8194
// If there are already any managed services, store all the used ports in a slice.
82-
portsInUse := []int32{}
95+
// Also store the LoadBalancerIP.
96+
portsInUse := make([]int32, 0, len(lbs.Items))
8397
for i := range lbs.Items {
8498
svc := lbs.Items[i]
8599
if len(svc.Spec.Ports) > 0 {
86100
portsInUse = append(portsInUse, svc.Spec.Ports[0].Port)
87101
}
102+
if svc.Spec.LoadBalancerIP != "" {
103+
// Technically, we only store the IP of the last Service in this list.
104+
// As there should only be one IP per postgreslet and one postgreslet per cluster, this is good enough.
105+
anyExistingLBIP = svc.Spec.LoadBalancerIP
106+
}
88107
}
89108

90109
// Now try all ports in the configured port range to find a free one.
@@ -96,11 +115,11 @@ func (m *LBManager) nextFreePort(ctx context.Context) (int32, error) {
96115
continue
97116
}
98117
// The postgreslet hasn't assigned this port yet, so use it.
99-
return port, nil
118+
return anyExistingLBIP, port, nil
100119
}
101120

102121
// If we made it this far, no free port could be found.
103-
return 0, errors.New("no free port in the configured port range found")
122+
return anyExistingLBIP, 0, errors.New("no free port in the configured port range found")
104123
}
105124

106125
func containsElem(s []int32, v int32) bool {

pkg/lbmanager/lbmanager_test.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ func TestLBManager_nextFreePort(t *testing.T) {
1616
portRangeSize := int32(5)
1717

1818
tests := []struct {
19-
name string
20-
lbMgr *LBManager
21-
want int32
22-
wantErr bool
19+
name string
20+
lbMgr *LBManager
21+
portWant int32
22+
wantErr bool
2323
}{
2424
{
2525
name: "no svc in the cluster",
@@ -29,8 +29,8 @@ func TestLBManager_nextFreePort(t *testing.T) {
2929
PortRangeStart: portRangeStart,
3030
PortRangeSize: portRangeSize,
3131
},
32-
want: 0,
33-
wantErr: false,
32+
portWant: 0,
33+
wantErr: false,
3434
},
3535
{
3636
name: "one svc already in the cluster",
@@ -40,8 +40,8 @@ func TestLBManager_nextFreePort(t *testing.T) {
4040
PortRangeStart: portRangeStart,
4141
PortRangeSize: portRangeSize,
4242
},
43-
want: 1,
44-
wantErr: false,
43+
portWant: 1,
44+
wantErr: false,
4545
},
4646
{
4747
name: "last free port left",
@@ -51,8 +51,8 @@ func TestLBManager_nextFreePort(t *testing.T) {
5151
PortRangeStart: portRangeStart,
5252
PortRangeSize: portRangeSize,
5353
},
54-
want: 4,
55-
wantErr: false,
54+
portWant: 4,
55+
wantErr: false,
5656
},
5757
{
5858
name: "no free port",
@@ -62,8 +62,8 @@ func TestLBManager_nextFreePort(t *testing.T) {
6262
PortRangeStart: portRangeStart,
6363
PortRangeSize: portRangeSize,
6464
},
65-
want: 0,
66-
wantErr: true,
65+
portWant: 0,
66+
wantErr: true,
6767
},
6868
{
6969
name: "re-use releaased port",
@@ -73,21 +73,21 @@ func TestLBManager_nextFreePort(t *testing.T) {
7373
PortRangeStart: portRangeStart,
7474
PortRangeSize: portRangeSize,
7575
},
76-
want: 1,
77-
wantErr: false,
76+
portWant: 1,
77+
wantErr: false,
7878
},
7979
}
8080

8181
for _, tt := range tests {
8282
tt := tt
8383
t.Run(tt.name, func(t *testing.T) {
84-
got, err := tt.lbMgr.nextFreePort(context.Background())
84+
_, portGot, err := tt.lbMgr.nextFreeSocket(context.Background())
8585
if (err != nil) != tt.wantErr {
8686
t.Errorf("LBManager.nextFreePort() error = %v, wantErr %v", err, tt.wantErr)
8787
return
8888
}
89-
if got != tt.want {
90-
t.Errorf("LBManager.nextFreePort() = %v, want %v", got, tt.want)
89+
if portGot != tt.portWant {
90+
t.Errorf("LBManager.nextFreePort() = %v, want %v", portGot, tt.portWant)
9191
}
9292
})
9393
}

0 commit comments

Comments
 (0)