playbook

package
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package playbook turns a multi-step operational procedure into a typed resource that Flynn can run: provision the command-line tools it needs, run them, verify the outcome, and register what it produced as a supervised Service. A playbook is the outcome-level companion to an integration: an integration spec says how to call one API operation, a playbook spec says how to accomplish a goal by composing many steps.

A playbook is data. Its body is a declarative flow (the same interpreter an integration uses, extended with the dependency, exec, and assert ops), so the stored spec is exactly what runs, and a runtime-authored playbook has no path to arbitrary code: every effect goes through a port the runner wires (a sandboxed command runner, the dependency manager, the resource store), never an ambient capability.

Index

Constants

View Source
const (
	// GroupVersion is the Playbook kind's API group and version.
	GroupVersion = "playbook.ionagent.io/v1alpha1"
	// Kind is the resource kind name playbooks are stored under.
	Kind = "Playbook"
)

Variables

View Source
var ErrNotFound = errors.New("playbook: not found")

ErrNotFound is returned when a playbook does not exist.

View Source
var KindDef = resource.Kind{
	APIVersion: GroupVersion,
	Name:       Kind,
	Schema:     specSchema,
	Singular:   "playbook",
	Plural:     "playbooks",
}

KindDef is the Playbook kind definition registered with a resource registry.

Functions

func RegisterKind

func RegisterKind(reg *resource.Registry) error

RegisterKind registers the Playbook kind so a store admits playbooks. It is idempotent.

func Reserved

func Reserved(name string) bool

Reserved reports whether a name belongs to an official bundled playbook, so a runtime-authored one cannot impersonate it.

func Sync

func Sync(ctx context.Context, store *Store) (int, error)

Sync writes every bundled playbook into the store. It is idempotent: the resource store dedups an unchanged spec by content, so re-syncing on each start is a no-op. It returns the number of playbooks written.

Types

type CredentialSink

type CredentialSink struct {
	// contains filtered or unexported fields
}

CredentialSink implements flow.CredentialSink: it resolves a secret by reference through the secret source (the origin) and materializes it into a hosting provider's secret store by driving the provider's CLI in the sandbox. The value is read from the source and delivered to the provider on standard input, so it never appears on a command line, in the flow's data, in the step output, or in a log. It is the provision-direction counterpart of secret.Source: Source resolves a credential for the agent to use; this sink hands a credential to a workload the agent is standing up.

func NewCredentialSink

func NewCredentialSink(src secret.Source, sb sandbox.Sandbox) *CredentialSink

NewCredentialSink builds a sink over the secret source that resolves references and the sandbox that runs the provider CLI. With either missing, every materialization fails closed.

func (*CredentialSink) Put

func (c *CredentialSink) Put(ctx context.Context, sink, ref string, target map[string]string) error

Put resolves the secret named by ref and materializes it into the named sink's target. The value is held only as a secret.Text and delivered inside the adapter; it is never returned, logged, or placed on a command line.

type Entry

type Entry struct {
	Name string
	Spec Spec
	Raw  json.RawMessage
}

Entry is one official playbook from the embedded catalog.

func Entries

func Entries() ([]Entry, error)

Entries returns the official playbook catalog, parsed once and ordered by name. A malformed embedded spec is a programming error in this package, surfaced as an error here and caught by the build-time gate.

type ManagerResolver

type ManagerResolver struct {
	// contains filtered or unexported fields
}

ManagerResolver adapts the dependency manager to the flow's DependencyResolver port, so a playbook's dependency steps ensure a program is present and yield the path to run it.

func NewManagerResolver

func NewManagerResolver(mgr *dependency.Manager) ManagerResolver

NewManagerResolver wraps a dependency manager as a flow dependency resolver.

func (ManagerResolver) Resolve

func (m ManagerResolver) Resolve(ctx context.Context, name string) (string, error)

Resolve satisfies the named dependency and returns the path to run it.

type Playbook

type Playbook struct {
	Name string
	Spec Spec
}

Playbook is the typed view of a playbook resource.

type Result

type Result struct {
	Output  any
	Service *service.Service
}

Result is the outcome of a playbook run: the flow's return value, and the supervised Service the run registered (nil when the playbook declares none or the result carried no workload to track).

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner executes a playbook's flow with the effect ports wired and, on success, registers the supervised Service the playbook declares. It holds no playbook knowledge: it runs whatever flow the spec carries, and the only things it can do are the ones its ports allow (run a command in the sandbox, resolve a dependency, write a service record).

func NewRunner

