@@ -31,30 +31,43 @@ func parseBouncersJSON(bouncerOutput string, computeStatus bool) ([]models.Bounc
3131 if ipAddr , err := jsonparser .GetString (value , "ip_address" ); err == nil {
3232 bouncer .IPAddress = ipAddr
3333 }
34- if valid , err := jsonparser .GetBoolean (value , "valid" ); err == nil {
35- bouncer .Valid = valid
36- }
37- if lastPull , err := jsonparser .GetString (value , "last_pull" ); err == nil {
38- for _ , layout := range []string {time .RFC3339Nano , time .RFC3339 } {
39- if t , err := time .Parse (layout , lastPull ); err == nil {
40- bouncer .LastPull = t
41- break
34+ // Parse timestamps with multiple format support
35+ parseTime := func (key string ) time.Time {
36+ if s , err := jsonparser .GetString (value , key ); err == nil {
37+ for _ , layout := range []string {time .RFC3339Nano , time .RFC3339 } {
38+ if t , err := time .Parse (layout , s ); err == nil {
39+ return t
40+ }
4241 }
4342 }
43+ return time.Time {}
4444 }
45+
46+ bouncer .LastPull = parseTime ("last_pull" )
47+ bouncer .CreatedAt = parseTime ("created_at" )
48+ bouncer .UpdatedAt = parseTime ("updated_at" )
49+
4550 if bouncerType , err := jsonparser .GetString (value , "type" ); err == nil {
4651 bouncer .Type = bouncerType
4752 }
4853 if version , err := jsonparser .GetString (value , "version" ); err == nil {
4954 bouncer .Version = version
5055 }
5156
57+ // A bouncer that exists in the list is valid by definition.
58+ // CrowdSec deletes revoked bouncers rather than marking them,
59+ // so the "revoked" and legacy "valid" fields are not reliable
60+ // indicators of actual connectivity (confirmed by CrowdSec team, see #47).
61+ bouncer .Valid = true
62+
5263 if computeStatus {
53- if ! bouncer .Valid {
54- bouncer .Status = "disconnected"
55- } else if bouncer .LastPull .IsZero () {
56- bouncer .Status = "pending" // valid key, never pulled yet
57- } else if time .Since (bouncer .LastPull ) <= 60 * time .Minute {
64+ lastActivity := bouncer .LastActivity ()
65+
66+ if ! lastActivity .IsZero () && time .Since (lastActivity ) <= 5 * time .Minute {
67+ bouncer .Status = "connected"
68+ } else if lastActivity .IsZero () {
69+ bouncer .Status = "registered" // enrolled but never pulled
70+ } else if time .Since (lastActivity ) <= 60 * time .Minute {
5871 bouncer .Status = "connected"
5972 } else {
6073 bouncer .Status = "stale"
@@ -99,7 +112,8 @@ func checkBouncersHealth(dockerClient *docker.Client, containerName string) mode
99112
100113 activeBouncers := 0
101114 for _ , b := range bouncers {
102- if b .Valid && time .Since (b .LastPull ) <= 60 * time .Minute {
115+ lastActivity := b .LastActivity ()
116+ if ! lastActivity .IsZero () && time .Since (lastActivity ) <= 60 * time .Minute {
103117 activeBouncers ++
104118 }
105119 }
0 commit comments