Handlers
This document describes the handler contract, built-in handlers, adapter-style patterns,
and tips for extending and testing handlers implemented in src/azure_functions_doctor/handlers.py.
Purpose
Handlers connect rule definitions (assets/rules/*.json) to actual check logic. Rules are declarative
and handlers must follow this contract:
Handler contract (simplified)
- Input: rule: dict (full rule object), path: pathlib.Path (project root)
- Output: bool or HandlerResult (this project returns simple boolean/detail pairs)
- Failure mode: prefer returning False or logging details instead of raising exceptions
Handlers are registered in the HandlerRegistry and are mapped by the type field. Custom handlers
can be registered with the @handler.register("your_type") decorator.
Built-in handlers overview
Below are the main handlers included in this repository with example rules. For full implementations,
see src/azure_functions_doctor/handlers.py.
1) compare_version
- Description: compare versions (e.g., Python or Core Tools).
- Example rule:
json
{"type": "compare_version", "target": "python", "operator": ">=", "value": "3.9"}
2) file_exists
- Description: check whether a file exists.
- Example rule:
json
{"type": "file_exists", "target": "host.json"}
3) file_contains - Description: check whether a file contains a key or string (simple text or key path).
v2 adapter/utility handlers
These lightweight handlers are used by the v2 rule set (assets/rules/v2.json). They intentionally
use simple heuristics to catch common configuration issues.
- executable_exists
- Purpose: verify an executable is present on PATH (e.g.,
func). -
Condition example:
{ "target": "func" } -
any_of_exists
- Purpose: pass if any item in
targets: [ ... ]exists (supports env vars,host.json:<jsonpath>, or relative file paths). -
Condition example:
{ "targets": ["requirements.txt", "Pipfile"] } -
file_glob_check
- Purpose: search for files using glob patterns. Useful for detecting sensitive files
(e.g.,
.env,.pem) or artifacts. -
Condition example:
{ "patterns": ["**/.env", "**/*.pem"] } -
host_json_property
- Purpose: check the existence or value of a simple key path inside
host.json(e.g.,$.extensionBundle.id). -
Condition example:
{ "key": "$.extensionBundle" } -
binding_validation
- Purpose: lightweight validation of
function.jsonbindings (e.g., ensurehttpTriggerhasauthLevelandmethods). -
Goal: catch common typos or omissions without full schema validation.
-
cron_validation
- Purpose: heuristic checks for
timerTriggerschedule strings (allowing 5- or 6-field cron). - Goal: detect common formatting errors (wrong field count, empty fields, etc.).
Note: These handlers do not enforce full schemas. For strict validation, consider a custom handler using libraries like
croniterorjsonschema.
Adapter pattern guide
To reduce duplication and reuse logic across multiple rules, write adapter-style handlers. Core idea:
- Rule JSON defines only simple conditions (e.g.,
targets,patterns,key). - Handlers parse different input shapes (env vars, file paths, host.json keys) and delegate to shared check functions.
Example: any_of_exists loops through targets and tries the following per entry:
- environment variable ($ENV)
- host.json:<path> parsing
- relative file existence check
Pass condition: any target is found.
Writing custom handlers (quick example)
- Add a new function in
src/azure_functions_doctor/handlers.py. - Register the type with
@handler.register("my_custom"). - Use
"type": "my_custom"in the rule JSON.
Template:
# src/azure_functions_doctor/handlers.py
@handler.register("my_custom")
def _handle_my_custom(rule: dict, path: pathlib.Path) -> bool:
condition = rule.get("condition", {})
# ... check logic ...
return True # or False
Example rule:
{
"id": "check_my_custom",
"section": "custom",
"label": "My custom check",
"type": "my_custom",
"condition": {"key": "value"},
"hint": "Do X if missing"
}
Testing and debugging tips
- Unit tests: add happy-path and failure cases in
tests/test_handler.py. - Logging: use
loggingin handlers to explain failures; useful in verbose CLI mode. - Performance: for globbing or large scans, add filters to reduce search scope.
Example rule
{
"id": "no_env_files",
"section": "secrets",
"label": ".env files present",
"type": "file_glob_check",
"condition": { "patterns": ["**/.env"] },
"hint": "Remove secrets from repository or add to .gitignore"
}
Extension ideas
- Stronger JSONPath support: integrate
jsonpath-ngfor complex host.json queries. - Strict cron validation: validate expressions with
croniter. - Advanced binding checks: deep validation aligned with Azure Functions schemas.
For detailed API reference, see the Handlers section in docs/api.md.