Skip to content

Commit

Permalink
Merge pull request #54 from weaveworks/52_separate_gw
Browse files Browse the repository at this point in the history
refactor: split http gateway into seperate command
  • Loading branch information
richardcase authored Aug 11, 2021
2 parents 8acd3b7 + b4b2b6e commit 074b7d0
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 49 deletions.
34 changes: 34 additions & 0 deletions internal/command/flags/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package flags

import (
"github.com/spf13/cobra"

"github.com/weaveworks/reignite/internal/config"
"github.com/weaveworks/reignite/pkg/defaults"
)

const (
grpcEndpointFlag = "grpc-endpoint"
httpEndpointFlag = "http-endpoint"
)

// AddGRPCServerFlagsToCommand will add gRPC server flags to the supplied command.
func AddGRPCServerFlagsToCommand(cmd *cobra.Command, cfg *config.Config) {
cmd.Flags().StringVar(&cfg.GRPCAPIEndpoint,
grpcEndpointFlag,
defaults.GRPCAPIEndpoint,
"The endpoint for the gRPC server to listen on.")
}

// AddGWServerFlagsToCommand will add gRPC HTTP gateway flags to the supplied command.
func AddGWServerFlagsToCommand(cmd *cobra.Command, cfg *config.Config) {
cmd.Flags().StringVar(&cfg.GRPCAPIEndpoint,
grpcEndpointFlag,
defaults.GRPCAPIEndpoint,
"The address of the gRPC server to act as a gateway for.")

cmd.Flags().StringVar(&cfg.HTTPAPIEndpoint,
httpEndpointFlag,
defaults.HTTPAPIEndpoint,
"The endpoint for the HTTP proxy to the gRPC service to listen on.")
}
126 changes: 126 additions & 0 deletions internal/command/gw/gw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package gw

import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"sync"

"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/spf13/cobra"
"google.golang.org/grpc"

mvmv1 "github.com/weaveworks/reignite/api/services/microvm/v1alpha1"
cmdflags "github.com/weaveworks/reignite/internal/command/flags"
"github.com/weaveworks/reignite/internal/config"
"github.com/weaveworks/reignite/pkg/flags"
"github.com/weaveworks/reignite/pkg/log"
)

// NewCommand creates a new cobra command for running the gRPC HTTP gateway.
func NewCommand(cfg *config.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "gw",
Short: "Start serving the HTTP gateway for the reignite gRPC API",
PreRunE: func(c *cobra.Command, _ []string) error {
flags.BindCommandToViper(c)

return nil
},
RunE: func(c *cobra.Command, _ []string) error {
return runGWServer(c.Context(), cfg)
},
}

cmdflags.AddGWServerFlagsToCommand(cmd, cfg)

return cmd
}

func runGWServer(ctx context.Context, cfg *config.Config) error {
logger := log.GetLogger(ctx)
logger.Info("reignited grpc api gateway starting")

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)

wg := &sync.WaitGroup{}
ctx, cancel := context.WithCancel(log.WithLogger(ctx, logger))

wg.Add(1)
go func() {
defer wg.Done()
if err := serveAPI(ctx, cfg); err != nil {
logger.Errorf("failed serving api: %v", err)
}
}()

<-sigChan
logger.Debug("shutdown signal received, waiting for work to finish")

cancel()
wg.Wait()

logger.Info("all work finished, exiting")

return nil
}

func serveAPI(ctx context.Context, cfg *config.Config) error {
logger := log.GetLogger(ctx)
mux := runtime.NewServeMux()

// TODO: create the dependencies for the server

// grpcServer := grpc.NewServer(
// grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
// grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
// )
// mvmv1.RegisterMicroVMServer(grpcServer, server.NewServer())
// grpc_prometheus.Register(grpcServer)
// http.Handle("/metrics", promhttp.Handler())

opts := []grpc.DialOption{
grpc.WithInsecure(),
}

if err := mvmv1.RegisterMicroVMHandlerFromEndpoint(ctx, mux, cfg.GRPCAPIEndpoint, opts); err != nil {
return fmt.Errorf("could not register microvm server: %w", err)
}

s := &http.Server{
Addr: cfg.HTTPAPIEndpoint,
Handler: mux,
}

go func() {
<-ctx.Done()
logger.Infof("shutting down the http gateway server")
if err := s.Shutdown(context.Background()); err != nil {
logger.Errorf("failed to shutdown http gateway server: %v", err)
}
// logger.Infof("shutting down grpc server")
// grpcServer.GracefulStop()
}()

// logger.Debugf("starting grpc server listening on endpoint %s", cfg.GRPCAPIEndpoint)
// l, err := net.Listen("tcp", cfg.GRPCAPIEndpoint)
// if err != nil {
// return fmt.Errorf("setting up gRPC api listener: %w", err)
// }
// defer l.Close()
// go func() {
// if err := grpcServer.Serve(l); err != nil {
// logger.Fatalf("serving grpc api: %v", err) // TODO: remove this fatal
// }
// }()

logger.Debugf("starting http server listening on endpoint %s", cfg.HTTPAPIEndpoint)
if err := s.ListenAndServe(); err != nil {
return fmt.Errorf("listening and serving http api: %w", err)
}

return nil
}
12 changes: 9 additions & 3 deletions internal/command/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/weaveworks/reignite/internal/command/gw"
"github.com/weaveworks/reignite/internal/command/run"
"github.com/weaveworks/reignite/internal/config"
"github.com/weaveworks/reignite/pkg/defaults"
"github.com/weaveworks/reignite/pkg/flags"
"github.com/weaveworks/reignite/pkg/log"
)

