From 57b709ca6cbc0d2e4a9be4a231e27cc4eaa3277b Mon Sep 17 00:00:00 2001 From: George Shaw Date: Thu, 5 Aug 2021 14:51:08 -0700 Subject: [PATCH] feat: common package [DTSS-595] (#115) --- cmd/localizer/expose.go | 13 +++++-------- cmd/localizer/list.go | 10 ++++------ internal/server/grpc.go | 29 ++++++++++++----------------- pkg/localizer/localizer.go | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 pkg/localizer/localizer.go diff --git a/cmd/localizer/expose.go b/cmd/localizer/expose.go index b424d5e..2ee4b4a 100644 --- a/cmd/localizer/expose.go +++ b/cmd/localizer/expose.go @@ -18,12 +18,11 @@ import ( "context" "fmt" "io" - "os" "strings" "time" apiv1 "github.com/getoutreach/localizer/api/v1" - "github.com/getoutreach/localizer/internal/server" + "github.com/getoutreach/localizer/pkg/localizer" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" @@ -54,7 +53,7 @@ func NewExposeCommand(log logrus.FieldLogger) *cli.Command { //nolint:funlen serviceNamespace := split[0] serviceName := split[1] - if _, err := os.Stat(server.SocketPath); os.IsNotExist(err) { + if !localizer.IsRunning() { return fmt.Errorf("localizer daemon not running (run localizer by itself?)") } @@ -62,14 +61,12 @@ func NewExposeCommand(log logrus.FieldLogger) *cli.Command { //nolint:funlen defer cancel() log.Info("connecting to localizer daemon") - conn, err := grpc.DialContext(ctx, "unix://"+server.SocketPath, - grpc.WithBlock(), grpc.WithInsecure()) + + client, err := localizer.Connect(ctx, grpc.WithBlock(), grpc.WithInsecure()) if err != nil { - return errors.Wrap(err, "failed to talk to localizer daemon") + return errors.Wrap(err, "failed to connect to localizer daemon") } - client := apiv1.NewLocalizerServiceClient(conn) - var stream apiv1.LocalizerService_ExposeServiceClient if c.Bool("stop") { log.Info("sending stop expose request to daemon") diff --git a/cmd/localizer/list.go b/cmd/localizer/list.go index 66a2167..46a07e0 100644 --- a/cmd/localizer/list.go +++ b/cmd/localizer/list.go @@ -24,7 +24,7 @@ import ( "time" apiv1 "github.com/getoutreach/localizer/api/v1" - "github.com/getoutreach/localizer/internal/server" + "github.com/getoutreach/localizer/pkg/localizer" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" @@ -37,20 +37,18 @@ func NewListCommand(_ logrus.FieldLogger) *cli.Command { //nolint:funlen Description: "list all port-forwarded services and their status(es)", Usage: "list", Action: func(c *cli.Context) error { - if _, err := os.Stat(server.SocketPath); os.IsNotExist(err) { + if !localizer.IsRunning() { return fmt.Errorf("localizer daemon not running (run localizer by itself?)") } ctx, cancel := context.WithTimeout(c.Context, 30*time.Second) defer cancel() - conn, err := grpc.DialContext(ctx, "unix://"+server.SocketPath, - grpc.WithBlock(), grpc.WithInsecure()) + client, err := localizer.Connect(ctx, grpc.WithBlock(), grpc.WithInsecure()) if err != nil { - return errors.Wrap(err, "failed to talk to localizer daemon") + return errors.Wrap(err, "failed to connect to localizer daemon") } - client := apiv1.NewLocalizerServiceClient(conn) resp, err := client.List(ctx, &apiv1.ListRequest{}) if err != nil { return err diff --git a/internal/server/grpc.go b/internal/server/grpc.go index 5f149d4..f25a2c6 100644 --- a/internal/server/grpc.go +++ b/internal/server/grpc.go @@ -27,10 +27,9 @@ import ( apiv1 "github.com/getoutreach/localizer/api/v1" "github.com/getoutreach/localizer/internal/kevents" + "github.com/getoutreach/localizer/pkg/localizer" ) -const SocketPath = "/var/run/localizer.sock" - type GRPCService struct { lis net.Listener srv *grpc.Server @@ -53,45 +52,41 @@ func NewGRPCService(opts *RunOpts) *GRPCService { // CleanupPreviousInstance attempts to cleanup after a dead localizer instance // if a not dead one is found, an error is returned or if it fails to cleanup func (g *GRPCService) CleanupPreviousInstance(ctx context.Context, log logrus.FieldLogger) error { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, time.Second*10) + ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() log.Info("checking if an instance of localizer is already running") - conn, err := grpc.DialContext(ctx, "unix://"+SocketPath, - grpc.WithBlock(), grpc.WithInsecure()) + client, err := localizer.Connect(ctx, grpc.WithBlock(), grpc.WithInsecure()) // if we made a connection, see if it's responding to pings // eventually we can expose useful information here? if err == nil { - client := apiv1.NewLocalizerServiceClient(conn) - _, err = client.Ping(ctx, &apiv1.PingRequest{}) - if err == nil { + if _, err := client.Ping(ctx, &apiv1.PingRequest{}); err == nil { return fmt.Errorf("localizer instance is already running") } } log.Warn("failed to contact existing instance, cleaning up socket") - return errors.Wrap(os.Remove(SocketPath), "failed to cleanup socket from old localizer instance") + + return errors.Wrap(os.Remove(localizer.Socket), "failed to cleanup socket from old localizer instance") } // Run starts a grpc server with the internal server handler func (g *GRPCService) Run(ctx context.Context, log logrus.FieldLogger) error { //nolint:funlen - if _, err := os.Stat(SocketPath); err == nil { + if _, err := os.Stat(localizer.Socket); err == nil { // if we found an existing instance, attempt to cleanup after it - err = g.CleanupPreviousInstance(ctx, log) - if err != nil { + if err := g.CleanupPreviousInstance(ctx, log); err != nil { return err } } - l, err := net.Listen("unix", SocketPath) + l, err := net.Listen("unix", localizer.Socket) if err != nil { return errors.Wrap(err, "failed to listen on socket") } - defer os.Remove(SocketPath) + defer os.Remove(localizer.Socket) - err = os.Chmod(SocketPath, 0777) + err = os.Chmod(localizer.Socket, 0777) if err != nil { return err } @@ -122,7 +117,7 @@ func (g *GRPCService) Run(ctx context.Context, log logrus.FieldLogger) error { / }() // One day Serve() will accept a context? - log.Infof("starting GRPC server on '%s'", SocketPath) + log.Infof("starting GRPC server on unix://'%s'", localizer.Socket) go func() { err := g.srv.Serve(g.lis) if err != nil { diff --git a/pkg/localizer/localizer.go b/pkg/localizer/localizer.go new file mode 100644 index 0000000..f1a8b48 --- /dev/null +++ b/pkg/localizer/localizer.go @@ -0,0 +1,37 @@ +// Package localizer is meant to contain useful helper functions, variables, and +// constants in order to better programatically interact with localizer. +package localizer + +import ( + "context" + "fmt" + "os" + + apiv1 "github.com/getoutreach/localizer/api/v1" + "github.com/pkg/errors" + "google.golang.org/grpc" +) + +// Socket is the communication endpoint that the localizer server is listening +// on. +const Socket = "/var/run/localizer.sock" + +// IsRunning checks to see if the localizer socket exists. +func IsRunning() bool { + if _, err := os.Stat(Socket); err != nil { + return false + } + + return true +} + +// Connect returns a new instance of LocalizerServiceClient given a gRPC client +// connection (returned from grpc.Dial*). +func Connect(ctx context.Context, opts ...grpc.DialOption) (apiv1.LocalizerServiceClient, error) { + clientConn, err := grpc.DialContext(ctx, fmt.Sprintf("unix://%s", Socket), opts...) + if err != nil { + return nil, errors.Wrap(err, "dial localizer") + } + + return apiv1.NewLocalizerServiceClient(clientConn), nil +}