Skip to content
This repository has been archived by the owner on Jun 18, 2024. It is now read-only.

Commit

Permalink
fix: implemenation
Browse files Browse the repository at this point in the history
  • Loading branch information
zbindenren committed Jun 14, 2024
1 parent 75210d5 commit 22e84dd
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
125 changes: 125 additions & 0 deletions internal/server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"context"
"errors"
"fmt"
"regexp"
"strings"
"time"

"connectrpc.com/connect"
"github.com/postfinance/discovery"
"github.com/postfinance/discovery/internal/auth"
"github.com/postfinance/discovery/internal/exporter"
"github.com/postfinance/discovery/internal/registry"
"github.com/postfinance/discovery/internal/repo"
"github.com/postfinance/discovery/internal/server/convert"
Expand All @@ -20,6 +22,7 @@ import (
)

var (
_ discoveryv1connect.ServiceAPIHandler = (*API)(nil)
_ discoveryv1connect.ServerAPIHandler = (*API)(nil)
_ discoveryv1connect.NamespaceAPIHandler = (*API)(nil)
_ discoveryv1connect.TokenAPIHandler = (*API)(nil)
Expand All @@ -31,6 +34,124 @@ type API struct {
tokenHandler *auth.TokenHandler
}

// ListService implements discoveryv1connect.ServiceAPIHandler.
func (a *API) ListService(_ context.Context, req *connect.Request[discoveryv1.ListServiceRequest]) (*connect.Response[discoveryv1.ListServiceResponse], error) {
s, err := a.r.ListService(req.Msg.GetNamespace(), "")
if err != nil {
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("could not list services: %w", err))
}

resp := connect.NewResponse(&discoveryv1.ListServiceResponse{
Services: convert.ServicesToPB(s),
})

return resp, nil
}

// ListTargetGroup implements discoveryv1connect.ServiceAPIHandler.
func (a *API) ListTargetGroup(_ context.Context, in *connect.Request[discoveryv1.ListTargetGroupRequest]) (*connect.Response[discoveryv1.ListTargetGroupResponse], error) {
var config discovery.ExportConfig

switch in.Msg.GetConfig() {
case "standard":
config = discovery.Standard
case "blackbox":
config = discovery.Blackbox
case "":
config = discovery.Standard
default:
return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid exporter config: '%s'", in.Msg.GetConfig()))
}

s, err := a.r.ListService(in.Msg.GetNamespace(), "")
if err != nil {
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("could not list services: %w", err))
}

serverFilter, err := regexp.Compile(fmt.Sprintf(`^%s$`, in.Msg.GetServer()))
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("invalid regular expression: '%s'", in.Msg.GetServer()))
}

s = s.Filter(discovery.ServiceByServer(serverFilter))

t := make([]*discoveryv1.TargetGroup, 0, len(s))

for i := range s {
tg := exporter.NewTargetGroup(s[i], config)
t = append(t, convert.TargetGroupToPB(&tg))
}

resp := connect.NewResponse(&discoveryv1.ListTargetGroupResponse{
Targetgroups: t,
})

return resp, nil
}

// RegisterService implements discoveryv1connect.ServiceAPIHandler.
func (a *API) RegisterService(ctx context.Context, req *connect.Request[discoveryv1.RegisterServiceRequest]) (*connect.Response[discoveryv1.RegisterServiceResponse], error) {
if err := verifyUser(ctx, req.Msg.GetNamespace()); err != nil {
return nil, err
}

s, err := discovery.NewService(req.Msg.GetName(), req.Msg.GetEndpoint())
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("service with endpoint %s is invalid: %w", req.Msg.GetEndpoint(), err))
}

s.Labels = req.Msg.GetLabels()
s.Description = req.Msg.GetDescription()
s.Selector = req.Msg.GetSelector()

if req.Msg.GetNamespace() != "" {
s.Namespace = req.Msg.GetNamespace()
}

svc, err := a.r.RegisterService(*s)
if err != nil {
if registry.IsServersNotFound(err) {
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("no server found for selector '%s'", req.Msg.GetSelector()))
}

if registry.IsNamespaceNotFound(err) {
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("namespace '%s' not found", req.Msg.GetNamespace()))
}

if registry.IsValidationError(err) {
return nil, connect.NewError(connect.CodeInvalidArgument, err)
}

return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("could not register service %s in store: %w", req.Msg.GetEndpoint(), err))
}

resp := connect.NewResponse(&discoveryv1.RegisterServiceResponse{
Service: convert.ServiceToPB(svc),
})

return resp, nil
}

// UnRegisterService implements discoveryv1connect.ServiceAPIHandler.
func (a *API) UnRegisterService(ctx context.Context, req *connect.Request[discoveryv1.UnRegisterServiceRequest]) (*connect.Response[discoveryv1.UnRegisterServiceResponse], error) {
if err := verifyUser(ctx, req.Msg.GetNamespace()); err != nil {
return nil, err
}

if err := a.r.UnRegisterService(req.Msg.GetId(), req.Msg.GetNamespace()); err != nil {
c := connect.CodeInternal
if errors.Is(err, repo.ErrNotFound) {
c = connect.CodeNotFound
}

return nil, connect.NewError(c, fmt.Errorf("could not unregister service %s in namespace %s: %w", req.Msg.GetId(), req.Msg.GetNamespace(), err))
}

resp := connect.NewResponse(&discoveryv1.UnRegisterServiceResponse{})

return resp, nil
}

// Create implements discoveryv1connect.TokenAPIHandler.
func (a *API) Create(_ context.Context, req *connect.Request[discoveryv1.CreateRequest]) (*connect.Response[discoveryv1.CreateResponse], error) {
var expiry time.Duration
Expand Down Expand Up @@ -107,6 +228,8 @@ func (a *API) RegisterServer(_ context.Context, req *connect.Request[discoveryv1
}

// UnregisterServer implements discoveryv1connect.ServerAPIHandler.
//
//nolint:dupl // is ok
func (a *API) UnregisterServer(_ context.Context, req *connect.Request[discoveryv1.UnregisterServerRequest]) (*connect.Response[discoveryv1.UnregisterServerResponse], error) {
if err := a.r.UnRegisterServer(req.Msg.GetName()); err != nil {
c := connect.CodeInternal
Expand Down Expand Up @@ -159,6 +282,8 @@ func (a *API) RegisterNamespace(_ context.Context, req *connect.Request[discover
}

// UnregisterNamespace implements discoveryv1connect.NamespaceAPIHandler.
//
//nolint:dupl // is ok
func (a *API) UnregisterNamespace(_ context.Context, req *connect.Request[discoveryv1.UnregisterNamespaceRequest]) (*connect.Response[discoveryv1.UnregisterNamespaceResponse], error) {
if err := a.r.UnRegisterNamespace(req.Msg.GetName()); err != nil {
c := connect.CodeInternal
Expand Down
2 changes: 2 additions & 0 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ func (s *Server) createMux(api *API) *http.ServeMux {
mux.Handle(httpPath, handler)
httpPath, handler = discoveryv1connect.NewTokenAPIHandler(api)
mux.Handle(httpPath, handler)
httpPath, handler = discoveryv1connect.NewServiceAPIHandler(api)
mux.Handle(httpPath, handler)

return mux
}
Expand Down

0 comments on commit 22e84dd

Please sign in to comment.