From 72acaf662339b1f90318f03a55d0c3a67ddffe7b Mon Sep 17 00:00:00 2001 From: Juana De La Cuesta Date: Thu, 21 Sep 2023 17:56:33 +0200 Subject: [PATCH] [17449] Introduces a locking mechanism over variables (#18207) It includes the work over the state store, the PRC server, the HTTP server, the go API package and the CLI's command. To read more on the actuall functionality, refer to the RFCs [NMD-178] Locking with Nomad Variables and [NMD-179] Leader election using locking mechanism for the Autoscaler. --- .changelog/18520.txt | 3 + api/api.go | 39 + api/locks.go | 377 +++++ api/locks_test.go | 499 +++++++ api/retry.go | 124 ++ api/retry_test.go | 129 ++ api/variables.go | 69 + api/variables_test.go | 68 +- ci/test-core.json | 1 + command/agent/variable_endpoint.go | 125 +- command/agent/variable_endpoint_test.go | 410 ++++-- command/commands.go | 7 + command/var_lock.go | 369 +++++ command/var_lock_test.go | 152 ++ command/var_put.go | 3 +- nomad/fsm.go | 7 +- nomad/leader.go | 15 + nomad/leader_test.go | 2 +- nomad/lock/delay.go | 90 ++ nomad/lock/delay_test.go | 43 + nomad/lock/ttl.go | 106 ++ nomad/lock/ttl_test.go | 75 + nomad/locks.go | 154 ++ nomad/locks_test.go | 202 +++ nomad/server.go | 9 + nomad/state/state_store_variables.go | 160 +- nomad/state/state_store_variables_test.go | 533 ++++++- nomad/structs/variables.go | 321 +++- nomad/structs/variables_test.go | 351 ++++- nomad/variables_endpoint.go | 319 +++- nomad/variables_endpoint_test.go | 1304 +++++++++++++---- website/content/api-docs/variables/index.mdx | 21 + website/content/api-docs/variables/locks.mdx | 211 +++ .../api-docs/{ => variables}/variables.mdx | 12 +- website/content/docs/commands/var/index.mdx | 2 + website/content/docs/commands/var/lock.mdx | 100 ++ website/content/docs/concepts/variables.mdx | 54 + website/data/api-docs-nav-data.json | 15 +- website/data/docs-nav-data.json | 4 + .../img/nomad-vars-leader-election-sdk.png | Bin 0 -> 557554 bytes 40 files changed, 5960 insertions(+), 525 deletions(-) create mode 100644 .changelog/18520.txt create mode 100644 api/locks.go create mode 100644 api/locks_test.go create mode 100644 api/retry.go create mode 100644 api/retry_test.go create mode 100644 command/var_lock.go create mode 100644 command/var_lock_test.go create mode 100644 nomad/lock/delay.go create mode 100644 nomad/lock/delay_test.go create mode 100644 nomad/lock/ttl.go create mode 100644 nomad/lock/ttl_test.go create mode 100644 nomad/locks.go create mode 100644 nomad/locks_test.go create mode 100644 website/content/api-docs/variables/index.mdx create mode 100644 website/content/api-docs/variables/locks.mdx rename website/content/api-docs/{ => variables}/variables.mdx (96%) create mode 100644 website/content/docs/commands/var/lock.mdx create mode 100644 website/public/img/nomad-vars-leader-election-sdk.png diff --git a/.changelog/18520.txt b/.changelog/18520.txt new file mode 100644 index 000000000..9ccdbfc97 --- /dev/null +++ b/.changelog/18520.txt @@ -0,0 +1,3 @@ +```release-note:improvement +vars: Added a locking feature for Nomad Variables +``` diff --git a/api/api.go b/api/api.go index ac755e254..7f9b41bd3 100644 --- a/api/api.go +++ b/api/api.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "io" + "math" "net" "net/http" "net/url" @@ -200,6 +201,10 @@ type Config struct { TLSConfig *TLSConfig Headers http.Header + + // retryOptions holds the configuration necessary to perform retries + // on put calls. + retryOptions *retryOptions } // ClientConfig copies the configuration with a new client address, region, and @@ -578,6 +583,40 @@ func (c *Client) SetSecretID(secretID string) { c.config.SecretID = secretID } +func (c *Client) configureRetries(ro *retryOptions) { + + c.config.retryOptions = &retryOptions{ + maxRetries: defaultNumberOfRetries, + maxBackoffDelay: defaultMaxBackoffDelay, + delayBase: defaultDelayTimeBase, + } + + if ro.delayBase != 0 { + c.config.retryOptions.delayBase = ro.delayBase + } + + if ro.maxRetries != defaultNumberOfRetries { + c.config.retryOptions.maxRetries = ro.maxRetries + } + + if ro.maxBackoffDelay != 0 { + c.config.retryOptions.maxBackoffDelay = ro.maxBackoffDelay + } + + if ro.maxToLastCall != 0 { + c.config.retryOptions.maxToLastCall = ro.maxToLastCall + } + + if ro.fixedDelay != 0 { + c.config.retryOptions.fixedDelay = ro.fixedDelay + } + + // Ensure that a big attempt number or a big delayBase number will not cause + // a negative delay by overflowing the delay increase. + c.config.retryOptions.maxValidAttempt = int64(math.Log2(float64(math.MaxInt64 / + c.config.retryOptions.delayBase.Nanoseconds()))) +} + // request is used to help build up a request type request struct { config *Config diff --git a/api/locks.go b/api/locks.go new file mode 100644 index 000000000..e26e68a9c --- /dev/null +++ b/api/locks.go @@ -0,0 +1,377 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +import ( + "context" + "errors" + "fmt" + "math/rand" + "net/http" + "time" + + "github.com/hashicorp/go-multierror" +) + +const ( + lockLeaseRenewalFactor = 0.7 + lockRetryBackoffFactor = 1.1 + + // DefaultLockTTL is the default value used to maintain a lock before it needs to + // be renewed. The actual value comes from the experience with Consul. + DefaultLockTTL = 15 * time.Second + + // DefaultLockDelay is the default a lock will be blocked after the TTL + // went by without any renews. It is intended to prevent split brain situations. + // The actual value comes from the experience with Consul. + DefaultLockDelay = 15 * time.Second +) + +var ( + // ErrLockConflict is returned in case a lock operation can't be performed + // because the caller is not the current holder of the lock. + ErrLockConflict = errors.New("conflicting operation over lock") + + //LockNoPathErr is returned when no path is provided in the variable to be + // used for the lease mechanism + LockNoPathErr = errors.New("variable's path can't be empty") +) + +// Locks returns a new handle on a lock for the given variable. +func (c *Client) Locks(wo WriteOptions, v Variable, opts ...LocksOption) (*Locks, error) { + + if v.Path == "" { + return nil, LockNoPathErr + } + + ttl, err := time.ParseDuration(v.Lock.TTL) + if err != nil { + return nil, err + } + + l := &Locks{ + c: c, + WriteOptions: wo, + variable: v, + ttl: ttl, + ro: retryOptions{ + maxToLastCall: ttl, + maxRetries: defaultNumberOfRetries, + }, + } + + for _, opt := range opts { + opt(l) + } + + l.c.configureRetries(&l.ro) + + return l, nil +} + +// Locks is used to maintain all the resources necessary to operate over a lock. +// It makes the calls to the http using an exponential retry mechanism that will +// try until it either reaches 5 attempts or the ttl of the lock expires. +// The variable doesn't need to exist, one will be created internally +// but a path most be provided. +// +// Important: It will be on the user to remove the variable created for the lock. +type Locks struct { + c *Client + variable Variable + ttl time.Duration + ro retryOptions + + WriteOptions +} + +type LocksOption = func(l *Locks) + +// LocksOptionWithMaxRetries allows access to configure the number of max retries the lock +// handler will perform in case of an expected response while interacting with the +// locks endpoint. +func LocksOptionWithMaxRetries(maxRetries int64) LocksOption { + return func(l *Locks) { + l.ro.maxRetries = maxRetries + } +} + +// Acquire will make the actual call to acquire the lock over the variable using +// the ttl in the Locks to create the VariableLock. It will return the +// path of the variable holding the lock. +// +// Acquire returns the path to the variable holding the lock. +func (l *Locks) Acquire(ctx context.Context) (string, error) { + + var out Variable + + _, err := l.c.retryPut(ctx, "/v1/var/"+l.variable.Path+"?lock-acquire", l.variable, &out, &l.WriteOptions) + if err != nil { + callErr, ok := err.(UnexpectedResponseError) + + // http.StatusConflict means the lock is already held. This will happen + // under the normal execution if multiple instances are fighting for the same lock and + // doesn't disrupt the flow. + if ok && callErr.statusCode == http.StatusConflict { + return "", fmt.Errorf("acquire conflict %w", ErrLockConflict) + } + + return "", err + } + + l.variable.Lock = out.Lock + + return l.variable.Path, nil +} + +// Release makes the call to release the lock over a variable, even if the ttl +// has not yet passed. +// In case of a call to release a non held lock, Release returns ErrLockConflict. +func (l *Locks) Release(ctx context.Context) error { + var out Variable + + rv := &Variable{ + Lock: &VariableLock{ + ID: l.variable.LockID(), + }, + } + + _, err := l.c.retryPut(ctx, "/v1/var/"+l.variable.Path+"?lock-release", rv, + &out, &l.WriteOptions) + if err != nil { + callErr, ok := err.(UnexpectedResponseError) + + if ok && callErr.statusCode == http.StatusConflict { + return fmt.Errorf("release conflict %w", ErrLockConflict) + } + return err + } + + return nil +} + +// Renew is used to extend the ttl of a lock. It can be used as a heartbeat or a +// lease to maintain the hold over the lock for longer periods or as a sync +// mechanism among multiple instances looking to acquire the same lock. +// Renew will return true if the renewal was successful. +// +// In case of a call to renew a non held lock, Renew returns ErrLockConflict. +func (l *Locks) Renew(ctx context.Context) error { + var out VariableMetadata + + _, err := l.c.retryPut(ctx, "/v1/var/"+l.variable.Path+"?lock-renew", l.variable, &out, &l.WriteOptions) + if err != nil { + callErr, ok := err.(UnexpectedResponseError) + + if ok && callErr.statusCode == http.StatusConflict { + return fmt.Errorf("renew conflict %w", ErrLockConflict) + } + + return err + } + return nil +} + +func (l *Locks) LockTTL() time.Duration { + return l.ttl +} + +// Locker is the interface that wraps the lock handler. It is used by the lock +// leaser to handle all lock operations. +type Locker interface { + // Acquire will make the actual call to acquire the lock over the variable using + // the ttl in the Locks to create the VariableLock. + // + // Acquire returns the path to the variable holding the lock. + Acquire(ctx context.Context) (string, error) + // Release makes the call to release the lock over a variable, even if the ttl + // has not yet passed. + Release(ctx context.Context) error + // Renew is used to extend the ttl of a lock. It can be used as a heartbeat or a + // lease to maintain the hold over the lock for longer periods or as a sync + // mechanism among multiple instances looking to acquire the same lock. + Renew(ctx context.Context) error + + // LockTTL returns the expiration time of the underlying lock. + LockTTL() time.Duration +} + +// LockLeaser is a helper used to run a protected function that should only be +// active if the instance that runs it is currently holding the lock. +// Can be used to provide synchrony among multiple independent instances. +// +// It includes the lease renewal mechanism and tracking in case the protected +// function returns an error. Internally it uses an exponential retry mechanism +// for the api calls. +type LockLeaser struct { + Name string + renewalPeriod time.Duration + waitPeriod time.Duration + randomDelay time.Duration + earlyReturn bool + locked bool + + locker Locker +} + +type LockLeaserOption = func(l *LockLeaser) + +// LockLeaserOptionWithEarlyReturn informs the leaser to return after the lock +// acquire fails and to not wait to attempt again. +func LockLeaserOptionWithEarlyReturn(er bool) LockLeaserOption { + return func(l *LockLeaser) { + l.earlyReturn = er + } +} + +// LockLeaserOptionWithWaitPeriod is used to set a back off period between +// calls to attempt to acquire the lock. By default it is set to 1.1 * TTLs. +func LockLeaserOptionWithWaitPeriod(wp time.Duration) LockLeaserOption { + return func(l *LockLeaser) { + l.waitPeriod = wp + } +} + +// NewLockLeaser returns an instance of LockLeaser. callerID +// is optional, in case they it is not provided, internal one will be created. +func (c *Client) NewLockLeaser(l Locker, opts ...LockLeaserOption) *LockLeaser { + + rn := rand.New(rand.NewSource(time.Now().Unix())).Intn(100) + + ll := &LockLeaser{ + renewalPeriod: time.Duration(float64(l.LockTTL()) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(l.LockTTL()) * lockRetryBackoffFactor), + randomDelay: time.Duration(rn) * time.Millisecond, + locker: l, + earlyReturn: false, + } + + for _, opt := range opts { + opt(ll) + } + + return ll +} + +// Start wraps the start function in charge of executing the protected +// function and maintain the lease but is in charge of releasing the +// lock before exiting. It is a blocking function. +func (ll *LockLeaser) Start(ctx context.Context, protectedFuncs ...func(ctx context.Context) error) error { + var mErr multierror.Error + + err := ll.start(ctx, protectedFuncs...) + if err != nil { + mErr.Errors = append(mErr.Errors, err) + } + + if ll.locked { + err = ll.locker.Release(ctx) + if err != nil { + mErr.Errors = append(mErr.Errors, fmt.Errorf("lock release: %w", err)) + } + } + + return mErr.ErrorOrNil() +} + +// start starts the process of maintaining the lease and executes the protected +// function on an independent go routine. It is a blocking function, it +// will return once the protected function is done or an execution error +// arises. +func (ll *LockLeaser) start(ctx context.Context, protectedFuncs ...func(ctx context.Context) error) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // errChannel is used track execution errors + errChannel := make(chan error, 1) + defer close(errChannel) + + // To avoid collisions if all the instances start at the same time, wait + // a random time before making the first call. + waitWithContext(ctx, ll.randomDelay) + + waitTicker := time.NewTicker(ll.waitPeriod) + defer waitTicker.Stop() + + for { + lockID, err := ll.locker.Acquire(ctx) + if err != nil { + + if errors.Is(err, ErrLockConflict) && ll.earlyReturn { + + return nil + } + + if !errors.Is(err, ErrLockConflict) { + errChannel <- err + } + } + + if lockID != "" { + ll.locked = true + + funcCtx, funcCancel := context.WithCancel(ctx) + defer funcCancel() + + // Execute the lock protected function. + go func() { + defer funcCancel() + for _, f := range protectedFuncs { + err := f(funcCtx) + if err != nil { + errChannel <- fmt.Errorf("error executing protected function %w", err) + return + } + cancel() + } + }() + + // Maintain lease is a blocking function, it will return if there is + // an error maintaining the lease or the protected function returned. + err = ll.maintainLease(funcCtx) + if err != nil && !errors.Is(err, ErrLockConflict) { + errChannel <- fmt.Errorf("error renewing the lease: %w", err) + } + } + + waitTicker.Stop() + waitTicker = time.NewTicker(ll.waitPeriod) + select { + case <-ctx.Done(): + return nil + + case err := <-errChannel: + return fmt.Errorf("locks: %w", err) + + case <-waitTicker.C: + } + } +} + +func (ll *LockLeaser) maintainLease(ctx context.Context) error { + renewTicker := time.NewTicker(ll.renewalPeriod) + defer renewTicker.Stop() + for { + select { + case <-ctx.Done(): + return nil + + case <-renewTicker.C: + err := ll.locker.Renew(ctx) + if err != nil { + return err + } + } + } +} + +func waitWithContext(ctx context.Context, d time.Duration) { + t := time.NewTimer(d) + defer t.Stop() + + select { + case <-ctx.Done(): + case <-t.C: + } +} diff --git a/api/locks_test.go b/api/locks_test.go new file mode 100644 index 000000000..89da82c8e --- /dev/null +++ b/api/locks_test.go @@ -0,0 +1,499 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +import ( + "context" + "errors" + "sync" + "testing" + "time" + + "github.com/shoenig/test/must" +) + +var testLease = 10 * time.Millisecond + +type mockLock struct { + locked bool + acquireCalls map[string]int + renewsCounter int + mu sync.Mutex + + leaseStartTime time.Time +} + +func (ml *mockLock) acquire(_ context.Context, callerID string) (string, error) { + ml.mu.Lock() + defer ml.mu.Unlock() + + if callerID == "hac-early-return" { + return "", ErrLockConflict + } + + ml.acquireCalls[callerID] += 1 + if ml.locked { + return "", nil + } + + ml.locked = true + ml.leaseStartTime = time.Now() + ml.renewsCounter = 0 + return "lockPath", nil +} + +type lockHandler struct { + *mockLock + callerID string +} + +func (lh *lockHandler) LockTTL() time.Duration { + return testLease +} + +func (lh *lockHandler) Acquire(ctx context.Context) (string, error) { + return lh.acquire(ctx, lh.callerID) +} + +func (ml *mockLock) Release(_ context.Context) error { + ml.mu.Lock() + defer ml.mu.Unlock() + + if !ml.locked { + return errors.New("lock not locked") + } + + ml.locked = false + ml.renewsCounter = 0 + return nil +} + +// The behavior of renew is not an exact replication of +// the lock work, its intended to test the behavior of the +// multiple instances running. +func (ml *mockLock) Renew(_ context.Context) error { + ml.mu.Lock() + defer ml.mu.Unlock() + + if !ml.locked { + return errors.New("error") + } + + if time.Since(ml.leaseStartTime) > testLease { + ml.locked = false + return ErrLockConflict + } + + ml.leaseStartTime = time.Now() + ml.renewsCounter += 1 + return nil +} + +func (ml *mockLock) getLockState() mockLock { + ml.mu.Lock() + defer ml.mu.Unlock() + + return mockLock{ + locked: ml.locked, + acquireCalls: copyMap(ml.acquireCalls), + renewsCounter: ml.renewsCounter, + } +} + +type mockService struct { + mockLock + + mu sync.Mutex + startsCounter int + starterID string +} + +func (ms *mockService) Run(callerID string, _ context.Context) func(ctx context.Context) error { + return func(ctx context.Context) error { + ms.mu.Lock() + ms.startsCounter += 1 + ms.starterID = callerID + ms.mu.Unlock() + + <-ctx.Done() + + ms.mu.Lock() + ms.starterID = "" + ms.mu.Unlock() + + return nil + } +} + +func (ms *mockService) getServiceState() mockService { + ms.mu.Lock() + defer ms.mu.Unlock() + + return mockService{ + startsCounter: ms.startsCounter, + starterID: ms.starterID, + } +} + +func TestAcquireLock_MultipleInstances(t *testing.T) { + l := mockLock{ + acquireCalls: map[string]int{}, + } + + s := mockService{} + + testCtx := context.Background() + + // Set up independent contexts to test the switch when one controller stops + hac1Ctx, hac1Cancel := context.WithCancel(testCtx) + defer hac1Cancel() + + // Wait time on hac1 is 0, it should always get the lock. + hac1 := LockLeaser{ + Name: "hac1", + locker: &lockHandler{ + mockLock: &l, + callerID: "hac1", + }, + renewalPeriod: time.Duration(float64(testLease) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + randomDelay: 0, + } + + hac2 := LockLeaser{ + Name: "hac2", + locker: &lockHandler{ + mockLock: &l, + callerID: "hac2", + }, + renewalPeriod: time.Duration(float64(testLease) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + randomDelay: 6 * time.Millisecond, + } + + lock := l.getLockState() + must.False(t, lock.locked) + + go func() { + err := hac1.Start(hac1Ctx, s.Run(hac1.Name, testCtx)) + must.NoError(t, err) + }() + + go func() { + err := hac2.Start(testCtx, s.Run(hac2.Name, testCtx)) + must.NoError(t, err) + }() + + time.Sleep(4 * time.Millisecond) + /* + After 4 ms more (4 ms total): + * hac2 should not have tried to acquire the lock because it has an initial delay of 6ms. + * hac1 should have the lock and the service should be running. + * The first lease is not over yet, no calls to renew should have been made. + */ + + lock = l.getLockState() + service := s.getServiceState() + + must.True(t, lock.locked) + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 0, lock.acquireCalls[hac2.Name]) + + must.Eq(t, 0, lock.renewsCounter) + + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac1.Name, service.starterID) + + time.Sleep(6 * time.Millisecond) + /* + After 6 ms more (10 ms total): + * hac2 should have tried to acquire the lock at least once, after the 6ms + initial delay has passed. + * hc1 should have renewed once the lease and still hold the lock. + */ + lock = l.getLockState() + service = s.getServiceState() + must.True(t, lock.locked) + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 1, lock.acquireCalls[hac2.Name]) + + must.One(t, lock.renewsCounter) + + must.One(t, service.startsCounter) + must.StrContains(t, hac1.Name, service.starterID) + + time.Sleep(5 * time.Millisecond) + + /* + After 5 ms more (15 ms total): + * hac2 should have tried to acquire the lock still just once: + initialDelay(6) + waitTime(11) = 18. + * hac1 should have renewed the lease 2 times and still hold the lock: + initialDelay(0) + renewals(2) * renewalPeriod(7) = 14. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 1, lock.acquireCalls[hac2.Name]) + + must.True(t, lock.locked) + + must.Eq(t, 2, lock.renewsCounter) + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac1.Name, service.starterID) + + time.Sleep(15 * time.Millisecond) + + /* + After 15 ms more (30 ms total): + * hac2 should have tried to acquire the lock 3 times: + initialDelay(6) + calls(2)* waitTime(11) = 28. + * hac1 should have renewed the lease 4 times and still hold the lock: + initialDelay(0) + renewals(4) * renewalPeriod(7) = 28. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 3, lock.acquireCalls[hac2.Name]) + + must.True(t, lock.locked) + + must.Eq(t, 4, lock.renewsCounter) + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac1.Name, service.starterID) + + // Start a new instance of the service with ha running, initial delay of 1ms + hac3 := LockLeaser{ + Name: "hac3", + locker: &lockHandler{ + mockLock: &l, + callerID: "hac3", + }, + renewalPeriod: time.Duration(float64(testLease) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + randomDelay: 1 * time.Millisecond, + } + + go func() { + err := hac3.Start(testCtx, s.Run(hac3.Name, testCtx)) + must.NoError(t, err) + }() + + time.Sleep(15 * time.Millisecond) + + /* + After 15 ms more (45 ms total): + * hac3 should have tried to acquire the lock twice, once on start and + once after waitTime(11). + * hac2 should have tried to acquire the lock 4 times: + initialDelay(6) + calls(3) * waitTime(11) = 39. + * hac1 should have renewed the lease 4 times and still hold the lock: + initialDelay(0) + renewals(6) * renewalPeriod(7) = 42. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 4, lock.acquireCalls[hac2.Name]) + must.Eq(t, 2, lock.acquireCalls[hac3.Name]) + + must.True(t, lock.locked) + + must.Eq(t, 6, lock.renewsCounter) + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac1.Name, service.starterID) + + // Stop hac1 and release the lock + hac1Cancel() + + time.Sleep(10 * time.Millisecond) + + /* + After 10 ms more (55 ms total): + * hac3 should have tried to acquire the lock 3 times. + * hac2 should have tried to acquire the lock 5 times and succeeded on the + the fifth, is currently holding the lock and Run the service, no renewals. + * hc1 is stopped. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 5, lock.acquireCalls[hac2.Name]) + must.Eq(t, 3, lock.acquireCalls[hac3.Name]) + + must.True(t, lock.locked) + + must.Eq(t, 0, lock.renewsCounter) + must.Eq(t, 2, service.startsCounter) + must.StrContains(t, hac2.Name, service.starterID) + + time.Sleep(5 * time.Millisecond) + + /* + After 5 ms more (60 ms total): + * hac3 should have tried to acquire the lock 3 times. + * hac2 should have renewed the lock once. + * hc1 is stopped. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac1.Name]) + must.Eq(t, 5, lock.acquireCalls[hac2.Name]) + must.Eq(t, 3, lock.acquireCalls[hac3.Name]) + + must.True(t, lock.locked) + + must.Eq(t, 1, lock.renewsCounter) + must.Eq(t, 2, service.startsCounter) + must.StrContains(t, hac2.Name, service.starterID) +} + +func TestFailedRenewal(t *testing.T) { + l := mockLock{ + acquireCalls: map[string]int{}, + } + + s := mockService{} + + testCtx, testCancel := context.WithCancel(context.Background()) + defer testCancel() + + // Set the renewal period to 1.5 * testLease (15 ms) to force and error. + hac := LockLeaser{ + Name: "hac1", + locker: &lockHandler{ + mockLock: &l, + callerID: "hac1", + }, + renewalPeriod: time.Duration(float64(testLease) * 1.5), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + randomDelay: 0, + } + + lock := l.getLockState() + must.False(t, lock.locked) + + go hac.Start(testCtx, s.Run(hac.Name, testCtx)) + + time.Sleep(5 * time.Millisecond) + /* + After 5ms, the service should be running and the lock held, + no renewals needed or performed yet. + */ + + lock = l.getLockState() + service := s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac.Name]) + must.True(t, lock.locked) + + must.Eq(t, 0, lock.renewsCounter) + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac.Name, service.starterID) + + time.Sleep(15 * time.Millisecond) + + /* + After 15ms (20ms total) hac should have tried and failed at renewing the + lock, causing the service to return, no new calls to acquire the lock yet + either. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 1, lock.acquireCalls[hac.Name]) + must.False(t, lock.locked) + + must.Eq(t, 0, lock.renewsCounter) + must.Eq(t, 1, service.startsCounter) + must.StrContains(t, hac.Name, "") + + time.Sleep(10 * time.Millisecond) + + /* + After 10ms (30ms total) hac should have tried and succeeded at getting + the lock and the service should be running again. + */ + + lock = l.getLockState() + service = s.getServiceState() + must.Eq(t, 2, lock.acquireCalls[hac.Name]) + must.True(t, lock.locked) + + must.Eq(t, 0, lock.renewsCounter) + must.Eq(t, 2, service.startsCounter) + must.StrContains(t, hac.Name, service.starterID) +} + +func TestStart_ProtectedFunctionError(t *testing.T) { + l := mockLock{ + acquireCalls: map[string]int{}, + } + + testCtx := context.Background() + + hac := LockLeaser{ + locker: &lockHandler{ + mockLock: &l, + callerID: "hac", + }, + renewalPeriod: time.Duration(float64(testLease) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + } + + lock := l.getLockState() + must.False(t, lock.locked) + + err := hac.Start(testCtx, func(ctx context.Context) error { + return errors.New("error") + }) + + must.Error(t, err) + + lock = l.getLockState() + must.False(t, lock.locked) + must.Zero(t, lock.renewsCounter) +} + +func copyMap(originalMap map[string]int) map[string]int { + newMap := map[string]int{} + for k, v := range originalMap { + newMap[k] = v + } + return newMap +} + +func Test_EarlyReturn(t *testing.T) { + l := mockLock{ + acquireCalls: map[string]int{}, + } + + testCtx := context.Background() + + hac := LockLeaser{ + locker: &lockHandler{ + mockLock: &l, + callerID: "hac-early-return", + }, + renewalPeriod: time.Duration(float64(testLease) * lockLeaseRenewalFactor), + waitPeriod: time.Duration(float64(testLease) * lockRetryBackoffFactor), + earlyReturn: true, + } + + lock := l.getLockState() + must.False(t, lock.locked) + + err := hac.Start(testCtx, func(ctx context.Context) error { + return errors.New("error") + }) + + must.NoError(t, err) + + lock = l.getLockState() + must.False(t, lock.locked) + must.Zero(t, lock.renewsCounter) +} diff --git a/api/retry.go b/api/retry.go new file mode 100644 index 000000000..965d0ef5e --- /dev/null +++ b/api/retry.go @@ -0,0 +1,124 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +import ( + "context" + "errors" + "net/http" + "time" +) + +const ( + defaultNumberOfRetries = 5 + defaultDelayTimeBase = time.Second + defaultMaxBackoffDelay = 5 * time.Minute +) + +type retryOptions struct { + maxRetries int64 // Optional, defaults to 5 + // maxBackoffDelay sets a capping value for the delay between calls, to avoid it growing infinitely + maxBackoffDelay time.Duration // Optional, defaults to 5 min + // maxToLastCall sets a capping value for all the retry process, in case there is a deadline to make the call. + maxToLastCall time.Duration // Optional, defaults to 0, meaning no time cap + // fixedDelay is used in case an uniform distribution of the calls is preferred. + fixedDelay time.Duration // Optional, defaults to 0, meaning Delay is exponential, starting at 1sec + // delayBase is used to calculate the starting value at which the delay starts to grow, + // When left empty, a value of 1 sec will be used as base and then the delays will + // grow exponentially with every attempt: starting at 1s, then 2s, 4s, 8s... + delayBase time.Duration // Optional, defaults to 1sec + + // maxValidAttempt is used to ensure that a big attempts number or a big delayBase number will not cause + // a negative delay by overflowing the delay increase. Every attempt after the + // maxValid will use the maxBackoffDelay if configured, or the defaultMaxBackoffDelay if not. + maxValidAttempt int64 +} + +func (c *Client) retryPut(ctx context.Context, endpoint string, in, out any, q *WriteOptions) (*WriteMeta, error) { + var err error + var wm *WriteMeta + + attemptDelay := time.Duration(100 * time.Second) // Avoid a tick before starting + startTime := time.Now() + + t := time.NewTimer(attemptDelay) + defer t.Stop() + + for attempt := int64(0); attempt < c.config.retryOptions.maxRetries+1; attempt++ { + attemptDelay = c.calculateDelay(attempt) + + t.Reset(attemptDelay) + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-t.C: + + } + + wm, err = c.put(endpoint, in, out, q) + + // Maximum retry period is up, don't retry + if c.config.retryOptions.maxToLastCall != 0 && time.Now().Sub(startTime) > c.config.retryOptions.maxToLastCall { + break + } + + // The put function only returns WriteMetadata if the call was successful + // don't retry + if wm != nil { + break + } + + // If WriteMetadata is nil, we need to process the error to decide if a retry is + // necessary or not + var callErr UnexpectedResponseError + ok := errors.As(err, &callErr) + + // If is not UnexpectedResponseError, it is an error while performing the call + // don't retry + if !ok { + break + } + + // Only 500+ or 429 status calls may be retried, otherwise + // don't retry + if !isCallRetriable(callErr.StatusCode()) { + break + } + } + + return wm, err +} + +// According to the HTTP protocol, it only makes sense to retry calls +// when the error is caused by a temporary situation, like a server being down +// (500s+) or the call being rate limited (429), this function checks if the +// statusCode is between the errors worth retrying. +func isCallRetriable(statusCode int) bool { + return statusCode > http.StatusInternalServerError && + statusCode < http.StatusNetworkAuthenticationRequired || + statusCode == http.StatusTooManyRequests +} + +func (c *Client) calculateDelay(attempt int64) time.Duration { + if c.config.retryOptions.fixedDelay != 0 { + return c.config.retryOptions.fixedDelay + } + + if attempt == 0 { + return 0 + } + + if attempt > c.config.retryOptions.maxValidAttempt { + return c.config.retryOptions.maxBackoffDelay + } + + newDelay := c.config.retryOptions.delayBase << (attempt - 1) + if c.config.retryOptions.maxBackoffDelay != defaultMaxBackoffDelay && + newDelay > c.config.retryOptions.maxBackoffDelay { + return c.config.retryOptions.maxBackoffDelay + } + + return newDelay +} diff --git a/api/retry_test.go b/api/retry_test.go new file mode 100644 index 000000000..cd4215b1c --- /dev/null +++ b/api/retry_test.go @@ -0,0 +1,129 @@ +package api + +import ( + "context" + "encoding/json" + "math" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/shoenig/test/must" +) + +type mockHandler struct { + callsCounter []time.Time +} + +func (mh *mockHandler) Handle(rw http.ResponseWriter, req *http.Request) { + mh.callsCounter = append(mh.callsCounter, time.Now()) + + // return a populated meta after 7 tries to test he retries stops after a + // successful call + if len(mh.callsCounter) < 7 { + http.Error(rw, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) + return + } + + rw.WriteHeader(http.StatusOK) + rw.Header().Set("Content-Type", "application/json") + + resp := &WriteMeta{} + jsonResp, _ := json.Marshal(resp) + + rw.Write(jsonResp) + return +} + +func Test_RetryPut_multiple_calls(t *testing.T) { + t.Run("successfully retries until no error, delayed capped to 100ms", func(t *testing.T) { + mh := mockHandler{ + callsCounter: []time.Time{}, + } + + server := httptest.NewServer(http.HandlerFunc(mh.Handle)) + + cm := &Client{ + httpClient: server.Client(), + config: Config{ + Address: server.URL, + retryOptions: &retryOptions{ + delayBase: 10 * time.Millisecond, + maxRetries: 10, + maxBackoffDelay: 100 * time.Millisecond, + }, + }, + } + + md, err := cm.retryPut(context.TODO(), "/endpoint", nil, nil, &WriteOptions{}) + must.NoError(t, err) + + must.Len(t, 7, mh.callsCounter) + + must.NotNil(t, md) + must.Greater(t, 10*time.Millisecond, mh.callsCounter[1].Sub(mh.callsCounter[0])) + must.Greater(t, 20*time.Millisecond, mh.callsCounter[2].Sub(mh.callsCounter[1])) + must.Greater(t, 40*time.Millisecond, mh.callsCounter[3].Sub(mh.callsCounter[2])) + must.Greater(t, 80*time.Millisecond, mh.callsCounter[4].Sub(mh.callsCounter[3])) + must.Greater(t, 100*time.Millisecond, mh.callsCounter[5].Sub(mh.callsCounter[4])) + must.Greater(t, 100*time.Millisecond, mh.callsCounter[6].Sub(mh.callsCounter[5])) + }) +} + +func Test_RetryPut_one_call(t *testing.T) { + t.Run("successfully retries until no error, delayed capped to 100ms", func(t *testing.T) { + mh := mockHandler{ + callsCounter: []time.Time{}, + } + + server := httptest.NewServer(http.HandlerFunc(mh.Handle)) + + cm := &Client{ + httpClient: server.Client(), + config: Config{ + Address: server.URL, + retryOptions: &retryOptions{ + delayBase: 10 * time.Millisecond, + maxRetries: 1, + }, + }, + } + + md, err := cm.retryPut(context.TODO(), "/endpoint/", nil, nil, &WriteOptions{}) + must.Error(t, err) + must.Nil(t, md) + + must.Len(t, 2, mh.callsCounter) + }) +} + +func Test_RetryPut_capped_base_too_big(t *testing.T) { + t.Run("successfully retries until no error, delayed capped to 100ms", func(t *testing.T) { + mh := mockHandler{ + callsCounter: []time.Time{}, + } + + server := httptest.NewServer(http.HandlerFunc(mh.Handle)) + cm := &Client{ + httpClient: server.Client(), + config: Config{ + Address: server.URL, + retryOptions: &retryOptions{ + delayBase: math.MaxInt64 * time.Nanosecond, + maxRetries: 3, + maxBackoffDelay: 200 * time.Millisecond, + }, + }, + } + + md, err := cm.retryPut(context.TODO(), "/endpoint", nil, nil, &WriteOptions{}) + must.Error(t, err) + + must.Len(t, 4, mh.callsCounter) + + must.Nil(t, md) + must.Greater(t, cm.config.retryOptions.maxBackoffDelay, mh.callsCounter[1].Sub(mh.callsCounter[0])) + must.Greater(t, cm.config.retryOptions.maxBackoffDelay, mh.callsCounter[2].Sub(mh.callsCounter[1])) + }) +} diff --git a/api/variables.go b/api/variables.go index 86458c13a..ccdfdfe44 100644 --- a/api/variables.go +++ b/api/variables.go @@ -183,6 +183,44 @@ func (vars *Variables) GetVariableItems(path string, qo *QueryOptions) (Variable return v.Items, qm, nil } +// RenewLock renews the lease for the lock on the given variable. It has to be called +// before the lock's TTL expires or the lock will be automatically released after the +// delay period. +func (vars *Variables) RenewLock(v *Variable, qo *WriteOptions) (*VariableMetadata, *WriteMeta, error) { + v.Path = cleanPathString(v.Path) + var out VariableMetadata + + wm, err := vars.client.put("/v1/var/"+v.Path+"?lock-renew", v, &out, qo) + if err != nil { + return nil, wm, err + } + return &out, wm, nil +} + +// ReleaseLock removes the lock on the given variable. +func (vars *Variables) ReleaseLock(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { + return vars.lockOperation(v, qo, "lock-release") +} + +// AcquireLock adds a lock on the given variable and starts a lease on it. In order +// to make any update on the locked variable, the lock ID has to be included in the +// request. In order to maintain ownership of the lock, the lease needs to be +// periodically renewed before the lock's TTL expires. +func (vars *Variables) AcquireLock(v *Variable, qo *WriteOptions) (*Variable, *WriteMeta, error) { + return vars.lockOperation(v, qo, "lock-acquire") +} + +func (vars *Variables) lockOperation(v *Variable, qo *WriteOptions, operation string) (*Variable, *WriteMeta, error) { + v.Path = cleanPathString(v.Path) + var out Variable + + wm, err := vars.client.put("/v1/var/"+v.Path+"?"+operation, v, &out, qo) + if err != nil { + return nil, wm, err + } + return &out, wm, nil +} + // readInternal exists because the API's higher-level read method requires // the status code to be 200 (OK). For Peek(), we do not consider 403 (Permission // Denied or 404 (Not Found) an error, this function just returns a nil in those @@ -358,6 +396,9 @@ type Variable struct { // Items contains the k/v variable component Items VariableItems `hcl:"items"` + + // Lock holds the information about the variable lock if its being used. + Lock *VariableLock `hcl:",lock,optional" json:",omitempty"` } // VariableMetadata specifies the metadata for a variable and @@ -380,6 +421,24 @@ type VariableMetadata struct { // ModifyTime is the unix nano of the last modified time ModifyTime int64 `hcl:"modify_time"` + + // Lock holds the information about the variable lock if its being used. + Lock *VariableLock `hcl:",lock,optional" json:",omitempty"` +} + +type VariableLock struct { + // ID is generated by Nomad to provide a unique caller ID which can be used + // for renewals and unlocking. + ID string + + // TTL describes the time-to-live of the current lock holder. + // This is a string version of a time.Duration like "2m". + TTL string + + // LockDelay describes a grace period that exists after a lock is lost, + // before another client may acquire the lock. This helps protect against + // split-brains. This is a string version of a time.Duration like "2m". + LockDelay string } // VariableItems are the key/value pairs of a Variable. @@ -446,6 +505,16 @@ func (v *Variable) AsPrettyJSON() string { return string(b) } +// LockID returns the ID of the lock. In the event this is not held, or the +// variable is not a lock, this string will be empty. +func (v *Variable) LockID() string { + if v.Lock == nil { + return "" + } + + return v.Lock.ID +} + type ErrCASConflict struct { CheckIndex uint64 Conflict *Variable diff --git a/api/variables_test.go b/api/variables_test.go index c480ae6bb..19beb9d44 100644 --- a/api/variables_test.go +++ b/api/variables_test.go @@ -20,7 +20,7 @@ func TestVariables_SimpleCRUD(t *testing.T) { defer s.Stop() nsv := c.Variables() - sv1 := NewVariable("my/first/variable") + sv1 := NewVariable("my/first/variable/SimpleCRUD") sv1.Namespace = "default" sv1.Items["k1"] = "v1" sv1.Items["k2"] = "v2" @@ -290,7 +290,6 @@ func TestVariables_GetVariableItems(t *testing.T) { func writeTestVariable(t *testing.T, c *Client, sv *Variable) { _, err := c.put("/v1/var/"+sv.Path, sv, sv, nil) must.NoError(t, err, must.Sprint("failed writing test variable")) - must.NoError(t, err, must.Sprint("failed writing test variable")) } func TestVariable_CreateReturnsContent(t *testing.T) { @@ -298,7 +297,7 @@ func TestVariable_CreateReturnsContent(t *testing.T) { defer s.Stop() nsv := c.Variables() - sv1 := NewVariable("my/first/variable") + sv1 := NewVariable("my/first/variable/create") sv1.Namespace = "default" sv1.Items["k1"] = "v1" sv1.Items["k2"] = "v2" @@ -308,3 +307,66 @@ func TestVariable_CreateReturnsContent(t *testing.T) { must.NotNil(t, sv1n) must.Eq(t, sv1.Items, sv1n.Items) } + +func TestVariables_LockRenewRelease(t *testing.T) { + testutil.Parallel(t) + + c, s := makeClient(t, nil, nil) + defer s.Stop() + path := fmt.Sprintf("%s-%v", "/first/variable", time.Now().UnixMilli()) + nsv := c.Variables() + sv1 := NewVariable(path) + sv1.Namespace = "default" + sv1.Items["k1"] = "v1" + sv1.Items["k2"] = "v2" + + t.Run("1 create sv1", func(t *testing.T) { + get, _, err := nsv.Create(sv1, nil) + must.NoError(t, err) + must.NotNil(t, get) + must.Positive(t, get.CreateIndex) + must.Positive(t, get.CreateTime) + must.Positive(t, get.ModifyIndex) + must.Positive(t, get.ModifyTime) + must.Eq(t, sv1.Items, get.Items) + *sv1 = *get + }) + + t.Run("2 acquire lock on sv1", func(t *testing.T) { + get, _, err := nsv.AcquireLock(sv1, nil) + must.NoError(t, err) + must.NotNil(t, get) + must.NotEq(t, sv1.ModifyIndex, get.ModifyIndex) + must.Eq(t, sv1.Items, get.Items) + must.NotNil(t, get.Lock) + + *sv1 = *get + }) + + t.Run("3 renew lock on sv1", func(t *testing.T) { + rlsv := *sv1 + get, _, err := nsv.RenewLock(&rlsv, nil) + must.NoError(t, err) + must.NotNil(t, get) + must.Eq(t, sv1.ModifyIndex, get.ModifyIndex) + must.NotNil(t, get.Lock) + must.Eq(t, sv1.Lock.ID, get.Lock.ID) + }) + + t.Run("4 list vars", func(t *testing.T) { + l, _, err := nsv.List(nil) + must.NoError(t, err) + must.Len(t, 1, l) + must.Nil(t, l[0].Lock) + }) + + t.Run("5 release lock on sv1", func(t *testing.T) { + sv1.Items = nil + get, _, err := nsv.ReleaseLock(sv1, nil) + must.NoError(t, err) + must.NotNil(t, get) + must.NotEq(t, sv1.ModifyIndex, get.ModifyIndex) + must.Zero(t, len(get.Items)) + must.Nil(t, get.Lock) + }) +} diff --git a/ci/test-core.json b/ci/test-core.json index a13a50f33..b113e8cf9 100644 --- a/ci/test-core.json +++ b/ci/test-core.json @@ -36,6 +36,7 @@ "lib/...", "nomad/deploymentwatcher/...", "nomad/drainer/...", + "nomad/lock/...", "nomad/state/...", "nomad/stream/...", "nomad/structs/...", diff --git a/command/agent/variable_endpoint.go b/command/agent/variable_endpoint.go index 3898025a6..7f6e598b7 100644 --- a/command/agent/variable_endpoint.go +++ b/command/agent/variable_endpoint.go @@ -4,14 +4,23 @@ package agent import ( + "errors" "fmt" "net/http" + "net/url" "strconv" "strings" "github.com/hashicorp/nomad/nomad/structs" ) +var ( + renewLockQueryParam = "lock-renew" + + acquireLockQueryParam = string(structs.VarOpLockAcquire) + releaseLockQueryParam = string(structs.VarOpLockRelease) +) + func (s *HTTPServer) VariablesListRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) { if req.Method != http.MethodGet { return nil, CodedError(http.StatusMethodNotAllowed, ErrInvalidMethod) @@ -40,11 +49,33 @@ func (s *HTTPServer) VariableSpecificRequest(resp http.ResponseWriter, req *http if len(path) == 0 { return nil, CodedError(http.StatusBadRequest, "missing variable path") } + switch req.Method { case http.MethodGet: return s.variableQuery(resp, req, path) case http.MethodPut, http.MethodPost: - return s.variableUpsert(resp, req, path) + urlParams := req.URL.Query() + lockOperation, err := getLockOperation(urlParams) + if err != nil { + return nil, CodedError(http.StatusBadRequest, err.Error()) + } + + cq := req.URL.Query().Get("cas") + + if cq != "" && lockOperation != "" { + return nil, CodedError(http.StatusBadRequest, "CAS can't be used with lock operations") + } + + if lockOperation == "" { + return s.variableUpsert(resp, req, path) + } + + if lockOperation == renewLockQueryParam { + return s.variableLockRenew(resp, req, path) + } + + return s.variableLockOperation(resp, req, path, lockOperation) + case http.MethodDelete: return s.variableDelete(resp, req, path) default: @@ -52,6 +83,65 @@ func (s *HTTPServer) VariableSpecificRequest(resp http.ResponseWriter, req *http } } +func (s *HTTPServer) variableLockRenew(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { + + // Parse the Variable + var Variable structs.VariableDecrypted + if err := decodeBody(req, &Variable); err != nil { + return nil, CodedError(http.StatusBadRequest, err.Error()) + } + + args := structs.VariablesRenewLockRequest{ + Path: path, + LockID: Variable.LockID(), + } + + s.parseWriteRequest(req, &args.WriteRequest) + + var out structs.VariablesRenewLockResponse + if err := s.agent.RPC(structs.VariablesRenewLockRPCMethod, &args, &out); err != nil { + return nil, err + } + + return out.VarMeta, nil +} + +func (s *HTTPServer) variableLockOperation(resp http.ResponseWriter, req *http.Request, + path, operation string) (interface{}, error) { + + // Parse the Variable + var Variable structs.VariableDecrypted + if err := decodeBody(req, &Variable); err != nil { + return nil, CodedError(http.StatusBadRequest, err.Error()) + } + + // At this point, the operation can be either acquire or release, and they are + // both handled by the VariablesApplyRPCMethod. + args := structs.VariablesApplyRequest{ + Op: structs.VarOp(operation), + Var: &Variable, + } + + Variable.Path = path + + s.parseWriteRequest(req, &args.WriteRequest) + + var out structs.VariablesApplyResponse + err := s.agent.RPC(structs.VariablesApplyRPCMethod, &args, &out) + defer setIndex(resp, out.WriteMeta.Index) + if err != nil { + return nil, err + } + + if out.Conflict != nil { + resp.WriteHeader(http.StatusConflict) + return out.Conflict, nil + } + + // Finally, we know that this is a success response, send it to the caller + return out.Output, nil +} + func (s *HTTPServer) variableQuery(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { args := structs.VariablesReadRequest{ @@ -75,11 +165,13 @@ func (s *HTTPServer) variableQuery(resp http.ResponseWriter, req *http.Request, func (s *HTTPServer) variableUpsert(resp http.ResponseWriter, req *http.Request, path string) (interface{}, error) { + // Parse the Variable var Variable structs.VariableDecrypted if err := decodeBody(req, &Variable); err != nil { return nil, CodedError(http.StatusBadRequest, err.Error()) } + if len(Variable.Items) == 0 { return nil, CodedError(http.StatusBadRequest, "variable missing required Items object") } @@ -186,3 +278,34 @@ func parseCAS(req *http.Request) (bool, uint64, error) { } return false, 0, nil } + +func isOneAndOnlyOneSet(a, b, c bool) bool { + return (a || b || c) && !a != !b != !c != !(a && b && c) +} + +// getLockOperation returns the lock operation to be performed in case there is +// one. It returns error if more than one is set. +func getLockOperation(queryParams url.Values) (string, error) { + _, renewLock := queryParams[renewLockQueryParam] + _, acquireLock := queryParams[acquireLockQueryParam] + _, releaseLock := queryParams[releaseLockQueryParam] + + if !renewLock && !acquireLock && !releaseLock { + return "", nil + } + + if !isOneAndOnlyOneSet(renewLock, acquireLock, releaseLock) { + return "", errors.New("multiple lock operations") + } + + switch { + case renewLock: + return renewLockQueryParam, nil + case acquireLock: + return acquireLockQueryParam, nil + case releaseLock: + return releaseLockQueryParam, nil + default: + return "", errors.New("unspecified lock operation") + } +} diff --git a/command/agent/variable_endpoint_test.go b/command/agent/variable_endpoint_test.go index 64e580f0b..48454a35d 100644 --- a/command/agent/variable_endpoint_test.go +++ b/command/agent/variable_endpoint_test.go @@ -6,6 +6,7 @@ package agent import ( "bytes" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/structs" + "github.com/shoenig/test/must" "github.com/stretchr/testify/require" ) @@ -35,26 +37,27 @@ func TestHTTP_Variables(t *testing.T) { // the costs of server startup and allow as much parallelization as possible. t.Run("error_badverb_list", func(t *testing.T) { req, err := http.NewRequest("LOLWUT", "/v1/vars", nil) - require.NoError(t, err) + must.NoError(t, err) respW := httptest.NewRecorder() _, err = s.Server.VariablesListRequest(respW, req) - require.EqualError(t, err, ErrInvalidMethod) + must.ErrorContains(t, err, ErrInvalidMethod) }) t.Run("error_parse_list", func(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/v1/vars?wait=99a", nil) require.NoError(t, err) + respW := httptest.NewRecorder() _, _ = s.Server.VariablesListRequest(respW, req) - require.Equal(t, http.StatusBadRequest, respW.Code) - require.Equal(t, "Invalid wait time", string(respW.Body.Bytes())) + must.Eq(t, http.StatusBadRequest, respW.Code) + must.Eq(t, "Invalid wait time", string(respW.Body.Bytes())) }) t.Run("error_rpc_list", func(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/v1/vars?region=bad", nil) require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariablesListRequest(respW, req) - require.EqualError(t, err, "No path to region") - require.Nil(t, obj) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) }) t.Run("list", func(t *testing.T) { // Test the empty list case @@ -64,14 +67,14 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariablesListRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // add vars and test a populated backend svMap := mock.Variables(4, 4) svs := svMap.List() svs[3].Path = svs[0].Path + "/child" for _, sv := range svs { - require.NoError(t, rpcWriteSV(s, sv, nil)) + must.NoError(t, rpcWriteSV(s, sv, nil)) } // Make the HTTP request @@ -81,15 +84,16 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err = s.Server.VariablesListRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, "true", respW.HeaderMap.Get("X-Nomad-KnownLeader")) - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-LastContact")) + + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, "true", respW.HeaderMap.Get("X-Nomad-KnownLeader")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-LastContact"))) // Check the output (the 4 we register ) - require.Len(t, obj.([]*structs.VariableMetadata), 4) + must.Len(t, 4, obj.([]*structs.VariableMetadata)) // test prefix query req, err = http.NewRequest(http.MethodGet, "/v1/vars?prefix="+svs[0].Path, nil) @@ -98,34 +102,34 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err = s.Server.VariablesListRequest(respW, req) - require.NoError(t, err) - require.Len(t, obj.([]*structs.VariableMetadata), 2) + must.NoError(t, err) + must.Len(t, 2, obj.([]*structs.VariableMetadata)) }) rpcResetSV(s) t.Run("error_badverb_query", func(t *testing.T) { req, err := http.NewRequest("LOLWUT", "/v1/var/does/not/exist", nil) - require.NoError(t, err) + must.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, ErrInvalidMethod) - require.Nil(t, obj) + must.ErrorContains(t, err, ErrInvalidMethod) + must.Nil(t, obj) }) t.Run("error_parse_query", func(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/v1/var/does/not/exist?wait=99a", nil) require.NoError(t, err) respW := httptest.NewRecorder() _, _ = s.Server.VariableSpecificRequest(respW, req) - require.Equal(t, http.StatusBadRequest, respW.Code) - require.Equal(t, "Invalid wait time", string(respW.Body.Bytes())) + must.Eq(t, http.StatusBadRequest, respW.Code) + must.Eq(t, "Invalid wait time", string(respW.Body.Bytes())) }) t.Run("error_rpc_query", func(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/v1/var/does/not/exist?region=bad", nil) require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "No path to region") - require.Nil(t, obj) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) }) t.Run("query_unset_path", func(t *testing.T) { // Make a request for a non-existing variable @@ -133,8 +137,8 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "missing variable path") - require.Nil(t, obj) + must.ErrorContains(t, err, "missing variable path") + must.Nil(t, obj) }) t.Run("query_unset_variable", func(t *testing.T) { // Make a request for a non-existing variable @@ -142,29 +146,29 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "variable not found") - require.Nil(t, obj) + must.ErrorContains(t, err, "variable not found") + must.Nil(t, obj) }) t.Run("query", func(t *testing.T) { // Use RPC to make a test variable out := new(structs.VariableDecrypted) sv1 := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv1, out)) + must.NoError(t, rpcWriteSV(s, sv1, out)) // Query a variable req, err := http.NewRequest(http.MethodGet, "/v1/var/"+sv1.Path, nil) require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, "true", respW.HeaderMap.Get("X-Nomad-KnownLeader")) - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-LastContact")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, "true", respW.HeaderMap.Get("X-Nomad-KnownLeader")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-LastContact"))) // Check the output - require.Equal(t, out, obj.(*structs.VariableDecrypted)) + must.Eq(t, out, obj.(*structs.VariableDecrypted)) }) rpcResetSV(s) @@ -175,8 +179,8 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "unexpected EOF") - require.Nil(t, obj) + must.ErrorContains(t, err, "unexpected EOF") + must.Nil(t, obj) }) t.Run("error_rpc_create", func(t *testing.T) { buf := encodeReq(sv1) @@ -184,8 +188,8 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "No path to region") - require.Nil(t, obj) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) }) t.Run("create_no_items", func(t *testing.T) { sv2 := sv1.Copy() @@ -195,8 +199,8 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "variable missing required Items object") - require.Nil(t, obj) + must.ErrorContains(t, err, "variable missing required Items object") + must.Nil(t, obj) }) t.Run("create", func(t *testing.T) { buf := encodeReq(sv1) @@ -204,23 +208,23 @@ func TestHTTP_Variables(t *testing.T) { require.NoError(t, err) respW := httptest.NewRecorder() obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // Test the returned object and rehydrate to a VariableDecrypted - require.NotNil(t, obj) + must.NotNil(t, obj) sv1, ok := obj.(*structs.VariableDecrypted) - require.True(t, ok, "Unable to convert obj to VariableDecrypted") + must.True(t, ok, must.Sprint(must.Sprint("Unable to convert obj to VariableDecrypted"))) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, fmt.Sprint(sv1.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, fmt.Sprint(sv1.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) // Check the variable was put and that the returned item matched the // fetched value out, err := rpcReadSV(s, sv1.Namespace, sv1.Path) - require.NoError(t, err) - require.NotNil(t, out) - require.Equal(t, sv1, out) + must.NoError(t, err) + must.NotNil(t, out) + must.Eq(t, sv1, out) }) rpcResetSV(s) @@ -237,11 +241,14 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "unexpected EOF") + must.ErrorContains(t, err, "unexpected EOF") + var cErr HTTPCodedError - require.ErrorAs(t, err, &cErr) - require.Equal(t, http.StatusBadRequest, cErr.Code()) - require.Nil(t, obj) + if !errors.As(err, &cErr) { + t.Fatalf("unexpected error") + } + must.Eq(t, http.StatusBadRequest, cErr.Code()) + must.Nil(t, obj) }) t.Run("error_rpc_update", func(t *testing.T) { sv1U := sv1.Copy() @@ -255,12 +262,12 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "No path to region") - require.Nil(t, obj) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) }) t.Run("update", func(t *testing.T) { sv := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv, sv)) + must.NoError(t, rpcWriteSV(s, sv, sv)) svU := sv.Copy() svU.Items["new"] = "new" @@ -272,31 +279,32 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // Test the returned object and rehydrate to a VariableDecrypted - require.NotNil(t, obj) + must.NotNil(t, obj) out, ok := obj.(*structs.VariableDecrypted) - require.True(t, ok, "Unable to convert obj to VariableDecrypted") + must.True(t, ok, must.Sprint("Unable to convert obj to VariableDecrypted")) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, fmt.Sprint(out.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, fmt.Sprint(out.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) { // Check that written varible does not equal the input to rule out input mutation - require.NotEqual(t, &svU.VariableMetadata, out.VariableMetadata) + must.NotEqual(t, svU.VariableMetadata, out.VariableMetadata) // Update the input token with the updated metadata so that we // can use a simple equality check svU.ModifyIndex = out.ModifyIndex svU.ModifyTime = out.ModifyTime - require.Equal(t, &svU, out) + must.Eq(t, &svU, out) } }) - t.Run("update-cas", func(t *testing.T) { + + t.Run("update_cas", func(t *testing.T) { sv := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv, sv)) + must.NoError(t, rpcWriteSV(s, sv, sv)) svU := sv.Copy() svU.Items["new"] = "new" @@ -310,23 +318,23 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) - require.Equal(t, http.StatusConflict, respW.Result().StatusCode) + must.NoError(t, err) + must.Eq(t, http.StatusConflict, respW.Result().StatusCode) // Evaluate the conflict variable - require.NotNil(t, obj) + must.NotNil(t, obj) conflict, ok := obj.(*structs.VariableDecrypted) - require.True(t, ok, "Expected *structs.VariableDecrypted, got %T", obj) - require.Equal(t, conflict, sv) + must.True(t, ok, must.Sprintf("Expected *structs.VariableDecrypted, got %T", obj)) + must.Eq(t, conflict, sv) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) } // Check the variable was not updated { out, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) - require.Equal(t, sv, out) + must.NoError(t, err) + must.Eq(t, sv, out) } // Make the HTTP request { @@ -337,49 +345,213 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) + must.NoError(t, err) // Test the returned object and rehydrate to a VariableDecrypted - require.NotNil(t, obj) + must.NotNil(t, obj) sv1, ok := obj.(*structs.VariableDecrypted) - require.True(t, ok, "Unable to convert obj to VariableDecrypted") + must.True(t, ok, must.Sprint("Unable to convert obj to VariableDecrypted")) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, fmt.Sprint(sv1.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, fmt.Sprint(sv1.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) // Check the variable was put and that the returned item matched the // fetched value out, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) - require.NotNil(t, out) - require.Equal(t, sv1, out) + must.NoError(t, err) + must.NotNil(t, out) + must.Eq(t, sv1, out) } // Check the variable was created correctly { out, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) - require.NotNil(t, out) + must.NoError(t, err) + must.NotNil(t, out) - require.NotEqual(t, sv, out) - require.NotEqual(t, svU.VariableMetadata, out.VariableMetadata) + must.NotEq(t, sv, out) + must.NotEqual(t, svU.VariableMetadata, out.VariableMetadata) // Update the input token with the updated metadata so that we // can use a simple equality check svU.CreateIndex, svU.ModifyIndex = out.CreateIndex, out.ModifyIndex svU.CreateTime, svU.ModifyTime = out.CreateTime, out.ModifyTime - require.Equal(t, svU.VariableMetadata, out.VariableMetadata) + must.Eq(t, svU.VariableMetadata, out.VariableMetadata) // fmt writes sorted output of maps for testability. - require.Equal(t, fmt.Sprint(svU.Items), fmt.Sprint(out.Items)) + must.Eq(t, fmt.Sprint(svU.Items), fmt.Sprint(out.Items)) } }) - rpcResetSV(s) + + t.Run("error_cas_and_acquire_lock", func(t *testing.T) { + svLA := sv1.Copy() + svLA.Items["new"] = "new" + + // break the request body + badBuf := encodeBrokenReq(&svLA) + + req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path+"?cas=1&"+acquireLockQueryParam, badBuf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + // Make the request + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.ErrorContains(t, err, "CAS can't be used with lock operations") + + var cErr HTTPCodedError + if !errors.As(err, &cErr) { + t.Fatalf("unexpected error") + } + + must.Eq(t, http.StatusBadRequest, cErr.Code()) + must.Nil(t, obj) + }) + t.Run("error_parse_acquire_lock", func(t *testing.T) { + svLA := sv1.Copy() + svLA.Items["new"] = "new" + + // break the request body + badBuf := encodeBrokenReq(&svLA) + + req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path+"?"+acquireLockQueryParam, badBuf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + // Make the request + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.ErrorContains(t, err, "unexpected EOF") + var cErr HTTPCodedError + + if !errors.As(err, &cErr) { + t.Fatalf("unexpected error") + } + + must.Eq(t, http.StatusBadRequest, cErr.Code()) + must.Nil(t, obj) + }) + t.Run("error_rpc_acquire_lock", func(t *testing.T) { + svLA := sv1.Copy() + svLA.Items["new"] = "new" + + // test broken rpc error + buf := encodeReq(&svLA) + req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path+"?region=bad&"+acquireLockQueryParam, buf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + // Make the request + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) + }) + + t.Run("acquire_lock", func(t *testing.T) { + svLA := sv1 + + svLA.Items["new"] = "new" + // Make the HTTP request + buf := encodeReq(&svLA) + req, err := http.NewRequest("PUT", "/v1/var/"+svLA.Path+"?"+acquireLockQueryParam, buf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.NoError(t, err) + + // Test the returned object and rehydrate to a VariableDecrypted + must.NotNil(t, obj) + out, ok := obj.(*structs.VariableDecrypted) + must.True(t, ok, must.Sprint("Unable to convert obj to VariableDecrypted")) + + // Check for the index + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, fmt.Sprint(out.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) + + // Check for the lock + must.NotNil(t, out.VariableMetadata.Lock) + must.NonZero(t, len(out.LockID())) + + // Check that written varible includes the new items + must.Eq(t, svLA.Items, out.Items) + + // Update the lock information for the following tests + sv1.VariableMetadata = out.VariableMetadata + }) + + t.Run("error_rpc_renew_lock", func(t *testing.T) { + svRL := sv1.Copy() + + // test broken rpc error + buf := encodeReq(&svRL) + req, err := http.NewRequest("PUT", "/v1/var/"+sv1.Path+"?region=bad&"+renewLockQueryParam, buf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + // Make the request + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) + }) + + t.Run("renew_lock", func(t *testing.T) { + svRL := sv1.Copy() + + // Make the HTTP request + buf := encodeReq(&svRL) + req, err := http.NewRequest("PUT", "/v1/var/"+svRL.Path+"?"+renewLockQueryParam, buf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.NoError(t, err) + + // Test the returned object and rehydrate to a VariableDecrypted + must.NotNil(t, obj) + out, ok := obj.(*structs.VariableMetadata) + must.True(t, ok, must.Sprint("Unable to convert obj to VariableDecrypted")) + + // Check for the lock + must.NotNil(t, out.Lock) + must.Eq(t, sv1.LockID(), out.Lock.ID) + }) + + t.Run("release_lock", func(t *testing.T) { + svLR := *sv1 + + svLR.Items = nil + // Make the HTTP request + buf := encodeReq(&svLR) + + req, err := http.NewRequest("PUT", "/v1/var/"+svLR.Path+"?"+releaseLockQueryParam, buf) + must.NoError(t, err) + respW := httptest.NewRecorder() + + obj, err := s.Server.VariableSpecificRequest(respW, req) + must.NoError(t, err) + + // Test the returned object and rehydrate to a VariableDecrypted + must.NotNil(t, obj) + out, ok := obj.(*structs.VariableDecrypted) + must.True(t, ok, must.Sprint("Unable to convert obj to VariableDecrypted")) + + // Check for the index + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, fmt.Sprint(out.ModifyIndex), respW.HeaderMap.Get("X-Nomad-Index")) + + // Check for the lock + must.Nil(t, out.VariableMetadata.Lock) + + // Check that written variable is equal the input + must.Zero(t, len(out.Items)) + + // Remove the lock information from the mock variable for the following tests + sv1.VariableMetadata = out.VariableMetadata + }) t.Run("error_rpc_delete", func(t *testing.T) { sv1 := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv1, nil)) + must.NoError(t, rpcWriteSV(s, sv1, nil)) // Make the HTTP request req, err := http.NewRequest(http.MethodDelete, "/v1/var/"+sv1.Path+"?region=bad", nil) @@ -388,14 +560,14 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.EqualError(t, err, "No path to region") - require.Nil(t, obj) + must.ErrorContains(t, err, "No path to region") + must.Nil(t, obj) }) t.Run("delete-cas", func(t *testing.T) { sv := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv, nil)) + must.NoError(t, rpcWriteSV(s, sv, nil)) sv, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) + must.NoError(t, err) // Make the HTTP request { @@ -405,25 +577,25 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) - require.Equal(t, http.StatusConflict, respW.Result().StatusCode) + must.NoError(t, err) + must.Eq(t, http.StatusConflict, respW.Result().StatusCode) // Evaluate the conflict variable - require.NotNil(t, obj) + must.NotNil(t, obj) conflict, ok := obj.(*structs.VariableDecrypted) - require.True(t, ok, "Expected *structs.VariableDecrypted, got %T", obj) - require.True(t, sv.Equal(*conflict)) + must.True(t, ok, must.Sprintf("Expected *structs.VariableDecrypted, got %T", obj)) + must.True(t, sv.Equal(*conflict)) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) } // Check variable was not deleted { svChk, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) - require.NotNil(t, svChk) - require.Equal(t, sv, svChk) + must.NoError(t, err) + must.NotNil(t, svChk) + must.Eq(t, sv, svChk) } // Make the HTTP request { @@ -433,19 +605,19 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) - require.Nil(t, obj) + must.NoError(t, err) + must.Nil(t, obj) } // Check variable was deleted { svChk, err := rpcReadSV(s, sv.Namespace, sv.Path) - require.NoError(t, err) - require.Nil(t, svChk) + must.NoError(t, err) + must.Nil(t, svChk) } }) t.Run("delete", func(t *testing.T) { sv1 := mock.Variable() - require.NoError(t, rpcWriteSV(s, sv1, nil)) + must.NoError(t, rpcWriteSV(s, sv1, nil)) // Make the HTTP request req, err := http.NewRequest(http.MethodDelete, "/v1/var/"+sv1.Path, nil) @@ -454,17 +626,27 @@ func TestHTTP_Variables(t *testing.T) { // Make the request obj, err := s.Server.VariableSpecificRequest(respW, req) - require.NoError(t, err) - require.Nil(t, obj) + must.NoError(t, err) + must.Nil(t, obj) // Check for the index - require.NotZero(t, respW.HeaderMap.Get("X-Nomad-Index")) - require.Equal(t, http.StatusNoContent, respW.Result().StatusCode) + must.NonZero(t, len(respW.HeaderMap.Get("X-Nomad-Index"))) + must.Eq(t, http.StatusNoContent, respW.Result().StatusCode) // Check variable was deleted sv, err := rpcReadSV(s, sv1.Namespace, sv1.Path) - require.NoError(t, err) - require.Nil(t, sv) + must.NoError(t, err) + must.Nil(t, sv) + }) + + // WIP + t.Run("error_parse_lock_acquire", func(t *testing.T) { + req, err := http.NewRequest("GET", "/v1/var/does/not/exist?wait=99a&lock=acquire", nil) + must.NoError(t, err) + respW := httptest.NewRecorder() + _, _ = s.Server.VariableSpecificRequest(respW, req) + must.Eq(t, http.StatusBadRequest, respW.Code) + must.Eq(t, "Invalid wait time", string(respW.Body.Bytes())) }) }) } @@ -521,7 +703,7 @@ func rpcResetSV(s *TestAgent) { }, } err := s.Agent.RPC(structs.VariablesListRPCMethod, &lArgs, &lResp) - require.NoError(s.T, err) + must.NoError(s.T, err) dArgs := structs.VariablesApplyRequest{ Op: structs.VarOpDelete, @@ -537,10 +719,10 @@ func rpcResetSV(s *TestAgent) { dArgs.Var.Path = v.Path dArgs.Var.Namespace = v.Namespace err := s.Agent.RPC(structs.VariablesApplyRPCMethod, &dArgs, &dResp) - require.NoError(s.T, err) + must.NoError(s.T, err) } err = s.Agent.RPC(structs.VariablesListRPCMethod, &lArgs, &lResp) - require.NoError(s.T, err) - require.Equal(s.T, 0, len(lResp.Data)) + must.NoError(s.T, err) + must.Eq(s.T, 0, len(lResp.Data)) } diff --git a/command/commands.go b/command/commands.go index f8923aeda..f833b1847 100644 --- a/command/commands.go +++ b/command/commands.go @@ -1121,6 +1121,13 @@ func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory { Meta: meta, }, nil }, + "var lock": func() (cli.Command, error) { + return &VarLockCommand{ + varPutCommand: &VarPutCommand{ + Meta: meta, + }, + }, nil + }, "var get": func() (cli.Command, error) { return &VarGetCommand{ Meta: meta, diff --git a/command/var_lock.go b/command/var_lock.go new file mode 100644 index 000000000..c306b819d --- /dev/null +++ b/command/var_lock.go @@ -0,0 +1,369 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package command + +import ( + "context" + "fmt" + "os" + "os/exec" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/hashicorp/nomad/api" + "github.com/posener/complete" +) + +const defaultMaxClientRetries = 5 + +type VarLockCommand struct { + shell bool + inFmt string + ttl string + lockDelay string + + varPutCommand *VarPutCommand +} + +func (c *VarLockCommand) Help() string { + helpText := ` +Usage: +nomad var lock [options] child... +nomad var lock [options] [] child... + + The lock command provides a mechanism for simple distributed locking. A lock + is created in the given variable, and only when held, is a child process invoked. + + The lock command can be called on an existing variable or an entire new variable + specification can be provided to the command from a file by using an + @-prefixed path to a variable specification file. Items to be stored in the + variable can be supplied using the specification file as well. + + Nomad lock launches its children in a shell. By default, Nomad will use the + shell defined in the environment variable SHELL. If SHELL is not defined, + it will default to /bin/sh. It should be noted that not all shells terminate + child processes when they receive SIGTERM. Under Ubuntu, /bin/sh is linked + to dash, which does not terminate its children. In order to ensure that + child processes are killed when the lock is lost, be sure to set the SHELL + environment variable appropriately, or run without a shell by setting -shell=false. + + If ACLs are enabled, this command requires the 'variables:write' capability + for the destination namespace and path. + +General Options: + + ` + generalOptionsUsage(usageOptsDefault) + ` + +Var lock Options: + -verbose + Provides additional information via standard error to preserve standard + output (stdout) for redirected output. + -ttl + Optional, TTL for the lock, time the variable will be locked. Defaults to 15s. + -delay + Optional, time the variable is blocked from locking when a lease is not renewed. + Defaults to 15s. + + -max-retry + Optional, max-retry up to this number of times if Nomad returns a 500 error + while monitoring the lock. This allows riding out brief periods of + unavailability without causing leader elections, but increases the amount of + time required to detect a lost lock in some cases. Defaults to 5. Set to 0 to + disable. + + -early-return + Optional, early-return indicates the command to return if the lock is not + acquired instead of waiting on stand by to try again. Defaults to false. + + -backoff + Optional, indicates how long to wait between attempts to obtain the lock. + By default the lease algorithm waits for 1.1 times the lock TTL. + + -shell + Optional, use a shell to run the command (can set a custom shell via + the SHELL environment variable). The default value is true. +` + return strings.TrimSpace(helpText) +} + +func (c *VarLockCommand) AutocompleteFlags() complete.Flags { + return mergeAutocompleteFlags(c.varPutCommand.Meta.AutocompleteFlags(FlagSetClient), + complete.Flags{}, + ) +} + +func (c *VarLockCommand) AutocompleteArgs() complete.Predictor { + return VariablePathPredictor(c.varPutCommand.Meta.Client) +} + +func (c *VarLockCommand) Synopsis() string { + return "Put a lock on a variable and run a child command if operation is successful" +} + +func (c *VarLockCommand) Name() string { return "var lock" } + +func (c *VarLockCommand) Run(args []string) int { + var doVerbose bool + var err error + var path string + var maxRetry int64 + var earlyReturn bool + var backoff time.Duration + + flags := c.varPutCommand.Meta.FlagSet(c.Name(), FlagSetClient) + flags.Usage = func() { c.varPutCommand.Ui.Output(c.Help()) } + + flags.BoolVar(&doVerbose, "verbose", false, "") + flags.StringVar(&c.ttl, "ttl", "", "") + flags.StringVar(&c.lockDelay, "delay", "", "") + flags.BoolVar(&c.shell, "shell", true, "") + flags.BoolVar(&earlyReturn, "early-return", false, "") + flags.Int64Var(&maxRetry, "max-retry", 5, "") + flags.DurationVar(&backoff, "backoff", 0, "") + + if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 { + flags.StringVar(&c.varPutCommand.outFmt, "out", "none", "") + } else { + flags.StringVar(&c.varPutCommand.outFmt, "out", "json", "") + } + + if err := flags.Parse(args); err != nil { + c.varPutCommand.Ui.Error(commandErrorText(c)) + return 1 + } + + args = flags.Args() + + // Manage verbose output + verbose := func(_ string) {} //no-op + if doVerbose { + verbose = func(msg string) { + c.varPutCommand.Ui.Warn(msg) + } + } + + c.varPutCommand.verbose = verbose + + if c.varPutCommand.Meta.namespace == api.AllNamespacesNamespace { + c.varPutCommand.Ui.Error(errWildcardNamespaceNotAllowed) + return 1 + } + + if len(args) < 2 { + c.varPutCommand.Ui.Error(fmt.Sprintf("Not enough arguments (expected >2, got %d)", len(args))) + return 1 + } + + path, args, err = c.readPathFromArgs(args) + if err != nil { + c.varPutCommand.Ui.Error(err.Error()) + return 1 + } + + sv, err := c.varPutCommand.makeVariable(path) + if err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("Failed to parse variable data: %s", err)) + return 1 + } + + if sv.Lock == nil { + if c.ttl == "" && c.lockDelay == "" { + c.varPutCommand.verbose("Using defaults for the lock") + } + + sv.Lock = &api.VariableLock{ + TTL: api.DefaultLockTTL.String(), + LockDelay: api.DefaultLockDelay.String(), + } + } + + if c.ttl != "" { + c.varPutCommand.verbose("Using TTL for the lock of " + c.ttl) + _, err := time.ParseDuration(c.ttl) + if err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("Invalid TTL: %s", err)) + return 1 + } + + sv.Lock.TTL = c.ttl + } + + if c.lockDelay != "" { + c.varPutCommand.verbose("Using delay for the lock of " + c.lockDelay) + _, err := time.ParseDuration(c.ttl) + if err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("Invalid Lock Delay: %s", err)) + return 1 + } + + sv.Lock.LockDelay = c.lockDelay + } + + // Get the HTTP client + client, err := c.varPutCommand.Meta.Client() + if err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) + return 1 + } + + // Set up the locks handler + lo := []api.LocksOption{} + if maxRetry != defaultMaxClientRetries { + lo = append(lo, api.LocksOptionWithMaxRetries(maxRetry)) + } + + l, err := client.Locks(api.WriteOptions{}, *sv, lo...) + if err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("Error initializing lock handler: %s", err)) + return 1 + } + + ctx := context.Background() + + // Set up the locks handler + llo := []api.LockLeaserOption{} + if earlyReturn { + c.varPutCommand.verbose("Setting up early return") + llo = append(llo, api.LockLeaserOptionWithEarlyReturn(true)) + } + + if backoff != 0 { + c.varPutCommand.verbose("Setting up backoff period") + llo = append(llo, api.LockLeaserOptionWithWaitPeriod(backoff)) + } + + ll := client.NewLockLeaser(l, llo...) + + c.varPutCommand.verbose("Attempting to acquire lock") + + // Run the shell inside the protected function. + if err := ll.Start(ctx, func(ctx context.Context) error { + c.varPutCommand.verbose(fmt.Sprintf("Variable locked, ready to execute: %s", + strings.Join(args, " "))) + + var newCommand func(ctx context.Context, args []string) (*exec.Cmd, error) + if !c.shell { + newCommand = subprocess + } else { + newCommand = script + } + + cmd, err := newCommand(ctx, args) + if err != nil { + return err + } + + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + signalCh := make(chan os.Signal, 10) + signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM) + defer signal.Stop(signalCh) + + go c.forwardSignals(ctx, cmd, signalCh) + + if err := cmd.Start(); err != nil { + return err + } + + return cmd.Wait() + + }); err != nil { + c.varPutCommand.Ui.Error("Lock error:" + err.Error()) + return 1 + } + + c.varPutCommand.verbose("Releasing the lock") + return 0 +} + +func (c *VarLockCommand) readPathFromArgs(args []string) (string, []string, error) { + var err error + var path string + + // Handle first argument: @file or «var path» + arg := args[0] + + switch { + case isArgFileRef(arg): + // ArgFileRefs start with "@" so we need to peel that off + // detect format based on file extension + specPath := arg[1:] + err = c.varPutCommand.setParserForFileArg(specPath) + if err != nil { + return "", args, err + } + + c.varPutCommand.verbose(fmt.Sprintf("Reading whole variable specification from %q", specPath)) + c.varPutCommand.contents, err = os.ReadFile(specPath) + if err != nil { + return "", args, fmt.Errorf("Error reading %q: %w", specPath, err) + } + default: + path = sanitizePath(arg) + c.varPutCommand.verbose(fmt.Sprintf("Writing to path %q", path)) + } + + // Handle second argument: can @file, or child process + args = args[1:] + switch { + case isArgFileRef(args[0]): + arg := args[0] + + err = c.varPutCommand.setParserForFileArg(arg) + if err != nil { + return "", args, err + } + + c.varPutCommand.verbose(fmt.Sprintf("Creating variable %q from specification file %q", path, arg)) + fPath := arg[1:] + c.varPutCommand.contents, err = os.ReadFile(fPath) + if err != nil { + return "", args, fmt.Errorf("error reading %q: %s", fPath, err) + } + args = args[1:] + default: + // no-op - should be child process + } + + return path, args, nil +} + +// script returns a command to execute a script through a shell. +func script(ctx context.Context, args []string) (*exec.Cmd, error) { + shell := "/bin/sh" + + if other := os.Getenv("SHELL"); other != "" { + shell = other + } + + return exec.CommandContext(ctx, shell, "-c", strings.Join(args, " ")), nil +} + +// subprocess returns a command to execute a subprocess directly. +func subprocess(ctx context.Context, args []string) (*exec.Cmd, error) { + if len(args) == 0 { + return nil, fmt.Errorf("need an executable to run") + } + return exec.CommandContext(ctx, args[0], args[1:]...), nil +} + +// ForwardSignals will fire up a goroutine to forward signals to the given +// subprocess until the context is canceled. +func (c *VarLockCommand) forwardSignals(ctx context.Context, cmd *exec.Cmd, sg chan os.Signal) { + for { + select { + case sig := <-sg: + if err := cmd.Process.Signal(sig); err != nil { + c.varPutCommand.Ui.Error(fmt.Sprintf("failed to send signal %q: %v", sig, err)) + } + + case <-ctx.Done(): + return + } + } +} diff --git a/command/var_lock_test.go b/command/var_lock_test.go new file mode 100644 index 000000000..b18ac377c --- /dev/null +++ b/command/var_lock_test.go @@ -0,0 +1,152 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package command + +import ( + "fmt" + "os" + "testing" + "time" + + "github.com/hashicorp/nomad/ci" + "github.com/mitchellh/cli" + "github.com/shoenig/test/must" + "github.com/stretchr/testify/require" +) + +func TestVarLockCommand_Implements(t *testing.T) { + ci.Parallel(t) + var _ cli.Command = &VarLockCommand{} +} + +func TestVarLockCommand_Fails(t *testing.T) { + ci.Parallel(t) + t.Run("bad_args", func(t *testing.T) { + ci.Parallel(t) + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + code := cmd.Run([]string{"-bad-flag"}) + out := ui.ErrorWriter.String() + must.One(t, code) + must.StrContains(t, out, commandErrorText(cmd)) + }) + + t.Run("bad_address", func(t *testing.T) { + ci.Parallel(t) + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + code := cmd.Run([]string{"-address=nope", "foo", "-"}) + out := ui.ErrorWriter.String() + must.One(t, code) + must.StrContains(t, out, "unsupported protocol scheme") + }) + + t.Run("missing_args", func(t *testing.T) { + ci.Parallel(t) + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + code := cmd.Run([]string{"foo"}) + out := ui.ErrorWriter.String() + must.One(t, code) + must.StrContains(t, out, "Not enough arguments (expected >2, got 1)") + }) + + t.Run("invalid_TTL", func(t *testing.T) { + ci.Parallel(t) + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + code := cmd.Run([]string{"-ttl=2", "bar", "foo"}) + out := ui.ErrorWriter.String() + must.One(t, code) + must.StrContains(t, out, "Invalid TTL: time") + }) + + t.Run("invalid_lock_delay", func(t *testing.T) { + ci.Parallel(t) + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + code := cmd.Run([]string{"-delay=2", "bar", "foo"}) + out := ui.ErrorWriter.String() + must.One(t, code) + must.StrContains(t, out, "Invalid Lock Delay: time") + }) +} + +func TestVarLockCommand_Good(t *testing.T) { + ci.Parallel(t) + + // Create a server + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + + filePath := fmt.Sprintf("%v.txt", time.Now().Unix()) + + // Get the variable + code := cmd.Run([]string{"-address=" + url, "test/var/shell", "touch ", filePath}) + require.Equal(t, 0, code, "expected exit 0, got: %d; %v", code, ui.ErrorWriter.String()) + + sv, _, err := srv.Client().Variables().Peek("test/var/shell", nil) + must.NoError(t, err) + + must.NotNil(t, sv) + must.Eq(t, "test/var/shell", sv.Path) + + // Check for the file + _, err = os.ReadFile(filePath) + must.NoError(t, err) + + t.Cleanup(func() { + os.Remove(filePath) + _, _ = client.Variables().Delete("test/var/shell", nil) + }) +} + +func TestVarLockCommand_Good_NoShell(t *testing.T) { + ci.Parallel(t) + + // Create a server + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := cli.NewMockUi() + cmd := &VarLockCommand{ + varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}}, + } + + filePath := fmt.Sprintf("%v.txt", time.Now().Unix()) + + // Get the variable + code := cmd.Run([]string{"-address=" + url, "-shell=false", "test/var/noShell", "touch", filePath}) + require.Zero(t, 0, code) + + sv, _, err := srv.Client().Variables().Peek("test/var/noShell", nil) + must.NoError(t, err) + + must.NotNil(t, sv) + must.Eq(t, "test/var/noShell", sv.Path) + + // Check for the file + _, err = os.ReadFile(filePath) + must.NoError(t, err) + + t.Cleanup(func() { + os.Remove(filePath) + _, _ = client.Variables().Delete("test/var/noShell", nil) + }) +} diff --git a/command/var_put.go b/command/var_put.go index 43f0ea969..0ed6c8ea8 100644 --- a/command/var_put.go +++ b/command/var_put.go @@ -73,7 +73,7 @@ General Options: ` + generalOptionsUsage(usageOptsDefault) + ` -Apply Options: +Var put Options: -check-index If set, the variable is only acted upon if the server-side version's index @@ -376,6 +376,7 @@ func (c *VarPutCommand) makeVariable(path string) (*api.Variable, error) { out.Items = make(map[string]string) return out, nil } + switch c.inFmt { case "json": err = json.Unmarshal(c.contents, out) diff --git a/nomad/fsm.go b/nomad/fsm.go index 77a47a6c3..4e4aead98 100644 --- a/nomad/fsm.go +++ b/nomad/fsm.go @@ -2254,7 +2254,8 @@ func (f *FSMFilter) Include(item interface{}) bool { return true } -func (n *nomadFSM) applyVariableOperation(msgType structs.MessageType, buf []byte, index uint64) interface{} { +func (n *nomadFSM) applyVariableOperation(msgType structs.MessageType, buf []byte, + index uint64) any { var req structs.VarApplyStateRequest if err := structs.Decode(buf, &req); err != nil { panic(fmt.Errorf("failed to decode request: %v", err)) @@ -2270,6 +2271,10 @@ func (n *nomadFSM) applyVariableOperation(msgType structs.MessageType, buf []byt return n.state.VarDeleteCAS(index, &req) case structs.VarOpCAS: return n.state.VarSetCAS(index, &req) + case structs.VarOpLockAcquire: + return n.state.VarLockAcquire(index, &req) + case structs.VarOpLockRelease: + return n.state.VarLockRelease(index, &req) default: err := fmt.Errorf("Invalid variable operation '%s'", req.Op) n.logger.Warn("Invalid variable operation", "operation", req.Op) diff --git a/nomad/leader.go b/nomad/leader.go index dce59eab5..719160fa5 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -397,6 +397,17 @@ func (s *Server) establishLeadership(stopCh chan struct{}) error { // Periodically publish job status metrics go s.publishJobStatusMetrics(stopCh) + // Populate the variable lock TTL timers, so we can start tracking renewals + // and expirations. + if err := s.restoreLockTTLTimers(); err != nil { + return err + } + + // Periodically publish metrics for the lock timer trackers which are only + // run on the leader. + go s.lockTTLTimer.EmitMetrics(1*time.Second, stopCh) + go s.lockDelayTimer.EmitMetrics(1*time.Second, stopCh) + // Setup the heartbeat timers. This is done both when starting up or when // a leader fail over happens. Since the timers are maintained by the leader // node, effectively this means all the timers are renewed at the time of failover. @@ -1465,6 +1476,10 @@ func (s *Server) revokeLeadership() error { return err } + // Stop all the tracked variable lock TTL and delay timers. + s.lockTTLTimer.StopAndRemoveAll() + s.lockDelayTimer.RemoveAll() + // Clear the heartbeat timers on either shutdown or step down, // since we are no longer responsible for TTL expirations. if err := s.clearAllHeartbeatTimers(); err != nil { diff --git a/nomad/leader_test.go b/nomad/leader_test.go index fe4330761..c07e88756 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -12,7 +12,7 @@ import ( "time" "github.com/hashicorp/go-hclog" - memdb "github.com/hashicorp/go-memdb" + "github.com/hashicorp/go-memdb" "github.com/hashicorp/go-version" "github.com/shoenig/test" "github.com/shoenig/test/must" diff --git a/nomad/lock/delay.go b/nomad/lock/delay.go new file mode 100644 index 000000000..1255a47f1 --- /dev/null +++ b/nomad/lock/delay.go @@ -0,0 +1,90 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package lock + +import ( + "sync" + "time" + + "github.com/armon/go-metrics" + "github.com/hashicorp/nomad/helper" +) + +// DelayTimer is used to mark certain locks as unacquirable. When a locks TTL +// expires, it is subject to the LockDelay configured within the variable. This +// prevents another caller from acquiring the lock for some period of time as a +// protection against split-brains. This is inspired by the lock-delay in +// Chubby. +type DelayTimer struct { + + // delayTimers has the set of active delay expiration times, organized by + // ID, which the caller dictates when adding entries. The lock should be + // used for all access. + delayTimers map[string]time.Time + lock sync.RWMutex +} + +// NewDelayTimer returns a new delay timer manager. +func NewDelayTimer() *DelayTimer { + return &DelayTimer{ + delayTimers: make(map[string]time.Time), + } +} + +// Get returns the expiration time of a key lock delay. This must be checked on +// the leader server only due to the variability of clocks. +func (d *DelayTimer) Get(id string) time.Time { + d.lock.RLock() + expires := d.delayTimers[id] + d.lock.RUnlock() + return expires +} + +// Set sets the expiration time for the lock delay to the given delay from the +// given now time. +func (d *DelayTimer) Set(id string, now time.Time, delay time.Duration) { + d.lock.Lock() + defer d.lock.Unlock() + + d.delayTimers[id] = now.Add(delay) + + // Set up the after func, but ignore the returned timer as we do not need + // this for cancellation. + _ = time.AfterFunc(delay, func() { + d.lock.Lock() + delete(d.delayTimers, id) + d.lock.Unlock() + }) +} + +// RemoveAll removes all registered timers. +func (d *DelayTimer) RemoveAll() { + d.lock.Lock() + defer d.lock.Unlock() + d.delayTimers = make(map[string]time.Time) +} + +// EmitMetrics is a long-running routine used to emit periodic metrics about +// the Delay. +func (d *DelayTimer) EmitMetrics(period time.Duration, shutdownCh chan struct{}) { + timer, stop := helper.NewSafeTimer(period) + defer stop() + + for { + timer.Reset(period) + select { + case <-timer.C: + metrics.SetGauge([]string{"variables", "locks", "delay_timer", "num"}, float32(d.timerNum())) + case <-shutdownCh: + return + } + } +} + +// timerNum returns the number of registered delay timers. +func (d *DelayTimer) timerNum() int { + d.lock.RLock() + defer d.lock.RUnlock() + return len(d.delayTimers) +} diff --git a/nomad/lock/delay_test.go b/nomad/lock/delay_test.go new file mode 100644 index 000000000..1f7e10f3c --- /dev/null +++ b/nomad/lock/delay_test.go @@ -0,0 +1,43 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package lock + +import ( + "testing" + "time" + + "github.com/hashicorp/nomad/ci" + "github.com/shoenig/test/must" +) + +func TestDelay(t *testing.T) { + ci.Parallel(t) + + delay := NewDelayTimer() + + // An unknown key should have a time in the past. + must.True(t, delay.Get("this-does-not-exist").Before(time.Now())) + must.Eq(t, 0, delay.timerNum()) + + // Add a key and set a short expiration. + timeNow := time.Now() + delay.Set("test-delay-1", timeNow, 100*time.Millisecond) + must.False(t, delay.Get("test-delay-1").Before(time.Now())) + must.Eq(t, 1, delay.timerNum()) + + // Wait for the key to expire and check again. + time.Sleep(120 * time.Millisecond) + must.True(t, delay.Get("test-delay-1").Before(timeNow)) + must.Eq(t, 0, delay.timerNum()) + + // Add a key and set a long expiration. + timeNow = time.Now() + delay.Set("test-delay-2", timeNow, 1000*time.Millisecond) + must.False(t, delay.Get("test-delay-2").Before(time.Now())) + must.Eq(t, 1, delay.timerNum()) + + // Perform the stop call which the leader will do when stepping down. + delay.RemoveAll() + must.Eq(t, 0, delay.timerNum()) +} diff --git a/nomad/lock/ttl.go b/nomad/lock/ttl.go new file mode 100644 index 000000000..752cb8789 --- /dev/null +++ b/nomad/lock/ttl.go @@ -0,0 +1,106 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package lock + +import ( + "sync" + "time" + + "github.com/armon/go-metrics" + "github.com/hashicorp/nomad/helper" +) + +// TTLTimer provides a map of named timers which is safe for concurrent use. +// Each timer is created using time.AfterFunc which will be triggered once the +// timer fires. +type TTLTimer struct { + + // timers is a mapping of timers which represent when a lock TTL will + // expire. The lock should be used for all access. + ttlTimers map[string]*time.Timer + lock sync.RWMutex +} + +// NewTTLTimer initializes a new TTLTimer. +func NewTTLTimer() *TTLTimer { + return &TTLTimer{ + ttlTimers: make(map[string]*time.Timer), + } +} + +// Get returns the timer with the given ID. If the timer is not found, nil is +// returned, so callers should be expected to handle this case. +func (t *TTLTimer) Get(id string) *time.Timer { + t.lock.RLock() + defer t.lock.RUnlock() + return t.ttlTimers[id] +} + +// Delete removes the timer with the given ID from the tracking. If the timer +// is not found, the call is noop. +func (t *TTLTimer) Delete(id string) { + t.lock.Lock() + defer t.lock.Unlock() + delete(t.ttlTimers, id) +} + +// Create sets the TTL of the timer with the given ID or creates a new +// one if it does not exist. +func (t *TTLTimer) Create(id string, ttl time.Duration, afterFn func()) { + t.lock.Lock() + defer t.lock.Unlock() + + if tm := t.ttlTimers[id]; tm != nil { + tm.Reset(ttl) + return + } + t.ttlTimers[id] = time.AfterFunc(ttl, afterFn) +} + +// StopAndRemove stops the timer with the given ID and removes it from +// tracking. +func (t *TTLTimer) StopAndRemove(id string) { + t.lock.Lock() + defer t.lock.Unlock() + + if tm := t.ttlTimers[id]; tm != nil { + tm.Stop() + delete(t.ttlTimers, id) + } +} + +// StopAndRemoveAll stops and removes all registered timers. +func (t *TTLTimer) StopAndRemoveAll() { + t.lock.Lock() + defer t.lock.Unlock() + + for _, tm := range t.ttlTimers { + tm.Stop() + } + t.ttlTimers = make(map[string]*time.Timer) +} + +// EmitMetrics is a long-running routine used to emit periodic metrics about +// the Timer. +func (t *TTLTimer) EmitMetrics(period time.Duration, shutdownCh chan struct{}) { + timer, stop := helper.NewSafeTimer(period) + defer stop() + + for { + timer.Reset(period) + select { + case <-timer.C: + metrics.SetGauge([]string{"variables", "locks", "ttl_timer", "num"}, float32(t.TimerNum())) + case <-shutdownCh: + return + } + } +} + +// timerNum returns the number of registered timers. +func (t *TTLTimer) TimerNum() int { + t.lock.RLock() + defer t.lock.RUnlock() + return len(t.ttlTimers) +} diff --git a/nomad/lock/ttl_test.go b/nomad/lock/ttl_test.go new file mode 100644 index 000000000..8cb88faf3 --- /dev/null +++ b/nomad/lock/ttl_test.go @@ -0,0 +1,75 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package lock + +import ( + "testing" + "time" + + "github.com/hashicorp/nomad/ci" + "github.com/shoenig/test/must" +) + +func TestTimer(t *testing.T) { + ci.Parallel(t) + + // Create a test channel and timer test function that will be used + // throughout the test. + newTimerCh := make(chan int) + + waitForTimer := func() { + select { + case <-newTimerCh: + return + case <-time.After(100 * time.Millisecond): + t.Fatal("timer did not fire") + } + } + + timer := NewTTLTimer() + + // Perform a lookup on a timer that doesn't exist, to ensure this is + // handled properly. + must.Nil(t, timer.Get("this-does-not-exist")) + + // Perform a create, read, update, and delete on a single timer. + timer.Create("test-timer-2", time.Millisecond, func() { newTimerCh <- 1 }) + must.Eq(t, 1, timer.TimerNum()) + waitForTimer() + + // Ensure the timer is still held within the mapping. + must.Eq(t, 1, timer.TimerNum()) + + // Update the timer and check that it fires again. + timer.Create("test-timer-2", time.Millisecond, nil) + waitForTimer() + + // Reset the timer with a long ttl and then stop it. + timer.Create("test-timer-2", 20*time.Millisecond, func() { newTimerCh <- 1 }) + timer.StopAndRemove("test-timer-2") + + select { + case <-newTimerCh: + t.Fatal("timer fired although it shouldn't") + case <-time.After(100 * time.Millisecond): + } + + // Ensure that stopping a stopped timer does not break anything. + timer.StopAndRemove("test-timer-2") + must.Eq(t, 0, timer.TimerNum()) + + // Create two timers, stopping them using the StopAll function to signify + // leadership loss. + timer.Create("test-timer-3", 20*time.Millisecond, func() { newTimerCh <- 1 }) + timer.Create("test-timer-4", 30*time.Millisecond, func() { newTimerCh <- 2 }) + timer.StopAndRemoveAll() + + select { + case msg := <-newTimerCh: + t.Fatalf("timer %d fired although it shouldn't", msg) + case <-time.After(100 * time.Millisecond): + } + + must.Eq(t, 0, timer.TimerNum()) +} diff --git a/nomad/locks.go b/nomad/locks.go new file mode 100644 index 000000000..464e11635 --- /dev/null +++ b/nomad/locks.go @@ -0,0 +1,154 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package nomad + +import ( + "errors" + "fmt" + "time" + + "github.com/hashicorp/nomad/nomad/structs" +) + +var ( + errTimerNotFound = errors.New("lock doesn't have a running timer ") +) + +// restoreLockTTLTimers iterates the stored variables and creates a lock TTL +// timer for each variable lock. This is used during leadership establishment +// to populate the in-memory timer. +func (s *Server) restoreLockTTLTimers() error { + + varIterator, err := s.fsm.State().Variables(nil) + if err != nil { + return fmt.Errorf("failed to list variables for lock TTL restore: %v", err) + } + + // Iterate the variables, identifying each one that is associated to a lock + // and adding a TTL timer for each. + for varInterface := varIterator.Next(); varInterface != nil; varInterface = varIterator.Next() { + if realVar, ok := varInterface.(*structs.VariableEncrypted); ok && realVar.IsLock() { + + // The variable will be modified in order to show that it no longer + // is held. We therefore need to ensure we perform modifications on + // a copy. + s.CreateVariableLockTTLTimer(realVar.Copy()) + } + } + + return nil +} + +// CreateVariableLockTTLTimer creates a TTL timer for the given lock. +// It is in charge of integrating the delay after the TTL expires. +func (s *Server) CreateVariableLockTTLTimer(variable structs.VariableEncrypted) { + s.logger.Debug("locks: adding lock", "namespace", variable.Namespace, "path", variable.Path) + // Adjust the given TTL by multiplier of 2. This is done to give a client a + // grace period and to compensate for network and processing delays. The + // contract is that a variable lock is not expired before the TTL expires, + // but there is no explicit promise about the upper bound so this is + // allowable. + lockTTL := variable.Lock.TTL * 2 + + // The lock ID is used a couple of times, so grab this now. + lockID := variable.LockID() + + lock := s.lockTTLTimer.Get(lockID) + if lock != nil { + // If this was to happen, there is a sync issue somewhere else + s.logger.Error("attempting to recreate existing lock: %s", lockID) + return + } + + s.lockTTLTimer.Create(lockID, lockTTL, func() { + s.logger.Debug("locks: lock TTL expired, starting delay", + "namespace", variable.Namespace, "path", variable.Path, "ttl", variable.Lock.TTL) + s.lockTTLTimer.StopAndRemove(lockID) + + _ = time.AfterFunc(variable.Lock.LockDelay, func() { + s.invalidateVariableLock(variable) + }) + }) +} + +// invalidateVariableLock exponentially tries to update Nomad's state to remove +// the lock ID from the variable. This can be used when a variable lock's TTL +// has expired. +func (s *Server) invalidateVariableLock(variable structs.VariableEncrypted) { + lockID := variable.LockID() + + s.logger.Debug("locks: lock delay expired, removing lock", + "namespace", variable.Namespace, "path", variable.Path) + + // Remove the lock from the variable + variable.VariableMetadata.Lock = nil + + args := structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: &structs.VariableEncrypted{ + VariableMetadata: variable.VariableMetadata, + }, + WriteRequest: structs.WriteRequest{ + Region: s.Region(), + Namespace: variable.Namespace, + }, + } + + // Retry with exponential backoff to remove the lock + for attempt := 0; attempt < maxAttemptsToRaftApply; attempt++ { + _, _, err := s.raftApply(structs.VarApplyStateRequestType, args) + if err == nil { + return + } + + s.logger.Error("lock expiration failed", + "namespace", variable.Namespace, "path", variable.Path, + "lock_id", lockID, "error", err) + // This exponential backoff will extend the lock Delay beyond the expected + // time if there is any raft error, should we make it dependant on the LockDelay? + time.Sleep((1 << attempt) * 10 * time.Second) + } +} + +func (s *Server) RenewTTLTimer(variable structs.VariableEncrypted) error { + lockID := variable.LockID() + + s.logger.Debug("locks: renewing the lock", + "namespace", variable.Namespace, "path", variable.Path, "ttl", variable.Lock.TTL) + + lock := s.lockTTLTimer.Get(lockID) + if lock == nil { + return errTimerNotFound + } + + // Adjust the given TTL by multiplier of 2. This is done to give a client a + // grace period and to compensate for network and processing delays. The + // contract is that a variable lock is not expired before the TTL expires, + // but there is no explicit promise about the upper bound so this is + // allowable. + lockTTL := variable.Lock.TTL * 2 + + // The create function resets the timer when it exists already, there is no + // need to provide the release function again. + s.lockTTLTimer.Create(lockID, lockTTL, nil) + return nil +} + +// RemoveVariableLockTTLTimer creates a TTL timer for the given lock. The +// passed ID is expected to be generated via the variable NamespacedID +// function. +func (s *Server) RemoveVariableLockTTLTimer(variable structs.VariableEncrypted) { + + // The lock ID is used a couple of times, so grab this now. + lockID := variable.LockID() + + lock := s.lockTTLTimer.Get(lockID) + if lock == nil { + // If this was to happen, there is a sync issue somewhere else. + s.logger.Error("attempting to removed missing lock: %s", lockID) + return + } + + s.lockTTLTimer.StopAndRemove(lockID) +} diff --git a/nomad/locks_test.go b/nomad/locks_test.go new file mode 100644 index 000000000..ffef5e1c5 --- /dev/null +++ b/nomad/locks_test.go @@ -0,0 +1,202 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package nomad + +import ( + "errors" + "testing" + "time" + + "github.com/hashicorp/nomad/ci" + "github.com/hashicorp/nomad/helper/uuid" + "github.com/hashicorp/nomad/nomad/mock" + "github.com/hashicorp/nomad/nomad/structs" + "github.com/hashicorp/nomad/testutil" + "github.com/shoenig/test/must" +) + +func TestServer_restoreLockTTLTimers(t *testing.T) { + ci.Parallel(t) + + testServer, testServerCleanup := TestServer(t, nil) + defer testServerCleanup() + testutil.WaitForLeader(t, testServer.RPC) + + // Generate two variables, one with and one without a lock and upsert these + // into state. + mockVar1 := mock.VariableEncrypted() + + mockVar2 := mock.VariableEncrypted() + mockVar2.Lock = &structs.VariableLock{ + ID: uuid.Generate(), + TTL: 15 * time.Second, + LockDelay: 15 * time.Second, + } + + upsertResp1 := testServer.fsm.State().VarSet(10, &structs.VarApplyStateRequest{Var: mockVar1, Op: structs.VarOpSet}) + must.NoError(t, upsertResp1.Error) + + upsertResp2 := testServer.fsm.State().VarSet(20, &structs.VarApplyStateRequest{Var: mockVar2, Op: structs.VarOpLockAcquire}) + must.NoError(t, upsertResp2.Error) + + // Call the server function that restores the lock TTL timers. This would + // usually happen on leadership transition. + must.NoError(t, testServer.restoreLockTTLTimers()) + + // Ensure the TTL timer tracking has the expected entries. + must.Nil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + must.NotNil(t, testServer.lockTTLTimer.Get(mockVar2.LockID())) +} + +func TestServer_invalidateVariableLock(t *testing.T) { + ci.Parallel(t) + + testServer, testServerCleanup := TestServer(t, nil) + defer testServerCleanup() + testutil.WaitForLeader(t, testServer.RPC) + + // Generate a variable that includes a lock entry and upsert this into our + // state. + mockVar1 := mock.VariableEncrypted() + mockVar1.Lock = &structs.VariableLock{ + ID: uuid.Generate(), + TTL: 15 * time.Second, + LockDelay: 15 * time.Second, + } + + upsertResp1 := testServer.fsm.State().VarSet(10, &structs.VarApplyStateRequest{Var: mockVar1, Op: structs.VarOpLockAcquire}) + must.NoError(t, upsertResp1.Error) + + // Create the timer manually, so we can control the invalidation for + // testing. + testServer.lockTTLTimer.Create(mockVar1.LockID(), mockVar1.Lock.TTL, func() {}) + + // Perform the invalidation call. + testServer.invalidateVariableLock(*mockVar1) + + // Pull the variable out of state and check that the lock ID has been + // removed. + varGetResp, err := testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Nil(t, varGetResp.Lock) +} + +func TestServer_createVariableLockTimer(t *testing.T) { + ci.Parallel(t) + + testServer, testServerCleanup := TestServer(t, nil) + defer testServerCleanup() + testutil.WaitForLeader(t, testServer.RPC) + + // Generate a variable that includes a lock entry and upsert this into our + // state. + mockVar1 := mock.VariableEncrypted() + mockVar1.Lock = &structs.VariableLock{ + ID: uuid.Generate(), + TTL: 10 * time.Millisecond, + LockDelay: 10 * time.Millisecond, + } + + upsertResp1 := testServer.fsm.State().VarSet(10, &structs.VarApplyStateRequest{Var: mockVar1, Op: structs.VarOpLockAcquire}) + must.NoError(t, upsertResp1.Error) + + testServer.CreateVariableLockTTLTimer(*mockVar1) + + time.Sleep(10 * time.Millisecond) + + // Check the timer is still present, meaning it didn't expired and the variable + // still holds a lock + must.NotNil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err := testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Eq(t, mockVar1.LockID(), varGetResp.LockID()) + + // After 15ms more, the TTL has expired, no timer should be running but the variable + // must still hold the lock. + time.Sleep(15 * time.Millisecond) + must.Nil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err = testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Eq(t, mockVar1.LockID(), varGetResp.LockID()) + + // After 10ms more, the delay should have expired as well and the variable + // should not hold the lock + time.Sleep(10 * time.Millisecond) + must.Nil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err = testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Nil(t, varGetResp.Lock) +} + +func TestServer_createAndRenewVariableLockTimer(t *testing.T) { + + ci.Parallel(t) + + testServer, testServerCleanup := TestServer(t, nil) + defer testServerCleanup() + testutil.WaitForLeader(t, testServer.RPC) + + // Generate a variable that includes a lock entry and upsert this into our + // state. + mockVar1 := mock.VariableEncrypted() + mockVar1.Lock = &structs.VariableLock{ + ID: uuid.Generate(), + TTL: 10 * time.Millisecond, + LockDelay: 10 * time.Millisecond, + } + + // Attempt to renew a lock that has no timer yet + err := testServer.RenewTTLTimer(*mockVar1) + + if !errors.Is(errTimerNotFound, err) { + t.Fatalf("expected error, got %s", err) + } + + upsertResp1 := testServer.fsm.State().VarSet(10, &structs.VarApplyStateRequest{Var: mockVar1, Op: structs.VarOpLockAcquire}) + must.NoError(t, upsertResp1.Error) + + testServer.CreateVariableLockTTLTimer(*mockVar1) + + time.Sleep(10 * time.Millisecond) + + // Check the timer is still present, meaning it didn't expired and the variable + // still holds a lock + must.NotNil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err := testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Eq(t, mockVar1.LockID(), varGetResp.LockID()) + + for i := 0; i < 3; i++ { + // Renew the lock + err = testServer.RenewTTLTimer(*mockVar1) + must.NoError(t, err) + + // After 10 ms the timer is must still present, meaning it was correctly renewed + // and the variable still holds a lock. + time.Sleep(10 * time.Millisecond) + + must.NotNil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err = testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Eq(t, mockVar1.LockID(), varGetResp.LockID()) + } + + // After 15ms more, the TTL has expired, no timer should be running but the variable + // must still hold the lock. + time.Sleep(15 * time.Millisecond) + + must.Nil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err = testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Eq(t, mockVar1.LockID(), varGetResp.LockID()) + + // After 10ms more, the delay should have expired as well and the variable + // should not hold the lock + time.Sleep(10 * time.Millisecond) + + must.Nil(t, testServer.lockTTLTimer.Get(mockVar1.LockID())) + varGetResp, err = testServer.fsm.State().GetVariable(nil, mockVar1.Namespace, mockVar1.Path) + must.NoError(t, err) + must.Nil(t, varGetResp.Lock) +} diff --git a/nomad/server.go b/nomad/server.go index 7721c389e..04fe9a342 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -41,6 +41,7 @@ import ( "github.com/hashicorp/nomad/lib/auth/oidc" "github.com/hashicorp/nomad/nomad/deploymentwatcher" "github.com/hashicorp/nomad/nomad/drainer" + "github.com/hashicorp/nomad/nomad/lock" "github.com/hashicorp/nomad/nomad/state" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" @@ -270,6 +271,12 @@ type Server struct { // shutting down, the oidcProviderCache.Shutdown() function must be called. oidcProviderCache *oidc.ProviderCache + // lockTTLTimer and lockDelayTimer are used to track variable lock timers. + // These are held in memory on the leader rather than in state to avoid + // large amount of Raft writes. + lockTTLTimer *lock.TTLTimer + lockDelayTimer *lock.DelayTimer + // leaderAcl is the management ACL token that is valid when resolved by the // current leader. leaderAcl string @@ -353,6 +360,8 @@ func NewServer(config *Config, consulCatalog consul.CatalogAPI, consulConfigEntr rpcTLS: incomingTLS, aclCache: aclCache, workersEventCh: make(chan interface{}, 1), + lockTTLTimer: lock.NewTTLTimer(), + lockDelayTimer: lock.NewDelayTimer(), } s.shutdownCtx, s.shutdownCancel = context.WithCancel(context.Background()) diff --git a/nomad/state/state_store_variables.go b/nomad/state/state_store_variables.go index 83311d891..e2abf5fb8 100644 --- a/nomad/state/state_store_variables.go +++ b/nomad/state/state_store_variables.go @@ -4,6 +4,7 @@ package state import ( + "errors" "fmt" "math" @@ -11,6 +12,12 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) +var ( + errVarAlreadyLocked = errors.New("variable already holds a lock") + errVarNotFound = errors.New("variable doesn't exist") + errLockNotFound = errors.New("variable doesn't hold a lock") +) + // Variables queries all the variables and is used only for // snapshot/restore and key rotation func (s *StateStore) Variables(ws memdb.WatchSet) (memdb.ResultIterator, error) { @@ -175,10 +182,12 @@ func (s *StateStore) varSetCASTxn(tx WriteTxn, idx uint64, req *structs.VarApply return req.ConflictResponse(idx, zeroVal) } - // If the existing index does not match the provided CAS index arg, then we - // shouldn't update anything and can safely return early here. - if ok && sv.ModifyIndex != svEx.ModifyIndex { - return req.ConflictResponse(idx, svEx) + if ok { + // If the existing index does not match the provided CAS index arg, then we + // shouldn't update anything and can safely return early here. + if sv.ModifyIndex != svEx.ModifyIndex { + return req.ConflictResponse(idx, svEx) + } } // If we made it this far, we should perform the set. @@ -193,6 +202,7 @@ func (s *StateStore) varSetTxn(tx WriteTxn, idx uint64, req *structs.VarApplySta if err != nil { return req.ErrorResponse(idx, fmt.Errorf("failed sve lookup: %s", err)) } + existing, _ := existingRaw.(*structs.VariableEncrypted) existingQuota, err := tx.First(TableVariablesQuotas, indexID, sv.Namespace) @@ -201,9 +211,21 @@ func (s *StateStore) varSetTxn(tx WriteTxn, idx uint64, req *structs.VarApplySta } var quotaChange int64 - // Set the CreateIndex and CreateTime if existing != nil { + + // If the variable is locked, it can only be updated by providing the correct + // lock ID. + if isLocked(existing.Lock, req) { + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Namespace: sv.Namespace, + Path: sv.Path, + }, + } + return req.ConflictResponse(idx, zeroVal) + } + sv.CreateIndex = existing.CreateIndex sv.CreateTime = existing.CreateTime @@ -379,13 +401,23 @@ func (s *StateStore) svDeleteTxn(tx WriteTxn, idx uint64, req *structs.VarApplyS return req.SuccessResponse(idx, nil) } + sv := existingRaw.(*structs.VariableEncrypted) + + if isLocked(sv.Lock, req) { + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Namespace: sv.Namespace, + Path: sv.Path, + }, + } + return req.ConflictResponse(idx, zeroVal) + } + existingQuota, err := tx.First(TableVariablesQuotas, indexID, req.Var.Namespace) if err != nil { return req.ErrorResponse(idx, fmt.Errorf("variable quota lookup failed: %v", err)) } - sv := existingRaw.(*structs.VariableEncrypted) - // Track quota usage if existingQuota != nil { quotaUsed := existingQuota.(*structs.VariablesQuota) @@ -448,3 +480,117 @@ func (s *StateStore) VariablesQuotaByNamespace(ws memdb.WatchSet, namespace stri quotaUsed := raw.(*structs.VariablesQuota) return quotaUsed, nil } + +// VarLockAcquire is the method used to append a lock to a variable, if the +// variable doesn't exists, it is created. +// IMPORTANT: this method overwrites the variable, data included. +func (s *StateStore) VarLockAcquire(idx uint64, + req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { + tx := s.db.WriteTxn(idx) + defer tx.Abort() + + // Try to fetch the variable. + raw, err := tx.First(TableVariables, indexID, req.Var.Namespace, req.Var.Path) + if err != nil { + return req.ErrorResponse(idx, fmt.Errorf("variable lookup failed: %v", err)) + } + + sv, ok := raw.(*structs.VariableEncrypted) + // If the variable exist, we must make sure it doesn't hold a lock already + if ok { + if isLocked(sv.VariableMetadata.Lock, req) { + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Namespace: sv.Namespace, + Path: sv.Path, + }, + } + return req.ConflictResponse(idx, zeroVal) + } + } + + resp := s.varSetTxn(tx, idx, req) + if resp.IsError() { + return resp + } + + if err := tx.Commit(); err != nil { + return req.ErrorResponse(idx, err) + } + + return resp +} + +func (s *StateStore) VarLockRelease(idx uint64, + req *structs.VarApplyStateRequest) *structs.VarApplyStateResponse { + tx := s.db.WriteTxn(idx) + defer tx.Abort() + + // Look up the entry in the state store. + raw, err := tx.First(TableVariables, indexID, req.Var.Namespace, req.Var.Path) + if err != nil { + return req.ErrorResponse(idx, fmt.Errorf("failed variable lookup: %s", err)) + } + + sv, ok := raw.(*structs.VariableEncrypted) + if !ok { + return req.ErrorResponse(idx, errVarNotFound) + } + + if sv.Lock == nil || sv.Lock.ID == "" { + return req.ErrorResponse(idx, errLockNotFound) + } + + if req.Var.Lock != nil && sv.Lock.ID != req.Var.Lock.ID { + // Avoid showing the variable data on a failed lock release + zeroVal := &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Namespace: sv.Namespace, + Path: sv.Path, + Lock: &structs.VariableLock{}, + }, + } + return req.ConflictResponse(idx, zeroVal) + } + + // Avoid overwriting the variable data when releasing the lock, to prevent + // a delay release to remove customer data. + + updated := sv.Copy() + updated.Lock = nil + updated.ModifyIndex = idx + + err = s.updateVarsAndIndexTxn(tx, idx, &updated) + if err != nil { + req.ErrorResponse(idx, fmt.Errorf("failed lock release: %s", err)) + } + + if err := tx.Commit(); err != nil { + return req.ErrorResponse(idx, err) + } + + return req.SuccessResponse(idx, &updated.VariableMetadata) +} + +func (s *StateStore) updateVarsAndIndexTxn(tx WriteTxn, idx uint64, sv *structs.VariableEncrypted) error { + if err := tx.Insert(TableVariables, sv); err != nil { + return fmt.Errorf("failed inserting variable: %w", err) + } + + if err := tx.Insert(tableIndex, + &IndexEntry{TableVariables, idx}); err != nil { + return fmt.Errorf("failed updating variable index: %w", err) + } + return nil +} + +func isLocked(lock *structs.VariableLock, req *structs.VarApplyStateRequest) bool { + if lock != nil { + if req.Var.VariableMetadata.Lock == nil || + req.Var.VariableMetadata.Lock.ID != lock.ID { + + return true + } + } + return false +} diff --git a/nomad/state/state_store_variables_test.go b/nomad/state/state_store_variables_test.go index a610af3ba..1847197de 100644 --- a/nomad/state/state_store_variables_test.go +++ b/nomad/state/state_store_variables_test.go @@ -5,6 +5,7 @@ package state import ( "encoding/json" + "errors" "sort" "strings" "testing" @@ -65,16 +66,8 @@ func TestStateStore_UpsertVariables(t *testing.T) { must.Eq(t, insertIndex, initialIndex) // List all the variables in the table - iter, err := testState.Variables(ws) + got, err := getAllVariables(testState, ws) must.NoError(t, err) - - got := []*structs.VariableEncrypted{} - for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.VariableEncrypted) - var svCopy structs.VariableEncrypted - svCopy = sv.Copy() - got = append(got, &svCopy) - } must.Len(t, 2, got, must.Sprintf("incorrect number of variables found")) // Ensure the create and modify indexes are populated correctly. @@ -148,19 +141,9 @@ func TestStateStore_UpsertVariables(t *testing.T) { must.NoError(t, err) must.Eq(t, update1Index, updateActualIndex, must.Sprintf("index should have changed")) - // Get the variables from the table. - iter, err := testState.Variables(ws) - must.NoError(t, err) - - got := []*structs.VariableEncrypted{} - // Iterate all the stored variables and assert indexes have been updated as expected - for raw := iter.Next(); raw != nil; raw = iter.Next() { - sv := raw.(*structs.VariableEncrypted) - var svCopy structs.VariableEncrypted - svCopy = sv.Copy() - got = append(got, &svCopy) - } + got, err := getAllVariables(testState, ws) + must.NoError(t, err) must.Len(t, 2, got) must.Eq(t, update1Index, got[0].ModifyIndex) must.Eq(t, insertIndex, got[1].ModifyIndex) @@ -216,6 +199,68 @@ func TestStateStore_UpsertVariables(t *testing.T) { must.Eq(t, expectedQuotaSize+1, quotaUsed.Size) }) + + // Acquire lock on first variable to test upserting on a locked variable. + t.Run("5 lock and upsert", func(t *testing.T) { + acquireIndex := uint64(60) + sv3 := svs[0].Copy() + sv3.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + resp := testState.VarLockAcquire(acquireIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv3, + }) + + must.NoError(t, resp.Error) + + // Check that the index for the table was modified as expected. + afterAcquireIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + must.Eq(t, acquireIndex, afterAcquireIndex) + + // Attempt to upsert variable without the lock ID + update4Index := uint64(65) + sv4 := svs[0].Copy() + sv4.KeyID = "sv4-update" + sv4.ModifyIndex = update4Index + + resp = testState.VarSet(update4Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &sv4, + }) + + must.NoError(t, resp.Error) + afterFailedUpsertIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + + must.Eq(t, afterAcquireIndex, afterFailedUpsertIndex, must.Sprintf("index should not have changed")) + must.True(t, resp.IsConflict()) + + // Attempt to upsert variable but this time include the lock ID + sv4.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + resp = testState.VarSet(update4Index, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &sv4, + }) + must.NoError(t, resp.Error) + + // Check that the index for the table was modified as expected. + updateActualIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + must.Eq(t, update4Index, updateActualIndex, must.Sprintf("index should have changed")) + + // Iterate all the stored variables and assert indexes have been updated as expected + got, err := getAllVariables(testState, ws) + must.NoError(t, err) + must.Len(t, 2, got) + must.Eq(t, update4Index, got[0].ModifyIndex) + }) } func TestStateStore_DeleteVariable(t *testing.T) { @@ -303,8 +348,66 @@ func TestStateStore_DeleteVariable(t *testing.T) { must.Eq(t, expectedQuotaSize, quotaUsed.Size) }) - t.Run("3 delete remaining variable", func(t *testing.T) { - delete2Index := uint64(30) + t.Run("3 lock the variable and attempt to delete it", func(t *testing.T) { + ws := memdb.NewWatchSet() + acquireIndex := uint64(25) + lsv := svs[1].Copy() + lsv.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + resp := testState.VarLockAcquire(acquireIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: &lsv, + }) + + must.NoError(t, resp.Error) + must.True(t, resp.IsOk()) + + deleteLockedIndex := uint64(27) + + // Attempt to delete without the lock ID + resp2 := testState.VarDelete(deleteLockedIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpDelete, + Var: svs[1], + }) + + must.NoError(t, resp2.Error) + must.True(t, resp2.IsConflict()) + + // Check that the index for the table was not modified. + failedDeleteIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + must.Eq(t, acquireIndex, failedDeleteIndex) + + svs, err := getAllVariables(testState, ws) + must.NoError(t, err) + must.One(t, len(svs)) + + // Release lock + releaseIndex := uint64(30) + + lsv.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + resp3 := testState.VarLockRelease(releaseIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: &lsv, + }) + must.NoError(t, err) + must.True(t, resp3.IsOk()) + + svs, err = getAllVariables(testState, ws) + must.NoError(t, err) + must.One(t, len(svs)) + + }) + + t.Run("4 delete remaining variable", func(t *testing.T) { + delete2Index := uint64(40) resp := testState.VarDelete(delete2Index, &structs.VarApplyStateRequest{ Op: structs.VarOpDelete, @@ -581,6 +684,7 @@ func TestStateStore_ListVariablesByNamespaceAndPrefix(t *testing.T) { } }) } + func TestStateStore_ListVariablesByKeyID(t *testing.T) { ci.Parallel(t) testState := testStateStore(t) @@ -714,6 +818,48 @@ func TestStateStore_Variables_DeleteCAS(t *testing.T) { must.NotNil(t, resp.Conflict) must.Eq(t, sv.VariableMetadata, resp.Conflict.VariableMetadata) }) + + t.Run("real_locked_var-cas_0", func(t *testing.T) { + ci.Parallel(t) + sv := mock.VariableEncrypted() + sv.Path = "real_var/cas_0" + resp := ts.VarSet(10, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: sv, + }) + must.True(t, resp.IsOk()) + + svCopy := sv.Copy() + svCopy.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + resp = ts.VarLockAcquire(15, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: &svCopy, + }) + + must.True(t, resp.IsOk()) + + // A CAS delete with a correct index should succeed. + req := &structs.VarApplyStateRequest{ + Op: structs.VarOpDelete, + Var: sv, + } + + resp = ts.VarDeleteCAS(15, req) + must.True(t, resp.IsConflict()) + + resp = ts.VarLockRelease(20, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: &svCopy, + }) + + must.True(t, resp.IsOk()) + }) + t.Run("real_var-cas_ok", func(t *testing.T) { ci.Parallel(t) sv := mock.VariableEncrypted() @@ -729,7 +875,346 @@ func TestStateStore_Variables_DeleteCAS(t *testing.T) { Op: structs.VarOpDelete, Var: sv, } - resp = ts.VarDeleteCAS(0, req) + resp = ts.VarDeleteCAS(10, req) must.True(t, resp.IsOk()) }) } + +func TestStateStore_AcquireAndReleaseLock(t *testing.T) { + ci.Parallel(t) + testState := testStateStore(t) + ws := memdb.NewWatchSet() + + mv := mock.VariableEncrypted() + + mv.Path = "thePath" + mv.Lock = &structs.VariableLock{ + ID: "theLockID", + } + + insertIndex := uint64(20) + + allVars, err := getAllVariables(testState, ws) + must.NoError(t, err) + + t.Run("1 lock on missing variable", func(t *testing.T) { + /* Attempt to acquire the lock on a variable that doesn't exist. */ + resp := testState.VarLockAcquire(insertIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: mv, + }) + + must.NoError(t, resp.Error) + + // Check that the index for the table was modified as expected. + initialIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + must.Eq(t, insertIndex, initialIndex) + + got, err := getAllVariables(testState, ws) + must.Eq(t, len(allVars)+1, len(got), must.Sprintf("incorrect number of variables found")) + + // Ensure the create and modify indexes are populated correctly. + must.Eq(t, 20, got[0].CreateIndex, must.Sprintf("%s: incorrect create index", got[0].Path)) + must.Eq(t, 20, got[0].ModifyIndex, must.Sprintf("%s: incorrect modify index", got[0].Path)) + + // Ensure the lock was persisted. + must.Eq(t, "theLockID", got[0].Lock.ID) + allVars = got + }) + + t.Run("2 lock on same variable", func(t *testing.T) { + /* Attempt to acquire the lock on the same variable again. */ + sv := *allVars[0] + sv.Lock = &structs.VariableLock{ + ID: "aDifferentLockID", + } + + resp := testState.VarLockAcquire(insertIndex+1, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + }) + + must.NoError(t, resp.Error) + must.Eq(t, structs.VarOpResultConflict, resp.Result) + // Ensure the create and modify were NOT modified + must.Eq(t, 20, sv.CreateIndex, must.Sprintf("%s: incorrect create index", sv.Path)) + must.Eq(t, 20, sv.ModifyIndex, must.Sprintf("%s: incorrect modify index", sv.Path)) + + }) + t.Run("3 release lock", func(t *testing.T) { + /* Test to release the lock */ + allVars, err := getAllVariables(testState, ws) + releaseIndex := uint64(40) + resp := testState.VarLockRelease(releaseIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: allVars[0], + }) + + must.NoError(t, resp.Error) + + // Check that the index for the table was modified as expected. + afterReleaseIndex, err := testState.Index(TableVariables) + + must.NoError(t, err) + must.Eq(t, releaseIndex, afterReleaseIndex) + + // Ensure the lock was removed, but the variable was not. + sve, err := testState.GetVariable(ws, mv.Namespace, mv.Path) + must.NoError(t, err) + must.NotNil(t, sve) + must.Nil(t, sve.VariableMetadata.Lock) + + // Ensure the create and modify indexes are populated correctly. + must.Eq(t, 20, sve.CreateIndex, must.Sprintf("%s: incorrect create index", sve.Path)) + must.Eq(t, 40, sve.ModifyIndex, must.Sprintf("%s: incorrect modify index", sve.Path)) + + // Ensure the variable data didn't change + must.Eq(t, mv.Data, sve.Data) + }) + + t.Run("3 reacquire lock", func(t *testing.T) { + /* Reacquire the lock, testing the mechanism to lock a previously existing variable */ + acquireIndex := uint64(60) + resp := testState.VarLockAcquire(acquireIndex, + &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: mv, + }) + + must.NoError(t, resp.Error) + + // Check that the index for the table was modified as expected. + afterAcquireIndex, err := testState.Index(TableVariables) + must.NoError(t, err) + must.Eq(t, acquireIndex, afterAcquireIndex) + + sve, err := testState.GetVariable(ws, mv.Namespace, mv.Path) + must.NoError(t, err) + + // Ensure the create and modify indexes are populated correctly. + must.Eq(t, 20, sve.CreateIndex, must.Sprintf("%s: incorrect create index", sve.Path)) + must.Eq(t, 60, sve.ModifyIndex, must.Sprintf("%s: incorrect modify index", sve.Path)) + + // Ensure the lock was persisted again. + must.Eq(t, "theLockID", sve.Lock.ID) + + // Ensure the variable data didn't change + must.Eq(t, mv.Data, sve.Data) + }) +} + +func TestStateStore_ReleaseLock(t *testing.T) { + ci.Parallel(t) + testState := testStateStore(t) + + insertIndex := uint64(20) + resp := testState.VarSet(insertIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: "/non/lock/variable/path", + Namespace: "default", + }, + VariableData: mock.VariableEncrypted().VariableData, + }, + }) + insertIndex++ + must.NoError(t, resp.Error) + + resp = testState.VarSet(insertIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: "lock/variable/path", + Namespace: "default", + Lock: &structs.VariableLock{ + ID: "theLockID", + }, + }, + VariableData: mock.VariableEncrypted().VariableData, + }, + }) + must.NoError(t, resp.Error) + + testCases := []struct { + name string + lookUpPath string + lockID string + expErr error + expResult structs.VarOpResult + }{ + { + name: "variable_not_found", + lookUpPath: "fake/path/", + expErr: errVarNotFound, + expResult: structs.VarOpResultError, + }, + { + name: "variable_has_no_lock", + lookUpPath: "/non/lock/variable/path", + expErr: errLockNotFound, + expResult: structs.VarOpResultError, + }, + { + name: "lock_id_doesn't_match", + lookUpPath: "lock/variable/path", + lockID: "wrongLockID", + expErr: nil, + expResult: structs.VarOpResultConflict, + }, + { + name: "lock_released", + lookUpPath: "lock/variable/path", + lockID: "theLockID", + expErr: nil, + expResult: structs.VarOpResultOk, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + req := &structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: tc.lookUpPath, + Namespace: "default", + }, + }, + } + + if tc.lockID != "" { + req.Var.VariableMetadata.Lock = &structs.VariableLock{ + ID: tc.lockID, + } + } + + resp = testState.VarLockRelease(insertIndex, req) + + if !errors.Is(tc.expErr, resp.Error) { + t.Fatalf("expected error, got %s", resp.Error) + } + + must.Eq(t, tc.expResult, resp.Result) + }) + } +} + +func TestStateStore_Release(t *testing.T) { + ci.Parallel(t) + testState := testStateStore(t) + + insertIndex := uint64(20) + resp := testState.VarSet(insertIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: "/non/lock/variable/path", + Namespace: "default", + }, + VariableData: mock.VariableEncrypted().VariableData, + }, + }) + insertIndex++ + must.NoError(t, resp.Error) + + resp = testState.VarSet(insertIndex, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: "lock/variable/path", + Namespace: "default", + Lock: &structs.VariableLock{ + ID: "theLockID", + }, + }, + VariableData: mock.VariableEncrypted().VariableData, + }, + }) + must.NoError(t, resp.Error) + + testCases := []struct { + name string + lookUpPath string + lockID string + expErr error + expResult structs.VarOpResult + }{ + { + name: "variable_not_found", + lookUpPath: "fake/path/", + expErr: errVarNotFound, + expResult: structs.VarOpResultError, + }, + { + name: "variable_has_no_lock", + lookUpPath: "/non/lock/variable/path", + expErr: errLockNotFound, + expResult: structs.VarOpResultError, + }, + { + name: "lock_id_doesn't_match", + lookUpPath: "lock/variable/path", + lockID: "wrongLockID", + expErr: nil, + expResult: structs.VarOpResultConflict, + }, + { + name: "lock_released", + lookUpPath: "lock/variable/path", + lockID: "theLockID", + expErr: nil, + expResult: structs.VarOpResultOk, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + req := &structs.VarApplyStateRequest{ + Op: structs.VarOpLockRelease, + Var: &structs.VariableEncrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: tc.lookUpPath, + Namespace: "default", + }, + }, + } + + if tc.lockID != "" { + req.Var.VariableMetadata.Lock = &structs.VariableLock{ + ID: tc.lockID, + } + } + + resp = testState.VarLockRelease(insertIndex, req) + + if !errors.Is(tc.expErr, resp.Error) { + t.Fatalf("expected error, got %s", resp.Error) + } + + must.Eq(t, tc.expResult, resp.Result) + }) + } +} + +func getAllVariables(ss *StateStore, ws memdb.WatchSet) ([]*structs.VariableEncrypted, error) { + // List all the variables in the table + iter, err := ss.Variables(ws) + if err != nil { + return []*structs.VariableEncrypted{}, err + } + + got := []*structs.VariableEncrypted{} + for raw := iter.Next(); raw != nil; raw = iter.Next() { + sv := raw.(*structs.VariableEncrypted) + var svCopy structs.VariableEncrypted + svCopy = sv.Copy() + got = append(got, &svCopy) + } + + return got, nil +} diff --git a/nomad/structs/variables.go b/nomad/structs/variables.go index e801a55de..a42d6a4f1 100644 --- a/nomad/structs/variables.go +++ b/nomad/structs/variables.go @@ -5,11 +5,16 @@ package structs import ( "bytes" + "encoding/json" "errors" "fmt" "reflect" "regexp" "strings" + "time" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/nomad/helper/uuid" ) const ( @@ -28,24 +33,59 @@ const ( VariablesListRPCMethod = "Variables.List" // VariablesReadRPCMethod is the RPC method for fetching a variable - // according to its namepace and path. + // according to its namespace and path. // // Args: VariablesByNameRequest // Reply: VariablesByNameResponse VariablesReadRPCMethod = "Variables.Read" + // VariablesRenewLockRPCMethod is the RPC method for renewing the lease on + // a lock according to its namespace, path and lock ID. + // + // Args: VariablesRenewLockRequest + // Reply: VariablesRenewLockResponse + VariablesRenewLockRPCMethod = "Variables.RenewLock" + // maxVariableSize is the maximum size of the unencrypted contents of a // variable. This size is deliberately set low and is not configurable, to // discourage DoS'ing the cluster maxVariableSize = 65536 + + // minVariableLockTTL and maxVariableLockTTL determine the range of valid durations for the + // TTL on a lock.They come from the experience on Consul. + minVariableLockTTL = 10 * time.Second + maxVariableLockTTL = 24 * time.Hour + + // defaultLockTTL is the default value used to maintain a lock before it needs to + // be renewed. The actual value comes from the experience with Consul. + defaultLockTTL = 15 * time.Second + + // defaultLockDelay is the default a lock will be blocked after the TTL + // went by without any renews. It is intended to prevent split brain situations. + // The actual value comes from the experience with Consul. + defaultLockDelay = 15 * time.Second +) + +var ( + errNoPath = errors.New("missing path") + errNoNamespace = errors.New("missing namespace") + errNoLock = errors.New("missing lock ID") + errWildCardNamespace = errors.New("can not target wildcard (\"*\")namespace") + errQuotaExhausted = errors.New("variables are limited to 64KiB in total size") + errNegativeDelayOrTTL = errors.New("Lock delay and TTL must be positive") + errInvalidTTL = errors.New("TTL must be between 10 seconds and 24 hours") ) // VariableMetadata is the metadata envelope for a Variable, it is the list // object and is shared data between an VariableEncrypted and a // VariableDecrypted object. type VariableMetadata struct { - Namespace string - Path string + Namespace string + Path string + + // Lock represents a variable which is used for locking functionality. + Lock *VariableLock `json:",omitempty"` + CreateIndex uint64 CreateTime int64 ModifyIndex uint64 @@ -66,17 +106,167 @@ type VariableData struct { } // VariableDecrypted structs are returned from the Encrypter's decrypt -// method. Since they contains sensitive material, they should never be +// method. Since they contain sensitive material, they should never be // persisted to disk. type VariableDecrypted struct { VariableMetadata - Items VariableItems + Items VariableItems `json:",omitempty"` } // VariableItems are the actual secrets stored in a variable. They are always // encrypted and decrypted as a single unit. type VariableItems map[string]string +// VariableLock represent a Nomad variable which is used to performing locking +// functionality such as leadership election. +type VariableLock struct { + + // ID is generated by Nomad to provide a unique caller ID which can be used + // for renewals and unlocking. + ID string + + // TTL describes the time-to-live of the current lock holder. The client + // must renew the lock before this TTL expires, otherwise the lock is + // considered lost. + TTL time.Duration + + // LockDelay describes a grace period that exists after a lock is lost, + // before another client may acquire the lock. This helps protect against + // split-brains. + LockDelay time.Duration +} + +// Equal performs an equality check on the two variable lock objects. It +// handles nil objects. +func (vl *VariableLock) Equal(vl2 *VariableLock) bool { + if vl == nil || vl2 == nil { + return vl == vl2 + } + if vl.ID != vl2.ID { + return false + } + if vl.TTL != vl2.TTL { + return false + } + if vl.LockDelay != vl2.LockDelay { + return false + } + return true +} + +// MarshalJSON implements the json.Marshaler interface and allows +// VariableLock.TTL and VariableLock.Delay to be marshaled correctly. +func (vl *VariableLock) MarshalJSON() ([]byte, error) { + type Alias VariableLock + exported := &struct { + TTL string + LockDelay string + *Alias + }{ + TTL: vl.TTL.String(), + LockDelay: vl.LockDelay.String(), + Alias: (*Alias)(vl), + } + + if vl.TTL == 0 { + exported.TTL = "" + } + + if vl.LockDelay == 0 { + exported.LockDelay = "" + } + return json.Marshal(exported) +} + +// UnmarshalJSON implements the json.Unmarshaler interface and allows +// VariableLock.TTL and VariableLock.Delay to be unmarshalled correctly. +func (vl *VariableLock) UnmarshalJSON(data []byte) (err error) { + type Alias VariableLock + aux := &struct { + TTL interface{} + LockDelay interface{} + *Alias + }{ + Alias: (*Alias)(vl), + } + + if err = json.Unmarshal(data, &aux); err != nil { + return err + } + + if aux.TTL != nil { + switch v := aux.TTL.(type) { + case string: + if v != "" { + if vl.TTL, err = time.ParseDuration(v); err != nil { + return err + } + } + case float64: + vl.TTL = time.Duration(v) + } + + } + + if aux.LockDelay != nil { + switch v := aux.LockDelay.(type) { + case string: + if v != "" { + if vl.LockDelay, err = time.ParseDuration(v); err != nil { + return err + } + } + case float64: + vl.LockDelay = time.Duration(v) + } + + } + + return nil +} + +// Copy creates a deep copy of the variable lock. This copy can then be safely +// modified. It handles nil objects. +func (vl *VariableLock) Copy() *VariableLock { + if vl == nil { + return nil + } + + nvl := new(VariableLock) + *nvl = *vl + + return nvl +} + +func (vl *VariableLock) Canonicalize() { + // If the lock ID is empty, it means this is a creation of a lock on this variable. + if vl.ID == "" { + vl.ID = uuid.Generate() + } + + if vl.LockDelay == 0 { + vl.LockDelay = defaultLockDelay + } + + if vl.TTL == 0 { + vl.TTL = defaultLockTTL + } +} + +func (vl *VariableLock) Validate() error { + var mErr *multierror.Error + + if vl.LockDelay < 0 || vl.TTL < 0 { + mErr = multierror.Append(mErr, errNegativeDelayOrTTL) + } + + if vl.TTL > maxVariableLockTTL || vl.TTL < minVariableLockTTL { + mErr = multierror.Append(mErr, errInvalidTTL) + } + + return mErr.ErrorOrNil() +} + func (vi VariableItems) Size() uint64 { var out uint64 for k, v := range vi { @@ -94,8 +284,26 @@ func (vd VariableDecrypted) Equal(v2 VariableDecrypted) bool { // Equal is a convenience method to provide similar equality checking syntax // for metadata and the VariablesData or VariableItems struct -func (sv VariableMetadata) Equal(sv2 VariableMetadata) bool { - return sv == sv2 +func (sv VariableMetadata) Equal(vm2 VariableMetadata) bool { + if sv.Namespace != vm2.Namespace { + return false + } + if sv.Path != vm2.Path { + return false + } + if sv.CreateIndex != vm2.CreateIndex { + return false + } + if sv.CreateTime != vm2.CreateTime { + return false + } + if sv.ModifyIndex != vm2.ModifyIndex { + return false + } + if sv.ModifyTime != vm2.ModifyTime { + return false + } + return sv.Lock.Equal(vm2.Lock) } // Equal performs deep equality checking on the cleartext items of a @@ -167,18 +375,43 @@ func (vd VariableDecrypted) Validate() error { if len(vd.Items) == 0 { return errors.New("empty variables are invalid") } + if vd.Items.Size() > maxVariableSize { return errors.New("variables are limited to 64KiB in total size") } - if err := validatePath(vd.Path); err != nil { + if err := ValidatePath(vd.Path); err != nil { return err } + if vd.Lock != nil { + return vd.Lock.Validate() + } + return nil } -func validatePath(path string) error { +// A new variable can be crated just to support a lock, it doesn't require to hold +// any items and it will validate the lock. +func (vd VariableDecrypted) ValidateForLock() error { + var mErr multierror.Error + if vd.Namespace == AllNamespacesSentinel { + mErr.Errors = append(mErr.Errors, errWildCardNamespace) + return &mErr + } + + if vd.Items.Size() > maxVariableSize { + return errQuotaExhausted + } + + if err := ValidatePath(vd.Path); err != nil { + return err + } + + return vd.Lock.Validate() +} + +func ValidatePath(path string) error { if len(path) == 0 { return fmt.Errorf("variable requires path") } @@ -217,13 +450,27 @@ func (vd *VariableDecrypted) Canonicalize() { if vd.Namespace == "" { vd.Namespace = DefaultNamespace } + + if vd.Lock != nil { + vd.Lock.Canonicalize() + } } // Copy returns a fully hydrated copy of VariableMetadata that can be // manipulated while ensuring the original is not touched. func (sv *VariableMetadata) Copy() *VariableMetadata { - var out = *sv - return &out + if sv == nil { + return nil + } + + nsl := new(VariableMetadata) + *nsl = *sv + + if sv.Lock != nil { + nsl.Lock = sv.Lock.Copy() + } + + return nsl } // GetNamespace returns the variable's namespace. Used for pagination. @@ -241,6 +488,19 @@ func (sv VariableMetadata) GetCreateIndex() uint64 { return sv.CreateIndex } +// LockID returns the ID of the lock. In the event this is not held, or the +// variable is not a lock, this string will be empty. +func (sv *VariableMetadata) LockID() string { + if sv.Lock == nil { + return "" + } + return sv.Lock.ID +} + +// IsLock is a helper to indicate whether the variable is being used for +// locking. +func (sv *VariableMetadata) IsLock() bool { return sv.Lock != nil } + // VariablesQuota is used to track the total size of variables entries per // namespace. The total length of Variable.EncryptedData in bytes will be added // to the VariablesQuota table in the same transaction as a write, update, or @@ -273,6 +533,14 @@ const ( VarOpDelete VarOp = "delete" VarOpDeleteCAS VarOp = "delete-cas" VarOpCAS VarOp = "cas" + + // VarOpLockAcquire is the variable operation used when attempting to + // acquire a variable lock. + VarOpLockAcquire VarOp = "lock-acquire" + + // VarOpLockRelease is the variable operation used when attempting to + // release a held variable lock. + VarOpLockRelease VarOp = "lock-release" ) // VarOpResult constants give possible operations results from a transaction. @@ -401,3 +669,34 @@ type VariablesReadResponse struct { Data *VariableDecrypted QueryMeta } + +// VariablesRenewLockRequest is used to renew the lease on a lock. This request +// behaves like a write because the renewal needs to be forwarded to the leader +// where the timers and lock work is kept. +type VariablesRenewLockRequest struct { + //Namespace string + Path string + LockID string + + WriteRequest +} + +func (v *VariablesRenewLockRequest) Validate() error { + var mErr multierror.Error + + if v.Path == "" { + mErr.Errors = append(mErr.Errors, errNoPath) + } + if v.LockID == "" { + mErr.Errors = append(mErr.Errors, errNoLock) + } + + return mErr.ErrorOrNil() +} + +// VariablesRenewLockResponse is sent back to the user to inform them of success or failure +// of the renewal process. +type VariablesRenewLockResponse struct { + VarMeta *VariableMetadata + WriteMeta +} diff --git a/nomad/structs/variables_test.go b/nomad/structs/variables_test.go index 0184dfcba..4a4072110 100644 --- a/nomad/structs/variables_test.go +++ b/nomad/structs/variables_test.go @@ -4,13 +4,261 @@ package structs import ( + "errors" + "fmt" "testing" "time" "github.com/hashicorp/nomad/ci" - "github.com/stretchr/testify/require" + "github.com/shoenig/test/must" ) +func TestVariableMetadata_Equal(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + inputMetadata VariableMetadata + inputMetadataFn VariableMetadata + expectedOutput bool + }{ + { + name: "no lock equal", + inputMetadata: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: nil, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251868, + }, + inputMetadataFn: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: nil, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251868, + }, + expectedOutput: true, + }, + { + name: "no lock unequal", + inputMetadata: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: nil, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251876, + }, + inputMetadataFn: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: nil, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 200, + ModifyTime: 1687251885, + }, + expectedOutput: false, + }, + + { + name: "lock equal", + inputMetadata: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: &VariableLock{ + ID: "896bdbef-8ce7-4b1d-9b4c-4e6c5639196d", + TTL: 20 * time.Second, + LockDelay: 5 * time.Second, + }, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251868, + }, + inputMetadataFn: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: &VariableLock{ + ID: "896bdbef-8ce7-4b1d-9b4c-4e6c5639196d", + TTL: 20 * time.Second, + LockDelay: 5 * time.Second, + }, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251868, + }, + expectedOutput: true, + }, + { + name: "lock unequal", + inputMetadata: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: &VariableLock{ + ID: "896bdbef-8ce7-4b1d-9b4c-4e6c5639196d", + TTL: 20 * time.Second, + LockDelay: 5 * time.Second, + }, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251876, + }, + inputMetadataFn: VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: &VariableLock{ + ID: "896bdbef-8ce7-4b1d-9b4c-4e6c5639196d", + TTL: 20 * time.Second, + LockDelay: 15 * time.Second, + }, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251876, + }, + expectedOutput: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + must.Eq(t, tc.expectedOutput, tc.inputMetadata.Equal(tc.inputMetadataFn)) + }) + } +} + +func TestVariableMetadata_Copy(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + inputVariableMetadata *VariableMetadata + }{ + { + name: "no lock", + inputVariableMetadata: &VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: nil, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251876, + }, + }, + { + name: "lock", + inputVariableMetadata: &VariableMetadata{ + Namespace: "default", + Path: "custom/test/path", + Lock: &VariableLock{ + ID: "896bdbef-8ce7-4b1d-9b4c-4e6c5639196d", + TTL: 20 * time.Second, + LockDelay: 15 * time.Second, + }, + CreateIndex: 10, + CreateTime: 1687251815, + ModifyIndex: 100, + ModifyTime: 1687251876, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actualOutput := tc.inputVariableMetadata.Copy() + must.Eq(t, tc.inputVariableMetadata, actualOutput) + must.NotEqOp(t, + fmt.Sprintf("%p", tc.inputVariableMetadata), + fmt.Sprintf("%p", actualOutput)) + + if tc.inputVariableMetadata.Lock != nil { + must.NotEqOp(t, + fmt.Sprintf("%p", tc.inputVariableMetadata.Lock), + fmt.Sprintf("%p", actualOutput.Lock)) + } + }) + } +} + +func TestVariableMetadata_LockID(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + inputVariableMetadata *VariableMetadata + expectedOutput string + }{ + { + name: "nil lock", + inputVariableMetadata: &VariableMetadata{ + Lock: nil, + }, + expectedOutput: "", + }, + { + name: "empty ID", + inputVariableMetadata: &VariableMetadata{ + Lock: &VariableLock{ID: ""}, + }, + expectedOutput: "", + }, + { + name: "populated ID", + inputVariableMetadata: &VariableMetadata{ + Lock: &VariableLock{ID: "mylovelylovelyid"}, + }, + expectedOutput: "mylovelylovelyid", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + must.Eq(t, tc.expectedOutput, tc.inputVariableMetadata.LockID()) + }) + } +} + +func TestVariableMetadata_IsLock(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + inputVariableMetadata *VariableMetadata + expectedOutput bool + }{ + { + name: "nil", + inputVariableMetadata: &VariableMetadata{ + Lock: nil, + }, + expectedOutput: false, + }, + { + name: "not nil", + inputVariableMetadata: &VariableMetadata{ + Lock: &VariableLock{}, + }, + expectedOutput: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + must.Eq(t, tc.expectedOutput, tc.inputVariableMetadata.IsLock()) + }) + } +} + func TestStructs_VariableDecrypted_Copy(t *testing.T) { ci.Parallel(t) n := time.Now() @@ -30,9 +278,9 @@ func TestStructs_VariableDecrypted_Copy(t *testing.T) { }, } sv2 := sv.Copy() - require.True(t, sv.Equal(sv2), "sv and sv2 should be equal") + must.True(t, sv.Equal(sv2), must.Sprintf("sv and sv2 should be equal")) sv2.Items["new"] = "new" - require.False(t, sv.Equal(sv2), "sv and sv2 should not be equal") + must.False(t, sv.Equal(sv2), must.Sprintf("sv and sv2 should not be equal")) } func TestStructs_VariableDecrypted_Validate(t *testing.T) { @@ -65,9 +313,102 @@ func TestStructs_VariableDecrypted_Validate(t *testing.T) { sv.Path = tc.path err := sv.Validate() if tc.ok { - require.NoError(t, err, "should not get error for: %s", tc.path) + must.NoError(t, err, must.Sprintf("should not get error for: %s", tc.path)) } else { - require.Error(t, err, "should get error for: %s", tc.path) + must.Error(t, err, must.Sprintf("should get error for: %s", tc.path)) } } } + +func TestStructs_VariablesRenewLockRequest_Validate(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + request *VariablesRenewLockRequest + expErr error + }{ + { + name: "missing_lockID", + request: &VariablesRenewLockRequest{ + Path: "path", + }, + expErr: errNoLock, + }, + { + name: "missing_path", + request: &VariablesRenewLockRequest{ + LockID: "lockID", + }, + expErr: errNoPath, + }, + { + name: "valid_request", + request: &VariablesRenewLockRequest{ + Path: "path", + LockID: "lockID", + }, + expErr: nil, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.request.Validate() + if !errors.Is(err, tc.expErr) { + t.Errorf("Expected error %v, but got error %v", tc.expErr, err) + } + }) + } +} + +func TestStructs_Lock_Validate(t *testing.T) { + ci.Parallel(t) + + testCases := []struct { + name string + lock *VariableLock + expErr error + }{ + { + name: "lock_delay_is_negative", + lock: &VariableLock{ + TTL: 5 * time.Second, + LockDelay: -5 * time.Second, + }, + expErr: errNegativeDelayOrTTL, + }, + { + name: "lock_ttl_is_negative", + lock: &VariableLock{ + TTL: -5 * time.Second, + LockDelay: 5 * time.Second, + }, + expErr: errNegativeDelayOrTTL, + }, + { + name: "lock_ttl_is_bigger_than_max", + lock: &VariableLock{ + TTL: maxVariableLockTTL + 5*time.Second, + LockDelay: 5 * time.Second, + }, + expErr: errInvalidTTL, + }, + { + name: "lock_ttl_is_smaller_than_min", + lock: &VariableLock{ + TTL: 5 * time.Second, + LockDelay: minVariableLockTTL - 5*time.Second, + }, + expErr: errInvalidTTL, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.lock.Validate() + if !errors.Is(err, tc.expErr) { + t.Errorf("Expected error %v, but got error %v", tc.expErr, err) + } + }) + } +} diff --git a/nomad/variables_endpoint.go b/nomad/variables_endpoint.go index 57644312f..cf7fbcf65 100644 --- a/nomad/variables_endpoint.go +++ b/nomad/variables_endpoint.go @@ -20,6 +20,27 @@ import ( "github.com/hashicorp/nomad/nomad/structs" ) +const ( + maxAttemptsToRaftApply = 6 +) + +var ( + errVarAlreadyLocked = structs.NewErrRPCCoded(http.StatusBadRequest, "variable already holds a lock") + errVarNotFound = structs.NewErrRPCCoded(http.StatusNotFound, "variable doesn't exist") + errLockNotFound = structs.NewErrRPCCoded(http.StatusConflict, "variable doesn't hold a lock") + errVarIsLocked = structs.NewErrRPCCoded(http.StatusConflict, "attempting to modify locked variable") + errMissingLockInfo = structs.NewErrRPCCoded(http.StatusBadRequest, "missing lock information") + errLockOnVarCreation = structs.NewErrRPCCoded(http.StatusBadRequest, "variable should not contain lock definition") + errItemsOnRelease = structs.NewErrRPCCoded(http.StatusBadRequest, "lock release operation doesn't take variable items") + errNoPath = structs.NewErrRPCCoded(http.StatusBadRequest, "delete requires a Path") +) + +type variableTimers interface { + CreateVariableLockTTLTimer(structs.VariableEncrypted) + RemoveVariableLockTTLTimer(structs.VariableEncrypted) + RenewTTLTimer(structs.VariableEncrypted) error +} + // Variables encapsulates the variables RPC endpoint which is // callable via the Variables RPCs and externally via the "/v1/var{s}" // HTTP API. @@ -27,12 +48,13 @@ type Variables struct { srv *Server ctx *RPCContext logger hclog.Logger + timers variableTimers encrypter *Encrypter } func NewVariablesEndpoint(srv *Server, ctx *RPCContext, enc *Encrypter) *Variables { - return &Variables{srv: srv, ctx: ctx, logger: srv.logger.Named("variables"), encrypter: enc} + return &Variables{srv: srv, ctx: ctx, logger: srv.logger.Named("variables"), encrypter: enc, timers: srv} } // Apply is used to apply a SV update request to the data store. @@ -49,12 +71,14 @@ func (sv *Variables) Apply(args *structs.VariablesApplyRequest, reply *structs.V defer metrics.MeasureSince([]string{ "nomad", "variables", "apply", string(args.Op)}, time.Now()) + // TODO: Add metrics for acquire and release if the operation is lock related - // Check if the Namespace is explicitly set on the variable. If - // not, use the RequestNamespace if args.Var == nil { return fmt.Errorf("variable must not be nil") } + + // Check if the Namespace is explicitly set on the variable. If + // not, use the RequestNamespace targetNS := args.Var.Namespace if targetNS == "" { targetNS = args.RequestNamespace() @@ -66,15 +90,30 @@ func (sv *Variables) Apply(args *structs.VariablesApplyRequest, reply *structs.V return fmt.Errorf("all servers must be running version %v or later to apply variables", minVersionKeyring) } - canRead, err := svePreApply(sv, args, args.Var) + // Perform the ACL resolution. + aclObj, err := sv.srv.ResolveACL(args) if err != nil { return err } + // IF ACL is being used, + if aclObj != nil { + err := hasOperationPermissions(aclObj, args.Var.Namespace, args.Var.Path, args.Op) + if err != nil { + return err + } + } + + err = canonicalizeAndValidate(args) + if err != nil { + return structs.NewErrRPCCoded(http.StatusBadRequest, err.Error()) + } + var ev *structs.VariableEncrypted switch args.Op { - case structs.VarOpSet, structs.VarOpCAS: + case structs.VarOpSet, structs.VarOpCAS, structs.VarOpLockAcquire, + structs.VarOpLockRelease: ev, err = sv.encrypt(args.Var) if err != nil { return fmt.Errorf("variable error: encrypt: %w", err) @@ -82,6 +121,7 @@ func (sv *Variables) Apply(args *structs.VariablesApplyRequest, reply *structs.V now := time.Now().UnixNano() ev.CreateTime = now // existing will override if it exists ev.ModifyTime = now + case structs.VarOpDelete, structs.VarOpDeleteCAS: ev = &structs.VariableEncrypted{ VariableMetadata: structs.VariableMetadata{ @@ -100,76 +140,124 @@ func (sv *Variables) Apply(args *structs.VariablesApplyRequest, reply *structs.V } // Apply the update. - out, index, err := sv.srv.raftApply(structs.VarApplyStateRequestType, sveArgs) + o, index, err := sv.srv.raftApply(structs.VarApplyStateRequestType, sveArgs) if err != nil { return fmt.Errorf("raft apply failed: %w", err) } - r, err := sv.makeVariablesApplyResponse(args, out.(*structs.VarApplyStateResponse), canRead) + + out, _ := o.(*structs.VarApplyStateResponse) + + // The return value depends on the operation results and the callers permissions + r, err := sv.makeVariablesApplyResponse(args, out, aclObj) if err != nil { return err } + *reply = *r reply.Index = index + + if out.IsOk() { + switch args.Op { + case structs.VarOpLockAcquire: + sv.timers.CreateVariableLockTTLTimer(ev.Copy()) + case structs.VarOpLockRelease: + sv.timers.RemoveVariableLockTTLTimer(ev.Copy()) + } + } + return nil } -func svePreApply(sv *Variables, args *structs.VariablesApplyRequest, vd *structs.VariableDecrypted) (canRead bool, err error) { +func hasReadPermission(aclObj *acl.ACL, namespace, path string) bool { + return aclObj.AllowVariableOperation(namespace, + path, acl.VariablesCapabilityRead, nil) +} - canRead = false - var aclObj *acl.ACL +func hasOperationPermissions(aclObj *acl.ACL, namespace, path string, op structs.VarOp) error { - // Perform the ACL resolution. - if aclObj, err = sv.srv.ResolveACL(args); err != nil { - return - } else if aclObj != nil { - hasPerm := func(perm string) bool { - return aclObj.AllowVariableOperation(args.Var.Namespace, - args.Var.Path, perm, nil) - } - canRead = hasPerm(acl.VariablesCapabilityRead) - - switch args.Op { - case structs.VarOpSet, structs.VarOpCAS: - if !hasPerm(acl.VariablesCapabilityWrite) { - err = structs.ErrPermissionDenied - return - } - case structs.VarOpDelete, structs.VarOpDeleteCAS: - if !hasPerm(acl.VariablesCapabilityDestroy) { - err = structs.ErrPermissionDenied - return - } - default: - err = fmt.Errorf("svPreApply: unexpected VarOp received: %q", args.Op) - return - } - } else { - // ACLs are not enabled. - canRead = true + hasPerm := func(perm string) bool { + return aclObj.AllowVariableOperation(namespace, + path, perm, nil) } - switch args.Op { - case structs.VarOpSet, structs.VarOpCAS: - args.Var.Canonicalize() - if err = args.Var.Validate(); err != nil { - return + switch op { + case structs.VarOpSet, structs.VarOpCAS, structs.VarOpLockAcquire, + structs.VarOpLockRelease: + if !hasPerm(acl.VariablesCapabilityWrite) { + return structs.ErrPermissionDenied } case structs.VarOpDelete, structs.VarOpDeleteCAS: - if args.Var == nil || args.Var.Path == "" { - err = fmt.Errorf("delete requires a Path") - return + if !hasPerm(acl.VariablesCapabilityDestroy) { + return structs.ErrPermissionDenied } + default: + return fmt.Errorf("svPreApply: unexpected VarOp received: %q", op) } - return + return nil +} + +func canonicalizeAndValidate(args *structs.VariablesApplyRequest) error { + + switch args.Op { + case structs.VarOpLockAcquire: + // In case the user wants to use the default values so no lock data was provided. + if args.Var.VariableMetadata.Lock == nil { + args.Var.VariableMetadata.Lock = &structs.VariableLock{} + } + + args.Var.Canonicalize() + + err := args.Var.ValidateForLock() + if err != nil { + return structs.NewErrRPCCoded(http.StatusBadRequest, err.Error()) + } + return nil + + case structs.VarOpSet, structs.VarOpCAS: + // Avoid creating a variable with a lock that is not actionable + if args.Var.VariableMetadata.Lock != nil && + (args.Var.VariableMetadata.Lock.LockDelay != 0 || args.Var.VariableMetadata.Lock.TTL != 0) { + return structs.NewErrRPCCoded(http.StatusBadRequest, errLockOnVarCreation.Error()) + } + + args.Var.Canonicalize() + + err := args.Var.Validate() + if err != nil { + return structs.NewErrRPCCoded(http.StatusBadRequest, err.Error()) + } + return nil + + case structs.VarOpDelete, structs.VarOpDeleteCAS: + if args.Var == nil || args.Var.Path == "" { + return errNoPath + } + + case structs.VarOpLockRelease: + if args.Var == nil || args.Var.Lock == nil || + args.Var.Lock.ID == "" { + return errMissingLockInfo + } + + // If the operation is a lock release and there are items on the variable + // reject the request, release doesn't update the variable. + if args.Var.Items != nil || len(args.Var.Items) != 0 { + return errItemsOnRelease + } + + return structs.ValidatePath(args.Var.Path) + } + + return nil } // MakeVariablesApplyResponse merges the output of this VarApplyStateResponse with the // VariableDataItems func (sv *Variables) makeVariablesApplyResponse( req *structs.VariablesApplyRequest, eResp *structs.VarApplyStateResponse, - canRead bool) (*structs.VariablesApplyResponse, error) { + aclObj *acl.ACL) (*structs.VariablesApplyResponse, error) { out := structs.VariablesApplyResponse{ Op: eResp.Op, @@ -179,6 +267,15 @@ func (sv *Variables) makeVariablesApplyResponse( WriteMeta: eResp.WriteMeta, } + // The read permission modify the way the response is populated. If ACL is not + // used, read permission is granted by default and every call is treated as management. + var canRead bool = true + var isManagement = true + if aclObj != nil { + canRead = hasReadPermission(aclObj, req.Var.Namespace, req.Var.Path) + isManagement = aclObj.IsManagement() + } + if eResp.IsOk() { if eResp.WrittenSVMeta != nil { // The writer is allowed to read their own write @@ -186,9 +283,18 @@ func (sv *Variables) makeVariablesApplyResponse( VariableMetadata: *eResp.WrittenSVMeta, Items: req.Var.Items.Copy(), } + + // Verify the caller is providing the correct lockID, meaning it is the + // lock holder and has access to the lock information or is a management call. + // If locked, remove the lock information from response. + if !(isCallerOwner(req, eResp.WrittenSVMeta) || isManagement) { + out.Output.VariableMetadata.Lock = nil + } } + return &out, nil } + if eResp.IsError() { return &out, eResp.Error } @@ -240,7 +346,7 @@ func (sv *Variables) Read(args *structs.VariablesReadRequest, reply *structs.Var defer metrics.MeasureSince([]string{"nomad", "variables", "read"}, time.Now()) - _, _, err := sv.handleMixedAuthEndpoint(args.QueryOptions, + aclObj, err := sv.handleMixedAuthEndpoint(args.QueryOptions, acl.PolicyRead, args.Path) if err != nil { return err @@ -259,11 +365,17 @@ func (sv *Variables) Read(args *structs.VariablesReadRequest, reply *structs.Var // Setup the output reply.Data = nil if out != nil { + dv, err := sv.decrypt(out) if err != nil { return err } + ov := dv.Copy() + if !(aclObj != nil && aclObj.IsManagement()) { + ov.Lock = nil + } + reply.Data = &ov reply.Index = out.ModifyIndex } else { @@ -336,6 +448,7 @@ func (sv *Variables) List( if !strings.HasPrefix(v.Path, args.Prefix) { return false, nil } + // Note: the authorize method modifies the aclObj parameter. err := sv.authorize(aclObj, claims, v.Namespace, acl.PolicyList, v.Path) return err == nil, nil }, @@ -352,6 +465,11 @@ func (sv *Variables) List( func(raw interface{}) error { sv := raw.(*structs.VariableEncrypted) svStub := sv.VariableMetadata + + if !(aclObj != nil && aclObj.IsManagement()) { + svStub.Lock = nil + } + svs = append(svs, &svStub) return nil }) @@ -427,6 +545,8 @@ func (sv *Variables) listAllVariables( if !strings.HasPrefix(v.Path, args.Prefix) { return false, nil } + + // Note: the authorize method modifies the aclObj parameter. err := sv.authorize(aclObj, claims, v.Namespace, acl.PolicyList, v.Path) return err == nil, nil }, @@ -439,6 +559,11 @@ func (sv *Variables) listAllVariables( func(raw interface{}) error { v := raw.(*structs.VariableEncrypted) svStub := v.VariableMetadata + + if !(aclObj != nil && aclObj.IsManagement()) { + svStub.Lock = nil + } + svs = append(svs, &svStub) return nil }) @@ -474,6 +599,7 @@ func (sv *Variables) encrypt(v *structs.VariableDecrypted) (*structs.VariableEnc ev := structs.VariableEncrypted{ VariableMetadata: v.VariableMetadata, } + ev.Data, ev.KeyID, err = sv.encrypter.Encrypt(b) if err != nil { return nil, err @@ -499,7 +625,7 @@ func (sv *Variables) decrypt(v *structs.VariableEncrypted) (*structs.VariableDec // handleMixedAuthEndpoint is a helper to handle auth on RPC endpoints that can // either be called by external clients or by workload identity -func (sv *Variables) handleMixedAuthEndpoint(args structs.QueryOptions, policy, pathOrPrefix string) (*acl.ACL, *structs.IdentityClaims, error) { +func (sv *Variables) handleMixedAuthEndpoint(args structs.QueryOptions, policy, pathOrPrefix string) (*acl.ACL, error) { var aclObj *acl.ACL var err error @@ -507,19 +633,23 @@ func (sv *Variables) handleMixedAuthEndpoint(args structs.QueryOptions, policy, if aclToken != nil { aclObj, err = sv.srv.ResolveACLForToken(aclToken) if err != nil { - return nil, nil, err + return nil, err } } claims := args.GetIdentity().GetClaims() + // Note: the authorize method modifies the aclObj parameter. err = sv.authorize(aclObj, claims, args.RequestNamespace(), policy, pathOrPrefix) if err != nil { - return aclObj, claims, err + return aclObj, err } - return aclObj, claims, nil + return aclObj, nil } +// The authorize method modifies the aclObj parameter. In case the incoming request +// uses identity workload claims, the aclObj is populated. This logic will be +// updated when the work to eliminate nil ACLs is merged. func (sv *Variables) authorize(aclObj *acl.ACL, claims *structs.IdentityClaims, ns, policy, pathOrPrefix string) error { if aclObj == nil && claims == nil { @@ -538,8 +668,9 @@ func (sv *Variables) authorize(aclObj *acl.ACL, claims *structs.IdentityClaims, // Check the workload-associated policies and automatic task access to // variables. + var err error if claims != nil { - aclObj, err := sv.srv.ResolveClaims(claims) + aclObj, err = sv.srv.ResolveClaims(claims) if err != nil { return err // returns internal errors only } @@ -579,3 +710,83 @@ func (sv *Variables) groupForAlloc(claims *structs.IdentityClaims) (string, erro } return alloc.TaskGroup, nil } + +// RenewLock is used to apply a SV renew lock operation on a variable to maintain the lease. +func (sv *Variables) RenewLock(args *structs.VariablesRenewLockRequest, reply *structs.VariablesRenewLockResponse) error { + authErr := sv.srv.Authenticate(sv.ctx, args) + if done, err := sv.srv.forward(structs.VariablesRenewLockRPCMethod, args, args, reply); done { + return err + } + + sv.srv.MeasureRPCRate("variables", structs.RateMetricWrite, args) + if authErr != nil { + return structs.ErrPermissionDenied + } + + defer metrics.MeasureSince([]string{ + "nomad", "variables", "lock", "renew"}, time.Now()) + + aclObj, err := sv.srv.ResolveACL(args) + if err != nil { + return err + } + + // ACLs are enabled, check for the correct permissions + if aclObj != nil { + if !aclObj.AllowVariableOperation(args.WriteRequest.Namespace, args.Path, + acl.VariablesCapabilityWrite, nil) { + return structs.ErrPermissionDenied + } + } + + if err := args.Validate(); err != nil { + return err + } + + // Get the variable from the SS to verify it exists and is currently lock + stateSnapshot, err := sv.srv.State().Snapshot() + if err != nil { + return err + } + + encryptedVar, err := stateSnapshot.GetVariable(nil, args.WriteRequest.Namespace, args.Path) + if err != nil { + return err + } + + if encryptedVar == nil { + return errVarNotFound + } + + if encryptedVar.Lock == nil { + return errLockNotFound + } + + // Verify the caller is providing the correct lockID, meaning it is the lock holder and + // can renew the lock. + if encryptedVar.Lock.ID != args.LockID { + return errVarIsLocked + } + + // if the lock exists in the variable, but not in the timer, it means + // it expired and cant be renewed anymore. The delay will take care of + // removing the lock from the variable when it expires. + err = sv.timers.RenewTTLTimer(encryptedVar.Copy()) + if err != nil { + return errVarIsLocked + } + + updatedVar := encryptedVar.Copy() + reply.VarMeta = &updatedVar.VariableMetadata + reply.Index = encryptedVar.ModifyIndex + return nil +} + +func isCallerOwner(req *structs.VariablesApplyRequest, respVarMeta *structs.VariableMetadata) bool { + reqLock := req.Var.VariableMetadata.Lock + savedLock := respVarMeta.Lock + + return reqLock != nil && + savedLock != nil && + reqLock.ID == savedLock.ID +} diff --git a/nomad/variables_endpoint_test.go b/nomad/variables_endpoint_test.go index 2f463a5f5..82130b989 100644 --- a/nomad/variables_endpoint_test.go +++ b/nomad/variables_endpoint_test.go @@ -22,12 +22,437 @@ import ( "github.com/hashicorp/nomad/testutil" ) +func TestVariablesEndpoint_GetVariable_Blocking(t *testing.T) { + ci.Parallel(t) + + s1, cleanupS1 := TestServer(t, nil) + defer cleanupS1() + + state := s1.fsm.State() + codec := rpcClient(t, s1) + testutil.WaitForLeader(t, s1.RPC) + + // First create an unrelated variable. + delay := 100 * time.Millisecond + time.AfterFunc(delay, func() { + writeVarGet(t, s1, 100, "default", "aaa") + }) + + // Upsert the variable we are watching later + delay = 200 * time.Millisecond + time.AfterFunc(delay, func() { + writeVarGet(t, s1, 200, "default", "bbb") + }) + + // Lookup the variable + req := &structs.VariablesReadRequest{ + Path: "bbb", + QueryOptions: structs.QueryOptions{ + Region: "global", + MinQueryIndex: 150, + MaxQueryTime: 500 * time.Millisecond, + }, + } + + var resp structs.VariablesReadResponse + + start := time.Now() + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp); err != nil { + t.Fatalf("err: %v", err) + } + elapsed := time.Since(start) + + if elapsed < delay { + t.Fatalf("should block (returned in %s) %#v", elapsed, resp) + } + + if elapsed > req.MaxQueryTime { + t.Fatalf("blocking query timed out %#v", resp) + } + + if resp.Index != 200 { + t.Fatalf("Bad index: %d %d", resp.Index, 200) + } + + if resp.Data == nil || resp.Data.Path != "bbb" { + t.Fatalf("bad: %#v", resp.Data) + } + + // Variable update triggers watches + delay = 100 * time.Millisecond + + time.AfterFunc(delay, func() { + writeVarGet(t, s1, 300, "default", "bbb") + }) + + req.QueryOptions.MinQueryIndex = 250 + var resp2 structs.VariablesReadResponse + start = time.Now() + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp2); err != nil { + t.Fatalf("err: %v", err) + } + elapsed = time.Since(start) + + if elapsed < delay { + t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) + } + + if elapsed > req.MaxQueryTime { + t.Fatal("blocking query timed out") + } + + if resp2.Index != 300 { + t.Fatalf("Bad index: %d %d", resp2.Index, 300) + } + + if resp2.Data == nil || resp2.Data.Path != "bbb" { + t.Fatalf("bad: %#v", resp2.Data) + } + + // Variable delete triggers watches + delay = 100 * time.Millisecond + time.AfterFunc(delay, func() { + sv := mock.VariableEncrypted() + sv.Path = "bbb" + if resp := state.VarDelete(400, &structs.VarApplyStateRequest{Op: structs.VarOpDelete, Var: sv}); !resp.IsOk() { + fmt.Println("\n *** resp", resp.Result, resp.Conflict.VariableMetadata) + t.Fatalf("err: %v", resp.Error) + } + }) + fmt.Println("\n\n start", elapsed) + req.QueryOptions.MinQueryIndex = 350 + var resp3 structs.VariablesReadResponse + start = time.Now() + if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp3); err != nil { + t.Fatalf("err: %v", err) + } + elapsed = time.Since(start) + fmt.Println("\n\n problematic", elapsed) + if elapsed < delay { + t.Fatalf("should block (returned in %s) %#v", elapsed, resp) + } + + if elapsed > req.MaxQueryTime { + t.Fatal("blocking query timed out") + } + + if resp3.Index != 400 { + t.Fatalf("Bad index: %d %d", resp3.Index, 400) + } + if resp3.Data != nil { + t.Fatalf("bad: %#v", resp3.Data) + } +} + +func writeVarGet(t *testing.T, s *Server, idx uint64, ns, path string) { + store := s.fsm.State() + sv := mock.Variable() + sv.Namespace = ns + sv.Path = path + + bPlain, err := json.Marshal(sv.Items) + must.NoError(t, err) + bEnc, kID, err := s.encrypter.Encrypt(bPlain) + must.NoError(t, err) + sve := &structs.VariableEncrypted{ + VariableMetadata: sv.VariableMetadata, + VariableData: structs.VariableData{ + Data: bEnc, + KeyID: kID, + }, + } + resp := store.VarSet(idx, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: sve, + }) + must.NoError(t, resp.Error) +} + +func TestVariablesEndpoint_Apply_ACL(t *testing.T) { + ci.Parallel(t) + srv, rootToken, shutdown := TestACLServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + codec := rpcClient(t, srv) + state := srv.fsm.State() + + writePol := mock.NamespacePolicyWithVariables( + structs.DefaultNamespace, "", []string{"list-jobs"}, + map[string][]string{ + "dropbox/*": {"write"}, + }) + writeToken := mock.CreatePolicyAndToken(t, state, 1003, "test-write-invalid", writePol) + + readPol := mock.NamespacePolicyWithVariables( + structs.DefaultNamespace, "", []string{"list-jobs"}, + map[string][]string{ + "dropbox/*": {"read"}, + }) + + readToken := mock.CreatePolicyAndToken(t, state, 1005, "test-read-invalid", readPol) + + sv1 := mock.Variable() + sv1.ModifyIndex = 0 + var svHold *structs.VariableDecrypted + + opMap := map[string]structs.VarOp{ + "set": structs.VarOpSet, + "cas": structs.VarOpCAS, + "delete": structs.VarOpDelete, + "delete-cas": structs.VarOpDeleteCAS, + "lock-acquire": structs.VarOpLockAcquire, + "lock-release": structs.VarOpLockRelease, + } + + for name, op := range opMap { + t.Run(name+"/no token", func(t *testing.T) { + sv := *sv1 + applyReq := structs.VariablesApplyRequest{ + Op: op, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + if op == "lock-release" { + sv.Items = nil + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + must.EqError(t, err, structs.ErrPermissionDenied.Error()) + }) + + } + + t.Run("cas/management token/new", func(t *testing.T) { + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv1, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv1.Items, applyResp.Output.Items) + + svHold = applyResp.Output + }) + + t.Run("cas with current", func(t *testing.T) { + must.NotNil(t, svHold) + sv := svHold + sv.Items["new"] = "newVal" + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + applyReq.AuthToken = rootToken.SecretID + + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv.Items, applyResp.Output.Items) + + svHold = applyResp.Output + }) + + t.Run("cas with stale", func(t *testing.T) { + must.NotNil(t, sv1) // TODO: query these directly + must.NotNil(t, svHold) + + sv1 := sv1 + svHold := svHold + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv1, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + applyReq.AuthToken = rootToken.SecretID + + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + must.Eq(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) + must.Eq(t, svHold.Items, applyResp.Conflict.Items) + }) + + sv3 := mock.Variable() + sv3.Path = "dropbox/a" + sv3.ModifyIndex = 0 + + t.Run("cas/write-only/read own new", func(t *testing.T) { + sv3 := sv3 + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv3, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: writeToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv3.Items, applyResp.Output.Items) + svHold = applyResp.Output + }) + + t.Run("cas/write only/conflict redacted", func(t *testing.T) { + must.NotNil(t, sv3) + must.NotNil(t, svHold) + sv3 := sv3 + svHold := svHold + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv3, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: writeToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultRedacted, applyResp.Result) + must.Eq(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) + must.Nil(t, applyResp.Conflict.Items) + }) + + t.Run("cas/write only/read own upsert", func(t *testing.T) { + must.NotNil(t, svHold) + sv := svHold + sv.Items["upsert"] = "read" + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: sv, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: writeToken.SecretID, + }, + } + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv.Items, applyResp.Output.Items) + }) + + t.Run("lock-acquire/management token/new", func(t *testing.T) { + must.NotNil(t, svHold) + sv := *svHold + + sv.Items["upsert"] = "read" + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.NonZero(t, len(applyResp.Output.VariableMetadata.Lock.ID)) + + svHold = applyResp.Output + }) + + t.Run("lock-release/management token/new", func(t *testing.T) { + must.NotNil(t, svHold) + sv := svHold + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockRelease, + Var: &structs.VariableDecrypted{ + VariableMetadata: structs.VariableMetadata{ + Path: sv.Path, + Lock: &structs.VariableLock{ + ID: sv.LockID(), + }, + }, + }, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Nil(t, applyResp.Output.VariableMetadata.Lock) + }) + + t.Run("lock-acquire/read token/new", func(t *testing.T) { + must.NotNil(t, svHold) + sv := *sv3 + + sv.Items["upsert"] = "read" + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: readToken.SecretID, + }, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) + must.EqError(t, err, structs.ErrPermissionDenied.Error()) + }) +} + func TestVariablesEndpoint_auth(t *testing.T) { ci.Parallel(t) srv, _, shutdown := TestACLServer(t, func(c *Config) { c.NumSchedulers = 0 // Prevent automatic dequeue }) + defer shutdown() testutil.WaitForLeader(t, srv.RPC) @@ -119,7 +544,7 @@ func TestVariablesEndpoint_auth(t *testing.T) { if err != nil { return structs.ErrPermissionDenied } - _, _, err = variablesRPC.handleMixedAuthEndpoint( + _, err = variablesRPC.handleMixedAuthEndpoint( *args, cap, path) return err } @@ -394,188 +819,6 @@ func TestVariablesEndpoint_auth(t *testing.T) { } }) } - -} - -func TestVariablesEndpoint_Apply_ACL(t *testing.T) { - ci.Parallel(t) - srv, rootToken, shutdown := TestACLServer(t, func(c *Config) { - c.NumSchedulers = 0 // Prevent automatic dequeue - }) - defer shutdown() - testutil.WaitForLeader(t, srv.RPC) - codec := rpcClient(t, srv) - state := srv.fsm.State() - - pol := mock.NamespacePolicyWithVariables( - structs.DefaultNamespace, "", []string{"list-jobs"}, - map[string][]string{ - "dropbox/*": {"write"}, - }) - writeToken := mock.CreatePolicyAndToken(t, state, 1003, "test-invalid", pol) - - sv1 := mock.Variable() - sv1.ModifyIndex = 0 - var svHold *structs.VariableDecrypted - - opMap := map[string]structs.VarOp{ - "set": structs.VarOpSet, - "cas": structs.VarOpCAS, - "delete": structs.VarOpDelete, - "delete-cas": structs.VarOpDeleteCAS, - } - - for name, op := range opMap { - t.Run(name+"/no token", func(t *testing.T) { - sv1 := sv1 - applyReq := structs.VariablesApplyRequest{ - Op: op, - Var: sv1, - WriteRequest: structs.WriteRequest{Region: "global"}, - } - applyResp := new(structs.VariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) - must.EqError(t, err, structs.ErrPermissionDenied.Error()) - }) - } - - t.Run("cas/management token/new", func(t *testing.T) { - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv1, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: rootToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultOk, applyResp.Result) - must.Eq(t, sv1.Items, applyResp.Output.Items) - - svHold = applyResp.Output - }) - - t.Run("cas with current", func(t *testing.T) { - must.NotNil(t, svHold) - sv := svHold - sv.Items["new"] = "newVal" - - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: rootToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - applyReq.AuthToken = rootToken.SecretID - - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultOk, applyResp.Result) - must.Eq(t, sv.Items, applyResp.Output.Items) - - svHold = applyResp.Output - }) - - t.Run("cas with stale", func(t *testing.T) { - must.NotNil(t, sv1) // TODO: query these directly - must.NotNil(t, svHold) - - sv1 := sv1 - svHold := svHold - - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv1, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: rootToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - applyReq.AuthToken = rootToken.SecretID - - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultConflict, applyResp.Result) - must.Eq(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) - must.Eq(t, svHold.Items, applyResp.Conflict.Items) - }) - - sv3 := mock.Variable() - sv3.Path = "dropbox/a" - sv3.ModifyIndex = 0 - - t.Run("cas/write-only/read own new", func(t *testing.T) { - sv3 := sv3 - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv3, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: writeToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultOk, applyResp.Result) - must.Eq(t, sv3.Items, applyResp.Output.Items) - svHold = applyResp.Output - }) - - t.Run("cas/write only/conflict redacted", func(t *testing.T) { - must.NotNil(t, sv3) - must.NotNil(t, svHold) - sv3 := sv3 - svHold := svHold - - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv3, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: writeToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultRedacted, applyResp.Result) - must.Eq(t, svHold.VariableMetadata, applyResp.Conflict.VariableMetadata) - must.Nil(t, applyResp.Conflict.Items) - }) - - t.Run("cas/write only/read own upsert", func(t *testing.T) { - must.NotNil(t, svHold) - sv := svHold - sv.Items["upsert"] = "read" - - applyReq := structs.VariablesApplyRequest{ - Op: structs.VarOpCAS, - Var: sv, - WriteRequest: structs.WriteRequest{ - Region: "global", - AuthToken: writeToken.SecretID, - }, - } - applyResp := new(structs.VariablesApplyResponse) - err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, &applyResp) - - must.NoError(t, err) - must.Eq(t, structs.VarOpResultOk, applyResp.Result) - must.Eq(t, sv.Items, applyResp.Output.Items) - }) } func TestVariablesEndpoint_ListFiltering(t *testing.T) { @@ -674,7 +917,6 @@ func TestVariablesEndpoint_ListFiltering(t *testing.T) { "nomad/jobs/job1/group/web", } must.Eq(t, expect, found) - } func TestVariablesEndpoint_ComplexACLPolicies(t *testing.T) { @@ -796,138 +1038,606 @@ namespace "*" {} testListPrefix("*", "config", 3, nil) testListPrefix("*", "project", 2, nil) testListPrefix("*", "", 6, nil) - } -func TestVariablesEndpoint_GetVariable_Blocking(t *testing.T) { +func TestVariablesEndpoint_Apply_LockAcquireUpsertAndRelease(t *testing.T) { + ci.Parallel(t) + srv, shutdown := TestServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + codec := rpcClient(t, srv) + + mockVar := mock.Variable() + mockVar.ModifyIndex = 0 + + latest := mockVar.Copy() + + t.Run("successfully acquire lock on new variable", func(t *testing.T) { + sv := mockVar.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.NonZero(t, len(applyResp.Output.VariableMetadata.Lock.ID)) + must.Eq(t, sv.Items, applyResp.Output.Items) + + must.NotNil(t, srv.lockTTLTimer.Get(applyResp.Output.VariableMetadata.Lock.ID)) + must.Eq(t, runningTimers+1, srv.lockTTLTimer.TimerNum()) + + latest = applyResp.Output.Copy() + }) + + t.Run("acquire lock on locked variable without lockID", func(t *testing.T) { + sv := mockVar.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, runningTimers, srv.lockTTLTimer.TimerNum()) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + }) + + t.Run("successfully re acquire lock on locked variable with the lockID", func(t *testing.T) { + sv := latest.Copy() + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv.Items, applyResp.Output.Items) + + must.Eq(t, runningTimers, srv.lockTTLTimer.TimerNum()) + + latest = applyResp.Output.Copy() + }) + + t.Run("upsert locked variable without the lockID", func(t *testing.T) { + sv := mockVar.Copy() + sv.Items = structs.VariableItems{ + "item1": "very important info", + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpSet, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + }) + + t.Run("successfully upsert locked variable with the lockID", func(t *testing.T) { + sv := latest.Copy() + sv.Items = structs.VariableItems{ + "item1": "very important info", + } + + sv.Lock.TTL = 0 + sv.Lock.LockDelay = 0 + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpSet, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv.Items, applyResp.Output.Items) + + latest = applyResp.Output.Copy() + }) + + t.Run("upsert locked variable with correct CAS without the lockID", func(t *testing.T) { + sv := latest.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{} + sv.Items = structs.VariableItems{ + "item1": "very important info", + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + }) + + t.Run("upsert locked variable with wrong CAS without the lockID", func(t *testing.T) { + sv := mockVar.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{} + sv.Items = structs.VariableItems{ + "item1": "very important info", + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + }) + + t.Run("upsert locked variable wrong CAS and the lockID", func(t *testing.T) { + sv := latest.Copy() + + sv.Items = structs.VariableItems{ + "item1": "very important info", + "item2": "not so important info", + } + + sv.Lock.LockDelay = 0 + sv.Lock.TTL = 0 + sv.ModifyIndex = sv.ModifyIndex + 30 + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + }) + + t.Run("successfully upsert locked variable with CAS and the lockID", func(t *testing.T) { + sv := latest.Copy() + + sv.Items = structs.VariableItems{ + "item1": "very important info", + "item2": "not so important info", + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpCAS, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, sv.Items, applyResp.Output.Items) + + latest = applyResp.Output.Copy() + }) + + t.Run("release locked variable without the lock", func(t *testing.T) { + sv := mockVar.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{ + ID: "wrongID", + } + + sv.Items = nil + sv.Lock = nil + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockRelease, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.Error(t, err) + must.Eq(t, runningTimers, srv.lockTTLTimer.TimerNum()) + + }) + t.Run("release locked variable without the lockID", func(t *testing.T) { + sv := mockVar.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{ + ID: "wrongID", + } + sv.Items = nil + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockRelease, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultConflict, applyResp.Result) + must.Eq(t, runningTimers, srv.lockTTLTimer.TimerNum()) + + }) + + t.Run("successfully release locked variable with the lockID", func(t *testing.T) { + sv := latest.Copy() + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockRelease, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + sv.Items = nil + + runningTimers := srv.lockTTLTimer.TimerNum() + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, runningTimers-1, srv.lockTTLTimer.TimerNum()) + + must.Nil(t, applyResp.Output.Lock) + must.Zero(t, len(applyResp.Output.Items)) + + latest = applyResp.Output.Copy() + }) + + t.Run("successfully acquire lock on variable with new data", func(t *testing.T) { + sv := latest.Copy() + + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + sv.Items = structs.VariableItems{ + "item1": "very important info", + "item2": "not so important info", + "item3": "the password", + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{Region: "global"}, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.Eq(t, runningTimers+1, srv.lockTTLTimer.TimerNum()) + must.Eq(t, sv.Items, applyResp.Output.Items) + + latest = applyResp.Output.Copy() + }) +} + +func TestVariablesEndpoint_List_Lock_ACL(t *testing.T) { ci.Parallel(t) - s1, cleanupS1 := TestServer(t, nil) - defer cleanupS1() - state := s1.fsm.State() - codec := rpcClient(t, s1) - testutil.WaitForLeader(t, s1.RPC) + srv, rootToken, shutdown := TestACLServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + codec := rpcClient(t, srv) + state := srv.fsm.State() - // First create an unrelated variable. - delay := 100 * time.Millisecond - time.AfterFunc(delay, func() { - writeVar(t, s1, 100, "default", "aaa") + listPol := mock.NamespacePolicyWithVariables( + structs.DefaultNamespace, "", []string{"list-jobs"}, + map[string][]string{ + "dropbox/*": {"list", "read", "write"}, + }) + listToken := mock.CreatePolicyAndToken(t, state, 1003, "test-write-invalid", listPol) + + sv1 := mock.VariableEncrypted() + sv1.Path = "dropbox/a" + + sv1.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + // Creating and locking the variable directly on the state store allows us to + // set up the lock ID and bypass the timers. + ssResp := state.VarLockAcquire(100, &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: sv1, }) - // Upsert the variable we are watching later - delay = 200 * time.Millisecond - time.AfterFunc(delay, func() { - writeVar(t, s1, 200, "default", "bbb") + must.NoError(t, ssResp.Error) + + t.Run("successfully read the lock information with a management call", func(t *testing.T) { + req := &structs.VariablesListRequest{ + QueryOptions: structs.QueryOptions{ + Namespace: structs.DefaultNamespace, + Prefix: "dropbox", + AuthToken: rootToken.SecretID, + Region: "global", + }, + } + + listResp := new(structs.VariablesListResponse) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.List", req, &listResp)) + must.NotNil(t, listResp.Data[0].Lock) + must.Eq(t, "theLockID", listResp.Data[0].Lock.ID) }) - // Lookup the variable - req := &structs.VariablesReadRequest{ - Path: "bbb", - QueryOptions: structs.QueryOptions{ - Region: "global", - MinQueryIndex: 150, - MaxQueryTime: 500 * time.Millisecond, - }, - } - var resp structs.VariablesReadResponse - start := time.Now() - if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp); err != nil { - t.Fatalf("err: %v", err) - } - elapsed := time.Since(start) + t.Run("try to read the lock information without a token", func(t *testing.T) { + req := &structs.VariablesListRequest{ + QueryOptions: structs.QueryOptions{ + Namespace: structs.DefaultNamespace, + Prefix: "dropbox", + Region: "global", + }, + } - if elapsed < delay { - t.Fatalf("should block (returned in %s) %#v", elapsed, resp) - } - if elapsed > req.MaxQueryTime { - t.Fatalf("blocking query timed out %#v", resp) - } - if resp.Index != 200 { - t.Fatalf("Bad index: %d %d", resp.Index, 200) - } - if resp.Data == nil || resp.Data.Path != "bbb" { - t.Fatalf("bad: %#v", resp.Data) - } - - // Variable update triggers watches - delay = 100 * time.Millisecond - - time.AfterFunc(delay, func() { - writeVar(t, s1, 300, "default", "bbb") + listResp := new(structs.VariablesListResponse) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.List", req, &listResp)) + must.Zero(t, len(listResp.Data)) }) - req.QueryOptions.MinQueryIndex = 250 - var resp2 structs.VariablesReadResponse - start = time.Now() - if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp2); err != nil { - t.Fatalf("err: %v", err) - } - elapsed = time.Since(start) + t.Run("try to read the lock information without a list token", func(t *testing.T) { + req := &structs.VariablesListRequest{ + QueryOptions: structs.QueryOptions{ + Namespace: structs.DefaultNamespace, + Prefix: "dropbox", + AuthToken: listToken.SecretID, + Region: "global", + }, + } - if elapsed < delay { - t.Fatalf("should block (returned in %s) %#v", elapsed, resp2) - } - if elapsed > req.MaxQueryTime { - t.Fatal("blocking query timed out") - } - if resp2.Index != 300 { - t.Fatalf("Bad index: %d %d", resp2.Index, 300) - } - if resp2.Data == nil || resp2.Data.Path != "bbb" { - t.Fatalf("bad: %#v", resp2.Data) + listResp := new(structs.VariablesListResponse) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.List", req, &listResp)) + must.NonZero(t, len(listResp.Data)) + must.Nil(t, listResp.Data[0].Lock) + }) +} + +func TestVariablesEndpoint_Read_Lock_ACL(t *testing.T) { + ci.Parallel(t) + srv, rootToken, shutdown := TestACLServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + codec := rpcClient(t, srv) + state := srv.fsm.State() + + listPol := mock.NamespacePolicyWithVariables( + structs.DefaultNamespace, "", []string{"list-jobs"}, + map[string][]string{ + "dropbox/*": {"list", "read"}, + }) + listToken := mock.CreatePolicyAndToken(t, state, 1003, "test-write-invalid", listPol) + + sv := mock.Variable() + sv.Path = "dropbox/a" + + latest := sv.Copy() + t.Run("successfully acquire lock on new variable", func(t *testing.T) { + sv := sv.Copy() + sv.VariableMetadata.Lock = &structs.VariableLock{ + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, + } + + applyReq := structs.VariablesApplyRequest{ + Op: structs.VarOpLockAcquire, + Var: &sv, + WriteRequest: structs.WriteRequest{ + Region: "global", + AuthToken: rootToken.SecretID, + }, + } + + runningTimers := srv.lockTTLTimer.TimerNum() + + applyResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesApplyRPCMethod, &applyReq, applyResp) + + must.NoError(t, err) + must.Eq(t, structs.VarOpResultOk, applyResp.Result) + must.NotNil(t, applyResp.Output.VariableMetadata.Lock) + must.Eq(t, sv.Items, applyResp.Output.Items) + + must.NotNil(t, srv.lockTTLTimer.Get(applyResp.Output.VariableMetadata.Lock.ID)) + must.Eq(t, runningTimers+1, srv.lockTTLTimer.TimerNum()) + latest = *applyResp.Output + + }) + + t.Run("successfully read the lock information with a management call", func(t *testing.T) { + req := &structs.VariablesReadRequest{ + Path: sv.Path, + QueryOptions: structs.QueryOptions{ + Namespace: structs.DefaultNamespace, + AuthToken: rootToken.SecretID, + Region: "global", + }, + } + + readResp := new(structs.VariablesReadResponse) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &readResp)) + must.NotNil(t, readResp.Data.VariableMetadata.Lock) + must.Eq(t, latest.LockID(), readResp.Data.LockID()) + }) + + t.Run("try to read the lock information with a list token", func(t *testing.T) { + req := &structs.VariablesReadRequest{ + Path: sv.Path, + QueryOptions: structs.QueryOptions{ + Namespace: structs.DefaultNamespace, + AuthToken: listToken.SecretID, + Region: "global", + }, + } + + readResp := new(structs.VariablesReadResponse) + must.NoError(t, msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &readResp)) + must.Nil(t, readResp.Data.VariableMetadata.Lock) + }) +} + +func TestVariablesEndpoint_RenewLock(t *testing.T) { + ci.Parallel(t) + srv, shutdown := TestServer(t, func(c *Config) { + c.NumSchedulers = 0 // Prevent automatic dequeue + }) + defer shutdown() + testutil.WaitForLeader(t, srv.RPC) + codec := rpcClient(t, srv) + state := srv.fsm.State() + + unlockedVar := mock.VariableEncrypted() + + vsResp := state.VarSet(102, &structs.VarApplyStateRequest{ + Op: structs.VarOpSet, + Var: unlockedVar, + }) + must.NoError(t, vsResp.Error) + + lockedVar := mock.VariableEncrypted() + lockedVar.VariableMetadata.Lock = &structs.VariableLock{ + ID: "theLockID", + TTL: 24 * time.Hour, + LockDelay: 15 * time.Second, } - // Variable delete triggers watches - delay = 100 * time.Millisecond - time.AfterFunc(delay, func() { - sv := mock.VariableEncrypted() - sv.Path = "bbb" - if resp := state.VarDelete(400, &structs.VarApplyStateRequest{Op: structs.VarOpDelete, Var: sv}); !resp.IsOk() { - t.Fatalf("err: %v", resp.Error) + // Creating and locking the variable directly on the state store allows us to + // set up the lock ID and bypass the timers. + vlResp := state.VarLockAcquire(104, &structs.VarApplyStateRequest{ + Op: structs.VarOpLockAcquire, + Var: lockedVar, + }) + + must.NoError(t, vlResp.Error) + + t.Run("error renewing lock", func(t *testing.T) { + + testCases := []struct { + name string + varPath string + lockID string + expError error + }{ + { + name: "renewing lock on a missing variable", + varPath: "missing/variable/path", + lockID: "missingVariableID", + expError: errVarNotFound, + }, + { + name: "renewing lock on unlocked variable", + varPath: unlockedVar.Path, + lockID: "randomLockID", + expError: errLockNotFound, + }, + { + name: "renewing lock with the wrong lockID", + varPath: lockedVar.Path, + lockID: "wrongLockID", + expError: errVarIsLocked, + }, + { + name: "renewing lock after it has expired", + varPath: lockedVar.Path, + lockID: lockedVar.LockID(), + expError: errVarIsLocked, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + rnReq := structs.VariablesRenewLockRequest{ + Path: tc.varPath, + LockID: tc.lockID, + WriteRequest: structs.WriteRequest{ + Region: "global", + Namespace: structs.DefaultNamespace, + }, + } + + rnResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesRenewLockRPCMethod, &rnReq, rnResp) + must.ErrorContains(t, err, tc.expError.Error()) + }) } }) - req.QueryOptions.MinQueryIndex = 350 - var resp3 structs.VariablesReadResponse - start = time.Now() - if err := msgpackrpc.CallWithCodec(codec, "Variables.Read", req, &resp3); err != nil { - t.Fatalf("err: %v", err) - } - elapsed = time.Since(start) + t.Run("successfully renewing lock", func(t *testing.T) { + // Add a running timer for the lock so it is consider active and can be renewed. + srv.lockTTLTimer.Create(vlResp.WrittenSVMeta.LockID(), 30*time.Second, func() {}) - if elapsed < delay { - t.Fatalf("should block (returned in %s) %#v", elapsed, resp) - } - if elapsed > req.MaxQueryTime { - t.Fatal("blocking query timed out") - } - if resp3.Index != 400 { - t.Fatalf("Bad index: %d %d", resp3.Index, 400) - } - if resp3.Data != nil { - t.Fatalf("bad: %#v", resp3.Data) - } -} + rnReq := structs.VariablesRenewLockRequest{ + Path: lockedVar.Path, + LockID: lockedVar.LockID(), + WriteRequest: structs.WriteRequest{ + Region: "global", + Namespace: structs.DefaultNamespace, + }, + } -func writeVar(t *testing.T, s *Server, idx uint64, ns, path string) { - store := s.fsm.State() - sv := mock.Variable() - sv.Namespace = ns - sv.Path = path - bPlain, err := json.Marshal(sv.Items) - must.NoError(t, err) - bEnc, kID, err := s.encrypter.Encrypt(bPlain) - must.NoError(t, err) - sve := &structs.VariableEncrypted{ - VariableMetadata: sv.VariableMetadata, - VariableData: structs.VariableData{ - Data: bEnc, - KeyID: kID, - }, - } - resp := store.VarSet(idx, &structs.VarApplyStateRequest{ - Op: structs.VarOpSet, - Var: sve, + rnResp := new(structs.VariablesApplyResponse) + err := msgpackrpc.CallWithCodec(codec, structs.VariablesRenewLockRPCMethod, &rnReq, rnResp) + must.NoError(t, err) }) - must.NoError(t, resp.Error) } diff --git a/website/content/api-docs/variables/index.mdx b/website/content/api-docs/variables/index.mdx new file mode 100644 index 000000000..8f1e8bcb2 --- /dev/null +++ b/website/content/api-docs/variables/index.mdx @@ -0,0 +1,21 @@ +--- +layout: api +page_title: Variables - HTTP API +description: |- + The /var endpoints are used to query for and interact with variables and variable + locking. +--- + +# Vars HTTP API + +The `/var` and `/vars` endpoints are used to query for and interact with +variables, and set up locks and leases over them. + +See the [Variables][] documentation for information how these capabilities are +used. For a CLI to perform these operations manually, please see the +documentation for the [`nomad var`][] commands. + +Please choose a sub-section in the navigation for more information + +[`nomad var`]: /nomad/docs/commands/var +[Variables]: /nomad/docs/concepts/variables \ No newline at end of file diff --git a/website/content/api-docs/variables/locks.mdx b/website/content/api-docs/variables/locks.mdx new file mode 100644 index 000000000..bbb79d758 --- /dev/null +++ b/website/content/api-docs/variables/locks.mdx @@ -0,0 +1,211 @@ +--- +layout: api +page_title: Variable Locks - HTTP API +description: The /var endpoints are used to query for and interact with variables and locks. +--- + +# Locks HTTP API + +The `/var` endpoint is used to hold, renew and release a lock over a variable. + +## Lock Variable + +The endpoint to create a variable can also be used to hold a lock and interact with +it through the use of a parameter defining the operation to be performed. + +| Method | Path | Produces | +|--------|--------------------------------------|--------------------| +| `PUT` | `/v1/var/:var_path?` | `application/json` | + +### Parameters + +The lock operation parameter can be: + +- `lock-acquire`: When used, the call will introduce a lock over the variable if +it exists, or create a new one if it doesn't. The lock ID will be returned in the +response and it must be provided to perform any other operation over the lock. +The variable items can be updated at any time using the lock ID, but the lock +parameters are unmmutable, attempting to modify them while a lock is present will +generate an error. + +In the case of attempting to acquire a variable that is already locked, a conflict +response will be returned. + +The lock-acquire operation will override the variable items if new values are +present. + + +#### Sample Request + +```shell-session +$ curl \ + -XPUT -d@spec.nsv.json \ + https://localhost:4646/v1/var/example/first?lock-acquire +``` + +#### Sample Payload + +```json +{ + "Namespace": "prod", + "Path": "example/first", + "Items": { + "user": "me", + "password": "passw0rd1" + }, + "Lock": { + "TTL": "15s", + "LockDelay": "1m" + } +} +``` + +#### Sample Response + +The response body returns the created or updated variable including the lock +parameters and ID, along with metadata created by the server: + +```json +{ + "CreateIndex": 15, + "CreateTime": 1694552155379696000, + "Items": { + "user": "me", + "password": "passw0rd1" + }, + "Lock": { + "TTL": "15s", + "LockDelay": "15s", + "ID": "670c7248-e2ef-f982-e4c5-f4437f75f1e4" + }, + "ModifyIndex": 16, + "ModifyTime": 1694552206138804000, + "Namespace": "prod", + "Path": "example/first" +} +``` + +- `lock-renew`: A valid call to lock renew needs to be placed before the lock's +TTL is up in order to mantain the variable locked. A valid call must include the +lock ID as part of the request body. If the lock TTL is up without a renewal or +release calls, the variable will remain unlockable for at least the lock delay. + +#### Sample Request + +```shell-session +$ curl \ + -XPUT -d@spec.nsv.json \ + https://localhost:4646/v1/var/example/first?lock-renew +``` + +#### Sample Payload + +```json +{ + "Path": "example/first", + "Namespace": "prod", + "Lock": { + "ID": "670c7248-e2ef-f982-e4c5-f4437f75f1e4" + } +} +``` + +#### Sample Response + +The response body only returns metadata created by the server and the lock +parameters: + +```json +{ + "CreateIndex": 11, + "CreateTime": 1694555280887153000, + "Lock": { + "TTL": "15s", + "LockDelay": "15s", + "ID": "670c7248-e2ef-f982-e4c5-f4437f75f1e4" + }, + "ModifyIndex": 43, + "ModifyTime": 1694556175092779000, + "Namespace": "prod", + "Path": "example/first" +} +``` + +- `lock-release`: A call to the endpoint with the `lock-release` operation will +immediately remove the lock over the variable, making it modifiable without +restrictions again. + +The lock-release operation will not override the variable items, if the request +body contains any item, it will generate a bad request response. + +#### Sample Request + +```shell-session +$ curl \ + -XPUT -d@spec.nsv.json \ + https://localhost:4646/v1/var/example/first?lock-release +``` + +#### Sample Payload + +```json +{ + "Path": "example/first", + "Namespace": "prod", + "Lock": { + "ID": "670c7248-e2ef-f982-e4c5-f4437f75f1e4" + } +} +``` + +#### Sample Response + +The response body returns the released variable along with metadata +created by the server: + +```json +{ + "CreateIndex": 11, + "CreateTime": 1694555280887153000, + "ModifyIndex": 66, + "ModifyTime": 1694556922600469000, + "Namespace": "prod", + "Path": "example/first" +} +``` + +### Sample Response for Conflict + +In the case of an attempt to lock, renew or modify a locked variable +without the correct ID, the API will return HTTP error code +409 and a response body showing the conflicting variable. If the provided ACL +token does not also have `read` permissions to the variable path, the response +will include only metadata and not the `Items` field: + +```json +{ + "CreateIndex": 0, + "CreateTime": 0, + "Items": null, + "Lock": null, + "ModifyIndex": 0, + "ModifyTime": 0, + "Namespace": "default", + "Path": "example/first" +} +``` + +## Restrictions + +When creating a new variable using the lock-acquire operation, all the known +[restrictions][] regarding the path and size of the content apply, but unlike +regular variables, locked variables can be created with or without any items. + +The lock TTL and Delay must be values between 10 seconds and 24 hours. + +[Variables]: /nomad/docs/concepts/variables +[restrictions]: /nomad/api-docs/variables/variables#restrictions +[`nomad var`]: /nomad/docs/commands/var +[blocking queries]: /nomad/api-docs#blocking-queries +[required ACLs]: /nomad/api-docs#acls +[RFC3986]: https://www.rfc-editor.org/rfc/rfc3986#section-2 diff --git a/website/content/api-docs/variables.mdx b/website/content/api-docs/variables/variables.mdx similarity index 96% rename from website/content/api-docs/variables.mdx rename to website/content/api-docs/variables/variables.mdx index f68c0fbd5..f53b0c7be 100644 --- a/website/content/api-docs/variables.mdx +++ b/website/content/api-docs/variables/variables.mdx @@ -9,9 +9,8 @@ description: The /var endpoints are used to query for and interact with variable The `/var` and `/vars` endpoints are used to query for and interact with variables. -See the [Variables] documentation for information how these capabilities are -used. For a CLI to perform these operations manually, please see the -documentation for the [`nomad var`] commands. +See the [Variables][] documentation for information how these capabilities are +used. ## List Variables @@ -150,6 +149,10 @@ The table below shows this endpoint's support for [blocking queries] and 0, the variable is only created if it does not already exist. This paradigm allows check-and-set style updates. +- `lock-operation` `(string: )` - This endpoint can also be used to create +and hold a lock over a variable, refer to the [locks section][] for more +information. + ## Restrictions Variable paths are restricted to [RFC3986][] URL-safe characters that don't @@ -290,9 +293,8 @@ the response will include only metadata and not the `Items` field: } ``` - [Variables]: /nomad/docs/concepts/variables -[`nomad var`]: /nomad/docs/commands/var +[locks section]:/nomad/api-docs/variables/locks [blocking queries]: /nomad/api-docs#blocking-queries [required ACLs]: /nomad/api-docs#acls [RFC3986]: https://www.rfc-editor.org/rfc/rfc3986#section-2 diff --git a/website/content/docs/commands/var/index.mdx b/website/content/docs/commands/var/index.mdx index 16f7bd533..695bf78dd 100644 --- a/website/content/docs/commands/var/index.mdx +++ b/website/content/docs/commands/var/index.mdx @@ -21,6 +21,7 @@ subcommands are available: - [`var get`][get] - Retrieve a variable - [`var put`][put] - Insert or update a variable - [`var purge`][purge] - Permanently delete a variable +- [`var lock`][lock] - Acquire a lock over a variable ## Examples @@ -62,3 +63,4 @@ user = dba [list]: /nomad/docs/commands/var/list [put]: /nomad/docs/commands/var/put [purge]: /nomad/docs/commands/var/purge +[lock]: /nomad/docs/commands/var/lock diff --git a/website/content/docs/commands/var/lock.mdx b/website/content/docs/commands/var/lock.mdx new file mode 100644 index 000000000..0e9921181 --- /dev/null +++ b/website/content/docs/commands/var/lock.mdx @@ -0,0 +1,100 @@ +--- +layout: docs +page_title: "Command: var lock" +description: |- + The "var lock" command locks a variable, only allowing the lock owner to modify it. +--- + +# Command: var lock + +The `var lock` command holds a lock on a [variable][]. + +## Usage + +```plaintext +nomad var lock [options] child... +nomad var lock [options] [] child +``` + +The lock command provides a mechanism for simple distributed locking. A lock +is created in the given variable, and only when held, is a child process invoked. + +The lock command can be called on an existing variable or an entire new variable +specification can be provided to the command from a file by using an +@-prefixed path to a variable specification file. Items to be stored in the +variable can be supplied using the specification file as well. + +Nomad lock launches its children in a shell. By default, Nomad will use the +shell defined in the environment variable SHELL. If SHELL is not defined, +it will default to /bin/sh. It should be noted that not all shells terminate +child processes when they receive SIGTERM. Under Ubuntu, /bin/sh is linked +to dash, which does not terminate its children. In order to ensure that +child processes are killed when the lock is lost, be sure to set the SHELL +environment variable appropriately, or run without a shell by setting -shell=false. + +If [ACLs][] are enabled, this command requires the 'variables:write' capability +for the destination namespace and path. + +## Restrictions + +Variable paths are restricted to [RFC3986][] URL-safe characters that don't +conflict with the use of the characters `@` and `.` in template blocks. This +includes alphanumeric characters and the special characters `-`, `_`, `~`, and +`/`. Paths may be up to 128 bytes long. The following regex matches the allowed +paths: `^[a-zA-Z0-9-_~/]{1,128}$` + +The keys for the items in a variable may contain any character, but keys +containing characters outside the set of Unicode letters, Unicode digits, and +the underscore (`_`) can not be read directly using dotted references in Nomad's +template engine. Instead, they require the use of the `index` template function +to directly access their values. This does not impact cases where the keys and +values are read using the `range` function. + +Variable items are restricted to 64KiB in size. This limit is calculated by +taking the sum of the length in bytes of all of the unencrypted keys and values. + +## General Options + +@include 'general_options.mdx' + +## Lock Options +- `-verbose`: Provides additional information via standard error to preserve + standard output (stdout) for redirected output. + +- `ttl`: Optional, TTL for the lock, time the variable will be locked. Defaults to 15s. + +- `delay`: Optional, time the variable is blocked from locking when a lease is not renewed. + Defaults to 15s. + +- `max-retry`:Optional, max-retry up to this number of times if Nomad returns a 500 error + while monitoring the lock. This allows riding out brief periods of + unavailability without causing leader elections, but increases the amount of + time required to detect a lost lock in some cases. Defaults to 5. Set to 0 to + disable. + +- `shell`: Optional, use a shell to run the command (can set a custom shell via + the SHELL environment variable). The default value is true. + +## Examples + +Attempts to acquire a lock over the variable at path "secret/creds" for a time of +15s and executes `nomad job run webapp.nomad.hcl` if it succeeds: + +```shell-session +$ nomad var lock -ttl=15s secret/creds "nomad job run webapp.nomad.hcl" +``` + +The data can also be consumed from a file on disk by prefixing with the "@" +symbol. For example, you can store a variable using a specification created with +the `nomad var init` command. + +```shell-session +$ nomad var lock secret/foo @spec.nv.json `nomad job run webapp.nomad.hcl` +``` + +[variable]: /nomad/docs/concepts/variables +[varspec]: /nomad/docs/other-specifications/variables +[ACL Policy]: /nomad/docs/other-specifications/acl-policy#variables +[RFC3986]: https://www.rfc-editor.org/rfc/rfc3986#section-2 +[ACL]: /nomad/docs/other-specifications/acl-policy#variables + diff --git a/website/content/docs/concepts/variables.mdx b/website/content/docs/concepts/variables.mdx index 85016a45e..6390de96f 100644 --- a/website/content/docs/concepts/variables.mdx +++ b/website/content/docs/concepts/variables.mdx @@ -186,6 +186,55 @@ apply. See [Workload Associated ACL Policies] for more details. +## Locks + +Nomad provides the ability to block a variable from being updated for a period +of time by setting a lock on it. Once a variable is locked, it can be read by +everyone, but it can only be updated by the lock holder. + +The locks are designed to provide granular locking and are heavily inspired by +[The Chubby Lock Service for Loosely-Coupled Distributed Systems][]. + +A lock is composed of an ID, a TTL, and a lock delay. The ID is generated by +the Nomad Server and must be provided on every request to modify the variable's +items or the lock itself. The TTL defines the time the lock will be held; if the +lock needs to be in place for longer, it can be renewed for as many new periods +as wanted. + +Once it is no longer needed, it must be released. If by the time the TTL expires, +and no renew or release calls were made, the variable will remain locked for at +least the lock delay duration, to avoid a possible split-brain situation, where +there are two holders at the same time. + +### Leader election backed by Nomad Variable Locks + +For some applications, like HDFS or the Nomad Autoscaler, it is necessary to +have multiple instances running to ensure redundancy in case of a failure, but +only one of them may be active at a time as a leader. + +As part of the [Go Package][], Nomad offers a helper that takes one variable and +uses a lock over it as a sync mechanism to run multiple instances but always +keeping just one running at any given time, using the following algorithm: + +[![Leader Election Helper](/img/nomad-vars-leader-election-sdk.png)](/img/nomad-vars-leader-election-sdk.png) + +As soon as any instance starts, it tries to lock the sync variable. If it succeeds, +it continues to execute while a secondary thread is in charge of keeping track of +the lock and renewing it when necessary. If by any chance the renewal fails, +the main process is forced to return, and the instance goes into standby until it +attempts to acquire the lock over the sync variable. + +Only threads 1 and 3 or thread 2 are running at any given time, because every +instance is either executing as normal while renewing the lock or waiting for a +chance to acquire it and run. + +When the main process, or protected function, returns, the helper releases the +lock, allowing a second instance to start running. + +To see it implemented live, look for the [`nomad var lock`][] command +implementation or the [Nomad Autoscaler][] High Availability implementation. + + [HashiCorp Consul]: https://www.consul.io/ [HashiCorp Vault]: https://www.vaultproject.io/ [Key Management]: /nomad/docs/operations/key-management @@ -194,3 +243,8 @@ See [Workload Associated ACL Policies] for more details. [workload identity]: /nomad/docs/concepts/workload-identity [Workload Associated ACL Policies]: /nomad/docs/concepts/workload-identity#workload-associated-acl-policies [ACL policy namespace rules]: /nomad/docs/other-specifications/acl-policy#namespace-rules +[The Chubby Lock Service for Loosely-Coupled Distributed Systems]: https://research.google/pubs/pub27897/ +[`nomad var lock`]: /nomad/docs/commands/var +[Go Package]: https://pkg.go.dev/github.com/hashicorp/nomad/api +[implementation]: https://github.com/hashicorp/nomad/blob/release/1.7.0/command/var_lock.go#L240 +[Nomad Autoscaler]: https://github.com/hashicorp/nomad-autoscaler/release/0.3.7command/agent.go#L368 \ No newline at end of file diff --git a/website/data/api-docs-nav-data.json b/website/data/api-docs-nav-data.json index c886c66f1..0ba76dac6 100644 --- a/website/data/api-docs-nav-data.json +++ b/website/data/api-docs-nav-data.json @@ -185,7 +185,20 @@ }, { "title": "Variables", - "path": "variables" + "routes": [ + { + "title": "Overview", + "path": "variables" + }, + { + "title": "Variables", + "path": "variables/variables" + }, + { + "title": "Locks", + "path": "variables/locks" + } + ] }, { "title": "Volumes", diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 93ee0ca23..5a1acc2a4 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -1088,6 +1088,10 @@ "title": "put", "path": "commands/var/put" }, + { + "title": "lock", + "path": "commands/var/lock" + }, { "title": "purge", "path": "commands/var/purge" diff --git a/website/public/img/nomad-vars-leader-election-sdk.png b/website/public/img/nomad-vars-leader-election-sdk.png new file mode 100644 index 0000000000000000000000000000000000000000..8f57c16098104382194b20a8960b4596d78681a4 GIT binary patch literal 557554 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

{D7nU{atk-vFP7@sXWFTBr#Cj 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�S_1c;Q~0XgyqQV@tQ#TU_#LYfdnMF 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�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%0AmZ)&UqgbtK&x@>i!vovQtCbYz)3cF^_-UHp8+a_ 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 literal 0 HcmV?d00001