package checker import ( "context" "fmt" sdk "git.happydns.org/checker-sdk-go/checker" ) // issue is a rule-internal description of a failed test. Rules return a // slice of issues from their check func; Evaluate converts them to // sdk.CheckState. type issue struct { Severity sdk.Status // StatusInfo / StatusWarn / StatusCrit Message string Hint string // remediation hint; surfaced as Meta["hint"] Subject string // optional; overrides default data.QueriedOwner } // ruleFunc consumes the facts + runtime options and returns zero or more // issues. No issues means the test passed. type ruleFunc func(d *EmailKeyData, opts sdk.CheckerOptions) []issue // rule is a data-driven CheckRule. All per-test rules share this type; // only name / description / applicable kinds / options / check differ. type rule struct { name string description string okMessage string // message for StatusOK returns kinds []string // applicable kinds; empty = both options sdk.CheckerOptionsDocumentation // per-rule options check ruleFunc } func (r *rule) Name() string { return r.name } func (r *rule) Description() string { return r.description } func (r *rule) Options() sdk.CheckerOptionsDocumentation { return r.options } func (r *rule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState { var data EmailKeyData if err := obs.Get(ctx, ObservationKey, &data); err != nil { return []sdk.CheckState{{ Status: sdk.StatusError, Message: fmt.Sprintf("Failed to read observation %q: %v", ObservationKey, err), Code: "openpgpkey_observation_error", }} } if len(r.kinds) > 0 && !containsString(r.kinds, data.Kind) { return []sdk.CheckState{{ Status: sdk.StatusUnknown, Message: fmt.Sprintf("Not applicable for %s records.", data.Kind), Code: r.name, Subject: data.QueriedOwner, }} } issues := r.check(&data, opts) if len(issues) == 0 { msg := r.okMessage if msg == "" { msg = "Check passed." } return []sdk.CheckState{{ Status: sdk.StatusOK, Message: msg, Code: r.name, Subject: data.QueriedOwner, }} } states := make([]sdk.CheckState, 0, len(issues)) for _, iss := range issues { subject := iss.Subject if subject == "" { subject = data.QueriedOwner } var meta map[string]any if iss.Hint != "" { meta = map[string]any{"hint": iss.Hint} } states = append(states, sdk.CheckState{ Status: iss.Severity, Message: iss.Message, Code: r.name, Subject: subject, Meta: meta, }) } return states } // Rules returns the full set of per-test rules for this checker. func Rules() []sdk.CheckRule { out := make([]sdk.CheckRule, len(allRules)) for i := range allRules { out[i] = allRules[i] } return out } func containsString(hay []string, needle string) bool { for _, v := range hay { if v == needle { return true } } return false }