Skip to content

Commit 8566684

Browse files
author
srahul3
committed
Refactor session health check management and update related tests
1 parent 29ea0e5 commit 8566684

File tree

3 files changed

+114
-38
lines changed

3 files changed

+114
-38
lines changed

agent/consul/state/session.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ func (s *Store) SessionCreate(idx uint64, sess *structs.Session) error {
220220
// future.
221221

222222
// Call the session creation
223-
if err := sessionCreateTxn(tx, idx, sess); err != nil {
223+
if err := s.sessionCreateTxn(tx, idx, sess); err != nil {
224224
return err
225225
}
226226

@@ -230,7 +230,7 @@ func (s *Store) SessionCreate(idx uint64, sess *structs.Session) error {
230230
// sessionCreateTxn is the inner method used for creating session entries in
231231
// an open transaction. Any health checks registered with the session will be
232232
// checked for failing status. Returns any error encountered.
233-
func sessionCreateTxn(tx WriteTxn, idx uint64, sess *structs.Session) error {
233+
func (s *Store) sessionCreateTxn(tx WriteTxn, idx uint64, sess *structs.Session) error {
234234
// Check that we have a session ID
235235
if sess.ID == "" {
236236
return ErrMissingSessionID
@@ -271,7 +271,7 @@ func sessionCreateTxn(tx WriteTxn, idx uint64, sess *structs.Session) error {
271271
return fmt.Errorf("failed inserting session: %s", err)
272272
}
273273

274-
return nil
274+
return s.updateSessionCheck(tx, idx, sess, api.HealthPassing)
275275
}
276276

277277
// SessionGet is used to retrieve an active session from the state store.
@@ -450,11 +450,11 @@ func (s *Store) deleteSessionTxn(tx WriteTxn, idx uint64, sessionID string, entM
450450
}
451451

452452
// session invalidating the health-checks
453-
return s.markSessionCheckCritical(tx, idx, session)
453+
return s.updateSessionCheck(tx, idx, session, api.HealthCritical)
454454
}
455455

456-
// markSessionCheckCritical The method marks the health-checks associated with the session as critical
457-
func (s *Store) markSessionCheckCritical(tx WriteTxn, idx uint64, session *structs.Session) error {
456+
// updateSessionCheck The method updates the health-checks associated with the session
457+
func (s *Store) updateSessionCheck(tx WriteTxn, idx uint64, session *structs.Session, checkState string) error {
458458
// Find all checks for the given Node
459459
iter, err := tx.Get(tableChecks, indexNode, Query{Value: session.Node, EnterpriseMeta: session.EnterpriseMeta})
460460
if err != nil {
@@ -464,8 +464,13 @@ func (s *Store) markSessionCheckCritical(tx WriteTxn, idx uint64, session *struc
464464
for check := iter.Next(); check != nil; check = iter.Next() {
465465
if hc := check.(*structs.HealthCheck); hc.Type == "session" && hc.Definition.SessionName == session.Name {
466466
updatedCheck := hc.Clone()
467-
updatedCheck.Status = api.HealthCritical
468-
updatedCheck.Output = fmt.Sprintf("Session '%s' is invalid", session.Name)
467+
updatedCheck.Status = checkState
468+
switch {
469+
case checkState == api.HealthPassing:
470+
updatedCheck.Output = fmt.Sprintf("Session '%s' in force", session.ID)
471+
default:
472+
updatedCheck.Output = fmt.Sprintf("Session '%s' is invalid", session.ID)
473+
}
469474

470475
if err := s.ensureCheckTxn(tx, idx, true, updatedCheck); err != nil {
471476
return err

agent/consul/state/session_ce.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ func validateSessionChecksTxn(tx ReadTxn, session *structs.Session) error {
151151
}
152152

153153
// Verify that the check is not in critical state
154-
status := check.(*structs.HealthCheck).Status
155-
if status == api.HealthCritical {
156-
return fmt.Errorf("Check '%s' is in %s state", checkID, status)
154+
healthCheck := check.(*structs.HealthCheck)
155+
if healthCheck.Status == api.HealthCritical && healthCheck.Type != "session" {
156+
return fmt.Errorf("Check '%s' is in %s state", checkID, healthCheck.Status)
157157
}
158158
}
159159
return nil

agent/consul/state/session_test.go

Lines changed: 98 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,48 @@ func TestStateStore_Session_Invalidate_PreparedQuery_Delete(t *testing.T) {
962962
}
963963
}
964964

965-
func TestHealthCheck_SessionDestroy(t *testing.T) {
965+
func TestHealthCheck_SessionRegistrationFail(t *testing.T) {
966+
s := testStateStore(t)
967+
968+
var check *structs.HealthCheck
969+
// setup node
970+
testRegisterNode(t, s, 1, "foo-node")
971+
testRegisterCheckCustom(t, s, 1, "foo", func(chk *structs.HealthCheck) {
972+
chk.Node = "foo-node"
973+
chk.Type = "tll"
974+
chk.Status = api.HealthCritical
975+
chk.Definition = structs.HealthCheckDefinition{
976+
SessionName: "test-session",
977+
}
978+
check = chk
979+
})
980+
981+
// Ensure the index was not updated if nothing was destroyed.
982+
if idx := s.maxIndex("sessions"); idx != 0 {
983+
t.Fatalf("bad index: %d", idx)
984+
}
985+
986+
// Register a new session
987+
sess := &structs.Session{
988+
ID: testUUID(),
989+
Node: "foo-node",
990+
Name: "test-session",
991+
Checks: make([]types.CheckID, 0),
992+
}
993+
994+
sess.Checks = append(sess.Checks, check.CheckID)
995+
// assert the check is critical initially
996+
assertHealthCheckStatus(t, s, sess, check.CheckID, api.HealthCritical)
997+
998+
if err := s.SessionCreate(2, sess); err == nil {
999+
// expecting error: Check 'foo' is in critical state
1000+
t.Fatalf("expected error, got nil")
1001+
}
1002+
}
1003+
1004+
// Allow the session to be created even if the check is critical.
1005+
// This is mainly to discount the health check of type `session`
1006+
func TestHealthCheck_SessionRegistrationAllow(t *testing.T) {
9661007
s := testStateStore(t)
9671008

9681009
var check *structs.HealthCheck
@@ -971,7 +1012,7 @@ func TestHealthCheck_SessionDestroy(t *testing.T) {
9711012
testRegisterCheckCustom(t, s, 1, "foo", func(chk *structs.HealthCheck) {
9721013
chk.Node = "foo-node"
9731014
chk.Type = "session"
974-
chk.Status = api.HealthPassing
1015+
chk.Status = api.HealthCritical
9751016
chk.Definition = structs.HealthCheckDefinition{
9761017
SessionName: "test-session",
9771018
}
@@ -985,50 +1026,80 @@ func TestHealthCheck_SessionDestroy(t *testing.T) {
9851026

9861027
// Register a new session
9871028
sess := &structs.Session{
988-
ID: testUUID(),
989-
Node: "foo-node",
990-
Name: "test-session",
1029+
ID: testUUID(),
1030+
Node: "foo-node",
1031+
Name: "test-session",
1032+
Checks: make([]types.CheckID, 0),
9911033
}
1034+
1035+
sess.Checks = append(sess.Checks, check.CheckID)
1036+
// assert the check is critical initially
1037+
assertHealthCheckStatus(t, s, sess, check.CheckID, api.HealthCritical)
1038+
9921039
if err := s.SessionCreate(2, sess); err != nil {
993-
t.Fatalf("err: %s", err)
1040+
t.Fatalf("The system shall allow session to be created ignoring the session check is critical. err: %s", err)
9941041
}
1042+
}
9951043

996-
_, hc, err := s.ChecksInState(nil, api.HealthAny, structs.DefaultEnterpriseMetaInPartition(""), structs.DefaultPeerKeyword)
997-
if err != nil {
998-
t.Fatalf("err: %s", err)
999-
}
1000-
// iterate over checks and find the right one
1001-
found := false
1002-
for _, c := range hc {
1003-
if c.CheckID == check.CheckID && c.Status == api.HealthPassing {
1004-
found = true
1005-
break
1044+
func TestHealthCheck_Session(t *testing.T) {
1045+
s := testStateStore(t)
1046+
1047+
var check *structs.HealthCheck
1048+
// setup node
1049+
testRegisterNode(t, s, 1, "foo-node")
1050+
testRegisterCheckCustom(t, s, 1, "foo", func(chk *structs.HealthCheck) {
1051+
chk.Node = "foo-node"
1052+
chk.Type = "session"
1053+
chk.Status = api.HealthCritical
1054+
chk.Definition = structs.HealthCheckDefinition{
1055+
SessionName: "test-session",
10061056
}
1057+
check = chk
1058+
})
1059+
1060+
// Ensure the index was not updated if nothing was destroyed.
1061+
if idx := s.maxIndex("sessions"); idx != 0 {
1062+
t.Fatalf("bad index: %d", idx)
1063+
}
1064+
1065+
// Register a new session
1066+
sess := &structs.Session{
1067+
ID: testUUID(),
1068+
Node: "foo-node",
1069+
Name: "test-session",
10071070
}
1071+
// assert the check is critical initially
1072+
assertHealthCheckStatus(t, s, sess, check.CheckID, api.HealthCritical)
10081073

1009-
if !found {
1010-
t.Fatalf("check is expected to be passing")
1074+
if err := s.SessionCreate(2, sess); err != nil {
1075+
t.Fatalf("The system shall allow session to be created ignoring the session check is critical. err: %s", err)
10111076
}
1077+
// assert the check is critical after session creation
1078+
assertHealthCheckStatus(t, s, sess, check.CheckID, api.HealthPassing)
10121079

10131080
// Destroy the session.
10141081
if err := s.SessionDestroy(3, sess.ID, nil); err != nil {
10151082
t.Fatalf("err: %s", err)
10161083
}
1084+
// assert the check is critical after session destroy
1085+
assertHealthCheckStatus(t, s, sess, check.CheckID, api.HealthCritical)
1086+
}
10171087

1018-
_, hc, err = s.ChecksInState(nil, api.HealthAny, structs.DefaultEnterpriseMetaInPartition(""), structs.DefaultPeerKeyword)
1088+
func assertHealthCheckStatus(t *testing.T, s *Store, session *structs.Session, checkID types.CheckID, expectedStatus string) {
1089+
_, hc, err := s.NodeChecks(nil, session.Node, structs.DefaultEnterpriseMetaInPartition(""), structs.DefaultPeerKeyword)
10191090
if err != nil {
10201091
t.Fatalf("err: %s", err)
10211092
}
1022-
// iterate over checks and find the right one
1023-
found = false
1093+
// assert the check is healthy
10241094
for _, c := range hc {
1025-
if c.CheckID == check.CheckID && c.Status == api.HealthCritical {
1026-
found = true
1027-
break
1095+
if c.CheckID == checkID {
1096+
if c.Status != expectedStatus {
1097+
t.Fatalf("check is expected to be %s but actually it is %s", expectedStatus, c.Status)
1098+
} else {
1099+
return
1100+
}
10281101
}
10291102
}
10301103

1031-
if !found {
1032-
t.Fatalf("check is expected to be critical")
1033-
}
1104+
t.Fatalf("check %s, is not found", string(checkID))
10341105
}

0 commit comments

Comments
 (0)