Resolvers¶
Configuration often needs to pull values from different sources: environment variables, other files, HTTP endpoints, cloud services, or even other parts of the configuration itself. This is where resolvers come in.
What Are Resolvers?¶
A resolver is a plugin that knows how to fetch a value from a specific source. When you write something like:
The env part is the resolver name, and DB_PASSWORD is the argument to that resolver. HoloConf sees this syntax and calls the env resolver to fetch the value.
Let's see a simple example:
Resolver Syntax¶
All resolvers use the same syntax:
Breaking this down:
${...}- Marks this as interpolationresolver- The resolver name (likeenv,file,http)argument- What to fetch (like a variable name, file path, or URL)option=value- Optional parameters (likedefault,sensitive,timeout)
Framework-Level Options¶
Some options work with ALL resolvers, not just specific ones:
default - Fallback Values¶
If the resolver can't find the value, use this instead:
sensitive - Automatic Redaction¶
Mark values that should never appear in logs or dumps:
Nested Defaults - Fallback Chains¶
Default values can themselves use resolvers, creating fallback chains:
api:
# Try PRIMARY_URL, fall back to SECONDARY_URL, then to localhost
url: ${env:PRIMARY_URL,default=${env:SECONDARY_URL,default=http://localhost:8000}}
import os
from holoconf import Config
# Neither variable set - uses final default
config = Config.load("config.yaml")
url = config.api.url
print(f"URL: {url}")
# URL: http://localhost:8000
# Only secondary set - uses secondary
os.environ["SECONDARY_URL"] = "http://backup.example.com"
config = Config.load("config.yaml")
url = config.api.url
print(f"URL: {url}")
# URL: http://backup.example.com
Lazy Evaluation
Default values are only evaluated if needed. If PRIMARY_URL is set, HoloConf never even looks at SECONDARY_URL or the final default.
Lazy Resolution¶
Here's something important: resolvers are invoked lazily - values are only resolved when you access them, not when the configuration is loaded.
expensive:
data: ${https:slow-api.example.com/data} # Not fetched during load
cached:
value: ${env:CACHE_KEY} # Not read during load
This makes HoloConf faster and more flexible: - Values you don't access aren't resolved - Default values are only evaluated if the primary resolver fails - You can load configuration without requiring all resources to be available
Available Resolvers¶
HoloConf provides several built-in resolvers:
Core Resolvers¶
Always available, no extra installation needed:
- env - Environment variables
- Self-references - Reference other config values (absolute and relative paths)
- file - Include content from files
- http/https - Fetch from HTTP endpoints
AWS Resolvers¶
Requires pip install holoconf-aws:
Custom Resolvers¶
You can create your own resolvers to integrate with any data source:
- Custom Resolvers Guide - Learn how to write your own
Quick Reference¶
Here's a handy table of the most common resolver patterns:
| Syntax | Description | Example |
|---|---|---|
${env:VAR} |
Environment variable | ${env:DATABASE_URL} |
${env:VAR,default=value} |
With default | ${env:PORT,default=8080} |
${env:VAR,sensitive=true} |
Mark as sensitive | ${env:API_KEY,sensitive=true} |
${path.to.value} |
Self-reference (absolute) | ${database.host} |
${.sibling} |
Self-reference (relative) | ${.port} |
${..parent.value} |
Self-reference (parent) | ${..shared.timeout} |
${file:path} |
Include file content | ${file:./secrets.yaml} |
${http:url} |
Fetch from HTTP (auto-prepends http://) | ${http:api.example.com/settings} |
${https:url} |
Fetch from HTTPS (auto-prepends https://) | ${https:config.example.com/settings} |
${ssm:/path} |
AWS SSM Parameter | ${ssm:/app/prod/db-password} |
\${literal} |
Escape interpolation | \${not_interpolated} |
What You've Learned¶
You now understand:
- What resolvers are and how they work
- The
${resolver:argument,option=value}syntax - Framework-level options:
defaultandsensitive - Nested defaults for fallback chains
- Lazy resolution behavior
- What resolvers are available
Next Steps¶
Now dive into specific resolver types:
- Core Resolvers - Environment variables, self-references, file includes, HTTP fetching
- AWS Resolvers - SSM, CloudFormation, S3 integration
- Custom Resolvers - Write your own resolvers
Or continue with other topics:
- Merging - Combine multiple configuration files
- Validation - Use JSON Schema to catch configuration errors
See Also¶
- ADR-002 Resolver Architecture - Design rationale for resolvers
- ADR-011 Interpolation Syntax - Technical details
- FEAT-002 Core Resolvers - Full resolver specification