Skip to content

Commit

Permalink
refactor: split server object per package
Browse files Browse the repository at this point in the history
Signed-off-by: Boris Glimcher <[email protected]>
  • Loading branch information
glimchb committed Oct 19, 2023
1 parent ddf7f9e commit ee38c8a
Show file tree
Hide file tree
Showing 32 changed files with 1,382 additions and 369 deletions.
18 changes: 12 additions & 6 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import (

pc "github.com/opiproject/opi-api/inventory/v1/gen/go"
pe "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"
"github.com/opiproject/opi-evpn-bridge/pkg/evpn"
"github.com/opiproject/opi-evpn-bridge/pkg/bridge"
"github.com/opiproject/opi-evpn-bridge/pkg/port"
"github.com/opiproject/opi-evpn-bridge/pkg/svi"
"github.com/opiproject/opi-evpn-bridge/pkg/utils"
"github.com/opiproject/opi-evpn-bridge/pkg/vrf"
"github.com/opiproject/opi-smbios-bridge/pkg/inventory"

"github.com/philippgille/gokv"
Expand Down Expand Up @@ -105,12 +108,15 @@ func runGrpcServer(grpcPort int, tlsFiles string, store gokv.Store) {
)
s := grpc.NewServer(serverOptions...)

opi := evpn.NewServer(store)
bridgeServer := bridge.NewServer(store)
portServer := port.NewServer(store)
vrfServer := vrf.NewServer(store)
sviServer := svi.NewServer(store)

pe.RegisterLogicalBridgeServiceServer(s, opi)
pe.RegisterBridgePortServiceServer(s, opi)
pe.RegisterVrfServiceServer(s, opi)
pe.RegisterSviServiceServer(s, opi)
pe.RegisterLogicalBridgeServiceServer(s, bridgeServer)
pe.RegisterBridgePortServiceServer(s, portServer)
pe.RegisterVrfServiceServer(s, vrfServer)
pe.RegisterSviServiceServer(s, sviServer)
pc.RegisterInventorySvcServer(s, &inventory.Server{})

reflection.Register(s)
Expand Down
4 changes: 2 additions & 2 deletions pkg/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries.
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package evpn is the main package of the application
package evpn
// Package bridge is the main package of the application
package bridge

import (
"context"
Expand Down
4 changes: 2 additions & 2 deletions pkg/bridge/bridge_netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries.
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package evpn is the main package of the application
package evpn
// Package bridge is the main package of the application
package bridge

import (
"context"
Expand Down
32 changes: 2 additions & 30 deletions pkg/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Copyright (c) 2022-2023 Intel Corporation, or its subsidiaries.
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package evpn is the main package of the application
package evpn
// Package bridge is the main package of the application
package bridge

import (
"context"
Expand All @@ -28,39 +28,11 @@ import (
"google.golang.org/protobuf/types/known/fieldmaskpb"

pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"
pc "github.com/opiproject/opi-api/network/opinetcommon/v1alpha1/gen/go"

"github.com/opiproject/opi-evpn-bridge/pkg/utils"
"github.com/opiproject/opi-evpn-bridge/pkg/utils/mocks"
)

var (
testLogicalBridgeID = "opi-bridge9"
testLogicalBridgeName = resourceIDToFullName("bridges", testLogicalBridgeID)
testLogicalBridge = pb.LogicalBridge{
Spec: &pb.LogicalBridgeSpec{
Vni: proto.Uint32(11),
VlanId: 22,
VtepIpPrefix: &pc.IPPrefix{
Addr: &pc.IPAddress{
Af: pc.IpAf_IP_AF_INET,
V4OrV6: &pc.IPAddress_V4Addr{
V4Addr: 167772162,
},
},
Len: 24,
},
},
}
testLogicalBridgeWithStatus = pb.LogicalBridge{
Name: testLogicalBridgeName,
Spec: testLogicalBridge.Spec,
Status: &pb.LogicalBridgeStatus{
OperStatus: pb.LBOperStatus_LB_OPER_STATUS_UP,
},
}
)

func Test_CreateLogicalBridge(t *testing.T) {
tests := map[string]struct {
id string
Expand Down
4 changes: 2 additions & 2 deletions pkg/bridge/bridge_validate.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package evpn is the main package of the application
package evpn
// Package bridge is the main package of the application
package bridge

import (
"fmt"
Expand Down
212 changes: 212 additions & 0 deletions pkg/bridge/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package bridge is the main package of the application
package bridge

import (
"context"
"crypto/rand"
"fmt"
"log"
"net"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"

pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"
pc "github.com/opiproject/opi-api/network/opinetcommon/v1alpha1/gen/go"
)

// TODO: move all of this to a common place
const (
tenantbridgeName = "br-tenant"
)

var (
testLogicalBridgeID = "opi-bridge9"
testLogicalBridgeName = resourceIDToFullName("bridges", testLogicalBridgeID)
testLogicalBridge = pb.LogicalBridge{
Spec: &pb.LogicalBridgeSpec{
Vni: proto.Uint32(11),
VlanId: 22,
VtepIpPrefix: &pc.IPPrefix{
Addr: &pc.IPAddress{
Af: pc.IpAf_IP_AF_INET,
V4OrV6: &pc.IPAddress_V4Addr{
V4Addr: 167772162,
},
},
Len: 24,
},
},
}
testLogicalBridgeWithStatus = pb.LogicalBridge{
Name: testLogicalBridgeName,
Spec: testLogicalBridge.Spec,
Status: &pb.LogicalBridgeStatus{
OperStatus: pb.LBOperStatus_LB_OPER_STATUS_UP,
},
}

testBridgePortID = "opi-port8"
testBridgePortName = resourceIDToFullName("ports", testBridgePortID)
testBridgePort = pb.BridgePort{
Spec: &pb.BridgePortSpec{
MacAddress: []byte{0xCB, 0xB8, 0x33, 0x4C, 0x88, 0x4F},
Ptype: pb.BridgePortType_TRUNK,
LogicalBridges: []string{testLogicalBridgeName},
},
}
testBridgePortWithStatus = pb.BridgePort{
Name: testBridgePortName,
Spec: testBridgePort.Spec,
Status: &pb.BridgePortStatus{
OperStatus: pb.BPOperStatus_BP_OPER_STATUS_UP,
},
}

testSviID = "opi-svi8"
testSviName = resourceIDToFullName("svis", testSviID)
testSvi = pb.Svi{
Spec: &pb.SviSpec{
Vrf: testVrfName,
LogicalBridge: testLogicalBridgeName,
MacAddress: []byte{0xCB, 0xB8, 0x33, 0x4C, 0x88, 0x4F},
GwIpPrefix: []*pc.IPPrefix{{Len: 24}},
},
}
testSviWithStatus = pb.Svi{
Name: testSviName,
Spec: testSvi.Spec,
Status: &pb.SviStatus{
OperStatus: pb.SVIOperStatus_SVI_OPER_STATUS_UP,
},
}

testVrfID = "opi-vrf8"
testVrfName = resourceIDToFullName("vrfs", testVrfID)
testVrf = pb.Vrf{
Spec: &pb.VrfSpec{
Vni: proto.Uint32(1000),
LoopbackIpPrefix: &pc.IPPrefix{
// Addr: &pc.IPAddress{
// Af: pc.IpAf_IP_AF_INET,
// V4OrV6: &pc.IPAddress_V4Addr{
// V4Addr: 167772162,
// },
// },
Len: 24,
},
VtepIpPrefix: &pc.IPPrefix{
Addr: &pc.IPAddress{
Af: pc.IpAf_IP_AF_INET,
V4OrV6: &pc.IPAddress_V4Addr{
V4Addr: 167772162,
},
},
Len: 24,
},
},
}
testVrfWithStatus = pb.Vrf{
Name: testVrfName,
Spec: testVrf.Spec,
Status: &pb.VrfStatus{
LocalAs: 4,
},
}
)

func resourceIDToFullName(container string, resourceID string) string {
return fmt.Sprintf("//network.opiproject.org/%s/%s", container, resourceID)
}

func protoClone[T proto.Message](protoStruct T) T {
return proto.Clone(protoStruct).(T)
}

func generateRandMAC() ([]byte, error) {
buf := make([]byte, 6)
if _, err := rand.Read(buf); err != nil {
return nil, fmt.Errorf("unable to retrieve 6 rnd bytes: %s", err)
}

Check warning on line 136 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L132-L136

Added lines #L132 - L136 were not covered by tests

// Set locally administered addresses bit and reset multicast bit
buf[0] = (buf[0] | 0x02) & 0xfe

return buf, nil

Check warning on line 141 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L139-L141

Added lines #L139 - L141 were not covered by tests
}

func extractPagination(pageSize int32, pageToken string, pagination map[string]int) (size int, offset int, err error) {
const (
maxPageSize = 250
defaultPageSize = 50
)
switch {
case pageSize < 0:
return -1, -1, status.Error(codes.InvalidArgument, "negative PageSize is not allowed")
case pageSize == 0:
size = defaultPageSize
case pageSize > maxPageSize:
size = maxPageSize
default:
size = int(pageSize)
}
// fetch offset from the database using opaque token
offset = 0
if pageToken != "" {
var ok bool
offset, ok = pagination[pageToken]
if !ok {
return -1, -1, status.Errorf(codes.NotFound, "unable to find pagination token %s", pageToken)
}
log.Printf("Found offset %d from pagination token: %s", offset, pageToken)
}
return size, offset, nil
}

func limitPagination[T any](result []T, offset int, size int) ([]T, bool) {
end := offset + size
hasMoreElements := false
if end < len(result) {
hasMoreElements = true

Check warning on line 176 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L176

Added line #L176 was not covered by tests
} else {
end = len(result)
}
return result[offset:end], hasMoreElements
}

func dialer(opi *Server) func(context.Context, string) (net.Conn, error) {
listener := bufconn.Listen(1024 * 1024)
server := grpc.NewServer()

pb.RegisterLogicalBridgeServiceServer(server, opi)

go func() {
if err := server.Serve(listener); err != nil {
log.Fatal(err)
}

Check warning on line 192 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L191-L192

Added lines #L191 - L192 were not covered by tests
}()

return func(context.Context, string) (net.Conn, error) {
return listener.Dial()
}
}

func equalProtoSlices[T proto.Message](x, y []T) bool {
if len(x) != len(y) {
return false
}

Check warning on line 203 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L202-L203

Added lines #L202 - L203 were not covered by tests

for i := 0; i < len(x); i++ {
if !proto.Equal(x[i], y[i]) {
return false
}

Check warning on line 208 in pkg/bridge/common.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/common.go#L207-L208

Added lines #L207 - L208 were not covered by tests
}

return true
}
58 changes: 58 additions & 0 deletions pkg/bridge/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2022-2023 Dell Inc, or its subsidiaries.

// Package bridge is the main package of the application
package bridge

import (
"log"

"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"

"github.com/philippgille/gokv"

pb "github.com/opiproject/opi-api/network/evpn-gw/v1alpha1/gen/go"

"github.com/opiproject/opi-evpn-bridge/pkg/utils"
)

// Server represents the Server object
type Server struct {
pb.UnimplementedLogicalBridgeServiceServer
Pagination map[string]int
ListHelper map[string]bool
nLink utils.Netlink
frr utils.Frr
tracer trace.Tracer
store gokv.Store
}

// NewServer creates initialized instance of EVPN server
func NewServer(store gokv.Store) *Server {
nLink := utils.NewNetlinkWrapper()
frr := utils.NewFrrWrapper()
return NewServerWithArgs(nLink, frr, store)

Check warning on line 35 in pkg/bridge/server.go

View check run for this annotation

Codecov / codecov/patch

pkg/bridge/server.go#L32-L35

Added lines #L32 - L35 were not covered by tests
}

// NewServerWithArgs creates initialized instance of EVPN server
// with externally created Netlink
func NewServerWithArgs(nLink utils.Netlink, frr utils.Frr, store gokv.Store) *Server {
if frr == nil {
log.Panic("nil for Frr is not allowed")
}
if nLink == nil {
log.Panic("nil for Netlink is not allowed")
}
if store == nil {
log.Panic("nil for Store is not allowed")
}
return &Server{
ListHelper: make(map[string]bool),
Pagination: make(map[string]int),
nLink: nLink,
frr: frr,
tracer: otel.Tracer(""),
store: store,
}
}
Loading

0 comments on commit ee38c8a

Please sign in to comment.