package engine import ( "errors" "fmt" "jarl/internal/bind" "jarl/internal/validate" ) // ErrorKind classifies engine errors (the API maps them to HTTP status // codes). type ErrorKind string const ( KindBadRequest ErrorKind = "bad_request" // malformed or invalid input KindForbidden ErrorKind = "forbidden" // permission denied KindNotFound ErrorKind = "not_found" // object does not exist KindConflict ErrorKind = "conflict" // concurrent change, wrong state KindValidation ErrorKind = "validation_failed" // the resulting config has errors KindBIND ErrorKind = "bind_failed" // named-checkconf or rndc failed KindDrift ErrorKind = "drift" // files were changed outside Jarl KindNotAdopted ErrorKind = "not_adopted" // named does not load Jarl's config yet ) // Error is an engine error with details for the caller. type Error struct { Kind ErrorKind `json:"code"` Message string `json:"message"` OpSeq int `json:"op,omitempty"` // the operation that failed // OpSummary describes that operation, so people can find it in the // changeset (record IDs mean little to them). OpSummary string `json:"op_summary,omitempty"` Problems []validate.Problem `json:"problems,omitempty"` Check []CheckMessage `json:"check,omitempty"` Diff string `json:"diff,omitempty"` } func (e *Error) Error() string { if e.OpSeq > 0 && e.OpSummary != "" { return fmt.Sprintf("operation %d (%s): %s", e.OpSeq, e.OpSummary, e.Message) } if e.OpSeq > 0 { return fmt.Sprintf("operation %d: %s", e.OpSeq, e.Message) } return e.Message } func errf(kind ErrorKind, format string, args ...any) *Error { return &Error{Kind: kind, Message: fmt.Sprintf(format, args...)} } // AsError returns err as *Error, if it is one. func AsError(err error) (*Error, bool) { var e *Error ok := errors.As(err, &e) return e, ok } // CheckMessage is a named-checkconf message mapped back to the Jarl object // that produced the offending line. type CheckMessage struct { bind.Message ObjectType string `json:"object_type,omitempty"` ObjectID int64 `json:"object_id,omitempty"` Object string `json:"object,omitempty"` }