Skip to content

Commit

Permalink
feat: common package [DTSS-595] (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
george-e-shaw-iv authored Aug 5, 2021
1 parent c4b0e2f commit 57b709c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 31 deletions.
13 changes: 5 additions & 8 deletions cmd/localizer/expose.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -54,22 +53,20 @@ 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?)")
}

ctx, cancel := context.WithTimeout(c.Context, 30*time.Second)
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")
Expand Down
10 changes: 4 additions & 6 deletions cmd/localizer/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down
29 changes: 12 additions & 17 deletions internal/server/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
37 changes: 37 additions & 0 deletions pkg/localizer/localizer.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 57b709c

Please sign in to comment.