Write a secret resolver¶
Prerequisites · You have a placeholder syntax you want DataCoolie to recognise (e.g. vault:path/to/secret).
End state · Resolver registered, used automatically during resolve_secrets before dataflows execute.
Minimal resolver¶
from datacoolie.core.secret_resolver import BaseSecretResolver
class VaultResolver(BaseSecretResolver):
PREFIX = "vault:"
def matches(self, value: str) -> bool:
return isinstance(value, str) and value.startswith(self.PREFIX)
def resolve(self, value: str, provider) -> str:
key = value[len(self.PREFIX):]
# Any concrete BaseSecretProvider subclass works here, including the platform.
return provider.fetch_secret(source="vault", field=key)
Register¶
Usage from metadata¶
At runtime resolve_secrets scans every string in configure, finds the
resolver whose matches() returns True, and replaces the value with the
resolver's resolve() output. Fall-through values are untouched.
Provider vs resolver split¶
- Resolver — parses the placeholder string (e.g.
vault:prod/db). - Provider — fetches the actual secret from a backend.
The built-in EnvResolver is the exception that handles both ends
(env:FOO is resolved from os.environ["FOO"] by the resolver itself).
For anything more elaborate, have the resolver call into a
BaseSecretProvider.
See ADR-0002.