Documentation
¶
Overview ¶
Package provider defines the interface that both builtin and external providers implement.
A provider is responsible for executing one or more action types against its target system (a database, an HTTP API, a command shell). The engine evaluates HCL action bodies into plain cty values and hands providers a flat, fully-resolved attribute map, so providers never see hcl.Body or hcl.EvalContext directly.
The same interface is satisfied by builtins compiled into the orchard binary and by external subprocess providers (the stdio adapter lives in pkg/provider/external). That symmetry is intentional — it means the engine has one code path, and the same schema-driven validation covers every provider regardless of how it runs.
Index ¶
- Variables
- func BuiltinSources() []string
- func RegisterBuiltin(source string, factory BuiltinFactory)
- type ActionPlanner
- type BuiltinFactory
- type Capture
- type InverseOptions
- type Invocation
- type Plan
- type PlanConfigurer
- type Provider
- type PullOptions
- type Registry
- func (r *Registry) Close() error
- func (r *Registry) Configure(ctx context.Context, configs map[string]map[string]cty.Value) error
- func (r *Registry) Get(name string) (Provider, error)
- func (r *Registry) Names() []string
- func (r *Registry) PlanConfigure(ctx context.Context, configs map[string]map[string]cty.Value, ...) error
- func (r *Registry) Register(name string, p Provider) error
- func (r *Registry) SetBaseDir(dir string)
- func (r *Registry) ValidateConfigs(configs map[string]map[string]cty.Value) error
- type SchemaSource
- type Undoer
Constants ¶
This section is empty.
Variables ¶
var ErrNoSchema = errors.New("no schema to check against")
ErrNoSchema is returned (wrapped) by PlanAction when a provider has no schema to check an action against.
Functions ¶
func BuiltinSources ¶
func BuiltinSources() []string
BuiltinSources returns the registered source strings in sorted order. Intended for error messages ("known sources: X, Y, Z") and for future `orchard providers list` style commands.
func RegisterBuiltin ¶
func RegisterBuiltin(source string, factory BuiltinFactory)
RegisterBuiltin registers a factory for a source string like "builtin/postgres". Provider packages call this from init to expose themselves to the runtime; cmd/run.go in turn imports each provider package for its side effects.
Panics on duplicate registration — a clash between two builtins claiming the same source is a programming error that must be caught at binary startup, not silently papered over.
Types ¶
type ActionPlanner ¶
type ActionPlanner interface {
PlanAction(ctx context.Context, action string, attrs map[string]cty.Value) (Plan, error)
}
ActionPlanner is implemented by providers whose actions can be checked against external state, such as a database's schema. It's optional; the engine calls it, when present, for each action before a run starts (and during `orchard plan`), so problems surface before any action has side effects.
attrs are the action's evaluated attributes. Values that depend on other actions' outputs aren't known yet and are cty unknowns, of a known type where one can be inferred. PlanAction returns what it learned in a Plan; an error means the action is invalid.
A provider with nothing to check an action against (no snapshot at plan time) returns an error wrapping ErrNoSchema; the engine treats that as "unchecked", not as a failure.
type BuiltinFactory ¶
type BuiltinFactory func() Provider
BuiltinFactory constructs an unconfigured Provider. It is called each time a scenario declares the corresponding source — one instance per scenario — so factories should return fresh state rather than a shared singleton.
type Capture ¶
type Capture struct {
// Kind names the body's format, e.g. "database" (pkg/dbschema).
Kind string
// Target identifies what was captured, without secrets, e.g.
// "postgres/app_dev". `schema pull` uses it to avoid overwriting
// one database's snapshot with another's.
Target string
// Body is the kind-specific JSON body.
Body json.RawMessage
}
Capture is what a SchemaSource returns.
type InverseOptions ¶
type InverseOptions struct {
// Requested is true when the action sets
// `lifecycle { managed_teardown = true }`: record an undo even where
// the provider wouldn't by default (a typed update of rows Orchard
// didn't create).
Requested bool
}
InverseOptions carries the scenario's say in automatic teardown.
type Invocation ¶
Invocation is an action call to make later: the action type and its already-evaluated attributes.
type Plan ¶
type Plan struct {
// Outputs is the type of the action's outputs, or
// cty.DynamicPseudoType (or the zero Type) when it can't say. A
// concrete type lets references to the outputs be type-checked.
Outputs cty.Type
// Hints are non-fatal observations worth showing the author, such
// as a foreign key set to a fixed value. `orchard plan` prints them.
Hints []string
}
Plan is what an ActionPlanner learned about one action.
type PlanConfigurer ¶
type PlanConfigurer interface {
PlanConfigure(ctx context.Context, config map[string]cty.Value, snap *snapshot.Snapshot) error
}
PlanConfigurer is implemented by providers that check actions at plan time from a snapshot, since `orchard plan` doesn't call Configure. PlanConfigure receives the provider's evaluated config and its snapshot (nil when there isn't one). It must not open connections or have other side effects.
type Provider ¶
type Provider interface {
// Schema returns the provider's self-description. It must be
// stable across a single process lifetime — the engine caches it
// after Configure and uses it to validate action bodies.
Schema() protocol.ProviderSchema
// Configure initializes the provider with evaluated config values.
// It is called exactly once, before any Execute calls. Providers
// that require no configuration may ignore the argument.
Configure(ctx context.Context, config map[string]cty.Value) error
// Execute performs the named action with the given attribute map
// and returns the action's outputs. The engine has already
// validated attrs against the schema, so providers can assume
// required fields are present and types match.
Execute(ctx context.Context, action string, attrs map[string]cty.Value) (map[string]cty.Value, error)
// Close releases any resources the provider holds (database
// connections, subprocess handles, ...). It is called during
// engine shutdown even if Configure failed, so implementations
// must tolerate being called on a partially-initialized provider.
Close() error
}
Provider executes actions and advertises the schema that describes them.
Lifecycle: after registration the engine calls Configure once with the evaluated `provider "name" {}` config from the scenario, then makes zero or more Execute calls, and finally calls Close during engine shutdown. Configure may be called with a nil/empty map when the provider declares no config attributes.
func NewBuiltin ¶
NewBuiltin instantiates the builtin provider registered under the given source string.
type PullOptions ¶
type PullOptions struct {
// Schemas limits database providers to the named schemas
// (namespaces). Empty means all. Providers without namespaces
// ignore it.
Schemas []string
}
PullOptions narrows what a SchemaSource captures.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds the set of providers available to an engine run, keyed by their scenario-local name (the alias chosen in `required_providers`). Two provider instances built from the same source can coexist under different names.
A Registry goes through three phases: providers are added with Register, then Configure is called to initialize each one with the config block from the scenario, then Execute dispatches actions to the right provider. Close tears everything down in reverse order.
func (*Registry) Close ¶
Close calls Close on every provider in reverse registration order. Errors are collected into a single error value so that one provider's Close failure does not prevent cleanup of the others — mirroring how defer cleanups compose in normal Go code.
func (*Registry) Configure ¶
Configure initializes every registered provider with the config values supplied by the scenario. Providers with no entry in configs receive a nil map, which matches the "empty config" contract.
Configure is one-shot: the first call flips the registry into the configured state and further Register calls are rejected. A single provider's Configure failure aborts the whole registry and causes subsequent calls to this method to return the same error without re-running Configure on any provider.
func (*Registry) PlanConfigure ¶
func (r *Registry) PlanConfigure(ctx context.Context, configs map[string]map[string]cty.Value, snaps map[string]*snapshot.Snapshot) error
PlanConfigure prepares providers for `orchard plan`, which doesn't call Configure: configs are validated and coerced as for Configure, then each PlanConfigurer receives its config and snapshot (looked up by provider name in snaps; nil when absent). Other providers are left alone.
func (*Registry) Register ¶
Register adds p under the given local name. The name is the alias the scenario chose in its `required_providers` block — not the provider's schema name. A scenario that declares
required_providers {
db = { source = "builtin/postgres" }
}
registers the postgres provider under the name "db". This is what lets two instances of the same provider coexist, and what makes the `provider "db" {}` config block, the routing disambiguator (`provider = "db"` on an action), and the Configure lookup all agree.
Returns an error on duplicate local names or after Configure has run — late registration would bypass the one-shot Configure contract.
func (*Registry) SetBaseDir ¶
SetBaseDir sets the directory relative values of `path` config attributes resolve against: the scenario file's directory, so a scenario behaves the same from any working directory. Without it, relative paths are passed through and resolve against the process's working directory.
func (*Registry) ValidateConfigs ¶
ValidateConfigs runs the schema-driven validation that Configure performs, without actually initializing any provider. `orchard plan` uses this to surface config typos at plan time — Configure itself is reserved for `orchard run`, since builtins like postgres open a live connection there.
The validation is strict: unknown attributes are rejected, required-but-missing attributes are flagged, and every value is coerced to its declared cty type. A provider with no config schema accepts no attributes; passing one is an error.
type SchemaSource ¶
type SchemaSource interface {
PullSchema(ctx context.Context, opts PullOptions) (*Capture, error)
}
SchemaSource is implemented by providers that can capture the shape of the system they act on (a database's tables, later an API spec), for `orchard schema pull` to store as a snapshot. It's optional; providers that don't implement it are skipped by `schema pull`.
PullSchema is called after Configure. It must only read metadata, never data, and the capture must not contain connection details or secrets, since snapshots are committed.
type Undoer ¶
type Undoer interface {
ExecuteUndo(ctx context.Context, action string, attrs map[string]cty.Value, opts InverseOptions) (outputs map[string]cty.Value, undo *Invocation, err error)
}
Undoer is implemented by providers that know how to undo some of their actions, so `orchard teardown` can clean them up without an explicit `lifecycle { teardown {} }` block (for instance, a typed insert is undone by deleting the row by its primary key). It's optional.
The engine calls ExecuteUndo in place of Execute when the action has no explicit teardown block and hasn't opted out with `managed_teardown = false`. It runs the action as Execute does and also returns the invocation that undoes it, or nil when there's no automatic undo; the engine stores it in the run record once the outputs pass validation. Returning the undo from the same call keeps what a provider learns while executing (a typed update's previous values, whether a key already existed) local to that call, so concurrent actions don't share state.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package exec is the builtin Orchard provider for shell command execution.
|
Package exec is the builtin Orchard provider for shell command execution. |
|
Package external implements a provider that runs as a subprocess and communicates with Orchard over JSON Lines on stdio.
|
Package external implements a provider that runs as a subprocess and communicates with Orchard over JSON Lines on stdio. |
|
Package grpc is the builtin Orchard provider for gRPC services.
|
Package grpc is the builtin Orchard provider for gRPC services. |
|
grpctest
Package grpctest serves the test Accounts service (testdata/ accounts.proto) for builtin/grpc's unit and integration tests.
|
Package grpctest serves the test Accounts service (testdata/ accounts.proto) for builtin/grpc's unit and integration tests. |
|
Package http is the builtin Orchard provider for HTTP requests.
|
Package http is the builtin Orchard provider for HTTP requests. |
|
Package mysql is the builtin Orchard provider for MySQL (and MariaDB).
|
Package mysql is the builtin Orchard provider for MySQL (and MariaDB). |
|
Package postgres is the builtin Orchard provider for PostgreSQL.
|
Package postgres is the builtin Orchard provider for PostgreSQL. |
|
Package redis is the builtin Orchard provider for Redis and wire-compatible stores (Valkey, Dragonfly, KeyDB).
|
Package redis is the builtin Orchard provider for Redis and wire-compatible stores (Valkey, Dragonfly, KeyDB). |
|
Package s3 is the builtin Orchard provider for Amazon S3 and S3-compatible object stores (MinIO, Cloudflare R2, LocalStack), and for Google Cloud Storage through its S3-compatible XML API.
|
Package s3 is the builtin Orchard provider for Amazon S3 and S3-compatible object stores (MinIO, Cloudflare R2, LocalStack), and for Google Cloud Storage through its S3-compatible XML API. |
|
Package sqlite is the builtin Orchard provider for SQLite.
|
Package sqlite is the builtin Orchard provider for SQLite. |