defer setting the state before returning to avoid stuck in `INITIALIZING` state (#10630)
* defer setting the state before returning to avoid being stuck in `INITIALIZING` state * add changelog * move comment with the right if statement * ca: report state transition error from setSTate * update comment to reflect state transition Co-authored-by: Daniel Nephin <dnephin@hashicorp.com>
This commit is contained in:
parent
79ab48ef81
commit
40baf98159
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
ca: fixed a bug when ca provider fail and provider state is stuck in `INITIALIZING` state.
|
||||||
|
```
|
|
@ -141,7 +141,7 @@ func NewCAManager(delegate caServerDelegate, leaderRoutineManager *routine.Manag
|
||||||
// setState attempts to update the CA state to the given state.
|
// setState attempts to update the CA state to the given state.
|
||||||
// Valid state transitions are:
|
// Valid state transitions are:
|
||||||
//
|
//
|
||||||
// caStateInitialized -> <any state>
|
// caStateInitialized -> <any state except caStateInitializing>
|
||||||
// caStateUninitialized -> caStateInitializing
|
// caStateUninitialized -> caStateInitializing
|
||||||
// caStateUninitialized -> caStateReconfig
|
// caStateUninitialized -> caStateReconfig
|
||||||
//
|
//
|
||||||
|
@ -154,16 +154,24 @@ func (c *CAManager) setState(newState caState, validateState bool) (caState, err
|
||||||
state := c.state
|
state := c.state
|
||||||
|
|
||||||
if !validateState ||
|
if !validateState ||
|
||||||
state == caStateInitialized ||
|
(state == caStateInitialized && newState != caStateInitializing) ||
|
||||||
(state == caStateUninitialized && newState == caStateInitializing) ||
|
(state == caStateUninitialized && newState == caStateInitializing) ||
|
||||||
(state == caStateUninitialized && newState == caStateReconfig) {
|
(state == caStateUninitialized && newState == caStateReconfig) {
|
||||||
c.state = newState
|
c.state = newState
|
||||||
} else {
|
} else {
|
||||||
return state, fmt.Errorf("CA is already in state %q", state)
|
return state, &caStateError{Current: state}
|
||||||
}
|
}
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type caStateError struct {
|
||||||
|
Current caState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *caStateError) Error() string {
|
||||||
|
return fmt.Sprintf("CA is already in state %q", e.Current)
|
||||||
|
}
|
||||||
|
|
||||||
// setPrimaryRoots updates the most recently seen roots from the primary.
|
// setPrimaryRoots updates the most recently seen roots from the primary.
|
||||||
func (c *CAManager) setPrimaryRoots(newRoots structs.IndexedCARoots) error {
|
func (c *CAManager) setPrimaryRoots(newRoots structs.IndexedCARoots) error {
|
||||||
c.stateLock.Lock()
|
c.stateLock.Lock()
|
||||||
|
@ -360,12 +368,12 @@ func (c *CAManager) InitializeCA() (reterr error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state before doing anything else.
|
// Update the state before doing anything else.
|
||||||
oldState, err := c.setState(caStateInitializing, true)
|
_, err := c.setState(caStateInitializing, true)
|
||||||
// if we were already in the initialized state then there is nothing to be done.
|
var errCaState *caStateError
|
||||||
if oldState == caStateInitialized {
|
switch {
|
||||||
|
case errors.As(err, &errCaState) && errCaState.Current == caStateInitialized:
|
||||||
return nil
|
return nil
|
||||||
}
|
case err != nil:
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue