orchestrator

package
v0.59.0 Latest Latest
Warning

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

Go to latest
Published: Jun 4, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package orchestrator — bridge_node.go implements the DAG executor's handler for RuntimeBridge services. This is the integration glue between the DAG and the internal/bridge/ package. (Idea 46.3)

Package orchestrator implements a DAG-based service dependency graph for ordered startup of databases, mock servers, and developer applications.

Index

Constants

View Source
const (
	ConditionServiceHealthy               = "service_healthy"
	ConditionServiceStarted               = "service_started"
	ConditionServiceCompletedSuccessfully = "service_completed_successfully"
)

Dependency conditions accepted on DependsOnEntry.Condition. Gating is tier-based: a dependent starts only once every node it depends on has reached readiness for its tier — a normal service when its healthcheck passes (or it has started, if it declares none), and a one-shot task when its process exits successfully (use ConditionServiceCompletedSuccessfully for that case).

Variables

This section is empty.

Functions

This section is empty.

Types

type BridgeMode added in v0.32.0

type BridgeMode string

BridgeMode distinguishes between outbound and inbound bridge operations.

const (
	BridgeModeConnect   BridgeMode = "connect"   // Outbound: kubectl port-forward
	BridgeModeIntercept BridgeMode = "intercept" // Inbound: agent + yamux tunnel
)

type BridgeNodeConfig added in v0.32.0

type BridgeNodeConfig struct {
	Kubeconfig    string
	Context       string
	Namespace     string
	TargetService string
	RemotePort    int
	LocalPort     int
	AgentImage    string
	Mode          BridgeMode
	InterceptMode string // "steal" or "mirror"
}

BridgeNodeConfig holds bridge-specific configuration for a DAG node.

type BridgeNodeState added in v0.32.0

type BridgeNodeState struct {
	PortForward *bridge.PortForward  // non-nil for connect mode
	Tunnel      *bridge.Tunnel       // non-nil for intercept mode
	AgentInfo   *bridge.AgentInfo    // non-nil for intercept mode
	SvcState    *bridge.ServiceState // non-nil for intercept mode
	SessionID   string               // set for intercept mode
	Kubeconfig  string               // for cleanup kubectl calls
	Context     string               // for cleanup kubectl calls
	Namespace   string               // for cleanup kubectl calls
}

BridgeNodeState holds the runtime state of a running bridge node, used for teardown.

func (*BridgeNodeState) Cleanup added in v0.32.0

func (s *BridgeNodeState) Cleanup()

Cleanup tears down bridge state in the correct order: 1. Stop tunnel (disconnect Yamux session) 2. Restore service selector (un-redirect traffic) 3. Remove agent pod 4. Stop port-forward subprocess 5. Remove session entry

type CloudRunNodeConfig added in v0.52.0

type CloudRunNodeConfig struct {
	Image                string            // container image to deploy
	Service              string            // Cloud Run service name (default: node name)
	Region               string            // GCP region
	Project              string            // GCP project ID
	Env                  map[string]string // env vars set on the service
	AllowUnauthenticated bool              // expose publicly
	Flags                []string          // extra `gcloud run deploy` flags
}

CloudRunNodeConfig holds Cloud Run deploy configuration for a DAG node (runtime: cloud): devx deploys Image to Cloud Run via `gcloud run deploy`.

type ContainerNodeConfig added in v0.56.0

type ContainerNodeConfig struct {
	Image        string      // pre-built image to run (empty when Build is set)
	Build        *image.Spec // build-from-context spec (nil when Image is set)
	Args         []string    // extra flags appended to `<runtime> run`
	ProviderName string      // container provider to resolve the runtime (e.g. "lima")
}

ContainerNodeConfig holds runtime: container configuration for a DAG node: devx runs a long-lived container in the VM via the provider runtime. Exactly one of Image or Build is set.

type DAG

type DAG struct {
	Nodes map[string]*Node
	// contains filtered or unexported fields
}

DAG is a directed acyclic graph of nodes.

func NewDAG

func NewDAG() *DAG

NewDAG creates an empty DAG.

func (*DAG) AccessSummary added in v0.55.0

func (d *DAG) AccessSummary() string

AccessSummary collects every node's active port-forwards into one block, printed after the DAG comes up so developers see exactly what to hit.

func (*DAG) AddNode

func (d *DAG) AddNode(n *Node) error

AddNode registers a node.

func (*DAG) BridgeServicesJSON added in v0.32.0

func (d *DAG) BridgeServicesJSON() ([]byte, error)

BridgeServicesJSON returns a JSON-serializable summary of bridge services for --dry-run.

func (*DAG) Execute

func (d *DAG) Execute(ctx context.Context) (cleanup func(), err error)

Execute starts all nodes in topological order, waiting for health checks between tiers. It returns a cleanup function to stop all started processes.

func (*DAG) GenerateBridgeEnvVars added in v0.32.0

func (d *DAG) GenerateBridgeEnvVars() map[string]string

GenerateBridgeEnvVars returns the BRIDGE_*_URL env vars for all bridge services in the DAG.

func (*DAG) TopologicalSort

func (d *DAG) TopologicalSort() ([][]string, error)

TopologicalSort returns execution tiers: each tier contains nodes that can be started in parallel once all nodes in previous tiers are healthy.

func (*DAG) Validate

func (d *DAG) Validate() error

Validate checks for missing dependencies and cycles.

func (*DAG) WriteBridgeEnvFile added in v0.32.0

func (d *DAG) WriteBridgeEnvFile() error

