From 40baf981595f3a38c926ca5424698a50af25f03d Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Thu, 5 Aug 2021 14:51:19 -0400 Subject: [PATCH] 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 --- .changelog/10630.txt | 3 +++ agent/consul/leader_connect_ca.go | 24 ++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 .changelog/10630.txt 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 }