mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 15:11:29 +00:00
7cb453a336
Mechanical reformat. The new 'gofmt drift' CI step (added in
ci-pipeline-cleanup Phase 4, commit 0f205a8) surfaced 111 files
with accumulated gofmt drift across cmd/, internal/, and deploy/test/.
Each file's diff is gofmt-standard: whitespace adjustments, intra-
group import sorting (alphabetical by import path within blank-line-
separated groups), and struct-tag column alignment. No semantic
changes — verified via 'git diff --ignore-all-space' which shows only
the line-position deltas from import reordering.
The gate stays in place after this commit. Going forward it catches
gofmt drift at PR time.
110 lines
4.3 KiB
Go
110 lines
4.3 KiB
Go
package domain
|
|
|
|
import "time"
|
|
|
|
// HealthStatus represents the current health state of a monitored endpoint.
|
|
type HealthStatus string
|
|
|
|
const (
|
|
HealthStatusHealthy HealthStatus = "healthy"
|
|
HealthStatusDegraded HealthStatus = "degraded"
|
|
HealthStatusDown HealthStatus = "down"
|
|
HealthStatusCertMismatch HealthStatus = "cert_mismatch"
|
|
HealthStatusUnknown HealthStatus = "unknown"
|
|
)
|
|
|
|
// IsValidHealthStatus checks if a health status string is valid.
|
|
func IsValidHealthStatus(s string) bool {
|
|
switch HealthStatus(s) {
|
|
case HealthStatusHealthy, HealthStatusDegraded, HealthStatusDown, HealthStatusCertMismatch, HealthStatusUnknown:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// EndpointHealthCheck represents a monitored TLS endpoint.
|
|
type EndpointHealthCheck struct {
|
|
ID string `json:"id"`
|
|
Endpoint string `json:"endpoint"`
|
|
CertificateID *string `json:"certificate_id,omitempty"`
|
|
NetworkScanTargetID *string `json:"network_scan_target_id,omitempty"`
|
|
ExpectedFingerprint string `json:"expected_fingerprint"`
|
|
ObservedFingerprint string `json:"observed_fingerprint"`
|
|
Status HealthStatus `json:"status"`
|
|
ConsecutiveFailures int `json:"consecutive_failures"`
|
|
ResponseTimeMs int `json:"response_time_ms"`
|
|
TLSVersion string `json:"tls_version"`
|
|
CipherSuite string `json:"cipher_suite"`
|
|
CertSubject string `json:"cert_subject"`
|
|
CertIssuer string `json:"cert_issuer"`
|
|
CertExpiry *time.Time `json:"cert_expiry,omitempty"`
|
|
LastCheckedAt *time.Time `json:"last_checked_at,omitempty"`
|
|
LastSuccessAt *time.Time `json:"last_success_at,omitempty"`
|
|
LastFailureAt *time.Time `json:"last_failure_at,omitempty"`
|
|
LastTransitionAt *time.Time `json:"last_transition_at,omitempty"`
|
|
FailureReason string `json:"failure_reason"`
|
|
DegradedThreshold int `json:"degraded_threshold"`
|
|
DownThreshold int `json:"down_threshold"`
|
|
CheckIntervalSecs int `json:"check_interval_seconds"`
|
|
Enabled bool `json:"enabled"`
|
|
Acknowledged bool `json:"acknowledged"`
|
|
AcknowledgedBy string `json:"acknowledged_by,omitempty"`
|
|
AcknowledgedAt *time.Time `json:"acknowledged_at,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// TransitionStatus computes the new health status based on the probe result.
|
|
// Returns the new status and whether a transition occurred.
|
|
func (h *EndpointHealthCheck) TransitionStatus(probeSuccess bool, observedFingerprint string) (HealthStatus, bool) {
|
|
oldStatus := h.Status
|
|
var newStatus HealthStatus
|
|
|
|
if probeSuccess {
|
|
if h.ExpectedFingerprint != "" && observedFingerprint != h.ExpectedFingerprint {
|
|
newStatus = HealthStatusCertMismatch
|
|
} else {
|
|
newStatus = HealthStatusHealthy
|
|
}
|
|
} else {
|
|
// Increment failures for next calculation (caller will update h.ConsecutiveFailures)
|
|
failures := h.ConsecutiveFailures + 1
|
|
if failures >= h.DownThreshold {
|
|
newStatus = HealthStatusDown
|
|
} else if failures >= h.DegradedThreshold {
|
|
newStatus = HealthStatusDegraded
|
|
} else {
|
|
// Keep current status during initial failures before threshold
|
|
// Unless we were in an error state, transition to degraded after first failure
|
|
if h.Status == HealthStatusUnknown || h.Status == HealthStatusHealthy {
|
|
newStatus = HealthStatusHealthy // still considered healthy during grace period
|
|
} else {
|
|
newStatus = h.Status
|
|
}
|
|
}
|
|
}
|
|
|
|
return newStatus, newStatus != oldStatus
|
|
}
|
|
|
|
// HealthHistoryEntry represents a single probe record.
|
|
type HealthHistoryEntry struct {
|
|
ID string `json:"id"`
|
|
HealthCheckID string `json:"health_check_id"`
|
|
Status string `json:"status"`
|
|
ResponseTimeMs int `json:"response_time_ms"`
|
|
Fingerprint string `json:"fingerprint"`
|
|
FailureReason string `json:"failure_reason"`
|
|
CheckedAt time.Time `json:"checked_at"`
|
|
}
|
|
|
|
// HealthCheckSummary contains aggregate counts by status.
|
|
type HealthCheckSummary struct {
|
|
Healthy int `json:"healthy"`
|
|
Degraded int `json:"degraded"`
|
|
Down int `json:"down"`
|
|
CertMismatch int `json:"cert_mismatch"`
|
|
Unknown int `json:"unknown"`
|
|
Total int `json:"total"`
|
|
}
|