WriteBridgeEnvFile writes the BRIDGE_*_URL env vars to ~/.devx/bridge.env.

type DependsOnEntry

type DependsOnEntry struct {
	Name      string `yaml:"name"`
	Condition string `yaml:"condition"` // one of the Condition* constants
}

DependsOnEntry references another node and a readiness condition.

type HealthcheckConfig

type HealthcheckConfig struct {
	// HTTP endpoint to poll (e.g., "http://localhost:8080/health")
	HTTP string `yaml:"http"`
	// TCP address to probe (e.g., "localhost:5432")
	TCP string `yaml:"tcp"`
	// Interval between checks
	Interval time.Duration `yaml:"interval"`
	// Timeout for each check attempt
	Timeout time.Duration `yaml:"timeout"`
	// Number of consecutive successes required
	Retries int `yaml:"retries"`
}

HealthcheckConfig defines how to verify a service is ready.

type KubeNodeConfig added in v0.48.0

type KubeNodeConfig struct {
	Manifests    string       // kustomize dir | raw manifest file/dir | helm chart
	Renderer     string       // "kustomize" (default) | "raw" | "helm"
	Namespace    string       // target namespace (default "default")
	Context      string       // kube context
	Kubeconfig   string       // kubeconfig path
	ProviderName string       // container provider for image builds (e.g. "lima"); resolved by the cmd layer
	Images       []image.Spec // images devx builds + loads into the cluster registry before apply
	Release      string       // helm release name (renderer: helm; default: service name)
	Values       []string     // helm values files (renderer: helm)
	Sync         []KubeSync   // live-reload: local dirs synced into the deployed pod
	PortForward  bool         // auto-discover the namespace's Services and forward them to localhost
}

KubeNodeConfig holds kubernetes-deploy configuration for a DAG node (runtime: kubernetes): devx renders Manifests and applies them via kubectl.

type KubeSync added in v0.51.0

type KubeSync struct {
	Src       string // local source dir (resolved against the service's working dir)
	Dest      string // destination path inside the pod
	Selector  string // pod label selector, e.g. "app=brms-offer"
	Container string // container in the pod (optional; default: the pod's first container)
}

KubeSync maps a local source directory to a path inside a deployed pod for live-reload: after deploy, devx copies src into the pod and re-copies it on change, so an in-pod watch process (e.g. `tsx watch`, nodemon) hot-reloads.

type LogMode added in v0.56.0

type LogMode int

LogMode controls how a service node's logs are surfaced during `devx up`.

const (
	LogOff      LogMode = iota // no inline output; for non-host, no file either (producer not started)
	LogRaw                     // inline raw (no prefix) + file — preserves today's host default
	LogPrefixed                // inline "[service]" prefixed+colored + file
)

func ResolveLogMode added in v0.56.0

func ResolveLogMode(flag, perSvc, topLevel *bool, runtime string) LogMode

ResolveLogMode applies the opt-in precedence: flag > per-service > top-level > built-in default. flag/perSvc/topLevel are nil when unset. Built-in default: host = LogRaw (today's behavior), all other runtimes = LogOff. Any explicit "on" yields LogPrefixed (the multi-service case where prefixes disambiguate); any explicit "off" yields LogOff.

type Node

type Node struct {
	Name        string
	Type        NodeType
	DependsOn   []string // names of nodes this depends on
	Healthcheck HealthcheckConfig
	Port        int // resolved port (after conflict resolution)
	Runtime     Runtime
	Command     []string
	Env         map[string]string
	Dir         string // Working directory for host process execution (set by include resolver for multirepo)
	OneShot     bool   // run-to-completion task: gate dependents on exit 0 instead of a healthcheck

	// Bridge-specific fields (Idea 46.3)
	BridgeMode   BridgeMode        // for RuntimeBridge nodes
	BridgeConfig *BridgeNodeConfig // bridge-specific parameters

	// Kubernetes-deploy field (runtime: kubernetes)
	Kube *KubeNodeConfig

	// Cloud Run deploy field (runtime: cloud) + what was deployed, for cleanup
	CloudRun *CloudRunNodeConfig

	// Container deploy field (runtime: container) + whether we started it, for cleanup
	Container *ContainerNodeConfig

	// Log mode resolved from flag/config for this node.
	LogMode LogMode // how this node's logs are surfaced (resolved in the cmd layer)
	// contains filtered or unexported fields
}

Node is a single unit of work in the DAG.

type NodeType

type NodeType int

NodeType categorises a DAG node.

const (
	NodeDatabase NodeType = iota
	NodeMock
	NodeService
)

type Runtime

type Runtime string

Runtime determines where a service executes.

const (
	RuntimeHost       Runtime = "host"
	RuntimeContainer  Runtime = "container"
	RuntimeKubernetes Runtime = "kubernetes"
	RuntimeCloud      Runtime = "cloud"
	RuntimeBridge     Runtime = "bridge" // Idea 46.3: hybrid bridge services
)

type ServiceConfig

type ServiceConfig struct {
	Name        string            `yaml:"name"`
	Runtime     Runtime           `yaml:"runtime"`
	Command     []string          `yaml:"command"`
	DependsOn   []DependsOnEntry  `yaml:"depends_on"`
	Healthcheck HealthcheckConfig `yaml:"healthcheck"`
	Port        int               `yaml:"port"`
	Env         map[string]string `yaml:"env"`
	OneShot     bool              `yaml:"oneshot"`
}

ServiceConfig defines a developer application in devx.yaml.

Jump to

Keyboard shortcuts

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