Skip to content

Commit d0c2fb5

Browse files
committed
try out auth detection
1 parent b29fb4a commit d0c2fb5

File tree

2 files changed

+203
-10
lines changed

2 files changed

+203
-10
lines changed

controllers/om/automation_status.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,25 @@ func checkAutomationStatusIsGoal(as *AutomationStatus, relevantProcesses []strin
8585

8686
goalsNotAchievedMap := map[string]int{}
8787
goalsAchievedMap := map[string]int{}
88+
authTransitionInProgress := map[string]string{}
89+
8890
for _, p := range as.Processes {
8991
if !stringutil.Contains(relevantProcesses, p.Name) {
9092
continue
9193
}
9294
if p.LastGoalVersionAchieved == as.GoalVersion {
9395
goalsAchievedMap[p.Name] = p.LastGoalVersionAchieved
96+
97+
// Check if authentication transitions are in the current plan
98+
// If a process has reached goal version but still has auth-related moves in plan,
99+
// it means authentication transition is likely in progress
100+
// The plan contains non-completed move names from the API
101+
for _, move := range p.Plan {
102+
if isAuthenticationTransitionMove(move) {
103+
authTransitionInProgress[p.Name] = move
104+
break
105+
}
106+
}
94107
} else {
95108
goalsNotAchievedMap[p.Name] = p.LastGoalVersionAchieved
96109
}
@@ -103,6 +116,18 @@ func checkAutomationStatusIsGoal(as *AutomationStatus, relevantProcesses []strin
103116
goalsAchievedMsgList := slices.Collect(maps.Keys(goalsAchievedMap))
104117
sort.Strings(goalsAchievedMsgList)
105118

119+
// Check if any authentication transitions are in progress
120+
if len(authTransitionInProgress) > 0 {
121+
var authTransitionMsgList []string
122+
for processName, step := range authTransitionInProgress {
123+
authTransitionMsgList = append(authTransitionMsgList, fmt.Sprintf("%s:%s", processName, step))
124+
}
125+
log.Infow("Authentication transitions still in progress, waiting for completion",
126+
"processes", authTransitionMsgList)
127+
return false, fmt.Sprintf("authentication transitions in progress for %d processes: %s",
128+
len(authTransitionInProgress), authTransitionMsgList)
129+
}
130+
106131
if len(goalsNotAchievedMap) > 0 {
107132
return false, fmt.Sprintf("%d processes waiting to reach automation config goal state (version=%d): %s, %d processes reached goal state: %s",
108133
len(goalsNotAchievedMap), as.GoalVersion, goalsNotAchievedMsgList, len(goalsAchievedMsgList), goalsAchievedMsgList)
@@ -113,17 +138,37 @@ func checkAutomationStatusIsGoal(as *AutomationStatus, relevantProcesses []strin
113138
}
114139
}
115140

141+
// isAuthenticationTransitionMove returns true if the given move is related to authentication transitions
142+
func isAuthenticationTransitionMove(move string) bool {
143+
// Authentication-related moves that can appear in the automation plan
144+
// Based on analysis of failed test showing auth transition in progress
145+
authMoves := []string{
146+
"RestartMongod", // Often involved in authentication mode changes
147+
"UpdateAuth", // Direct authentication update moves
148+
"UpdateConfig", // Configuration updates that may include auth changes
149+
"WaitForHealthy", // Waiting for cluster health after auth changes
150+
"InitiateReplSet", // ReplicaSet initialization with authentication
151+
}
152+
153+
for _, authMove := range authMoves {
154+
if move == authMove {
155+
return true
156+
}
157+
}
158+
return false
159+
}
160+
116161
func areAnyAgentsInKubeUpgradeMode(as *AutomationStatus, relevantProcesses []string, log *zap.SugaredLogger) bool {
117162
for _, p := range as.Processes {
118163
if !stringutil.Contains(relevantProcesses, p.Name) {
119164
continue
120165
}
121-
for _, plan := range p.Plan {
166+
for _, planStep := range p.Plan {
122167
// This means the following:
123168
// - the cluster is in static architecture
124169
// - the agents are in a dedicated upgrade process, waiting for their binaries to be replaced by kubernetes
125170
// - this can only happen if the statefulset is ready, therefore we are returning ready here
126-
if plan == automationAgentKubeUpgradePlan {
171+
if planStep == automationAgentKubeUpgradePlan {
127172
log.Debug("cluster is in changeVersionKube mode, returning the agent is ready.")
128173
return true
129174
}

controllers/om/automation_status_test.go

Lines changed: 156 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ func TestCheckAutomationStatusIsGoal(t *testing.T) {
2525
Processes: []ProcessStatus{
2626
{
2727
Name: "a",
28-
Plan: []string{"FCV"},
28+
Plan: []string{},
2929
LastGoalVersionAchieved: 1,
3030
},
3131
{
3232
Name: "b",
33-
Plan: []string{"FCV"},
33+
Plan: []string{},
3434
LastGoalVersionAchieved: 1,
3535
},
3636
},
@@ -48,12 +48,12 @@ func TestCheckAutomationStatusIsGoal(t *testing.T) {
4848
Processes: []ProcessStatus{
4949
{
5050
Name: "a",
51-
Plan: []string{"FCV"},
51+
Plan: []string{},
5252
LastGoalVersionAchieved: 0,
5353
},
5454
{
5555
Name: "b",
56-
Plan: []string{"FCV"},
56+
Plan: []string{},
5757
LastGoalVersionAchieved: 1,
5858
},
5959
},
@@ -70,12 +70,12 @@ func TestCheckAutomationStatusIsGoal(t *testing.T) {
7070
Processes: []ProcessStatus{
7171
{
7272
Name: "a",
73-
Plan: []string{"FCV", "something-else"},
73+
Plan: []string{"something-else"},
7474
LastGoalVersionAchieved: 0,
7575
},
7676
{
7777
Name: "b",
78-
Plan: []string{"FCV", automationAgentKubeUpgradePlan},
78+
Plan: []string{automationAgentKubeUpgradePlan},
7979
LastGoalVersionAchieved: 1,
8080
},
8181
},
@@ -93,12 +93,12 @@ func TestCheckAutomationStatusIsGoal(t *testing.T) {
9393
Processes: []ProcessStatus{
9494
{
9595
Name: "a",
96-
Plan: []string{"X", "Y"},
96+
Plan: []string{},
9797
LastGoalVersionAchieved: 1,
9898
},
9999
{
100100
Name: "b",
101-
Plan: []string{"Y", "Z"},
101+
Plan: []string{},
102102
LastGoalVersionAchieved: 1,
103103
},
104104
},
@@ -119,3 +119,151 @@ func TestCheckAutomationStatusIsGoal(t *testing.T) {
119119
})
120120
}
121121
}
122+
123+
func TestCheckAutomationStatusIsGoal_AuthenticationTransitions(t *testing.T) {
124+
logger := zap.NewNop().Sugar()
125+
126+
tests := []struct {
127+
name string
128+
automationStatus *AutomationStatus
129+
relevantProcesses []string
130+
expectedReady bool
131+
expectedMessage string
132+
}{
133+
{
134+
name: "should wait for UpdateAuth move to complete",
135+
automationStatus: &AutomationStatus{
136+
GoalVersion: 5,
137+
Processes: []ProcessStatus{
138+
{
139+
Name: "rs0_0",
140+
LastGoalVersionAchieved: 5,
141+
Plan: []string{"UpdateAuth"},
142+
},
143+
},
144+
},
145+
relevantProcesses: []string{"rs0_0"},
146+
expectedReady: false,
147+
expectedMessage: "authentication transitions in progress for 1 processes",
148+
},
149+
{
150+
name: "should wait for InitiateReplSet move to complete",
151+
automationStatus: &AutomationStatus{
152+
GoalVersion: 3,
153+
Processes: []ProcessStatus{
154+
{
155+
Name: "rs0_0",
156+
LastGoalVersionAchieved: 3,
157+
Plan: []string{"InitiateReplSet"},
158+
},
159+
},
160+
},
161+
relevantProcesses: []string{"rs0_0"},
162+
expectedReady: false,
163+
expectedMessage: "authentication transitions in progress for 1 processes",
164+
},
165+
{
166+
name: "should be ready when authentication transitions are complete",
167+
automationStatus: &AutomationStatus{
168+
GoalVersion: 5,
169+
Processes: []ProcessStatus{
170+
{
171+
Name: "rs0_0",
172+
LastGoalVersionAchieved: 5,
173+
Plan: []string{}, // Empty plan means all moves completed
174+
},
175+
},
176+
},
177+
relevantProcesses: []string{"rs0_0"},
178+
expectedReady: true,
179+
expectedMessage: "processes that reached goal state: [rs0_0]",
180+
},
181+
{
182+
name: "should wait for multiple processes with auth transitions",
183+
automationStatus: &AutomationStatus{
184+
GoalVersion: 7,
185+
Processes: []ProcessStatus{
186+
{
187+
Name: "rs0_0",
188+
LastGoalVersionAchieved: 7,
189+
Plan: []string{}, // This process completed
190+
},
191+
{
192+
Name: "rs0_1",
193+
LastGoalVersionAchieved: 7,
194+
Plan: []string{"RestartMongod"}, // Auth-related move in progress
195+
},
196+
},
197+
},
198+
relevantProcesses: []string{"rs0_0", "rs0_1"},
199+
expectedReady: false,
200+
expectedMessage: "authentication transitions in progress for 1 processes",
201+
},
202+
{
203+
name: "should ignore non-authentication moves in progress",
204+
automationStatus: &AutomationStatus{
205+
GoalVersion: 4,
206+
Processes: []ProcessStatus{
207+
{
208+
Name: "rs0_0",
209+
LastGoalVersionAchieved: 4,
210+
Plan: []string{"SomeOtherMove"}, // Non-auth move
211+
},
212+
},
213+
},
214+
relevantProcesses: []string{"rs0_0"},
215+
expectedReady: true,
216+
expectedMessage: "processes that reached goal state: [rs0_0]",
217+
},
218+
}
219+
220+
for _, tt := range tests {
221+
t.Run(tt.name, func(t *testing.T) {
222+
ready, message := checkAutomationStatusIsGoal(
223+
tt.automationStatus,
224+
tt.relevantProcesses,
225+
logger,
226+
)
227+
228+
assert.Equal(t, tt.expectedReady, ready, "Ready state should match expected")
229+
assert.Contains(t, message, tt.expectedMessage, "Message should contain expected text")
230+
231+
if tt.expectedReady {
232+
t.Logf("✅ Process correctly marked as ready: %s", message)
233+
} else {
234+
t.Logf("⏳ Process correctly waiting for auth transition: %s", message)
235+
}
236+
})
237+
}
238+
}
239+
240+
func TestIsAuthenticationTransitionMove(t *testing.T) {
241+
authMoves := []string{
242+
"RestartMongod",
243+
"UpdateAuth",
244+
"UpdateConfig",
245+
"WaitForHealthy",
246+
"InitiateReplSet",
247+
}
248+
249+
nonAuthMoves := []string{
250+
"SomeOtherMove",
251+
"CreateIndex",
252+
"DropCollection",
253+
"BackupDatabase",
254+
}
255+
256+
for _, move := range authMoves {
257+
t.Run("auth_move_"+move, func(t *testing.T) {
258+
assert.True(t, isAuthenticationTransitionMove(move),
259+
"Move %s should be recognized as authentication transition", move)
260+
})
261+
}
262+
263+
for _, move := range nonAuthMoves {
264+
t.Run("non_auth_move_"+move, func(t *testing.T) {
265+
assert.False(t, isAuthenticationTransitionMove(move),
266+
"Move %s should not be recognized as authentication transition", move)
267+
})
268+
}
269+
}

0 commit comments

Comments
 (0)