Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
New: Import utilities from other programs
Browse files Browse the repository at this point in the history
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
impl committed Jun 16, 2020
1 parent 8b3bcbf commit 2086c81
Show file tree
Hide file tree
Showing 1,049 changed files with 302,338 additions and 96,542 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/puppetlabs/horsehead/v2
go 1.13

require (
cloud.google.com/go/storage v1.9.0
github.com/DATA-DOG/go-sqlmock v1.3.3
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261 // indirect
Expand All @@ -17,14 +18,13 @@ require (
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709
github.com/pkg/errors v0.8.1 // indirect
github.com/prometheus/client_golang v0.9.0
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 // indirect
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect
github.com/puppetlabs/errawr-gen v1.0.1
github.com/puppetlabs/errawr-go/v2 v2.2.0
github.com/reflect/xparse v0.0.0-20171128034418-ab29bdc5e11c
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.4.0
golang.org/x/text v0.3.0
golang.org/x/text v0.3.2
google.golang.org/api v0.26.0
gopkg.in/yaml.v2 v2.2.7 // indirect
)
340 changes: 336 additions & 4 deletions go.sum

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions hashutil/structured.go
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),
}
}
13 changes: 13 additions & 0 deletions hashutil/sum.go
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()
}
99 changes: 99 additions & 0 deletions httputil/serving/lifecycle.go
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()
}
Loading

0 comments on commit 2086c81

Please sign in to comment.