Migrate a bunch of stuff around to prep for worker command (#2)

Right now it's essentially a copy; it needs some updating, integration
into dev, and so on.
This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-03-19 15:17:40 -04:00
1 parent c2d385d851
commit 1645c3106e
18 files changed
+1200 -157

No files matched your search

+11 -11
View File
@@ -54,7 +54,7 @@ Usage: watchtower controller [options]
Start a controller with a configuration file:
$ watchtower controller -config=/etc/controller/config.hcl
$ watchtower controller -config=/etc/watchtower/controller.hcl
For a full list of examples, please see the documentation.
@@ -147,15 +147,15 @@ func (c *Command) Run(args []string) int {
return result
}
if memProfilerEnabled {
c.startMemProfiler()
}
if err := c.SetupLogging(c.flagLogLevel, c.flagLogFormat, c.Config.LogLevel, c.Config.LogFormat); err != nil {
c.UI.Error(err.Error())
return 1
}
if memProfilerEnabled {
base.StartMemProfiler(c.Logger)
}
if err := c.SetupMetrics(c.UI, c.Config.Telemetry); err != nil {
c.UI.Error(err.Error())
return 1
@@ -259,21 +259,21 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
func (c *Command) Start() int {
// Instantiate the wait group
controllerConfig := &controller.Config{
conf := &controller.Config{
RawConfig: c.Config,
Server: c.Server,
}
// Initialize the core
controller, err := controller.New(controllerConfig)
ctlr, err := controller.New(conf)
if err != nil {
c.UI.Error(fmt.Sprintf("Error initializing controller: %w", err))
return 1
}
if err := controller.Start(); err != nil {
if err := ctlr.Start(); err != nil {
c.UI.Error(fmt.Sprint("Error starting controller: %w", err))
if err := controller.Shutdown(); err != nil {
if err := ctlr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with controller shutdown: %w", err))
}
return 1
@@ -287,7 +287,7 @@ func (c *Command) Start() int {
case <-c.ShutdownCh:
c.UI.Output("==> Watchtower controller shutdown triggered")
if err := controller.Shutdown(); err != nil {
if err := ctlr.Shutdown(); err != nil {
c.UI.Error(fmt.Sprintf("Error with controller shutdown: %w", err))
}
@@ -337,7 +337,7 @@ func (c *Command) Start() int {
c.Logger.Error("unknown log level found on reload", "level", newConf.LogLevel)
goto RUNRELOADFUNCS
}
controller.SetLogLevel(level)
ctlr.SetLogLevel(level)
}
RUNRELOADFUNCS:
@@ -1,6 +0,0 @@
// +build !memprofiler
package controller
func (c *Command) startMemProfiler() {
}
@@ -1,40 +0,0 @@
// +build memprofiler
package controller
import (
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"time"
)
func init() {
memProfilerEnabled = true
}
func (c *Command) startMemProfiler() {
profileDir := filepath.Join(os.TempDir(), "watchtowerprof")
if err := os.MkdirAll(profileDir, 0700); err != nil {
c.logger.Debug("could not create profile directory", "error", err)
return
}
go func() {
for {
filename := filepath.Join(profileDir, time.Now().UTC().Format("20060102_150405")) + ".pprof"
f, err := os.Create(filename)
if err != nil {
c.logger.Debug("could not create memory profile", "error", err)
}
runtime.GC()
if err := pprof.WriteHeapProfile(f); err != nil {
c.logger.Debug("could not write memory profile", "error", err)
}
f.Close()
c.logger.Debug("wrote memory profile", "filename", filename)
time.Sleep(5 * time.Minute)
}
}()
}
@@ -1,81 +0,0 @@
package listener
import (
"errors"
"io"
"github.com/pires/go-proxyproto"
// We must import sha512 so that it registers with the runtime so that
// certificates that use it can be parsed.
_ "crypto/sha512"
"fmt"
"net"
"github.com/hashicorp/go-alpnmux"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/hashicorp/vault/internalshared/reloadutil"
"github.com/mitchellh/cli"
)
// Factory is the factory function to create a listener.
type Factory func(*configutil.Listener, io.Writer, cli.Ui) (*alpnmux.ALPNMux, map[string]string, reloadutil.ReloadFunc, error)
// BuiltinListeners is the list of built-in listener types.
var BuiltinListeners = map[string]Factory{
"tcp": tcpListenerFactory,
}
// New creates a new listener of the given type with the given
// configuration. The type is looked up in the BuiltinListeners map.
func New(l *configutil.Listener, w io.Writer, ui cli.Ui) (*alpnmux.ALPNMux, map[string]string, reloadutil.ReloadFunc, error) {
f, ok := BuiltinListeners[l.Type]
if !ok {
return nil, nil, nil, fmt.Errorf("unknown listener type: %q", l.Type)
}
return f(l, w, ui)
}
func listenerWrapProxy(ln net.Listener, l *configutil.Listener) (net.Listener, error) {
behavior := l.ProxyProtocolBehavior
if behavior == "" {
return ln, nil
}
authorizedAddrs := make([]string, 0, len(l.ProxyProtocolAuthorizedAddrs))
for _, v := range l.ProxyProtocolAuthorizedAddrs {
authorizedAddrs = append(authorizedAddrs, v.String())
}
var policyFunc proxyproto.PolicyFunc
switch behavior {
case "use_always":
policyFunc = func(upstream net.Addr) (proxyproto.Policy, error) {
return proxyproto.USE, nil
}
case "allow_authorized":
if len(authorizedAddrs) == 0 {
return nil, errors.New("proxy_protocol_behavior set but no proxy_protocol_authorized_addrs value")
}
policyFunc = proxyproto.MustLaxWhiteListPolicy(authorizedAddrs)
case "deny_unauthorized":
if len(authorizedAddrs) == 0 {
return nil, errors.New("proxy_protocol_behavior set but no proxy_protocol_authorized_addrs value")
}
policyFunc = proxyproto.MustStrictWhiteListPolicy(authorizedAddrs)
default:
return nil, fmt.Errorf("unknown %q value: %q", "proxy_protocol_behavior", behavior)
}
proxyListener := &proxyproto.Listener{
Listener: ln,
Policy: policyFunc,
}
return proxyListener, nil
}
@@ -1,90 +0,0 @@
package listener
import (
"io"
"net"
"strings"
"time"
"github.com/hashicorp/go-alpnmux"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/hashicorp/vault/internalshared/listenerutil"
"github.com/hashicorp/vault/internalshared/reloadutil"
"github.com/mitchellh/cli"
)
func tcpListenerFactory(l *configutil.Listener, _ io.Writer, ui cli.Ui) (*alpnmux.ALPNMux, map[string]string, reloadutil.ReloadFunc, error) {
if l.Address == "" {
l.Address = "127.0.0.1:9200"
}
bindProto := "tcp"
// If they've passed 0.0.0.0, we only want to bind on IPv4
// rather than golang's dual stack default
if strings.HasPrefix(l.Address, "0.0.0.0:") {
bindProto = "tcp4"
}
ln, err := net.Listen(bindProto, l.Address)
if err != nil {
return nil, nil, nil, err
}
ln = TCPKeepAliveListener{ln.(*net.TCPListener)}
ln, err = listenerWrapProxy(ln, l)
if err != nil {
return nil, nil, nil, err
}
props := map[string]string{
"addr": l.Address,
}
alpnMux := alpnmux.New(ln, nil)
if l.TLSDisable {
if _, err = alpnMux.RegisterProto(alpnmux.NoProto, nil); err != nil {
return nil, nil, nil, err
}
return alpnMux, props, nil, nil
}
tlsConfig, reloadFunc, err := listenerutil.GetTLSConfig(ln, l, props, ui)
if err != nil {
return nil, nil, nil, err
}
// Register no proto, "http/1.1", and "h2", with same TLS config
if _, err = alpnMux.RegisterProto("", tlsConfig); err != nil {
return nil, nil, nil, err
}
if _, err = alpnMux.RegisterProto("http/1.1", tlsConfig); err != nil {
return nil, nil, nil, err
}
if _, err = alpnMux.RegisterProto("h2", tlsConfig); err != nil {
return nil, nil, nil, err
}
return alpnMux, props, reloadFunc, nil
}
// TCPKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
//
// This is copied directly from the Go source code.
type TCPKeepAliveListener struct {
*net.TCPListener
}
func (ln TCPKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}