feature (worker): add WithFetchNodeCredentialsRequest to CreateWorker (#2131)

* feature (errors): add support fmt specifier with operands to WithMsg(...)

* feature (worker): add WithFetchNodeCredentialsRequest to CreateWorker

* fixup! feature (worker): add WithFetchNodeCredentialsRequest to CreateWorker
pull/2132/head
Jim 4 years ago committed by GitHub
parent abbfe45419
commit 5f66d8f2af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -74,7 +74,7 @@ func E(ctx context.Context, opt ...Option) error {
Code: code,
Op: opts.withOp,
Wrapped: opts.withErrWrapped,
Msg: opts.withErrMsg,
Msg: fmt.Sprintf(opts.withErrMsg, opts.withErrMsgArgs...),
}
if opts.withoutEvent {
return err

@ -17,6 +17,7 @@ type Options struct {
withCode Code
withErrWrapped error
withErrMsg string
withErrMsgArgs []any
withOp Op
withoutEvent bool
}
@ -34,10 +35,12 @@ func WithWrap(e error) Option {
}
// WithMsg provides an option to provide a message when creating a new
// error.
func WithMsg(msg string) Option {
// error. If args are provided, the the msg string is used as a fmt specifier
// for the arguments and the resulting string is used as the msg.
func WithMsg(msg string, args ...any) Option {
return func(o *Options) {
o.withErrMsg = msg
o.withErrMsgArgs = args
}
}

@ -22,6 +22,13 @@ func Test_getOpts(t *testing.T) {
opts = GetOpts(WithMsg("test msg"))
testOpts.withErrMsg = "test msg"
assert.Equal(opts, testOpts)
opts = GetOpts(WithMsg("%s msg", "test"))
testOpts.withErrMsg = "%s msg"
testOpts.withErrMsgArgs = []any{"test"}
assert.Equal(opts, testOpts)
assert.Equal("#1 test msg: unknown: error #0", E(context.Background(), WithMsg("#%d %s msg", 1, "test")).Error())
})
t.Run("WithWrap", func(t *testing.T) {
assert := assert.New(t)

@ -3,6 +3,8 @@ package servers
import (
"context"
"time"
"github.com/hashicorp/nodeenrollment/types"
)
// getOpts - iterate the inbound Options and return a struct
@ -32,6 +34,7 @@ type options struct {
withKeyId string
withNonce []byte
withNewIdFunc func(context.Context) (string, error)
withFetchNodeCredentialsRequest *types.FetchNodeCredentialsRequest
}
func getDefaultOptions() options {
@ -132,3 +135,11 @@ func WithNewIdFunc(fn func(context.Context) (string, error)) Option {
o.withNewIdFunc = fn
}
}
// WithFetchNodeCredentialsRequest allows an optional
// FetchNodeCredentialsRequest to be specified.
func WithFetchNodeCredentialsRequest(req *types.FetchNodeCredentialsRequest) Option {
return func(o *options) {
o.withFetchNodeCredentialsRequest = req
}
}

@ -8,8 +8,12 @@ import (
"github.com/hashicorp/boundary/internal/db"
dbcommon "github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers/store"
"github.com/hashicorp/boundary/internal/types/scope"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
"github.com/hashicorp/nodeenrollment"
"github.com/hashicorp/nodeenrollment/registration"
)
// DeleteWorker will delete a worker from the repository.
@ -383,7 +387,8 @@ func (r *Repository) UpdateWorker(ctx context.Context, worker *Worker, version u
// ReportedStatus and Tags are intentionally ignored when creating a worker (not
// included). Currently, a worker can only be created in the global scope
//
// Options supported: WithNewIdFunc (this option is likely only useful for tests)
// Options supported: WithFetchNodeCredentialsRequest and WithNewIdFunc (this
// option is likely only useful for tests)
func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Option) (*Worker, error) {
const op = "servers.CreateWorker"
switch {
@ -409,25 +414,47 @@ func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Op
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to generate worker id"))
}
var databaseWrapper wrapping.Wrapper
var workerAuthRepo *WorkerAuthRepositoryStorage
if opts.withFetchNodeCredentialsRequest != nil {
// used to encrypt the privKey within the NodeInformation
databaseWrapper, err = r.kms.GetWrapper(ctx, scope.Global.String(), kms.KeyPurposeDatabase)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
}
var returnedWorker *Worker
_, err = r.writer.DoTx(
if _, err := r.writer.DoTx(
ctx,
db.StdRetryCnt,
db.ExpBackoff{},
func(_ db.Reader, w db.Writer) error {
returnedWorker = worker.clone()
err := w.Create(
if err := w.Create(
ctx,
returnedWorker,
)
if err != nil {
return errors.Wrap(ctx, err, op)
); err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create worker"))
}
if opts.withFetchNodeCredentialsRequest != nil {
workerAuthRepo, err = NewRepositoryStorage(ctx, r.reader, r.writer, r.kms)
if err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to create worker auth repository"))
}
nodeInfo, err := registration.AuthorizeNode(ctx, workerAuthRepo, opts.withFetchNodeCredentialsRequest, nodeenrollment.WithSkipStorage(true))
if err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to authorize node"))
}
if err := StoreNodeInformationTx(ctx, w, databaseWrapper, nodeInfo); err != nil {
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to store node information"))
}
}
return nil
},
)
if err != nil {
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to create worker"))
); err != nil {
return nil, errors.Wrap(ctx, err, op)
}
return returnedWorker, nil
}

Loading…
Cancel
Save