func NewRootCommand() (*cobra.Command, error) {
cfg := &Config{}
cfg := &config.Config{}

cmd := &cobra.Command{
Use: "reignited",
Expand Down Expand Up @@ -54,7 +57,10 @@ func initCobra() {
viper.ReadInConfig() //nolint: errcheck
}

func addRootSubCommands(cmd *cobra.Command, cfg *Config) {
runCmd := newRunCommand(cfg)
func addRootSubCommands(cmd *cobra.Command, cfg *config.Config) {
runCmd := run.NewCommand(cfg)
cmd.AddCommand(runCmd)

gwCmd := gw.NewCommand(cfg)
cmd.AddCommand(gwCmd)
}
56 changes: 11 additions & 45 deletions internal/command/run.go → internal/command/run/run.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package command
package run

import (
"context"
Expand All @@ -10,19 +10,20 @@ import (
"sync"

grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
"google.golang.org/grpc"

mvmv1 "github.com/weaveworks/reignite/api/services/microvm/v1alpha1"
"github.com/weaveworks/reignite/pkg/defaults"
cmdflags "github.com/weaveworks/reignite/internal/command/flags"
"github.com/weaveworks/reignite/internal/config"
"github.com/weaveworks/reignite/pkg/flags"
"github.com/weaveworks/reignite/pkg/log"
"github.com/weaveworks/reignite/pkg/server"
)

func newRunCommand(cfg *Config) *cobra.Command {
// NewCommand creates a new cobra command for running reignite.
func NewCommand(cfg *config.Config) *cobra.Command {
cmd := &cobra.Command{
Use: "run",
Short: "Start running the reignite API",
Expand All @@ -36,25 +37,14 @@ func newRunCommand(cfg *Config) *cobra.Command {
},
}

addFlagsToCommand(cmd, cfg)
cmdflags.AddGRPCServerFlagsToCommand(cmd, cfg)

return cmd
}

func addFlagsToCommand(cmd *cobra.Command, cfg *Config) {
cmd.Flags().StringVar(&cfg.GRPCAPIEndpoint,
"grpc-endpoint",
defaults.GRPCAPIEndpoint,
"The endpoint for the gRPC server to listen on.")
cmd.Flags().StringVar(&cfg.HTTPAPIEndpoint,
"http-endpoint",
defaults.HTTPAPIEndpoint,
"The endpoint for the HTTP proxy to the gRPC service to listen on.")
}

func runServer(ctx context.Context, cfg *Config) error {
func runServer(ctx context.Context, cfg *config.Config) error {
logger := log.GetLogger(ctx)
logger.Info("reignited api server starting")
logger.Info("reignited grpc api server starting")

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
Expand Down Expand Up @@ -83,9 +73,8 @@ func runServer(ctx context.Context, cfg *Config) error {
return nil
}

func serveAPI(ctx context.Context, cfg *Config) error {
func serveAPI(ctx context.Context, cfg *config.Config) error {
logger := log.GetLogger(ctx)
mux := runtime.NewServeMux()

// TODO: create the dependencies for the server

Expand All @@ -97,25 +86,8 @@ func serveAPI(ctx context.Context, cfg *Config) error {
grpc_prometheus.Register(grpcServer)
http.Handle("/metrics", promhttp.Handler())

opts := []grpc.DialOption{
grpc.WithInsecure(),
}

if err := mvmv1.RegisterMicroVMHandlerFromEndpoint(ctx, mux, cfg.GRPCAPIEndpoint, opts); err != nil {
return fmt.Errorf("could not register microvm server: %w", err)
}

s := &http.Server{
Addr: cfg.HTTPAPIEndpoint,
Handler: mux,
}

go func() {
<-ctx.Done()
logger.Infof("shutting down the http gateway server")
if err := s.Shutdown(context.Background()); err != nil {
logger.Errorf("failed to shutdown http gateway server: %v", err)
}
logger.Infof("shutting down grpc server")
grpcServer.GracefulStop()
}()
Expand All @@ -126,15 +98,9 @@ func serveAPI(ctx context.Context, cfg *Config) error {
return fmt.Errorf("setting up gRPC api listener: %w", err)
}
defer l.Close()
go func() {
if err := grpcServer.Serve(l); err != nil {
logger.Fatalf("serving grpc api: %v", err) // TODO: remove this fatal
}
}()

logger.Debugf("starting http server listening on endpoint %s", cfg.HTTPAPIEndpoint)
if err := s.ListenAndServe(); err != nil {
return fmt.Errorf("listening and serving http api: %w", err)
if err := grpcServer.Serve(l); err != nil {
logger.Fatalf("serving grpc api: %v", err) // TODO: remove this fatal
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/command/config.go → internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package command
package config

import (
"github.com/weaveworks/reignite/pkg/log"
Expand Down

0 comments on commit 074b7d0

Please sign in to comment.