feat(workers): worker operational state (#2427)

* feat(workers): worker operational state
This commit is contained in:
Irena Rindos authored and GitHub committed 2022-09-12 16:10:03 -04:00
1 parent f3f0c55d91
commit fc0ead73e6
17 files changed
+696 -166

No files matched your search

@@ -92,12 +92,23 @@ func (ws *workerServiceServer) Status(ctx context.Context, req *pbs.StatusReques
})
}
if wStat.OperationalState == "" {
// If this is an older worker (pre 0.11), it will not have ReleaseVersion and we'll default to active.
// Otherwise, default to Uknown.
if wStat.ReleaseVersion == "" {
wStat.OperationalState = server.ActiveOperationalState.String()
} else {
wStat.OperationalState = server.UnknownOperationalState.String()
}
}
wConf := server.NewWorker(scope.Global.String(),
server.WithName(wStat.GetName()),
server.WithDescription(wStat.GetDescription()),
server.WithAddress(wStat.GetAddress()),
server.WithWorkerTags(workerTags...),
server.WithReleaseVersion(wStat.ReleaseVersion))
server.WithReleaseVersion(wStat.ReleaseVersion),
server.WithOperationalState(wStat.OperationalState))
opts := []server.Option{server.WithUpdateTags(req.GetUpdateTags())}
if wStat.GetPublicId() != "" {
opts = append(opts, server.WithPublicId(wStat.GetPublicId()))
@@ -723,3 +723,108 @@ func TestStatusWorkerWithKeyId(t *testing.T) {
})
}
}
func TestWorkerOperationalStatus(t *testing.T) {
ctx := context.Background()
conn, _ := db.TestSetup(t, "postgres")
rw := db.New(conn)
wrapper := db.TestWrapper(t)
kms := kms.TestKms(t, conn, wrapper)
serverRepo, _ := server.NewRepository(rw, rw, kms)
serverRepo.UpsertController(ctx, &store.Controller{
PrivateId: "test_controller1",
Address: "127.0.0.1",
})
serversRepoFn := func() (*server.Repository, error) {
return serverRepo, nil
}
sessionRepoFn := func(opt ...session.Option) (*session.Repository, error) {
return session.NewRepository(ctx, rw, rw, kms)
}
connRepoFn := func() (*session.ConnectionRepository, error) {
return session.NewConnectionRepository(ctx, rw, rw, kms)
}
worker1 := server.TestKmsWorker(t, conn, wrapper)
s := handlers.NewWorkerServiceServer(serversRepoFn, sessionRepoFn, connRepoFn, new(sync.Map), kms)
require.NotNil(t, s)
cases := []struct {
name string
wantErr bool
wantErrMsg string
req *pbs.StatusRequest
wantState string
}{
{
name: "Active worker",
wantErr: false,
req: &pbs.StatusRequest{
WorkerStatus: &pb.ServerWorkerStatus{
PublicId: worker1.GetPublicId(),
Name: worker1.GetName(),
Address: worker1.GetAddress(),
OperationalState: "active",
},
},
wantState: "active",
},
{
name: "Worker in shutdown",
wantErr: false,
req: &pbs.StatusRequest{
WorkerStatus: &pb.ServerWorkerStatus{
PublicId: worker1.GetPublicId(),
Name: worker1.GetName(),
Address: worker1.GetAddress(),
OperationalState: "shutdown",
},
},
wantState: "shutdown",
},
{
name: "No operational state- default to unknown",
wantErr: false,
req: &pbs.StatusRequest{
WorkerStatus: &pb.ServerWorkerStatus{
PublicId: worker1.GetPublicId(),
Name: worker1.GetName(),
Address: worker1.GetAddress(),
ReleaseVersion: "Boundary v0.11.0",
},
},
wantState: "unknown",
},
{
name: "Old worker (empty release version) and no operational state- default to active",
wantErr: false,
req: &pbs.StatusRequest{
WorkerStatus: &pb.ServerWorkerStatus{
PublicId: worker1.GetPublicId(),
Name: worker1.GetName(),
Address: worker1.GetAddress(),
},
},
wantState: "active",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
got, err := s.Status(ctx, tc.req)
if tc.wantErr {
require.Error(err)
assert.Equal(tc.wantErrMsg, err.Error())
return
}
require.NoError(err)
require.NotNil(got)
repoWorker, err := serverRepo.LookupWorkerByName(ctx, worker1.Name)
require.NoError(err)
assert.Equal(tc.wantState, repoWorker.OperationalState)
})
}
}
@@ -813,7 +813,7 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession
// worker IDs below is used to contain their IDs in the same order. This is
// used to fetch tags for filtering. But we avoid allocation unless we
// actually need it.
selectedWorkers, err := serversRepo.ListWorkers(ctx, []string{scope.Global.String()})
selectedWorkers, err := serversRepo.ListWorkers(ctx, []string{scope.Global.String()}, server.WithExcludeShutdownWorkers(true))
if err != nil {
return nil, err
}
+9 -8
View File
@@ -7,13 +7,13 @@ import (
"math/rand"
"time"
"github.com/hashicorp/boundary/version"
"github.com/hashicorp/boundary/internal/daemon/worker/common"
"github.com/hashicorp/boundary/internal/daemon/worker/session"
pb "github.com/hashicorp/boundary/internal/gen/controller/servers"
pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
"github.com/hashicorp/boundary/internal/observability/event"
"github.com/hashicorp/boundary/internal/server"
"github.com/hashicorp/boundary/version"
"github.com/hashicorp/go-secure-stdlib/strutil"
)
@@ -165,12 +165,13 @@ func (w *Worker) sendWorkerStatus(cancelCtx context.Context, sessionManager sess
result, err := client.Status(statusCtx, &pbs.StatusRequest{
Jobs: activeJobs,
WorkerStatus: &pb.ServerWorkerStatus{
Name: w.conf.RawConfig.Worker.Name,
Description: w.conf.RawConfig.Worker.Description,
Address: w.conf.RawConfig.Worker.PublicAddr,
Tags: tags,
KeyId: keyId,
ReleaseVersion: versionInfo.FullVersionNumber(false),
Name: w.conf.RawConfig.Worker.Name,
Description: w.conf.RawConfig.Worker.Description,
Address: w.conf.RawConfig.Worker.PublicAddr,
Tags: tags,
KeyId: keyId,
ReleaseVersion: versionInfo.FullVersionNumber(false),
OperationalState: w.operationalState.Load().(server.OperationalState).String(),
},
UpdateTags: w.updateTags.Load(),
})
+13 -7
View File
@@ -13,28 +13,28 @@ import (
"sync/atomic"
"time"
"github.com/hashicorp/boundary/internal/errors"
pb "github.com/hashicorp/boundary/internal/gen/controller/servers"
"github.com/hashicorp/nodeenrollment"
nodeenet "github.com/hashicorp/nodeenrollment/net"
"github.com/mr-tron/base58"
"google.golang.org/grpc/resolver/manual"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/config"
"github.com/hashicorp/boundary/internal/daemon/worker/internal/metric"
"github.com/hashicorp/boundary/internal/daemon/worker/session"
"github.com/hashicorp/boundary/internal/errors"
pb "github.com/hashicorp/boundary/internal/gen/controller/servers"
pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services"
"github.com/hashicorp/boundary/internal/observability/event"
"github.com/hashicorp/boundary/internal/server"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/base62"
"github.com/hashicorp/go-secure-stdlib/mlock"
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/hashicorp/nodeenrollment"
nodeenet "github.com/hashicorp/nodeenrollment/net"
nodeefile "github.com/hashicorp/nodeenrollment/storage/file"
"github.com/hashicorp/nodeenrollment/types"
"github.com/mr-tron/base58"
ua "go.uber.org/atomic"
"google.golang.org/grpc"
"google.golang.org/grpc/resolver/manual"
"google.golang.org/protobuf/proto"
)
@@ -90,6 +90,7 @@ type Worker struct {
everAuthenticated *ua.Uint32
lastStatusSuccess *atomic.Value
workerStartTime time.Time
operationalState *atomic.Value
controllerMultihopConn *atomic.Value
@@ -142,6 +143,7 @@ func New(conf *Config) (*Worker, error) {
updateTags: ua.NewBool(false),
nonceFn: base62.Random,
WorkerAuthCurrentKeyId: new(ua.String),
operationalState: new(atomic.Value),
}
if downstreamRouterFactory != nil {
@@ -382,6 +384,8 @@ func (w *Worker) Start() error {
return errors.Wrap(w.baseContext, err, op, errors.WithMsg("error starting worker listeners"))
}
w.operationalState.Store(server.ActiveOperationalState)
// Rather than deal with some of the potential error conditions for Add on
// the waitgroup vs. Done (in case a function exits immediately), we will
// always start rotation and simply exit early if we're using KMS
@@ -430,6 +434,8 @@ func (w *Worker) Shutdown() error {
return nil
}
// Set state to shutdown
w.operationalState.Store(server.ShutdownOperationalState)
// Stop listeners first to prevent new connections to the
// controller.
defer w.started.Store(false)