initial commit

master
q3k 2018-10-14 08:12:46 -07:00
commit 3fd70d89a0
2 changed files with 174 additions and 0 deletions

53
README Normal file
View File

@ -0,0 +1,53 @@
Mirko, the HSWAW microservice helper library
============================================
Wanna write a Go microservice for HSWAW? Can't be arsed to copy paste code? This is the library for you!
Usage (dev)
-----------
package main
import (
"code.hackerspace.pl/q3k/mirko"
)
func main() {
m := mirko.New()
// setup/checks before TCP ports are opened...
// ...
if err := m.Listen(); err != nil {
glog.Exitf("Listen(): %v", err)
}
// register your gRPC and http handlers...
// (relfection and basic debug http is automatically registered)
// pb.RegisterFooServer(m.GRPC(), s)
// m.HTTPMux().HandleFunc("/debug/foo", fooHandler)
if err := m.Serve(); err != nil {
glog.Exitf("Serve(): %v", err)
}
// start any other background processing...
select {}
}
Usage (running)
---------------
The following flags are automatically registered:
- `-listen_address` (default: `127.0.0.1:42000`): where to listen for gRPC requests
- `-debug_address` (default: `127.0.0.1:42001`): where to listen for debug HTTP requests
Since this library also includes [hspki](https://code.hackerspace.pl/q3k/hspki), you also get all the typical `-hspki_{...}` flags included.
The following debug HTTP handlers are installed:
- `/debug/status`: show the [statusz](https://github.com/q3k/statusz) page
- `/debug/requests`: show the [net/trace](https://godoc.org/golang.org/x/net/trace) page (including gRPC traces)

121
mirko.go Normal file
View File

@ -0,0 +1,121 @@
package mirko
import (
"flag"
"fmt"
"net"
"net/http"
"time"
"code.hackerspace.pl/q3k/hspki"
"github.com/golang/glog"
"github.com/q3k/statusz"
"golang.org/x/net/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
var (
flagListenAddress string
flagDebugAddress string
)
func init() {
flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:42000", "gRPC listen address")
flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:42001", "HTTP debug/status listen address")
}
type Mirko struct {
grpcListen net.Listener
grpcServer *grpc.Server
httpListen net.Listener
httpServer *http.Server
httpMux *http.ServeMux
}
func New() *Mirko {
return &Mirko{}
}
func (m *Mirko) Listen() error {
grpc.EnableTracing = true
grpcLis, err := net.Listen("tcp", flagListenAddress)
if err != nil {
return fmt.Errorf("net.Listen: %v", err)
}
m.grpcListen = grpcLis
m.grpcServer = grpc.NewServer(hspki.WithServerHSPKI()...)
reflection.Register(m.grpcServer)
httpLis, err := net.Listen("tcp", flagDebugAddress)
if err != nil {
return fmt.Errorf("net.Listen: %v", err)
}
m.httpMux = http.NewServeMux()
// Canonical URLs
m.httpMux.HandleFunc("/debug/status", statusz.StatusHandler)
m.httpMux.HandleFunc("/debug/requests", trace.Traces)
// -z legacy URLs
m.httpMux.HandleFunc("/statusz", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/debug/status", http.StatusSeeOther)
})
m.httpMux.HandleFunc("/rpcz", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/debug/requests", http.StatusSeeOther)
})
m.httpMux.HandleFunc("/requestz", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/debug/requests", http.StatusSeeOther)
})
// root redirect
m.httpMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/debug/status", http.StatusSeeOther)
})
m.httpListen = httpLis
m.httpServer = &http.Server{
Addr: flagDebugAddress,
Handler: m.httpMux,
}
return nil
}
func (m *Mirko) GRPC() *grpc.Server {
if m.grpcServer == nil {
panic("GRPC() called before Listen()")
}
return m.grpcServer
}
func (m *Mirko) HTTPMux() *http.ServeMux {
if m.httpMux == nil {
panic("HTTPMux() called before Listen()")
}
return m.httpMux
}
func (m *Mirko) Serve() error {
errs := make(chan error, 1)
go func() {
if err := m.grpcServer.Serve(m.grpcListen); err != nil {
errs <- err
}
}()
go func() {
if err := m.httpServer.Serve(m.httpListen); err != nil {
errs <- err
}
}()
ticker := time.NewTicker(1 * time.Second)
select {
case <-ticker.C:
glog.Infof("gRPC listening on %s", flagListenAddress)
glog.Infof("HTTP listening on %s", flagDebugAddress)
return nil
case err := <-errs:
return err
}
}