Skip to content

Commit

Permalink
Validate load balancer listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
yaocw2020 authored and futuretea committed Jun 6, 2023
1 parent c2abc16 commit 9577d17
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
35 changes: 35 additions & 0 deletions pkg/webhook/loadbalancer/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func NewValidator(vmiCache ctlkubevirtv1.VirtualMachineInstanceCache) admission.
func (v *validator) Create(_ *admission.Request, newObj runtime.Object) error {
lb := newObj.(*lbv1.LoadBalancer)

if err := checkListeners(lb); err != nil {
return fmt.Errorf("create loadbalancer %s/%s failed: %w", lb.Namespace, lb.Name, err)
}

ok, err := v.matchAtLeastOneVmi(lb)
if err != nil {
return fmt.Errorf("create loadbalancer %s/%s failed: %w", lb.Namespace, lb.Name, err)
Expand All @@ -46,6 +50,10 @@ func (v *validator) Update(_ *admission.Request, oldObj, newObj runtime.Object)
return nil
}

if err := checkListeners(lb); err != nil {
return fmt.Errorf("update loadbalancer %s/%s failed: %w", lb.Namespace, lb.Name, err)
}

ok, err := v.matchAtLeastOneVmi(lb)
if err != nil {
return fmt.Errorf("update loadbalancer %s/%s failed: %w", lb.Namespace, lb.Name, err)
Expand Down Expand Up @@ -84,3 +92,30 @@ func (v *validator) matchAtLeastOneVmi(lb *lbv1.LoadBalancer) (bool, error) {

return len(vmis) > 0, nil
}

func checkListeners(lb *lbv1.LoadBalancer) error {
nameMap, portMap, backendMap := map[string]bool{}, map[int32]int{}, map[int32]int{}
for i, listener := range lb.Spec.Listeners {
// check listener name
if _, ok := nameMap[listener.Name]; ok {
return fmt.Errorf("listener has duplicate name %s", listener.Name)
}
nameMap[listener.Name] = true

// check listener port
if index, ok := portMap[listener.Port]; ok {
return fmt.Errorf("listener %s has duplicate port %d with listener %s", listener.Name,
listener.Port, lb.Spec.Listeners[index].Name)
}
portMap[listener.Port] = i

// check backend port
if index, ok := backendMap[listener.BackendPort]; ok {
return fmt.Errorf("listener %s has duplicate backend port %d with listener %s", listener.Name,
listener.BackendPort, lb.Spec.Listeners[index].Name)
}
backendMap[listener.BackendPort] = i
}

return nil
}
70 changes: 70 additions & 0 deletions pkg/webhook/loadbalancer/validator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package loadbalancer

import (
"testing"

lbv1 "github.com/harvester/harvester-load-balancer/pkg/apis/loadbalancer.harvesterhci.io/v1beta1"
)

func TestCheckListeners(t *testing.T) {
tests := []struct {
name string
lb *lbv1.LoadBalancer
wantErr bool
}{
{
name: "duplicate name",
lb: &lbv1.LoadBalancer{
Spec: lbv1.LoadBalancerSpec{
Listeners: []lbv1.Listener{
{Name: "a"},
{Name: "a"},
},
},
},
wantErr: true,
},
{
name: "duplicate port",
lb: &lbv1.LoadBalancer{
Spec: lbv1.LoadBalancerSpec{
Listeners: []lbv1.Listener{
{Name: "a", Port: 80},
{Name: "b", Port: 80},
},
},
},
wantErr: true,
},
{
name: "duplicate backend port",
lb: &lbv1.LoadBalancer{
Spec: lbv1.LoadBalancerSpec{
Listeners: []lbv1.Listener{
{Name: "a", BackendPort: 80},
{Name: "b", BackendPort: 80},
},
},
},
wantErr: true,
},
{
name: "right case",
lb: &lbv1.LoadBalancer{
Spec: lbv1.LoadBalancerSpec{
Listeners: []lbv1.Listener{
{Name: "a", Port: 80, BackendPort: 80},
{Name: "b", Port: 81, BackendPort: 81},
},
},
},
wantErr: false,
},
}

for _, tt := range tests {
if err := checkListeners(tt.lb); (err != nil) != tt.wantErr {
t.Errorf("%q. checkPorts() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
}
}

0 comments on commit 9577d17

Please sign in to comment.