Providers and endpoints
Some tasks need to reach something alive while they run: a database for a migration, a SOCKS proxy into a private cluster, a throwaway Redis for an end-to-end test. The contract declares that need with a single type:
dependencies: db: type: endpoint/tcpThe worker receives an address through the variable the implementation maps —
DB (host:port), plus DB_HOST and DB_PORT split for it — and nothing
else. It cannot tell where the address came from, and that is the point: the
task never changes between environments; only the wiring does.
Three origins, one dependency
Section titled “Three origins, one dependency”# A routable address — production, a LAN service, anything already reachable.db: "10.20.0.5:5432"
# THIS machine's own service — dev only. `localhost` inside a container is the# container; `host:` rides the engine back to your machine.db: host:5432
# A provider — a service container that lives and dies with the step.db: provider: techlite/cloud-sql-proxy@^1.0.0 inputs: { instance: "project:region:db" } dependencies: gcpCredential: ${env.OREN_GCP_CREDENTIAL}Put the split in per-environment properties: the dev
file wires host:5432, the CI file wires a provider, production wires the
real address — and oren.yaml does not change a line.
What a provider is
Section titled “What a provider is”A provider is a container bound to the step’s network, started before the worker and killed with it. Its open port is the readiness gate: the step only starts once the service accepts connections. Nothing survives the step — a throwaway database really is thrown away.
The reference can be:
- published —
provider: techlite/gke-iap-proxy@^1.0.0, resolved from the catalogue byoren installlike any task; - a local document —
provider: local/my-proxy@^1.0.0, read from.oren/registry/*.provider.yamlin the project; - inline —
provider: { image: redis:7, port: 6379 }, identity by digest, for the case too small to deserve a document.
A provider declares its own dependencies — the credential the tunnel needs, which the task’s contract never mentions — and its inputs parameterize the path to the service (which bastion, which zone). Both use the same grammar a step uses.
Composing the address
Section titled “Composing the address”Only endpoint dependencies are readable in expressions, because their value is the one thing the pipeline both needs and rightfully owns:
inputs: databaseUrl: "postgres://app@${dependencies.db.host}:${dependencies.db.port}/app"address, host and port re-read the wiring — with a literal you get what
you wrote; with a provider, the address the runner assigned.
What the authorisation covers
Section titled “What the authorisation covers”The consent gate prices the whole arrangement: the provider’s image (pinned to
a digest by oren install, like the worker’s), the dependencies the provider
itself consumes, and — for host: — the fact that the step reaches this
machine’s services. Swapping any of it invalidates the grant, exactly as
swapping the worker’s image does.
Seeing it
Section titled “Seeing it”oren explain <pipeline> -o pipeline.htmldraws the pipeline as cards — each step’s dependencies, inputs and outputs,
the provider beside the step that consumes it, and the wires between them,
with a padlock wherever a secret travels. oren trace draws the last run as a
waterfall. See the CLI reference.