Skip to content

Commit

Permalink
rip apart the main.go into main.gen.go. The user may now modify the m…
Browse files Browse the repository at this point in the history
…ain.go
  • Loading branch information
lukasjarosch committed Jul 23, 2019
1 parent 50db52d commit 0d289ce
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 91 deletions.
5 changes: 3 additions & 2 deletions a_main-packr.go

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ func addCmd(cmd *cobra.Command, args []string) {
os.Exit(1)
}

logrus.Warning("User intervention in 'main.go' required:")
logrus.Info("Ensure to create a new AMQP connection for the subscribers by calling: initRabbitMQ(logger)")
logrus.Info("Use that connection to setup the subscriptions: initSubscriptions(logger, svc, subscriptionConnection")
logrus.Info("If you did not modify the main.go, you can also remove it and let Godin generate everything for you.")

case "publisher":
_, err := transport.InitializeAMQP()
if err != nil {
Expand All @@ -103,6 +108,10 @@ func addCmd(cmd *cobra.Command, args []string) {
os.Exit(1)
}

logrus.Warning("User intervention in 'main.go' required:")
logrus.Info("Ensure to create a new AMQP connection for the publishers by calling: initRabbitMQ(logger)")
logrus.Info("Use that connection to fetch the publishers: publishers := amqp.Publishers(publishConnection, logger)")
logrus.Info("If you did not modify the main.go, you can also remove it and let Godin generate everything for you.")

// TODO: godin.json is NOT a service configuration, thus the 'topic', 'queue' and 'exchange' values must be configurable with ENV variables
}
Expand Down
12 changes: 10 additions & 2 deletions cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ func updateCmd(cmd *cobra.Command, args []string) {
}
}

// cmd/<service>/main.go
main := template.NewGenerator(template.MainStubOptions(tplContext))
if err := main.GenerateFile(TemplateFilesystem); err != nil {
logrus.Warning(fmt.Sprintf("failed to generate cmd/%s/main.go: %s", tplContext.Service.Name, err.Error()))
} else {
logrus.Info(fmt.Sprintf("generated cmd/%s/main.go", tplContext.Service.Name))
}

