This repository has been archived by the owner on Dec 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New: Import utilities from other programs
This change adds our storage drivers, a lifecycle implementation for HTTP servers to allow graceful termination, and some string and hash utilities.
- Loading branch information
Showing
1,049 changed files
with
302,338 additions
and
96,542 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package hashutil | ||
|
||
import ( | ||
"encoding/json" | ||
"hash" | ||
) | ||
|
||
type StructuredHash struct { | ||
factory func() hash.Hash | ||
data map[string][]string | ||
} | ||
|
||
func (sh *StructuredHash) Set(name string, values ...string) { | ||
sh.data[name] = values | ||
} | ||
|
||
func (sh *StructuredHash) Sum() (Sum, error) { | ||
b, err := json.Marshal(sh.data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
h := sh.factory() | ||
h.Write(b) | ||
return Sum(h.Sum(nil)), nil | ||
} | ||
|
||
func NewStructuredHash(factory func() hash.Hash) *StructuredHash { | ||
return &StructuredHash{ | ||
factory: factory, | ||
data: make(map[string][]string), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package hashutil | ||
|
||
import "encoding/hex" | ||
|
||
type Sum []byte | ||
|
||
func (s Sum) HexEncoding() string { | ||
return hex.EncodeToString(s) | ||
} | ||
|
||
func (s Sum) String() string { | ||
return s.HexEncoding() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package serving | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/puppetlabs/horsehead/v2/lifecycle" | ||
) | ||
|
||
const ( | ||
// DefaultListenWaitHTTPShutdownTimeout is the time to allow connections to | ||
// cleanly close. 30 seconds is the GKE preemption time, so we cut it a | ||
// little shorter. | ||
DefaultListenWaitHTTPShutdownTimeout = 25 * time.Second | ||
) | ||
|
||
type ListenWaitHTTPOptions struct { | ||
ShutdownTimeout time.Duration | ||
CloserWhens []func(ctx context.Context) error | ||
CloserRequireContexts []func(ctx context.Context) error | ||
TLSCertificateFile string | ||
TLSKeyFile string | ||
} | ||
|
||
type ListenWaitHTTPOption func(opts *ListenWaitHTTPOptions) | ||
|
||
func ListenWaitWithHTTPCloserWhen(fn func(ctx context.Context) error) ListenWaitHTTPOption { | ||
return func(opts *ListenWaitHTTPOptions) { | ||
opts.CloserWhens = append(opts.CloserWhens, fn) | ||
} | ||
} | ||
|
||
func ListenWaitWithHTTPCloserRequireContext(fn func(ctx context.Context) error) ListenWaitHTTPOption { | ||
return func(opts *ListenWaitHTTPOptions) { | ||
opts.CloserRequireContexts = append(opts.CloserRequireContexts, fn) | ||
} | ||
} | ||
|
||
func ListenWaitWithHTTPShutdownTimeout(timeout time.Duration) ListenWaitHTTPOption { | ||
return func(opts *ListenWaitHTTPOptions) { | ||
opts.ShutdownTimeout = timeout | ||
} | ||
} | ||
|
||
func ListenWaitWithTLS(certificateFile, keyFile string) ListenWaitHTTPOption { | ||
return func(opts *ListenWaitHTTPOptions) { | ||
opts.TLSCertificateFile = certificateFile | ||
opts.TLSKeyFile = keyFile | ||
} | ||
} | ||
|
||
// ListenWaitHTTP will run a server and catch the context close but allow | ||
// existing connections to clean up nicely instead of immediately exiting. | ||
func ListenWaitHTTP(ctx context.Context, s *http.Server, opts ...ListenWaitHTTPOption) error { | ||
ho := &ListenWaitHTTPOptions{ | ||
ShutdownTimeout: DefaultListenWaitHTTPShutdownTimeout, | ||
} | ||
for _, opt := range opts { | ||
opt(ho) | ||
} | ||
|
||
cb := lifecycle.NewCloserBuilder(). | ||
Timeout(ho.ShutdownTimeout). | ||
When(func(cctx context.Context) error { | ||
select { | ||
case <-cctx.Done(): | ||
case <-ctx.Done(): | ||
} | ||
|
||
return nil | ||
}). | ||
RequireContext(func(ctx context.Context) error { | ||
return s.Shutdown(ctx) | ||
}) | ||
|
||
for _, when := range ho.CloserWhens { | ||
cb.When(when) | ||
} | ||
|
||
for _, req := range ho.CloserRequireContexts { | ||
cb.RequireContext(req) | ||
} | ||
|
||
closer := cb.Build() | ||
|
||
var err error | ||
if ho.TLSKeyFile != "" { | ||
err = s.ListenAndServeTLS(ho.TLSCertificateFile, ho.TLSKeyFile) | ||
} else { | ||
err = s.ListenAndServe() | ||
} | ||
if err != nil && err != http.ErrServerClosed { | ||
return err | ||
} | ||
|
||
<-closer.Done() | ||
return closer.Err() | ||
} |
Oops, something went wrong.