From 1ebd7deccf35d4f7947ff3f7bd2ec52258962f9e Mon Sep 17 00:00:00 2001 From: Hugo Vieira Date: Wed, 9 Mar 2022 19:50:11 +0000 Subject: [PATCH] refactor(worker): Validate listener configuration in New With this change, the Worker is now aware of its own listeners in a more codified and structured way. These changes have already been made in the controller on 8d48a8515cb8c14aebf58f04c1d38a9b87db48b7. They're now made on the worker for similar reasons. --- internal/servers/worker/worker.go | 20 +++++ internal/servers/worker/worker_test.go | 100 +++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 internal/servers/worker/worker_test.go diff --git a/internal/servers/worker/worker.go b/internal/servers/worker/worker.go index f7ca0163e..7141e2aba 100644 --- a/internal/servers/worker/worker.go +++ b/internal/servers/worker/worker.go @@ -14,6 +14,7 @@ import ( "sync/atomic" "time" + "github.com/hashicorp/boundary/internal/cmd/base" "github.com/hashicorp/boundary/internal/cmd/config" pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services" "github.com/hashicorp/boundary/internal/observability/event" @@ -45,6 +46,8 @@ type Worker struct { controllerSessionConn *atomic.Value sessionInfoMap *sync.Map + listeners []*base.ServerListener + // We store the current set in an atomic value so that we can add // reload-on-sighup behavior later tags *atomic.Value @@ -105,6 +108,23 @@ func New(conf *Config) (*Worker, error) { } } + for i := range conf.Listeners { + l := conf.Listeners[i] + if l == nil || l.Config == nil || l.Config.Purpose == nil { + continue + } + if len(l.Config.Purpose) != 1 { + return nil, fmt.Errorf("found listener with multiple purposes %q", strings.Join(l.Config.Purpose, ",")) + } + switch l.Config.Purpose[0] { + case "proxy": + w.listeners = append(w.listeners, l) + } + } + if len(w.listeners) == 0 { + return nil, fmt.Errorf("no proxy listeners found") + } + return w, nil } diff --git a/internal/servers/worker/worker_test.go b/internal/servers/worker/worker_test.go new file mode 100644 index 000000000..62136f53c --- /dev/null +++ b/internal/servers/worker/worker_test.go @@ -0,0 +1,100 @@ +package worker + +import ( + "testing" + + "github.com/hashicorp/boundary/internal/cmd/base" + "github.com/hashicorp/boundary/internal/cmd/config" + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-secure-stdlib/configutil/v2" + "github.com/hashicorp/go-secure-stdlib/listenerutil" + "github.com/stretchr/testify/require" +) + +func TestWorkerNewListenerConfig(t *testing.T) { + tests := []struct { + name string + in *Config + expErr bool + expErrMsg string + assertions func(t *testing.T, w *Worker) + }{ + { + name: "nil listeners", + in: &Config{Server: &base.Server{Listeners: nil}}, + expErr: true, + expErrMsg: "no proxy listeners found", + }, + { + name: "zero listeners", + in: &Config{Server: &base.Server{Listeners: []*base.ServerListener{}}}, + expErr: true, + expErrMsg: "no proxy listeners found", + }, + { + name: "populated with nil values", + in: &Config{ + Server: &base.Server{ + Listeners: []*base.ServerListener{ + nil, + {Config: nil}, + {Config: &listenerutil.ListenerConfig{Purpose: nil}}, + }, + }, + }, + expErr: true, + expErrMsg: "no proxy listeners found", + }, + { + name: "multiple purposes", + in: &Config{ + Server: &base.Server{ + Listeners: []*base.ServerListener{ + nil, + {Config: nil}, + {Config: &listenerutil.ListenerConfig{Purpose: []string{"api", "proxy"}}}, + }, + }, + }, + expErr: true, + expErrMsg: `found listener with multiple purposes "api,proxy"`, + }, + { + name: "valid listeners", + in: &Config{ + Server: &base.Server{ + Listeners: []*base.ServerListener{ + {Config: &listenerutil.ListenerConfig{Purpose: []string{"api"}}}, + {Config: &listenerutil.ListenerConfig{Purpose: []string{"proxy"}}}, + {Config: &listenerutil.ListenerConfig{Purpose: []string{"proxy"}}}, + {Config: &listenerutil.ListenerConfig{Purpose: []string{"cluster"}}}, + }, + }, + }, + expErr: false, + assertions: func(t *testing.T, w *Worker) { + require.Len(t, w.listeners, 2) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // New() panics if these aren't set + tt.in.Logger = hclog.Default() + tt.in.RawConfig = &config.Config{SharedConfig: &configutil.SharedConfig{DisableMlock: true}} + + w, err := New(tt.in) + if tt.expErr { + require.EqualError(t, err, tt.expErrMsg) + require.Nil(t, w) + return + } + + require.NoError(t, err) + if tt.assertions != nil { + tt.assertions(t, w) + } + }) + } +}