func NewRunner(exec flow.Execer, deps flow.DependencyResolver, svc *service.Store, opts ...RunnerOption) *Runner

NewRunner builds a playbook runner. exec runs the flow's exec steps (through the sandbox); deps resolves its dependency steps (through the dependency manager); svc is the service store a successful run registers its workload in (nil disables registration).

func (*Runner) Run

func (r *Runner) Run(ctx context.Context, pb Playbook, config map[string]any) (Result, error)

Run executes the playbook's flow with config exposed to it, then registers the declared supervised Service from the flow's result. A flow failure is returned as-is; the service is registered only after the flow succeeds, so a failed run never records a workload it did not finish standing up.

type RunnerOption

type RunnerOption func(*Runner)

RunnerOption configures a Runner.

func WithClock

func WithClock(c clock.Timing) RunnerOption

WithClock sets the time source used to stamp a registered service (default clock.System).

func WithConfirmer

func WithConfirmer(c flow.Confirmer) RunnerOption

WithConfirmer sets the port that asks the operator to approve a playbook's confirm steps (an interactive terminal prompt, or a fail-closed instruction for a non-interactive run). Without it, a confirm step fails closed.

func WithCredentialSink

func WithCredentialSink(s flow.CredentialSink) RunnerOption

WithCredentialSink sets the port that materializes a playbook's secret steps into a provider's secret store. Without it, a secret step fails closed.

func WithObserver

func WithObserver(o flow.Observer) RunnerOption

WithObserver sets the port that watches each command and dependency step as it runs, so a host can show progress while a playbook executes. Without it, the playbook still runs; nothing is reported.

type SandboxExecer

type SandboxExecer struct {
	// contains filtered or unexported fields
}

SandboxExecer adapts a sandbox to the flow's Execer port, so a playbook's exec steps run confined in the sandbox rather than spawning a process directly.

func NewSandboxExecer

func NewSandboxExecer(sb sandbox.Sandbox) SandboxExecer

NewSandboxExecer wraps a sandbox as a flow command runner.

func (SandboxExecer) Exec

Exec runs the command through the sandbox and returns its exit code and combined output.

type ServiceBlock

type ServiceBlock struct {
	// Provider is the provider that owns the workload (for example "fly").
	Provider string `json:"provider"`
	// Target classifies the workload (static-site, container, vps). Optional.
	Target service.Target `json:"target,omitempty"`
}

ServiceBlock declares how to classify the supervised Service a playbook registers when its flow succeeds. The live fields (the service name, its URL, the provider's external id, and the addressing the supervisor replays) come from the flow's return value, so all templating stays inside the flow; this block supplies only the static classification.

type Spec

type Spec struct {
	// Description is a short human summary of what the playbook accomplishes.
	Description string `json:"description,omitempty"`
	// Inputs is a JSON Schema describing the config an operator passes to a run. It is
	// documentation and (later) validation; the runner exposes the config to the flow as
	// "config" regardless.
	Inputs json.RawMessage `json:"inputs,omitempty"`
	// Flow is the declarative procedure the playbook runs, in the flow interpreter's shape.
	Flow json.RawMessage `json:"flow"`
	// Service, when set, is the supervised Service to register from the flow's result.
	Service *ServiceBlock `json:"service,omitempty"`
}

Spec is the desired shape of a playbook: a description, an optional input schema for the config an operator supplies, the flow that carries out the procedure, and an optional service block to register on success.

func DecodeSpec

func DecodeSpec(r resource.Resource) (Spec, error)

DecodeSpec reads the typed spec from a resource.

func (Spec) DecodeFlow

func (s Spec) DecodeFlow() (flow.Flow, error)

DecodeFlow parses and validates the playbook's flow, so a caller can confirm the procedure is well-formed before running it (the build-time gate uses this).

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the typed playbook facade over a resource.Store. Playbooks live in the instance-global scope, addressed by name.

func NewStore

func NewStore(rs resource.Store) *Store

NewStore returns a playbook facade over rs. The caller must have registered the Playbook kind with the registry rs admits against (see RegisterKind).

func (*Store) Get

func (s *Store) Get(ctx context.Context, name string) (Playbook, error)

Get returns the named playbook, or ErrNotFound.

func (*Store) List

func (s *Store) List(ctx context.Context) ([]Playbook, error)

List returns every playbook, ordered by name.

func (*Store) Put

func (s *Store) Put(ctx context.Context, name string, spec Spec) (Playbook, error)

Put creates or updates the named playbook.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL