-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Unlock key delete conditional on being old leader's #6637
Changes from 1 commit
a95cf02
54d8c25
01bfce8
60b0e89
3e24392
0aba117
a81fa01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -571,10 +571,28 @@ func (l *DynamoDBLock) Unlock() error { | |
} | ||
|
||
l.held = false | ||
if err := l.backend.Delete(context.Background(), l.key); err != nil { | ||
return err | ||
|
||
// Conditionally delete after check that the key is actually this Vault's and | ||
// not been already claimed by another leader | ||
condition := "#identity = :identity" | ||
deleteMyLock := &dynamodb.DeleteItemInput{ | ||
TableName: &l.backend.table, | ||
ConditionExpression: &condition, | ||
Key: map[string]*dynamodb.AttributeValue{ | ||
"Path": &dynamodb.AttributeValue{S: aws.String(recordPathForVaultKey(l.key))}, | ||
"Key": &dynamodb.AttributeValue{S: aws.String(recordKeyForVaultKey(l.key))}, | ||
}, | ||
ExpressionAttributeNames: map[string]*string{ | ||
"#identity": aws.String("Identity"), | ||
}, | ||
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | ||
":identity": &dynamodb.AttributeValue{B: []byte(l.identity)}, | ||
}, | ||
} | ||
return nil | ||
|
||
_, err := l.backend.client.DeleteItem(deleteMyLock) | ||
|
||
return err | ||
} | ||
|
||
// Value checks whether or not the lock is held by any instance of DynamoDBLock, | ||
|
@@ -634,7 +652,10 @@ func (l *DynamoDBLock) periodicallyRenewLock(done chan struct{}) { | |
select { | ||
case <-ticker.C: | ||
// This should not renew the lock if the lock was deleted from under you. | ||
l.updateItem(false) | ||
err := l.updateItem(false) | ||
if err != nil { | ||
l.backend.logger.Error("error renewing leadership lock", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hclog takes a message and then label/value pairs, so this needs to be like: |
||
} | ||
case <-done: | ||
ticker.Stop() | ||
return | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -576,7 +576,9 @@ func (c *Core) waitForLeadership(newLeaderCh chan func(), manualStepDownCh, stop | |||
c.logger.Error("clearing leader advertisement failed", "error", err) | ||||
} | ||||
|
||||
c.heldHALock.Unlock() | ||||
if err := c.heldHALock.Unlock(); err != nil { | ||||
c.logger.Error("unlocking HA lock failed", "error", err) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hclog takes a message and then label/value pairs, so this needs to be like: That said, I'm hesitant about this change until we understand what all of the HA backends are returning. For example even DynamoDB would need to have some additional guards around the error from To be clear I do like the idea here, but we may want to run some additional tests with other backends lest customers start seeing errors. Thoughts, @briankassouf ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After some discussion, we decided that this line is OK to leave in. But please add a check to Unlock() (which calls your modified Delete) to catch the ConditionCheck error and not report it as an error, similar to that handling here: vault/physical/dynamodb/dynamodb.go Line 632 in 54d8c25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do think this case is a bit different from the tryToLock one because in that case it is speculatively attempting to update and has the expectation that it can reasonably fail. Whereas for Unlock() this shouldn't really expected unless something aberrant has happened. Though as long as Vault will always attempt unlock when it steps down, even if it knows there is a new leader already, it's reasonable to not report the error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is interesting b/c I've seen this occur in Unlock at least once, but that was during a simulated network outage. Much more common (and I didn't mention this previously) is
I appreciate the effort on this! I'd like to get this merged fairly soon, so if you need any help I'm able to push to your branch as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those all make sense to me and should be taken care of now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alas, my suggested refactor was too much. The presence of an error is needed from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changes look good to me. |
||||
} | ||||
c.heldHALock = nil | ||||
} | ||||
|
||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type (&dynamodb.AttributeValue) isn't required here, or on 583 & 589.