// k8s/service.yaml
k8sService := template.NewGenerator(template.K8sServiceOptions())
if err := k8sService.GenerateFile(TemplateFilesystem); err != nil {
Expand All @@ -226,10 +234,10 @@ func updateCmd(cmd *cobra.Command, args []string) {
logrus.Info("generated k8s/deployment.yaml")
}

// Makefile // TODO: remove and move to init
// Makefile
makefile := template.NewGenerator(template.MakefileOptions(tplContext))
if err := makefile.GenerateFile(TemplateFilesystem); err != nil {
logrus.Error(fmt.Sprintf("failed to generate Makefile: %s", err.Error()))
logrus.Warning(fmt.Sprintf("failed to generate Makefile: %s", err.Error()))
} else {
logrus.Info("generated Makefile")
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package cmd

import (
"fmt"
"github.com/spf13/cobra"

"github.com/lukasjarosch/godin/internal"
"github.com/spf13/cobra"
)

func init() {
Expand Down
4 changes: 2 additions & 2 deletions internal/generate/cmd_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func NewCmdMain(box packr.Box, serviceInterface *types.Interface, ctx template.C
Context: ctx,
Overwrite: true,
IsGoSource: true,
Template: "cmd_main",
TargetFile: fmt.Sprintf("cmd/%s/main.go", strings.ToLower(ctx.Service.Name)),
Template: "cmd_main_gen",
TargetFile: fmt.Sprintf("cmd/%s/main.gen.go", strings.ToLower(ctx.Service.Name)),
}

for _, opt := range options {
Expand Down
14 changes: 14 additions & 0 deletions internal/template/godin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package template

import (
config "github.com/spf13/viper"
"path"
)

var fileOptions = map[string]GenerateOptions{
Expand All @@ -11,6 +12,11 @@ var fileOptions = map[string]GenerateOptions{
TargetFile: "internal/service/service.go",
Overwrite: true,
},
"cmd_main": {
Template: "cmd_main",
IsGoSource: true,
Overwrite: false,
},
"logging_middleware": {
Template: "logging_middleware",
IsGoSource: true,
Expand Down Expand Up @@ -81,6 +87,14 @@ func FileOptions(name string, tplContext Context, targetPath string) GenerateOpt
return ctx
}

func MainStubOptions(ctx Context) GenerateOptions {
opts := fileOptions["cmd_main"]
opts.TargetFile = path.Join("cmd", ctx.Service.Name, "main.go")
opts.Context = ctx

return opts
}

func K8sDeploymentOptions() GenerateOptions {
ctx := Context{
Service: Service{
Expand Down
86 changes: 4 additions & 82 deletions templates/cmd_main.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Code generated by Godin v{{ .Godin.Version }}; DO NOT EDIT.
// Code generated by Godin v{{ .Godin.Version }}.
package main

import (
Expand Down Expand Up @@ -34,6 +34,8 @@ var g group.Group

func main() {
logger := log.NewLoggerFromEnv()
// setup AMQP connections (separate publish and subscribe connections to reduce AMQP pressure)
{{- if gt (len .Service.Subscriber) 0 }}
rabbitmqSubConn := initRabbitMQ(logger)
defer rabbitmqSubConn.Close()
Expand All @@ -42,8 +44,7 @@ func main() {
rabbitmqPubConn := initRabbitMQ(logger)
defer rabbitmqPubConn.Close()
{{- end }}

{{- if gt (len .Service.Publisher) 0 }}
{{ if gt (len .Service.Publisher) 0 }}
// init publishers
publishers := amqp.Publishers(rabbitmqPubConn, logger)
{{- end }}
Expand All @@ -70,17 +71,6 @@ func main() {
grpcHandler = svcGrpc.NewServer(endpoints, logger)
)

{{- if gt (len .Service.Subscriber) 0 }}
// setup AMQP subscriptions
subscriptions := amqp.Subscriptions(rabbitmqSubConn)
{{- range .Service.Subscriber }}
if err := subscriptions.{{ .Handler }}(logger, svc); err != nil {
logger.Error("failed to create subscription", "err", err)
os.Exit(-1)
}
{{- end }}
{{- end }}

// serve gRPC server
grpcServer := googleGrpc.NewServer(
googleGrpc.UnaryInterceptor(grpc_interceptor.UnaryInterceptor),
Expand Down Expand Up @@ -112,71 +102,3 @@ func main() {
}
}

// getEnv get key environment variable if exist otherwise return defalutValue
func getEnv(key, defaultValue string) string {
value := os.Getenv(key)
if len(value) == 0 {
return defaultValue
}
return value
}

// shutdownHandler to handle graceful shutdowns
func shutdownHandler(interruptChannel chan struct{}) func() error {
return func() error {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
select {
case sig := <-c:
return fmt.Errorf("received signal %s", sig)
case <-interruptChannel:
return nil
}
}
}

// initGrpc serve up GRPC
func initGrpc(grpcServer *googleGrpc.Server, handler pb.{{ .Protobuf.Service }}Server, logger log.Logger) func() error {
grpcListener, err := net.Listen("tcp", GrpcAddr)
if err != nil {
logger.Log("transport", "gRPC", "during", "Listen", "err", err)
os.Exit(1)
}

return func() error {
logger.Log("transport", "gRPC", "addr", GrpcAddr)
pb.Register{{ .Protobuf.Service }}Server(grpcServer, handler)
return grpcServer.Serve(grpcListener)
}
}

{{ if .Service.Transport.AMQP }}
// initRabbitMQ will initialize the amqp connection and create a new channel
func initRabbitMQ(logger log.Logger) *rabbitmq.RabbitMQ {
rabbitmqConn, err := rabbitmq.NewRabbitMQFromEnv()
if err != nil {
logger.Error("failed to initialize RabbitMQ connection", "err", err)
os.Exit(-1)
}
if err := rabbitmqConn.Connect(); err != nil {
logger.Error("failed to connect to RabbitMQ", "err", err)
os.Exit(-1)
}
if rabbitmqConn.Channel, err = rabbitmqConn.NewChannel(); err != nil {
logger.Error("failed to create AMQP channel", "err", err)
os.Exit(-1)
}

return rabbitmqConn
}
{{ end }}

func initDebugHttp(logger log.Logger) net.Listener {
debugListener, err := net.Listen("tcp", DebugAddr)
if err != nil {
logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err)
os.Exit(1)
}
return debugListener
}

100 changes: 100 additions & 0 deletions templates/cmd_main_gen.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Code generated by Godin v{{ .Godin.Version }}; DO NOT EDIT.
package main

import (
"fmt"
"net"
"os"
"os/signal"
"syscall"

googleGrpc "google.golang.org/grpc"
"github.com/go-godin/rabbitmq"

pb "{{ .Protobuf.Package }}"
"{{ .Service.Module }}/internal/amqp"
"{{ .Service.Module }}/internal/service"

"github.com/go-godin/log"
)

// getEnv get key environment variable if exist otherwise return defaultValue
func getEnv(key, defaultValue string) string {
value := os.Getenv(key)
if len(value) == 0 {
return defaultValue
}
return value
}

// shutdownHandler to handle graceful shutdowns
func shutdownHandler(interruptChannel chan struct{}) func() error {
return func() error {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
select {
case sig := <-c:
return fmt.Errorf("received signal %s", sig)
case <-interruptChannel:
return nil
}
}
}

// initGrpc serve up GRPC
func initGrpc(grpcServer *googleGrpc.Server, handler pb.{{ .Protobuf.Service }}Server, logger log.Logger) func() error {
grpcListener, err := net.Listen("tcp", GrpcAddr)
if err != nil {
logger.Log("transport", "gRPC", "during", "Listen", "err", err)
os.Exit(1)
}

return func() error {
logger.Log("transport", "gRPC", "addr", GrpcAddr)
pb.Register{{ .Protobuf.Service }}Server(grpcServer, handler)
return grpcServer.Serve(grpcListener)
}
}

{{ if .Service.Transport.AMQP }}
// initRabbitMQ will initialize the amqp connection and create a new channel
func initRabbitMQ(logger log.Logger) *rabbitmq.RabbitMQ {
rabbitmqConn, err := rabbitmq.NewRabbitMQFromEnv()
if err != nil {
logger.Error("failed to initialize RabbitMQ connection", "err", err)
os.Exit(-1)
}
if err := rabbitmqConn.Connect(); err != nil {
logger.Error("failed to connect to RabbitMQ", "err", err)
os.Exit(-1)
}
if rabbitmqConn.Channel, err = rabbitmqConn.NewChannel(); err != nil {
logger.Error("failed to create AMQP channel", "err", err)
os.Exit(-1)
}

return rabbitmqConn
}
{{ end }}

{{ if gt (len .Service.Subscriber) 0 }}
func initSubscriptions(logger log.Logger, svc service.{{ title .Service.Name}}, connection *rabbitmq.RabbitMQ) {
subscriptions := amqp.Subscriptions(connection)
{{- range .Service.Subscriber }}
if err := subscriptions.{{ .Handler }}(logger, svc); err != nil {
logger.Error("failed to create subscription", "err", err)
os.Exit(-1)
}
{{- end }}
}
{{- end }}

func initDebugHttp(logger log.Logger) net.Listener {
debugListener, err := net.Listen("tcp", DebugAddr)
if err != nil {
logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err)
os.Exit(1)
}
return debugListener
}

4 changes: 2 additions & 2 deletions templates/makefile.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ PROTO_SRC="<< .Protobuf.Path >>"
.PHONY: build
build: check vendor
@echo "--> building"
@go build -o ${GOBIN}/<< .Service.Name >> ./cmd/<< .Service.Name >>/main.go
@go build -o ${GOBIN}/<< .Service.Name >> ./cmd/<< .Service.Name >>/*.go

.PHONY: run
run:
@echo "--> starting locally"
@LOG_LEVEL=debug go run cmd/<< .Service.Name >>/main.go
@LOG_LEVEL=debug go run cmd/<< .Service.Name >>/*.go

.PHONY: vendor
vendor:
Expand Down

0 comments on commit 0d289ce

Please sign in to comment.