Combine controller and worker commands (#415)
This commit is contained in:
1 parent
0a4669e96d
commit
38ce9d9eac
12 files changed
+320
-579
No files matched your search
@@ -449,7 +449,7 @@ func (v *verifier) decryptToken() {
|
||||
// verified is before the current time, with a minute of fudging), and
|
||||
// it's before now, it's expired and might be a replay.
|
||||
if info.CreationTime.Add(globals.RecoveryTokenValidityPeriod).Before(time.Now()) {
|
||||
v.logger.Warn("WARNING: decrypt recovery token: recovery token has expired (possible replay attack)")
|
||||
v.logger.Warn("decrypt recovery token: recovery token has expired (possible replay attack)")
|
||||
v.requestInfo.TokenFormat = AuthTokenTypeUnknown
|
||||
return
|
||||
}
|
||||
@@ -460,10 +460,10 @@ func (v *verifier) decryptToken() {
|
||||
return
|
||||
}
|
||||
if err := repo.AddRecoveryNonce(v.ctx, info.Nonce); err != nil {
|
||||
v.logger.Warn("WARNING: decrypt recovery token: error adding nonce to database (possible replay attack)", "error", err)
|
||||
v.logger.Warn("decrypt recovery token: error adding nonce to database (possible replay attack)", "error", err)
|
||||
v.requestInfo.TokenFormat = AuthTokenTypeUnknown
|
||||
return
|
||||
}
|
||||
v.logger.Info("NOTE: recovery KMS was used to authorize a call", "url", v.requestInfo.Path, "method", v.requestInfo.Method)
|
||||
v.logger.Warn("recovery KMS was used to authorize a call", "url", v.requestInfo.Path, "method", v.requestInfo.Method)
|
||||
}
|
||||
}
|
||||
@@ -73,9 +73,6 @@ type Command struct {
|
||||
FlagDescription string
|
||||
FlagVersion int
|
||||
|
||||
FlagDevPassthroughDirectory string
|
||||
FlagDevRecoveryKey string
|
||||
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// +build dev
|
||||
|
||||
package base
|
||||
|
||||
func init() {
|
||||
DevOnlyControllerFlags = addDevOnlyControllerFlags
|
||||
}
|
||||
|
||||
func addDevOnlyControllerFlags(c *Command, f *FlagSet) {
|
||||
f.StringVar(&StringVar{
|
||||
Name: "dev-passthrough-directory",
|
||||
Target: &c.FlagDevPassthroughDirectory,
|
||||
EnvVar: "BOUNDARY_DEV_PASSTHROUGH_DIRECTORY",
|
||||
Usage: "Enables a passthrough directory in the webserver at /",
|
||||
})
|
||||
|
||||
f.StringVar(&StringVar{
|
||||
Name: "dev-recovery-key",
|
||||
Target: &c.FlagDevRecoveryKey,
|
||||
EnvVar: "BOUNDARY_DEV_RECOVERY_KEY",
|
||||
Usage: "Specifies the base64'd 256-bit AES key to use for recovery operations",
|
||||
})
|
||||
}
|
||||
@@ -100,6 +100,15 @@ func tcpListenerFactory(l *configutil.Listener, logger hclog.Logger, ui cli.Ui)
|
||||
return nil, nil, nil, errors.New("could not determine port")
|
||||
}
|
||||
|
||||
switch purpose {
|
||||
case "cluster":
|
||||
l.TLSDisable = true
|
||||
case "proxy":
|
||||
// TODO: Eventually we'll support bringing your own cert, and we'd only
|
||||
// want to disable if you aren't actually bringing your own
|
||||
l.TLSDisable = true
|
||||
}
|
||||
|
||||
bindProto := "tcp"
|
||||
|
||||
// If they've passed 0.0.0.0, we only want to bind on IPv4
|
||||
|
||||
@@ -68,9 +68,15 @@ type Server struct {
|
||||
|
||||
Listeners []*ServerListener
|
||||
|
||||
DevAuthMethodId string
|
||||
DevLoginName string
|
||||
DevPassword string
|
||||
DevAuthMethodId string
|
||||
DevLoginName string
|
||||
DevPassword string
|
||||
DevOrgId string
|
||||
DevProjectId string
|
||||
DevHostCatalogId string
|
||||
DevHostSetId string
|
||||
DevHostId string
|
||||
DevTargetId string
|
||||
|
||||
DatabaseUrl string
|
||||
DevDatabaseCleanupFunc func() error
|
||||
@@ -198,7 +204,7 @@ func (b *Server) SetupMetrics(ui cli.Ui, telemetry *configutil.Telemetry) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Server) PrintInfo(ui cli.Ui, mode string) {
|
||||
func (b *Server) PrintInfo(ui cli.Ui) {
|
||||
b.InfoKeys = append(b.InfoKeys, "version")
|
||||
verInfo := version.Get()
|
||||
b.Info["version"] = verInfo.FullVersionNumber(false)
|
||||
@@ -221,7 +227,7 @@ func (b *Server) PrintInfo(ui cli.Ui, mode string) {
|
||||
}
|
||||
}
|
||||
sort.Strings(b.InfoKeys)
|
||||
ui.Output(fmt.Sprintf("==> Boundary %s configuration:\n", mode))
|
||||
ui.Output(fmt.Sprintf("==> Boundary server configuration:\n"))
|
||||
for _, k := range b.InfoKeys {
|
||||
ui.Output(fmt.Sprintf(
|
||||
"%s%s: %s",
|
||||
@@ -233,7 +239,7 @@ func (b *Server) PrintInfo(ui cli.Ui, mode string) {
|
||||
|
||||
// Output the header that the server has started
|
||||
if !b.CombineLogs {
|
||||
ui.Output(fmt.Sprintf("==> Boundary %s started! Log data will stream in below:\n", mode))
|
||||
ui.Output(fmt.Sprintf("==> Boundary server started! Log data will stream in below:\n"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,8 +347,8 @@ func (b *Server) SetupKMSes(ui cli.Ui, config *config.Config) error {
|
||||
return errors.New("KMS block missing 'purpose'")
|
||||
case "root", "worker-auth", "config":
|
||||
case "recovery":
|
||||
if config.Controller != nil && config.Controller.DevRecoveryKey != "" {
|
||||
kms.Config["key"] = config.Controller.DevRecoveryKey
|
||||
if config.Controller != nil && config.DevRecoveryKey != "" {
|
||||
kms.Config["key"] = config.DevRecoveryKey
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Unknown KMS purpose %q", kms.Purpose)
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/authmethods"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/authtokens"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/config"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/controller"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/database"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/dev"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/groups"
|
||||
@@ -21,10 +20,10 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/proxy"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/roles"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/scopes"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/server"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/sessions"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/users"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/worker"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
@@ -34,18 +33,8 @@ var Commands map[string]cli.CommandFactory
|
||||
|
||||
func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
Commands = map[string]cli.CommandFactory{
|
||||
"controller": func() (cli.Command, error) {
|
||||
return &controller.Command{
|
||||
Server: base.NewServer(&base.Command{
|
||||
UI: serverCmdUi,
|
||||
ShutdownCh: base.MakeShutdownCh(),
|
||||
}),
|
||||
SighupCh: MakeSighupCh(),
|
||||
SigUSR2Ch: MakeSigUSR2Ch(),
|
||||
}, nil
|
||||
},
|
||||
"worker": func() (cli.Command, error) {
|
||||
return &worker.Command{
|
||||
"server": func() (cli.Command, error) {
|
||||
return &server.Command{
|
||||
Server: base.NewServer(&base.Command{
|
||||
UI: serverCmdUi,
|
||||
ShutdownCh: base.MakeShutdownCh(),
|
||||
|
||||
@@ -171,20 +171,20 @@ func (c *InitCommand) Run(args []string) int {
|
||||
"in a Docker container, provide the IPC_LOCK cap to the container."))
|
||||
}
|
||||
|
||||
if c.Config.Database == nil {
|
||||
c.UI.Error(`"database" config block not found`)
|
||||
if c.Config.Controller.Database == nil {
|
||||
c.UI.Error(`"controller.database" config block not found`)
|
||||
return 1
|
||||
}
|
||||
|
||||
urlToParse := c.Config.Database.Url
|
||||
urlToParse := c.Config.Controller.Database.Url
|
||||
if urlToParse == "" {
|
||||
c.UI.Error(`"url" not specified in "database" config block"`)
|
||||
return 1
|
||||
}
|
||||
|
||||
var migrationUrlToParse string
|
||||
if c.Config.Database.MigrationUrl != "" {
|
||||
migrationUrlToParse = c.Config.Database.MigrationUrl
|
||||
if c.Config.Controller.Database.MigrationUrl != "" {
|
||||
migrationUrlToParse = c.Config.Controller.Database.MigrationUrl
|
||||
}
|
||||
if c.flagMigrationUrl != "" && c.flagMigrationUrl != base.NotSetValue {
|
||||
migrationUrlToParse = c.flagMigrationUrl
|
||||
|
||||
@@ -4,14 +4,15 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
controllercmd "github.com/hashicorp/boundary/internal/cmd/commands/controller"
|
||||
workercmd "github.com/hashicorp/boundary/internal/cmd/commands/worker"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/servers/worker"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
@@ -27,6 +28,10 @@ type Command struct {
|
||||
ReloadedCh chan struct{}
|
||||
SigUSR2Ch chan struct{}
|
||||
|
||||
Config *config.Config
|
||||
controller *controller.Controller
|
||||
worker *worker.Worker
|
||||
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
flagCombineLogs bool
|
||||
@@ -181,9 +186,9 @@ func (c *Command) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
childShutdownCh := make(chan struct{})
|
||||
//childShutdownCh := make(chan struct{})
|
||||
|
||||
devConfig, err := config.DevCombined()
|
||||
c.Config, err = config.DevCombined()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error creating controller dev config: %w", err).Error())
|
||||
return 1
|
||||
@@ -198,6 +203,11 @@ func (c *Command) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
c.DevAuthMethodId = fmt.Sprintf("%s_%s", password.AuthMethodPrefix, c.flagIdSuffix)
|
||||
c.DevOrgId = fmt.Sprintf("%s_%s", scope.Org.Prefix(), c.flagIdSuffix)
|
||||
c.DevProjectId = fmt.Sprintf("%s_%s", scope.Project.Prefix(), c.flagIdSuffix)
|
||||
c.DevHostCatalogId = fmt.Sprintf("%s_%s", static.HostCatalogPrefix, c.flagIdSuffix)
|
||||
c.DevHostSetId = fmt.Sprintf("%s_%s", static.HostSetPrefix, c.flagIdSuffix)
|
||||
c.DevHostId = fmt.Sprintf("%s_%s", static.HostPrefix, c.flagIdSuffix)
|
||||
}
|
||||
if c.flagLoginName != "" {
|
||||
c.DevLoginName = c.flagLoginName
|
||||
@@ -206,11 +216,12 @@ func (c *Command) Run(args []string) int {
|
||||
c.DevPassword = c.flagPassword
|
||||
}
|
||||
|
||||
devConfig.PassthroughDirectory = c.FlagDevPassthroughDirectory
|
||||
c.Config.PassthroughDirectory = c.flagPassthroughDirectory
|
||||
|
||||
for _, l := range devConfig.Listeners {
|
||||
for _, l := range c.Config.Listeners {
|
||||
if len(l.Purpose) != 1 {
|
||||
continue
|
||||
c.UI.Error("Only one purpose supported for each listener")
|
||||
return 1
|
||||
}
|
||||
switch l.Purpose[0] {
|
||||
case "api":
|
||||
@@ -237,15 +248,15 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
base.StartMemProfiler(c.Logger)
|
||||
|
||||
if err := c.SetupMetrics(c.UI, devConfig.Telemetry); err != nil {
|
||||
if err := c.SetupMetrics(c.UI, c.Config.Telemetry); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.FlagDevRecoveryKey != "" {
|
||||
devConfig.Controller.DevRecoveryKey = c.FlagDevRecoveryKey
|
||||
if c.flagRecoveryKey != "" {
|
||||
c.Config.DevRecoveryKey = c.flagRecoveryKey
|
||||
}
|
||||
if err := c.SetupKMSes(c.UI, devConfig); err != nil {
|
||||
if err := c.SetupKMSes(c.UI, c.Config); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
@@ -258,27 +269,27 @@ func (c *Command) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
c.InfoKeys = append(c.InfoKeys, "[Controller] AEAD Key Bytes")
|
||||
c.Info["[Controller] AEAD Key Bytes"] = devConfig.Controller.DevControllerKey
|
||||
c.Info["[Controller] AEAD Key Bytes"] = c.Config.DevControllerKey
|
||||
c.InfoKeys = append(c.InfoKeys, "[Worker-Auth] AEAD Key Bytes")
|
||||
c.Info["[Worker-Auth] AEAD Key Bytes"] = devConfig.Controller.DevWorkerAuthKey
|
||||
c.Info["[Worker-Auth] AEAD Key Bytes"] = c.Config.DevWorkerAuthKey
|
||||
c.InfoKeys = append(c.InfoKeys, "[Recovery] AEAD Key Bytes")
|
||||
c.Info["[Recovery] AEAD Key Bytes"] = devConfig.Controller.DevRecoveryKey
|
||||
c.Info["[Recovery] AEAD Key Bytes"] = c.Config.DevRecoveryKey
|
||||
|
||||
// Initialize the listeners
|
||||
if err := c.SetupListeners(c.UI, devConfig.SharedConfig, []string{"api", "cluster", "proxy"}); err != nil {
|
||||
if err := c.SetupListeners(c.UI, c.Config.SharedConfig, []string{"api", "cluster", "proxy"}); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := c.SetupWorkerPublicAddress(devConfig, c.flagWorkerPublicAddr); err != nil {
|
||||
if err := c.SetupWorkerPublicAddress(c.Config, c.flagWorkerPublicAddr); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
c.InfoKeys = append(c.InfoKeys, "worker public addr")
|
||||
c.Info["worker public addr"] = devConfig.Worker.PublicAddr
|
||||
c.Info["worker public addr"] = c.Config.Worker.PublicAddr
|
||||
|
||||
// Write out the PID to the file now that server has successfully started
|
||||
if err := c.StorePidFile(devConfig.PidFile); err != nil {
|
||||
if err := c.StorePidFile(c.Config.PidFile); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
@@ -298,47 +309,97 @@ func (c *Command) Run(args []string) int {
|
||||
c.ShutdownFuncs = append(c.ShutdownFuncs, c.DestroyDevDatabase)
|
||||
}
|
||||
|
||||
c.PrintInfo(c.UI, "dev mode")
|
||||
c.PrintInfo(c.UI)
|
||||
c.ReleaseLogGate()
|
||||
|
||||
// Instantiate the wait group
|
||||
shutdownWg := &sync.WaitGroup{}
|
||||
shutdownWg.Add(2)
|
||||
controllerSighupCh := make(chan struct{})
|
||||
c.childSighupCh = append(c.childSighupCh, controllerSighupCh)
|
||||
{
|
||||
conf := &controller.Config{
|
||||
RawConfig: c.Config,
|
||||
Server: c.Server,
|
||||
}
|
||||
|
||||
devController := &controllercmd.Command{
|
||||
Server: c.Server,
|
||||
ExtShutdownCh: childShutdownCh,
|
||||
SighupCh: controllerSighupCh,
|
||||
Config: devConfig,
|
||||
}
|
||||
if err := devController.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
var err error
|
||||
c.controller, err = controller.New(conf)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error initializing controller: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
workerSighupCh := make(chan struct{})
|
||||
c.childSighupCh = append(c.childSighupCh, workerSighupCh)
|
||||
devWorker := &workercmd.Command{
|
||||
Server: c.Server,
|
||||
ExtShutdownCh: childShutdownCh,
|
||||
SighupCh: workerSighupCh,
|
||||
Config: devConfig,
|
||||
}
|
||||
if err := devWorker.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
if err := c.controller.Start(); err != nil {
|
||||
retErr := fmt.Errorf("Error starting controller: %w", err)
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(retErr.Error())
|
||||
retErr = fmt.Errorf("Error shutting down controller: %w", err)
|
||||
}
|
||||
c.UI.Error(retErr.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
{
|
||||
conf := &worker.Config{
|
||||
RawConfig: c.Config,
|
||||
Server: c.Server,
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer shutdownWg.Done()
|
||||
devController.WaitForInterrupt()
|
||||
}()
|
||||
go func() {
|
||||
defer shutdownWg.Done()
|
||||
devWorker.WaitForInterrupt()
|
||||
}()
|
||||
var err error
|
||||
c.worker, err = worker.New(conf)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error initializing controller: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := c.worker.Start(); err != nil {
|
||||
retErr := fmt.Errorf("Error starting worker: %w", err)
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(retErr.Error())
|
||||
retErr = fmt.Errorf("Error shutting down worker: %w", err)
|
||||
}
|
||||
c.UI.Error(retErr.Error())
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error with controller shutdown: %w", err).Error())
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
/*
|
||||
shutdownWg := &sync.WaitGroup{}
|
||||
shutdownWg.Add(2)
|
||||
controllerSighupCh := make(chan struct{})
|
||||
c.childSighupCh = append(c.childSighupCh, controllerSighupCh)
|
||||
|
||||
devController := &controllercmd.Command{
|
||||
Server: c.Server,
|
||||
ExtShutdownCh: childShutdownCh,
|
||||
SighupCh: controllerSighupCh,
|
||||
Config: c.Config,
|
||||
}
|
||||
if err := devController.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
workerSighupCh := make(chan struct{})
|
||||
c.childSighupCh = append(c.childSighupCh, workerSighupCh)
|
||||
devWorker := &workercmd.Command{
|
||||
Server: c.Server,
|
||||
ExtShutdownCh: childShutdownCh,
|
||||
SighupCh: workerSighupCh,
|
||||
Config: c.Config,
|
||||
}
|
||||
if err := devWorker.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer shutdownWg.Done()
|
||||
devController.WaitForInterrupt()
|
||||
}()
|
||||
go func() {
|
||||
defer shutdownWg.Done()
|
||||
devWorker.WaitForInterrupt()
|
||||
}()
|
||||
*/
|
||||
|
||||
// Wait for shutdown
|
||||
shutdownTriggered := false
|
||||
@@ -348,16 +409,27 @@ func (c *Command) Run(args []string) int {
|
||||
case <-c.ShutdownCh:
|
||||
c.UI.Output("==> Boundary dev environment shutdown triggered")
|
||||
|
||||
childShutdownCh <- struct{}{}
|
||||
childShutdownCh <- struct{}{}
|
||||
/*
|
||||
childShutdownCh <- struct{}{}
|
||||
childShutdownCh <- struct{}{}
|
||||
*/
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error shutting down worker: %w", err).Error())
|
||||
}
|
||||
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error shutting down controller: %w", err).Error())
|
||||
}
|
||||
|
||||
shutdownTriggered = true
|
||||
|
||||
case <-c.SighupCh:
|
||||
c.UI.Output("==> Boundary dev environment reload triggered")
|
||||
for _, v := range c.childSighupCh {
|
||||
v <- struct{}{}
|
||||
}
|
||||
/*
|
||||
case <-c.SighupCh:
|
||||
c.UI.Output("==> Boundary dev environment reload triggered")
|
||||
for _, v := range c.childSighupCh {
|
||||
v <- struct{}{}
|
||||
}
|
||||
*/
|
||||
|
||||
case <-c.SigUSR2Ch:
|
||||
buf := make([]byte, 32*1024*1024)
|
||||
@@ -366,7 +438,7 @@ func (c *Command) Run(args []string) int {
|
||||
}
|
||||
}
|
||||
|
||||
shutdownWg.Wait()
|
||||
//shutdownWg.Wait()
|
||||
|
||||
return 0
|
||||
}
|
||||
+131
-59
@@ -1,4 +1,4 @@
|
||||
package controller
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller"
|
||||
"github.com/hashicorp/boundary/sdk/strutil"
|
||||
"github.com/hashicorp/boundary/internal/servers/worker"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
@@ -32,6 +32,7 @@ type Command struct {
|
||||
|
||||
Config *config.Config
|
||||
controller *controller.Controller
|
||||
worker *worker.Worker
|
||||
|
||||
configWrapper wrapping.Wrapper
|
||||
|
||||
@@ -43,16 +44,16 @@ type Command struct {
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
return "Start a Boundary controller"
|
||||
return "Start a Boundary server"
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpText := `
|
||||
Usage: boundary controller [options]
|
||||
Usage: boundary server [options]
|
||||
|
||||
Start a controller with a configuration file:
|
||||
Start a server (controller, worker, or both) with a configuration file:
|
||||
|
||||
$ boundary controller -config=/etc/boundary/controller.hcl
|
||||
$ boundary server -config=/etc/boundary/controller.hcl
|
||||
|
||||
For a full list of examples, please see the documentation.
|
||||
|
||||
@@ -141,16 +142,15 @@ func (c *Command) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.FlagDevRecoveryKey != "" {
|
||||
c.Config.Controller.DevRecoveryKey = c.FlagDevRecoveryKey
|
||||
}
|
||||
if err := c.SetupKMSes(c.UI, c.Config); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
if c.RootKms == nil {
|
||||
c.UI.Error("Root KMS not found after parsing KMS blocks")
|
||||
return 1
|
||||
if c.Config.Controller != nil {
|
||||
if c.RootKms == nil {
|
||||
c.UI.Error("Root KMS not found after parsing KMS blocks")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if c.WorkerAuthKms == nil {
|
||||
c.UI.Error("Worker Auth KMS not found after parsing KMS blocks")
|
||||
@@ -175,67 +175,84 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
// Perform controller-specific listener checks here before setup
|
||||
var foundCluster bool
|
||||
var foundAPI bool
|
||||
var foundApi bool
|
||||
var foundProxy bool
|
||||
for _, lnConfig := range c.Config.Listeners {
|
||||
switch len(lnConfig.Purpose) {
|
||||
case 0:
|
||||
c.UI.Error("Listener specified without a purpose")
|
||||
return 1
|
||||
|
||||
case 1:
|
||||
switch lnConfig.Purpose[0] {
|
||||
purpose := lnConfig.Purpose[0]
|
||||
switch purpose {
|
||||
case "cluster":
|
||||
foundCluster = true
|
||||
case "api":
|
||||
foundAPI = true
|
||||
foundApi = true
|
||||
case "proxy":
|
||||
// Do nothing, in a dev mode we might see it here
|
||||
foundProxy = true
|
||||
default:
|
||||
c.UI.Error(fmt.Sprintf("Unknown listener purpose %q", lnConfig.Purpose[0]))
|
||||
return 1
|
||||
}
|
||||
|
||||
case 0:
|
||||
lnConfig.Purpose = []string{"api", "cluster"}
|
||||
fallthrough
|
||||
|
||||
case 2:
|
||||
if !strutil.StrListContains(lnConfig.Purpose, "api") || !strutil.StrListContains(lnConfig.Purpose, "cluster") {
|
||||
c.UI.Error(fmt.Sprintf("Invalid listener purpose set: %v", lnConfig.Purpose))
|
||||
return 1
|
||||
}
|
||||
if lnConfig.TLSDisable {
|
||||
c.UI.Error(fmt.Sprintf("TLS cannot be disabled on listener when serving both %q and %q purposes", "api", "cluster"))
|
||||
return 1
|
||||
}
|
||||
foundAPI = true
|
||||
foundCluster = true
|
||||
default:
|
||||
c.UI.Error("Specifying a listener with more than one purpose is not supported")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if foundAPI && !foundCluster {
|
||||
c.UI.Error("No listener marked for cluster purpose found, but listener explicitly marked for api was found")
|
||||
return 1
|
||||
if c.Config.Controller != nil {
|
||||
if !foundApi {
|
||||
c.UI.Error(`Config activates controller but no listener with "api" purpose found`)
|
||||
return 1
|
||||
}
|
||||
if !foundCluster {
|
||||
c.UI.Error(`Config activates controller but no listener with "cluster" purpose found`)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if err := c.SetupListeners(c.UI, c.Config.SharedConfig, []string{"api", "cluster"}); err != nil {
|
||||
if c.Config.Worker != nil {
|
||||
if !foundProxy {
|
||||
c.UI.Error(`Config activates worker but no listener with "proxy" purpose found`)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if err := c.SetupListeners(c.UI, c.Config.SharedConfig, []string{"api", "cluster", "proxy"}); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.Config.Worker != nil {
|
||||
if err := c.SetupWorkerPublicAddress(c.Config, ""); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
c.InfoKeys = append(c.InfoKeys, "public addr")
|
||||
c.Info["public addr"] = c.Config.Worker.PublicAddr
|
||||
}
|
||||
|
||||
// Write out the PID to the file now that server has successfully started
|
||||
if err := c.StorePidFile(c.Config.PidFile); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.Config.Database == nil || c.Config.Database.Url == "" {
|
||||
c.UI.Error(`"url" not specified in "database" config block"`)
|
||||
return 1
|
||||
}
|
||||
dbaseUrl, err := config.ParseAddress(c.Config.Database.Url)
|
||||
if err != nil && err != config.ErrNotAUrl {
|
||||
c.UI.Error(fmt.Errorf("Error parsing database url: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.DatabaseUrl = strings.TrimSpace(dbaseUrl)
|
||||
if err := c.ConnectToDatabase("postgres"); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error connecting to database: %w", err).Error())
|
||||
return 1
|
||||
if c.Config.Controller != nil {
|
||||
if c.Config.Controller.Database == nil || c.Config.Controller.Database.Url == "" {
|
||||
c.UI.Error(`"url" not specified in "controller.database" config block"`)
|
||||
return 1
|
||||
}
|
||||
dbaseUrl, err := config.ParseAddress(c.Config.Controller.Database.Url)
|
||||
if err != nil && err != config.ErrNotAUrl {
|
||||
c.UI.Error(fmt.Errorf("Error parsing database url: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.DatabaseUrl = strings.TrimSpace(dbaseUrl)
|
||||
if err := c.ConnectToDatabase("postgres"); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error connecting to database: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -244,12 +261,24 @@ func (c *Command) Run(args []string) int {
|
||||
}
|
||||
}()
|
||||
|
||||
c.PrintInfo(c.UI, "controller")
|
||||
c.PrintInfo(c.UI)
|
||||
c.ReleaseLogGate()
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
if c.Config.Controller != nil {
|
||||
if err := c.StartController(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if c.Config.Worker != nil {
|
||||
if err := c.StartWorker(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error with controller shutdown: %w", err).Error())
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
return c.WaitForInterrupt()
|
||||
@@ -293,17 +322,28 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.Config.Controller == nil && c.Config.Worker == nil {
|
||||
c.UI.Error("Neither worker nor controller specified in configuration file.")
|
||||
return 1
|
||||
}
|
||||
if c.Config.Controller != nil && c.Config.Controller.Name == "" {
|
||||
c.UI.Error("Controller has no name set. It must be the unique name of this instance.")
|
||||
return 1
|
||||
}
|
||||
if c.Config.Worker != nil && c.Config.Worker.Name == "" {
|
||||
c.UI.Error("Worker has no name set. It must be the unique name of this instance.")
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Command) Start() error {
|
||||
// Instantiate the wait group
|
||||
func (c *Command) StartController() error {
|
||||
conf := &controller.Config{
|
||||
RawConfig: c.Config,
|
||||
Server: c.Server,
|
||||
}
|
||||
|
||||
// Initialize the core
|
||||
var err error
|
||||
c.controller, err = controller.New(conf)
|
||||
if err != nil {
|
||||
@@ -314,7 +354,31 @@ func (c *Command) Start() error {
|
||||
retErr := fmt.Errorf("Error starting controller: %w", err)
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(retErr.Error())
|
||||
retErr = fmt.Errorf("Error with controller shutdown: %w", err)
|
||||
retErr = fmt.Errorf("Error shutting down controller: %w", err)
|
||||
}
|
||||
return retErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Command) StartWorker() error {
|
||||
conf := &worker.Config{
|
||||
RawConfig: c.Config,
|
||||
Server: c.Server,
|
||||
}
|
||||
|
||||
var err error
|
||||
c.worker, err = worker.New(conf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error initializing worker: %w", err)
|
||||
}
|
||||
|
||||
if err := c.worker.Start(); err != nil {
|
||||
retErr := fmt.Errorf("Error starting worker: %w", err)
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(retErr.Error())
|
||||
retErr = fmt.Errorf("Error shutting down worker: %w", err)
|
||||
}
|
||||
return retErr
|
||||
}
|
||||
@@ -334,10 +398,18 @@ func (c *Command) WaitForInterrupt() int {
|
||||
for !shutdownTriggered {
|
||||
select {
|
||||
case <-shutdownCh:
|
||||
c.UI.Output("==> Boundary controller shutdown triggered")
|
||||
c.UI.Output("==> Boundary server shutdown triggered")
|
||||
|
||||
if err := c.controller.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error with controller shutdown: %w", err).Error())
|
||||
if c.Config.Worker != nil {
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error shutting down worker: %w", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
if c.Config.Controller != nil {
|
||||
if err := c.controller.Shutdown(c.Config.Worker != nil); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error shutting down controller: %w", err).Error())
|
||||
}
|
||||
}
|
||||
|
||||
shutdownTriggered = true
|
||||
@@ -1,381 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/servers/worker"
|
||||
"github.com/hashicorp/boundary/sdk/wrapper"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/vault/sdk/helper/mlock"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*Command)(nil)
|
||||
var _ cli.CommandAutocomplete = (*Command)(nil)
|
||||
|
||||
type Command struct {
|
||||
*base.Server
|
||||
|
||||
ExtShutdownCh chan struct{}
|
||||
SighupCh chan struct{}
|
||||
ReloadedCh chan struct{}
|
||||
SigUSR2Ch chan struct{}
|
||||
|
||||
cleanupGuard sync.Once
|
||||
|
||||
Config *config.Config
|
||||
worker *worker.Worker
|
||||
|
||||
configWrapper wrapping.Wrapper
|
||||
|
||||
flagConfig string
|
||||
flagConfigKms string
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
flagCombineLogs bool
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
return "Start a Boundary worker"
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpText := `
|
||||
Usage: boundary worker [options]
|
||||
|
||||
Start a worker with a configuration file:
|
||||
|
||||
$ boundary worker -config=/etc/boundary/worker.hcl
|
||||
|
||||
For a full list of examples, please see the documentation.
|
||||
|
||||
` + c.Flags().Help()
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetNone)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "config",
|
||||
Target: &c.flagConfig,
|
||||
Completion: complete.PredictOr(
|
||||
complete.PredictFiles("*.hcl"),
|
||||
complete.PredictFiles("*.json"),
|
||||
),
|
||||
Usage: "Path to a configuration file.",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "config-kms",
|
||||
Target: &c.flagConfigKms,
|
||||
Completion: complete.PredictOr(
|
||||
complete.PredictFiles("*.hcl"),
|
||||
complete.PredictFiles("*.json"),
|
||||
),
|
||||
Usage: `Path to a configuration file containing a "kms" block marked for "config" purpose, to perform decryption of the main configuration file. If not set, will look for such a block in the main configuration file, which has some drawbacks; see the help output for "boundary config encrypt -h" for details.`,
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "log-level",
|
||||
Target: &c.flagLogLevel,
|
||||
Default: base.NotSetValue,
|
||||
EnvVar: "BOUNDARY_LOG_LEVEL",
|
||||
Completion: complete.PredictSet("trace", "debug", "info", "warn", "err"),
|
||||
Usage: "Log verbosity level. Supported values (in order of more detail to less) are " +
|
||||
"\"trace\", \"debug\", \"info\", \"warn\", and \"err\".",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "log-format",
|
||||
Target: &c.flagLogFormat,
|
||||
Default: base.NotSetValue,
|
||||
Completion: complete.PredictSet("standard", "json"),
|
||||
Usage: `Log format. Supported values are "standard" and "json".`,
|
||||
})
|
||||
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: "combine-logs",
|
||||
Target: &c.flagCombineLogs,
|
||||
Default: false,
|
||||
Usage: "If set, both startup information and logs will be sent to stdout. If not set (the default), startup information will go to stdout and logs will be sent to stderr.",
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictNothing
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) int {
|
||||
c.CombineLogs = c.flagCombineLogs
|
||||
|
||||
if result := c.ParseFlagsAndConfig(args); result > 0 {
|
||||
return result
|
||||
}
|
||||
|
||||
if c.configWrapper != nil {
|
||||
defer func() {
|
||||
if err := c.configWrapper.Finalize(c.Context); err != nil {
|
||||
c.UI.Warn(fmt.Errorf("Error finalizing config kms: %w", err).Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if err := c.SetupLogging(c.flagLogLevel, c.flagLogFormat, c.Config.LogLevel, c.Config.LogFormat); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
base.StartMemProfiler(c.Logger)
|
||||
|
||||
if err := c.SetupMetrics(c.UI, c.Config.Telemetry); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := c.SetupKMSes(c.UI, c.Config); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
if c.WorkerAuthKms == nil {
|
||||
c.UI.Error("Worker Auth KMS not found after parsing KMS blocks")
|
||||
return 1
|
||||
}
|
||||
|
||||
// If mlockall(2) isn't supported, show a warning. We disable this in dev
|
||||
// because it is quite scary to see when first using Boundary. We also disable
|
||||
// this if the user has explicitly disabled mlock in configuration.
|
||||
if !c.Config.DisableMlock && !mlock.Supported() {
|
||||
c.UI.Warn(base.WrapAtLength(
|
||||
"WARNING! mlock is not supported on this system! An mlockall(2)-like " +
|
||||
"syscall to prevent memory from being swapped to disk is not " +
|
||||
"supported on this system. For better security, only run Boundary on " +
|
||||
"systems where this call is supported. If you are running Boundary" +
|
||||
"in a Docker container, provide the IPC_LOCK cap to the container."))
|
||||
}
|
||||
|
||||
if err := c.SetupListeners(c.UI, c.Config.SharedConfig, []string{"proxy"}); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := c.SetupWorkerPublicAddress(c.Config, ""); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
c.InfoKeys = append(c.InfoKeys, "public addr")
|
||||
c.Info["public addr"] = c.Config.Worker.PublicAddr
|
||||
|
||||
// Write out the PID to the file now that server has successfully started
|
||||
if err := c.StorePidFile(c.Config.PidFile); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error storing PID: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := c.RunShutdownFuncs(); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error running shutdown tasks: %w", err).Error())
|
||||
}
|
||||
}()
|
||||
|
||||
c.PrintInfo(c.UI, "worker")
|
||||
c.ReleaseLogGate()
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
return c.WaitForInterrupt()
|
||||
}
|
||||
|
||||
func (c *Command) ParseFlagsAndConfig(args []string) int {
|
||||
var err error
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err = f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
wrapperPath := c.flagConfig
|
||||
if c.flagConfigKms != "" {
|
||||
wrapperPath = c.flagConfigKms
|
||||
}
|
||||
wrapper, err := wrapper.GetWrapperFromPath(wrapperPath, "config")
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
if wrapper != nil {
|
||||
c.configWrapper = wrapper
|
||||
if err := wrapper.Init(c.Context); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Could not initialize kms: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
if len(c.flagConfig) == 0 {
|
||||
c.UI.Error("Must supply a config file with -config")
|
||||
return 1
|
||||
}
|
||||
c.Config, err = config.LoadFile(c.flagConfig, wrapper)
|
||||
if err != nil {
|
||||
c.UI.Error("Error parsing config: " + err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Command) Start() error {
|
||||
// Instantiate the wait group
|
||||
conf := &worker.Config{
|
||||
RawConfig: c.Config,
|
||||
Server: c.Server,
|
||||
}
|
||||
|
||||
// Initialize the core
|
||||
var err error
|
||||
c.worker, err = worker.New(conf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error initializing worker: %w", err)
|
||||
}
|
||||
|
||||
if err := c.worker.Start(); err != nil {
|
||||
retErr := fmt.Errorf("Error starting worker: %w", err)
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(retErr.Error())
|
||||
retErr = fmt.Errorf("Error with worker shutdown: %w", err)
|
||||
}
|
||||
return retErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Command) WaitForInterrupt() int {
|
||||
// Wait for shutdown
|
||||
shutdownTriggered := false
|
||||
|
||||
shutdownCh := c.ShutdownCh
|
||||
if c.ExtShutdownCh != nil {
|
||||
shutdownCh = c.ExtShutdownCh
|
||||
}
|
||||
|
||||
for !shutdownTriggered {
|
||||
select {
|
||||
case <-shutdownCh:
|
||||
c.UI.Output("==> Boundary worker shutdown triggered")
|
||||
|
||||
if err := c.worker.Shutdown(false); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error with worker shutdown: %w", err).Error())
|
||||
}
|
||||
|
||||
shutdownTriggered = true
|
||||
|
||||
case <-c.SighupCh:
|
||||
c.UI.Output("==> Boundary worker reload triggered")
|
||||
|
||||
// Check for new log level
|
||||
var level hclog.Level
|
||||
var err error
|
||||
var newConf *config.Config
|
||||
|
||||
if c.flagConfig == "" {
|
||||
goto RUNRELOADFUNCS
|
||||
}
|
||||
|
||||
newConf, err = config.LoadFile(c.flagConfig, c.configWrapper)
|
||||
if err != nil {
|
||||
c.Logger.Error("could not reload config", "path", c.flagConfig, "error", err)
|
||||
goto RUNRELOADFUNCS
|
||||
}
|
||||
|
||||
// Ensure at least one config was found.
|
||||
if newConf == nil {
|
||||
c.Logger.Error("no config found at reload time")
|
||||
goto RUNRELOADFUNCS
|
||||
}
|
||||
|
||||
if newConf.LogLevel != "" {
|
||||
configLogLevel := strings.ToLower(strings.TrimSpace(newConf.LogLevel))
|
||||
switch configLogLevel {
|
||||
case "trace":
|
||||
level = hclog.Trace
|
||||
case "debug":
|
||||
level = hclog.Debug
|
||||
case "notice", "info", "":
|
||||
level = hclog.Info
|
||||
case "warn", "warning":
|
||||
level = hclog.Warn
|
||||
case "err", "error":
|
||||
level = hclog.Error
|
||||
default:
|
||||
c.Logger.Error("unknown log level found on reload", "level", newConf.LogLevel)
|
||||
goto RUNRELOADFUNCS
|
||||
}
|
||||
c.Logger.SetLevel(level)
|
||||
}
|
||||
|
||||
RUNRELOADFUNCS:
|
||||
if err := c.Reload(); err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error(s) were encountered during worker reload: %w", err).Error())
|
||||
}
|
||||
|
||||
case <-c.SigUSR2Ch:
|
||||
buf := make([]byte, 32*1024*1024)
|
||||
n := runtime.Stack(buf[:], true)
|
||||
c.Logger.Info("goroutine trace", "stack", string(buf[:n]))
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Command) Reload() error {
|
||||
c.ReloadFuncsLock.RLock()
|
||||
defer c.ReloadFuncsLock.RUnlock()
|
||||
|
||||
var reloadErrors *multierror.Error
|
||||
|
||||
for k, relFuncs := range c.ReloadFuncs {
|
||||
switch {
|
||||
case strings.HasPrefix(k, "listener|"):
|
||||
for _, relFunc := range relFuncs {
|
||||
if relFunc != nil {
|
||||
if err := relFunc(); err != nil {
|
||||
reloadErrors = multierror.Append(reloadErrors, fmt.Errorf("error encountered reloading listener: %w", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send a message that we reloaded. This prevents "guessing" sleep times
|
||||
// in tests.
|
||||
select {
|
||||
case c.ReloadedCh <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
|
||||
return reloadErrors.ErrorOrNil()
|
||||
}
|
||||
@@ -65,7 +65,6 @@ listener "tcp" {
|
||||
|
||||
listener "tcp" {
|
||||
purpose = "cluster"
|
||||
tls_disable = true
|
||||
proxy_protocol_behavior = "allow_authorized"
|
||||
proxy_protocol_authorized_addrs = "127.0.0.1"
|
||||
}
|
||||
@@ -74,7 +73,6 @@ listener "tcp" {
|
||||
devWorkerExtraConfig = `
|
||||
listener "tcp" {
|
||||
purpose = "proxy"
|
||||
tls_disable = true
|
||||
proxy_protocol_behavior = "allow_authorized"
|
||||
proxy_protocol_authorized_addrs = "127.0.0.1"
|
||||
}
|
||||
@@ -91,19 +89,21 @@ worker {
|
||||
type Config struct {
|
||||
*configutil.SharedConfig `hcl:"-"`
|
||||
|
||||
DevController bool `hcl:"-"`
|
||||
PassthroughDirectory string `hcl:"-"`
|
||||
Worker *Worker `hcl:"worker"`
|
||||
Controller *Controller `hcl:"controller"`
|
||||
Database *Database `hcl:"database"`
|
||||
Worker *Worker `hcl:"worker"`
|
||||
Controller *Controller `hcl:"controller"`
|
||||
|
||||
// Dev-related options
|
||||
DevController bool `hcl:"-"`
|
||||
PassthroughDirectory string `hcl:"-"`
|
||||
DevControllerKey string `hcl:"-"`
|
||||
DevWorkerAuthKey string `hcl:"-"`
|
||||
DevRecoveryKey string `hcl:"-"`
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
Name string `hcl:"name"`
|
||||
Description string `hcl:"description"`
|
||||
DevControllerKey string `hcl:"-"`
|
||||
DevWorkerAuthKey string `hcl:"-"`
|
||||
DevRecoveryKey string `hcl:"-"`
|
||||
Name string `hcl:"name"`
|
||||
Description string `hcl:"description"`
|
||||
Database *Database `hcl:"database"`
|
||||
}
|
||||
|
||||
type Worker struct {
|
||||
@@ -159,9 +159,9 @@ func DevController() (*Config, error) {
|
||||
return nil, fmt.Errorf("error parsing dev config: %w", err)
|
||||
}
|
||||
parsed.DevController = true
|
||||
parsed.Controller.DevControllerKey = controllerKey
|
||||
parsed.Controller.DevWorkerAuthKey = workerAuthKey
|
||||
parsed.Controller.DevRecoveryKey = recoveryKey
|
||||
parsed.DevControllerKey = controllerKey
|
||||
parsed.DevWorkerAuthKey = workerAuthKey
|
||||
parsed.DevRecoveryKey = recoveryKey
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
@@ -173,9 +173,9 @@ func DevCombined() (*Config, error) {
|
||||
return nil, fmt.Errorf("error parsing dev config: %w", err)
|
||||
}
|
||||
parsed.DevController = true
|
||||
parsed.Controller.DevControllerKey = controllerKey
|
||||
parsed.Controller.DevWorkerAuthKey = workerAuthKey
|
||||
parsed.Controller.DevRecoveryKey = recoveryKey
|
||||
parsed.DevControllerKey = controllerKey
|
||||
parsed.DevWorkerAuthKey = workerAuthKey
|
||||
parsed.DevRecoveryKey = recoveryKey
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -90,9 +90,9 @@ func TestDevController(t *testing.T) {
|
||||
exp.Seals[0].Config["key"] = actual.Seals[0].Config["key"]
|
||||
exp.Seals[1].Config["key"] = actual.Seals[1].Config["key"]
|
||||
exp.Seals[2].Config["key"] = actual.Seals[2].Config["key"]
|
||||
exp.Controller.DevControllerKey = actual.Seals[0].Config["key"]
|
||||
exp.Controller.DevWorkerAuthKey = actual.Seals[1].Config["key"]
|
||||
exp.Controller.DevRecoveryKey = actual.Seals[2].Config["key"]
|
||||
exp.DevControllerKey = actual.Seals[0].Config["key"]
|
||||
exp.DevWorkerAuthKey = actual.Seals[1].Config["key"]
|
||||
exp.DevRecoveryKey = actual.Seals[2].Config["key"]
|
||||
|
||||
assert.Equal(t, exp, actual)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user