Skip to content

Commit 57a7668

Browse files
committed
feat: Evaluate state based on priority
1 parent 1fd22c2 commit 57a7668

File tree

4 files changed

+45
-11
lines changed

4 files changed

+45
-11
lines changed

config/config.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,26 +517,37 @@ func ValidateStatesConfig(config *Config) error { // TODO#227 Add tests
517517
}
518518
}
519519

520-
// Validate custom states TODO#227 Validate that priorities don't
520+
// Validate custom states
521521
stateNames := make(map[string]bool)
522+
statePriorities := make(map[int]string)
522523
for _, state := range config.States {
523524
// Check for duplicate state names
524525
if stateNames[state.Name] {
525526
return fmt.Errorf("duplicate state name: %s", state.Name)
526527
}
527528
stateNames[state.Name] = true
529+
530+
// Check for duplicate state priorities
531+
if existingState, exists := statePriorities[state.Priority]; exists {
532+
return fmt.Errorf("priority of state '%s' (%d) conflicts with state '%s'", state.Name, state.Priority, existingState)
533+
}
534+
statePriorities[state.Priority] = state.Name
535+
528536
// Validate the state configuration
529537
if err := state.ValidateAndSetDefaults(); err != nil {
530538
return fmt.Errorf("invalid state '%s': %w", state.Name, err)
531539
}
532540
}
533-
logr.Infof("[config.ValidateStatesConfig] Validated %d state(s)", len(config.States))
541+
logr.Infof("[config.ValidateStatesConfig] Validated %d state(s) (%d custom)", len(config.States), len(config.States)-len(defaultStates))
534542
return nil
535543
}
536544

537545
func ValidateEndpointsConfig(config *Config) error {
538-
duplicateValidationMap := make(map[string]bool)
546+
// Set state configuration for all endpoints
547+
endpoint.SetStateConfig(config.States)
548+
539549
// Validate endpoints
550+
duplicateValidationMap := make(map[string]bool)
540551
for _, ep := range config.Endpoints {
541552
logr.Debugf("[config.ValidateEndpointsConfig] Validating endpoint with key %s", ep.Key())
542553
if endpointKey := ep.Key(); duplicateValidationMap[endpointKey] {
@@ -549,6 +560,7 @@ func ValidateEndpointsConfig(config *Config) error {
549560
}
550561
}
551562
logr.Infof("[config.ValidateEndpointsConfig] Validated %d endpoints", len(config.Endpoints))
563+
552564
// Validate external endpoints
553565
for _, ee := range config.ExternalEndpoints {
554566
logr.Debugf("[config.ValidateEndpointsConfig] Validating external endpoint '%s'", ee.Key())
@@ -561,6 +573,7 @@ func ValidateEndpointsConfig(config *Config) error {
561573
return fmt.Errorf("invalid external endpoint %s: %w", ee.Key(), err)
562574
}
563575
}
576+
564577
logr.Infof("[config.ValidateEndpointsConfig] Validated %d external endpoints", len(config.ExternalEndpoints))
565578
return nil
566579
}

config/endpoint/condition.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ func (c Condition) evaluate(result *Result, dontResolveFailedConditions bool, co
3838
condition := string(c)
3939
success := false
4040

41-
var linkedState string
41+
var linkedStateName string
4242
if strings.Contains(condition, "::") {
4343
conditionParts := strings.Split(condition, "::")
4444
if len(conditionParts) != 2 { // TODO#227 Not sure if this makes sense. Checking that it is 2 or more should be enough. Then there is no character restriction in the remaining condition.
4545
result.AddError(fmt.Sprintf("invalid linked state syntax: %s", condition))
4646
return false
4747
}
48-
linkedState = conditionParts[0]
48+
linkedStateName = conditionParts[0]
4949
condition = conditionParts[1]
5050
}
5151

@@ -93,7 +93,8 @@ func (c Condition) evaluate(result *Result, dontResolveFailedConditions bool, co
9393
if !success {
9494
//logr.Debugf("[Condition.evaluate] Condition '%s' did not succeed because '%s' is false", condition, condition)
9595
}
96-
result.ConditionResults = append(result.ConditionResults, &ConditionResult{Condition: conditionToDisplay, Success: success, LinkedState: linkedState})
96+
97+
result.ConditionResults = append(result.ConditionResults, &ConditionResult{Condition: conditionToDisplay, Success: success, LinkedStateName: linkedStateName})
9798
return success
9899
}
99100

config/endpoint/condition_result.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ type ConditionResult struct {
88
// Success whether the condition was met (successful) or not (failed)
99
Success bool `json:"success"`
1010

11-
// The state the condition is linked to
12-
LinkedState string `json:"-"`
11+
// Name of the state the condition is linked to
12+
LinkedStateName string `json:"-"`
1313
}

config/endpoint/endpoint.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ var (
7575
// This is because the free whois service we are using should not be abused, especially considering the fact that
7676
// the data takes a while to be updated.
7777
ErrInvalidEndpointIntervalForDomainExpirationPlaceholder = errors.New("the minimum interval for an endpoint with a condition using the " + DomainExpirationPlaceholder + " placeholder is 300s (5m)")
78+
79+
// State config
80+
states []*state.State
7881
)
7982

8083
// Endpoint is the configuration of a service to be monitored
@@ -152,6 +155,19 @@ type Endpoint struct {
152155
AlwaysRun bool `yaml:"always-run,omitempty"`
153156
}
154157

158+
func SetStateConfig(cfg []*state.State) {
159+
states = cfg
160+
}
161+
162+
func FindStateByName(name string) *state.State {
163+
for _, state := range states {
164+
if state.Name == name {
165+
return state
166+
}
167+
}
168+
return nil
169+
}
170+
155171
// IsEnabled returns whether the endpoint is enabled or not
156172
func (e *Endpoint) IsEnabled() bool {
157173
if e.Enabled == nil {
@@ -341,10 +357,14 @@ func (e *Endpoint) EvaluateHealthWithContext(context *gontext.Gontext) *Result {
341357
if result.Success {
342358
result.State = state.DefaultHealthyStateName
343359
} else { // Go over condition results to see if any of them has a specific state to set
360+
highestPrioritySeen := 0
344361
for _, conditionResult := range result.ConditionResults {
345-
if !conditionResult.Success && len(conditionResult.LinkedState) > 0 {
346-
result.State = conditionResult.LinkedState // TODO#227 Only set if no other state with higher priority has been set
347-
break
362+
if !conditionResult.Success && len(conditionResult.LinkedStateName) > 0 {
363+
linkedState := FindStateByName(conditionResult.LinkedStateName)
364+
if linkedState != nil && (linkedState.Priority > highestPrioritySeen) {
365+
highestPrioritySeen = linkedState.Priority
366+
result.State = conditionResult.LinkedStateName
367+
}
348368
}
349369
}
350370
if len(result.State) == 0 {

0 commit comments

Comments
 (0)