From 3fd70d89a0f00f43bb9163fa6b522030728d38ed Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 08:12:46 -0700 Subject: [PATCH 01/11] initial commit --- README | 53 ++++++++++++++++++++++++ mirko.go | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 README create mode 100644 mirko.go diff --git a/README b/README new file mode 100644 index 0000000..fdcdaaa --- /dev/null +++ b/README @@ -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) + diff --git a/mirko.go b/mirko.go new file mode 100644 index 0000000..3acf9b1 --- /dev/null +++ b/mirko.go @@ -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 + } +} From b21f9b9a2ec6ada755aac41595acdf1961d3c48d Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 08:16:33 -0700 Subject: [PATCH 02/11] godepify --- Gopkg.lock | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Gopkg.toml | 50 +++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..4dcbe22 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,180 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + digest = "1:2af0bc306f77bef606f6f6033652f0de3cc80e77008f4da52197b4b0a6be5853" + name = "code.hackerspace.pl/q3k/hspki" + packages = ["."] + pruneopts = "UT" + revision = "624295da664fea57a1e3bd8cee639ae04f4c0ccf" + +[[projects]] + digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214" + name = "github.com/StackExchange/wmi" + packages = ["."] + pruneopts = "UT" + revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338" + version = "1.0.0" + +[[projects]] + digest = "1:64a5a67c69b70c2420e607a8545d674a23778ed9c3e80607bfd17b77c6c87f6a" + name = "github.com/go-ole/go-ole" + packages = [ + ".", + "oleutil", + ] + pruneopts = "UT" + revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506" + version = "v1.2.1" + +[[projects]] + branch = "master" + digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467" + name = "github.com/golang/glog" + packages = ["."] + pruneopts = "UT" + revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" + +[[projects]] + digest = "1:5d1b5a25486fc7d4e133646d834f6fca7ba1cef9903d40e7aa786c41b89e9e91" + name = "github.com/golang/protobuf" + packages = [ + "proto", + "protoc-gen-go/descriptor", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + ] + pruneopts = "UT" + revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" + version = "v1.2.0" + +[[projects]] + branch = "master" + digest = "1:a7cc4447e0c2432f217fd2bed937c100ec475272a7a9306477170c2934297357" + name = "github.com/q3k/statusz" + packages = ["."] + pruneopts = "UT" + revision = "924f04ea71149b75f5b10f426cc4c39d6d90f6f2" + +[[projects]] + branch = "master" + digest = "1:8f042d4b4c48d38d7a1201096299bd26d044c97c032ab20ee171fe5b0d201d2e" + name = "github.com/shirou/gopsutil" + packages = [ + "internal/common", + "load", + ] + pruneopts = "UT" + revision = "a11c78ba2c13c5b1ee59c53296ba35f92f0ce658" + +[[projects]] + branch = "master" + digest = "1:505dbee0833715a72a529bb57c354826ad42a4496fad787fa143699b4de1a6d0" + name = "golang.org/x/net" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "trace", + ] + pruneopts = "UT" + revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a" + +[[projects]] + branch = "master" + digest = "1:f5aa274a0377f85735edc7fedfb0811d3cbc20af91633797cb359e29c3272271" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows", + ] + pruneopts = "UT" + revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844" + +[[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "UT" + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + branch = "master" + digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + pruneopts = "UT" + revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04" + +[[projects]] + digest = "1:dc0c170b110c22d9a4eccf08ab58490608053eac450bf456f3aaf9b30a668781" + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclog", + "internal", + "internal/backoff", + "internal/channelz", + "internal/envconfig", + "internal/grpcrand", + "internal/transport", + "keepalive", + "metadata", + "naming", + "peer", + "reflection", + "reflection/grpc_reflection_v1alpha", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + ] + pruneopts = "UT" + revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" + version = "v1.15.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "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", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..ef3d897 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,50 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "code.hackerspace.pl/q3k/hspki" + +[[constraint]] + branch = "master" + name = "github.com/golang/glog" + +[[constraint]] + branch = "master" + name = "github.com/q3k/statusz" + +[[constraint]] + branch = "master" + name = "golang.org/x/net" + +[[constraint]] + name = "google.golang.org/grpc" + version = "1.15.0" + +[prune] + go-tests = true + unused-packages = true From aa81aa205ff6b570606c2f71542d35d426eabb7d Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 08:36:05 -0700 Subject: [PATCH 03/11] add Trace() and always log to stderr --- mirko.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mirko.go b/mirko.go index 3acf9b1..a2ed85d 100644 --- a/mirko.go +++ b/mirko.go @@ -1,6 +1,7 @@ package mirko import ( + "context" "flag" "fmt" "net" @@ -23,6 +24,7 @@ var ( 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") + flag.Set("logtostderr", "true") } type Mirko struct { @@ -82,6 +84,16 @@ func (m *Mirko) Listen() error { return nil } +func (m *Mirko) Trace(ctx context.Context, f string, args ...interface{}) { + tr, ok := trace.FromContext(ctx) + if !ok { + fmtd := fmt.Sprintf(f, args...) + glog.Warningf("No trace in %v: %s", ctx, fmtd) + return + } + tr.LazyPrintf(f, args...) +} + func (m *Mirko) GRPC() *grpc.Server { if m.grpcServer == nil { panic("GRPC() called before Listen()") From 69de9cb3e4592e02ff05d658b9a7ccc7e5bebc80 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 08:49:04 -0700 Subject: [PATCH 04/11] change default ports to not collide with linux local port space --- mirko.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mirko.go b/mirko.go index a2ed85d..4a5f01f 100644 --- a/mirko.go +++ b/mirko.go @@ -22,8 +22,8 @@ var ( ) 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") + flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:4200", "gRPC listen address") + flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:4201", "HTTP debug/status listen address") flag.Set("logtostderr", "true") } From 2a6175cf6fff061ef6d75505f9e139688b83b0ae Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 08:49:28 -0700 Subject: [PATCH 05/11] bump readme --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index fdcdaaa..940db3f 100644 --- a/README +++ b/README @@ -41,8 +41,8 @@ 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 + - `-listen_address` (default: `127.0.0.1:4200`): where to listen for gRPC requests + - `-debug_address` (default: `127.0.0.1:4201`): 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. From 446c9e1fa6050ac0032d6cf1fffc6e4c8add0455 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 17:06:09 +0100 Subject: [PATCH 06/11] implement basic ACL for debug http --- README | 1 + mirko.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/README b/README index 940db3f..2147adb 100644 --- a/README +++ b/README @@ -43,6 +43,7 @@ The following flags are automatically registered: - `-listen_address` (default: `127.0.0.1:4200`): where to listen for gRPC requests - `-debug_address` (default: `127.0.0.1:4201`): where to listen for debug HTTP requests + - `-debug_allow_all` (default: false): whether to allow all IP address (vs. localhost) to connect to debug endpoint Since this library also includes [hspki](https://code.hackerspace.pl/q3k/hspki), you also get all the typical `-hspki_{...}` flags included. diff --git a/mirko.go b/mirko.go index 4a5f01f..90959ae 100644 --- a/mirko.go +++ b/mirko.go @@ -19,11 +19,13 @@ import ( var ( flagListenAddress string flagDebugAddress string + flagDebugAllowAll bool ) func init() { flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:4200", "gRPC listen address") flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:4201", "HTTP debug/status listen address") + flag.StringVar(&flagDebugAllowAll, "debug_allow_all", false, "HTTP debug/status available to everyone") flag.Set("logtostderr", "true") } @@ -39,8 +41,28 @@ func New() *Mirko { return &Mirko{} } +func authRequest(req *http.Request) (any, sensitive bool) { + host, _, err := net.SplitHostPort(req.RemoteAddr) + if err != nil { + host = req.RemoteAddr + } + + if flagDebugAllowAll { + return true, true + } + + switch host { + case "localhost", "127.0.0.1", "::1": + return true, true + default: + return false, false + } +} + func (m *Mirko) Listen() error { grpc.EnableTracing = true + trace.AuthRequest = authRequest + grpcLis, err := net.Listen("tcp", flagListenAddress) if err != nil { return fmt.Errorf("net.Listen: %v", err) @@ -56,7 +78,14 @@ func (m *Mirko) Listen() error { m.httpMux = http.NewServeMux() // Canonical URLs - m.httpMux.HandleFunc("/debug/status", statusz.StatusHandler) + m.httpMux.HandleFunc("/debug/status", func(w http.ResponseWriter, r *http.Request) { + any, sensitive := authRequest(r) + if !any { + http.Error(w, "not allowed", http.StatusUnauthorized) + return + } + statusz.StatusHandler(w, r) + }) m.httpMux.HandleFunc("/debug/requests", trace.Traces) // -z legacy URLs From f77e7d31afd3d5448bcab91361cef137c7468a82 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 17:11:08 +0100 Subject: [PATCH 07/11] whoops --- mirko.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirko.go b/mirko.go index 90959ae..b40f27a 100644 --- a/mirko.go +++ b/mirko.go @@ -25,7 +25,7 @@ var ( func init() { flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:4200", "gRPC listen address") flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:4201", "HTTP debug/status listen address") - flag.StringVar(&flagDebugAllowAll, "debug_allow_all", false, "HTTP debug/status available to everyone") + flag.BoolVar(&flagDebugAllowAll, "debug_allow_all", false, "HTTP debug/status available to everyone") flag.Set("logtostderr", "true") } From bbb5b5fa96ad35de43bb6873a3b3a5afed0f956a Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 17:13:16 +0100 Subject: [PATCH 08/11] whoops2 --- mirko.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirko.go b/mirko.go index b40f27a..c7778d1 100644 --- a/mirko.go +++ b/mirko.go @@ -79,7 +79,7 @@ func (m *Mirko) Listen() error { m.httpMux = http.NewServeMux() // Canonical URLs m.httpMux.HandleFunc("/debug/status", func(w http.ResponseWriter, r *http.Request) { - any, sensitive := authRequest(r) + any, _ := authRequest(r) if !any { http.Error(w, "not allowed", http.StatusUnauthorized) return From c99e0b916643515374270ec111eccfd2f2973ef4 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 18:03:48 +0100 Subject: [PATCH 09/11] make Trace be a function instead of a method --- mirko.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mirko.go b/mirko.go index c7778d1..417e45d 100644 --- a/mirko.go +++ b/mirko.go @@ -113,7 +113,7 @@ func (m *Mirko) Listen() error { return nil } -func (m *Mirko) Trace(ctx context.Context, f string, args ...interface{}) { +func Trace(ctx context.Context, f string, args ...interface{}) { tr, ok := trace.FromContext(ctx) if !ok { fmtd := fmt.Sprintf(f, args...) From 4f7ee51e9a73e05e5b2dbc6cfa178ace2f83b155 Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Sun, 14 Oct 2018 18:20:59 +0100 Subject: [PATCH 10/11] add background context --- README | 4 +++- mirko.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/README b/README index 2147adb..d2c369f 100644 --- a/README +++ b/README @@ -32,8 +32,10 @@ Usage (dev) } // start any other background processing... + // (you can use m.Context() to get a context that will get + // canceled when the service is about to shut down) - select {} + <-m.Done() } Usage (running) diff --git a/mirko.go b/mirko.go index 417e45d..6ce91fa 100644 --- a/mirko.go +++ b/mirko.go @@ -6,6 +6,8 @@ import ( "fmt" "net" "net/http" + "os" + "os/signal" "time" "code.hackerspace.pl/q3k/hspki" @@ -35,10 +37,19 @@ type Mirko struct { httpListen net.Listener httpServer *http.Server httpMux *http.ServeMux + + ctx context.Context + cancel context.CancelFunc + waiters []chan bool } func New() *Mirko { - return &Mirko{} + ctx, cancel := context.WithCancel(context.Background()) + return &Mirko{ + ctx: ctx, + cancel: cancel, + waiters: []chan bool{}, + } } func authRequest(req *http.Request) (any, sensitive bool) { @@ -113,6 +124,8 @@ func (m *Mirko) Listen() error { return nil } +// Trace logs debug information to either a context trace (if present) +// or stderr (if not) func Trace(ctx context.Context, f string, args ...interface{}) { tr, ok := trace.FromContext(ctx) if !ok { @@ -123,6 +136,7 @@ func Trace(ctx context.Context, f string, args ...interface{}) { tr.LazyPrintf(f, args...) } +// GRPC returns the microservice's grpc.Server object func (m *Mirko) GRPC() *grpc.Server { if m.grpcServer == nil { panic("GRPC() called before Listen()") @@ -130,6 +144,7 @@ func (m *Mirko) GRPC() *grpc.Server { return m.grpcServer } +// HTTPMux returns the microservice's debug HTTP mux func (m *Mirko) HTTPMux() *http.ServeMux { if m.httpMux == nil { panic("HTTPMux() called before Listen()") @@ -137,6 +152,22 @@ func (m *Mirko) HTTPMux() *http.ServeMux { return m.httpMux } +// Context returns a background microservice context that will be canceled +// when the service is shut down +func (m *Mirko) Context() context.Context { + return m.ctx +} + +// Done() returns a channel that will emit a value when the service is +// shut down. This should be used in the main() function instead of a select{} +// call, to allow the background context to be canceled fully. +func (m *Mirko) Done() chan bool { + c := make(chan bool, 1) + m.waiters = append(m.waiters, c) + return c +} + +// Serve starts serving HTTP and gRPC requests func (m *Mirko) Serve() error { errs := make(chan error, 1) go func() { @@ -150,6 +181,19 @@ func (m *Mirko) Serve() error { } }() + signalCh := make(chan os.Signal, 1) + signal.Notify(signalCh, os.Interrupt) + go func() { + select { + case <-signalCh: + m.cancel() + time.Sleep(time.Second) + for _, w := range m.waiters { + w <- true + } + } + }() + ticker := time.NewTicker(1 * time.Second) select { case <-ticker.C: From dccb401e216fccc5aa0fa9af2cae392262cb7cae Mon Sep 17 00:00:00 2001 From: Serge Bazanski Date: Thu, 25 Oct 2018 12:11:16 +0100 Subject: [PATCH 11/11] monorepoization: move everything into mirko/ --- Gopkg.lock | 180 ------------------------------------- Gopkg.toml | 50 ----------- README => mirko/README | 0 mirko.go => mirko/mirko.go | 0 4 files changed, 230 deletions(-) delete mode 100644 Gopkg.lock delete mode 100644 Gopkg.toml rename README => mirko/README (100%) rename mirko.go => mirko/mirko.go (100%) diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 4dcbe22..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,180 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:2af0bc306f77bef606f6f6033652f0de3cc80e77008f4da52197b4b0a6be5853" - name = "code.hackerspace.pl/q3k/hspki" - packages = ["."] - pruneopts = "UT" - revision = "624295da664fea57a1e3bd8cee639ae04f4c0ccf" - -[[projects]] - digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214" - name = "github.com/StackExchange/wmi" - packages = ["."] - pruneopts = "UT" - revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338" - version = "1.0.0" - -[[projects]] - digest = "1:64a5a67c69b70c2420e607a8545d674a23778ed9c3e80607bfd17b77c6c87f6a" - name = "github.com/go-ole/go-ole" - packages = [ - ".", - "oleutil", - ] - pruneopts = "UT" - revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506" - version = "v1.2.1" - -[[projects]] - branch = "master" - digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467" - name = "github.com/golang/glog" - packages = ["."] - pruneopts = "UT" - revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" - -[[projects]] - digest = "1:5d1b5a25486fc7d4e133646d834f6fca7ba1cef9903d40e7aa786c41b89e9e91" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "protoc-gen-go/descriptor", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp", - ] - pruneopts = "UT" - revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" - version = "v1.2.0" - -[[projects]] - branch = "master" - digest = "1:a7cc4447e0c2432f217fd2bed937c100ec475272a7a9306477170c2934297357" - name = "github.com/q3k/statusz" - packages = ["."] - pruneopts = "UT" - revision = "924f04ea71149b75f5b10f426cc4c39d6d90f6f2" - -[[projects]] - branch = "master" - digest = "1:8f042d4b4c48d38d7a1201096299bd26d044c97c032ab20ee171fe5b0d201d2e" - name = "github.com/shirou/gopsutil" - packages = [ - "internal/common", - "load", - ] - pruneopts = "UT" - revision = "a11c78ba2c13c5b1ee59c53296ba35f92f0ce658" - -[[projects]] - branch = "master" - digest = "1:505dbee0833715a72a529bb57c354826ad42a4496fad787fa143699b4de1a6d0" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace", - ] - pruneopts = "UT" - revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a" - -[[projects]] - branch = "master" - digest = "1:f5aa274a0377f85735edc7fedfb0811d3cbc20af91633797cb359e29c3272271" - name = "golang.org/x/sys" - packages = [ - "unix", - "windows", - ] - pruneopts = "UT" - revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844" - -[[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "UT" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - branch = "master" - digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a" - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - pruneopts = "UT" - revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04" - -[[projects]] - digest = "1:dc0c170b110c22d9a4eccf08ab58490608053eac450bf456f3aaf9b30a668781" - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclog", - "internal", - "internal/backoff", - "internal/channelz", - "internal/envconfig", - "internal/grpcrand", - "internal/transport", - "keepalive", - "metadata", - "naming", - "peer", - "reflection", - "reflection/grpc_reflection_v1alpha", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - ] - pruneopts = "UT" - revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" - version = "v1.15.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "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", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index ef3d897..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,50 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[[constraint]] - branch = "master" - name = "code.hackerspace.pl/q3k/hspki" - -[[constraint]] - branch = "master" - name = "github.com/golang/glog" - -[[constraint]] - branch = "master" - name = "github.com/q3k/statusz" - -[[constraint]] - branch = "master" - name = "golang.org/x/net" - -[[constraint]] - name = "google.golang.org/grpc" - version = "1.15.0" - -[prune] - go-tests = true - unused-packages = true diff --git a/README b/mirko/README similarity index 100% rename from README rename to mirko/README diff --git a/mirko.go b/mirko/mirko.go similarity index 100% rename from mirko.go rename to mirko/mirko.go