diff --git a/.changelog/10630.txt b/.changelog/10630.txt new file mode 100644 index 000000000..15b029500 --- /dev/null +++ b/.changelog/10630.txt @@ -0,0 +1,3 @@ +```release-note:bug +ca: fixed a bug when ca provider fail and provider state is stuck in `INITIALIZING` state. +``` diff --git a/agent/consul/leader_connect_ca.go b/agent/consul/leader_connect_ca.go index aa17bf646..f9e357f79 100644 --- a/agent/consul/leader_connect_ca.go +++ b/agent/consul/leader_connect_ca.go @@ -141,7 +141,7 @@ func NewCAManager(delegate caServerDelegate, leaderRoutineManager *routine.Manag // setState attempts to update the CA state to the given state. // Valid state transitions are: // -// caStateInitialized -> +// caStateInitialized -> // caStateUninitialized -> caStateInitializing // caStateUninitialized -> caStateReconfig // @@ -154,16 +154,24 @@ func (c *CAManager) setState(newState caState, validateState bool) (caState, err state := c.state if !validateState || - state == caStateInitialized || + (state == caStateInitialized && newState != caStateInitializing) || (state == caStateUninitialized && newState == caStateInitializing) || (state == caStateUninitialized && newState == caStateReconfig) { c.state = newState } else { - return state, fmt.Errorf("CA is already in state %q", state) + return state, &caStateError{Current: state} } 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. func (c *CAManager) setPrimaryRoots(newRoots structs.IndexedCARoots) error { c.stateLock.Lock() @@ -360,12 +368,12 @@ func (c *CAManager) InitializeCA() (reterr error) { } // Update the state before doing anything else. - oldState, err := c.setState(caStateInitializing, true) - // if we were already in the initialized state then there is nothing to be done. - if oldState == caStateInitialized { + _, err := c.setState(caStateInitializing, true) + var errCaState *caStateError + switch { + case errors.As(err, &errCaState) && errCaState.Current == caStateInitialized: return nil - } - if err != nil { + case err != nil: return err }