reconcile

package module
v0.0.0-...-dddc2fe Latest Latest
Warning

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

Go to latest
Published: May 4, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package reconcile provides the plan/apply reconciliation framework for CogOS.

Reconciliation is the core control-plane pattern: providers declare desired state, the reconciler diffs against actual state, produces a plan of changes, and applies them idempotently. This is the same Terraform-style loop used throughout the CogOS kernel, extracted as an importable library.

The Reconcilable interface is the central contract: any provider that implements its seven methods (Type, LoadConfig, FetchLive, ComputePlan, ApplyPlan, BuildState, Health) gets plan/apply/status/refresh for free through the generic orchestration layer.

Architecture

Types and interfaces define the contract (types.go). State management handles persistence with lineage tracking (state.go). The registry maps provider names to implementations (registry.go). Events provide lifecycle observability (events.go). The meta-reconciler orchestrates multi-provider reconciliation with dependency resolution via Kahn's topological sort (meta.go).

Index

Constants

View Source
const (
	EventPlanStart     = "cog.reconcile.plan.start"
	EventPlanComplete  = "cog.reconcile.plan.complete"
	EventApplyStart    = "cog.reconcile.apply.start"
	EventApplyAction   = "cog.reconcile.apply.action"
	EventApplyComplete = "cog.reconcile.apply.complete"
	EventDrift         = "cog.reconcile.drift.detected"
	EventError         = "cog.reconcile.error"
)

Event type constants for the reconciliation lifecycle.

Variables

This section is empty.

Functions

func ConfigureProvider

func ConfigureProvider(provider Reconcilable, resourceType, flagToken string)

ConfigureProvider sets up a provider with auth token if needed.

func GenerateLineage

func GenerateLineage() string

GenerateLineage creates a random hex string for state lineage tracking.

func HasProvider

func HasProvider(name string) bool

HasProvider returns true if a provider is registered for the given name.

func ListProviders

func ListProviders() []string

ListProviders returns sorted names of all registered providers.

func RegisterProvider

func RegisterProvider(name string, provider Reconcilable)

RegisterProvider adds a reconciliation provider to the global registry. Panics if a provider with the same name is already registered.

func ResetProviders

func ResetProviders()

ResetProviders clears the registry (for testing only).

func ResolveOrder

func ResolveOrder(resources []MetaResource) ([][]MetaResource, error)

ResolveOrder returns resources in dependency-resolved order. Uses Kahn's algorithm with wave-based ordering within levels.

func ResolveToken

func ResolveToken(resourceType, flagToken string) string

ResolveToken resolves an auth token from flag or environment. Checks flag first, then {RESOURCE_TYPE}_TOKEN env vars.

func ResourceByExternalID

func ResourceByExternalID(state *State) map[string]*Resource

ResourceByExternalID returns a map from external ID to resource.

func ResourceIndex

func ResourceIndex(state *State) map[string]*Resource

ResourceIndex returns a map from address to resource for fast lookup.

func StatePath

func StatePath(root, resourceType string) string

StatePath returns the path to a provider's state file.

func UpsertProvider

func UpsertProvider(name string, provider Reconcilable)

UpsertProvider adds or replaces a reconciliation provider in the global registry. Unlike RegisterProvider, this does not panic on duplicate names — the new provider replaces the existing one. Used by BuildRouter to register MLXSupervisedProvider instances without conflicting with daemon-side stubs.

func WriteState

func WriteState(root, resourceType string, state *State) error

WriteState atomically writes the state file for a resource type. Increments serial and sets generated_at timestamp automatically.

Types

type Action

type Action struct {
	Action       ActionType     `json:"action"`
	ResourceType string         `json:"resource_type"`
	Name         string         `json:"name"`
	Details      map[string]any `json:"details"`
}

Action describes a single create/update/delete/skip operation.

type ActionType

type ActionType string

ActionType identifies what a plan action does.

const (
	ActionCreate ActionType = "create"
	ActionUpdate ActionType = "update"
	ActionDelete ActionType = "delete"
	ActionSkip   ActionType = "skip"
)

type ApplyStatus

type ApplyStatus string

ApplyStatus indicates the result of applying a single action.

const (
	ApplySucceeded ApplyStatus = "succeeded"
	ApplyFailed    ApplyStatus = "failed"
	ApplySkipped   ApplyStatus = "skipped"
)

type ConfigExporter

type ConfigExporter interface {
	ExportConfig(root string) error
}

ConfigExporter is an optional interface for providers that can generate a declared config file (e.g., config.yaml) from live state.

type Event

type Event struct {
	EventType    string         `json:"event"`
	ResourceType string         `json:"resource_type"`
	Timestamp    string         `json:"timestamp"`
	DurationMs   int64          `json:"duration_ms,omitempty"`
	Summary      map[string]any `json:"summary,omitempty"`
	Error        string         `json:"error,omitempty"`
}

Event is the structured payload emitted for reconciliation lifecycle events.

func EmitApplyAction

func EmitApplyAction(resourceType string, action, name, status string) *Event

EmitApplyAction emits an apply.action event for an individual action execution.

func EmitApplyComplete

func EmitApplyComplete(resourceType string, results []Result, durationMs int64) *Event

EmitApplyComplete emits an apply.complete event with aggregated results and duration.

func EmitApplyStart

func EmitApplyStart(resourceType string, actionCount int) *Event

EmitApplyStart emits an apply.start event with the number of actions to apply.

func EmitDriftDetected

func EmitDriftDetected(resourceType string, drifts int) *Event

EmitDriftDetected emits a drift.detected event with the number of drifts found.

func EmitError

func EmitError(resourceType string, err error) *Event

EmitError emits an error event for a failed reconciliation.

func EmitEvent

func EmitEvent(eventType string, resourceType string, summary map[string]any) *Event

EmitEvent creates an Event, logs it to stderr, and returns it for optional forwarding.

func EmitPlanComplete

func EmitPlanComplete(resourceType string, summary Summary, durationMs int64) *Event

EmitPlanComplete emits a plan.complete event with plan summary and duration.

func EmitPlanStart

func EmitPlanStart(resourceType string) *Event

EmitPlanStart emits a plan.start event for the given resource type.

type HealthStatus

type HealthStatus string

HealthStatus indicates the health of the managed resource.

const (
	HealthHealthy     HealthStatus = "Healthy"
	HealthDegraded    HealthStatus = "Degraded"
	HealthProgressing HealthStatus = "Progressing"
	HealthMissing     HealthStatus = "Missing"
	HealthSuspended   HealthStatus = "Suspended"
)

type MetaConfig

type MetaConfig struct {
	Resources []MetaResource `yaml:"resources" json:"resources"`
}

MetaConfig holds the full resources declaration.

func AutoDiscoverResources

func AutoDiscoverResources() *MetaConfig

AutoDiscoverResources creates a MetaConfig from all registered providers. Each gets default settings (manual interval, no prune, no auto-apply).

type MetaOpts

type MetaOpts struct {
	DryRun         bool   // plan only, no apply
	ResourceFilter string // if set, only reconcile this resource
	Token          string // auth token (passed to providers)
	JSONOutput     bool
}

MetaOpts controls meta-reconciler behavior.

type MetaResource

type MetaResource struct {
	Name      string   `yaml:"name" json:"name"`
	Source    string   `yaml:"source" json:"source"`
	Interval  string   `yaml:"interval" json:"interval"`
	Prune     bool     `yaml:"prune" json:"prune"`
	AutoApply bool     `yaml:"auto_apply" json:"auto_apply"`
	DependsOn []string `yaml:"depends_on" json:"depends_on"`
	Wave      int      `yaml:"wave" json:"wave"`
	Suspended bool     `yaml:"suspended" json:"suspended"`
}

MetaResource declares a single resource provider to reconcile.

type MetaResult

type MetaResult struct {
	Resource string `json:"resource"`
	Status   string `json:"status"` // "synced", "drifted", "applied", "failed", "skipped", "suspended"
	Plan     *Plan  `json:"plan,omitempty"`
	Error    string `json:"error,omitempty"`
	Duration int64  `json:"duration_ms"`
}

MetaResult tracks the outcome of reconciling a single resource.

func RunMeta

func RunMeta(root string, cfg *MetaConfig, opts MetaOpts) ([]MetaResult, error)

RunMeta orchestrates reconciliation across all declared resources.

type OperationPhase

type OperationPhase string

OperationPhase indicates the current reconciliation operation.

const (
	OperationIdle    OperationPhase = "Idle"
	OperationSyncing OperationPhase = "Syncing"
	OperationWaiting OperationPhase = "Waiting"
)

type Plan

type Plan struct {
	ResourceType string         `json:"resource_type"`
	GeneratedAt  string         `json:"generated_at"`
	ConfigPath   string         `json:"config_path"`
	Actions      []Action       `json:"actions"`
	Summary      Summary        `json:"summary"`
	Warnings     []string       `json:"warnings"`
	Metadata     map[string]any `json:"metadata,omitempty"`
}

Plan describes the set of changes needed to bring live state into alignment with declared config. Provider-agnostic.

type Reconcilable

type Reconcilable interface {
	// Type returns the resource type identifier (e.g., "discord", "agent", "workspace").
	Type() string

	// LoadConfig loads the declared configuration from the workspace.
	LoadConfig(root string) (any, error)

	// FetchLive retrieves the current live state from the external system.
	FetchLive(ctx context.Context, config any) (any, error)

	// ComputePlan compares declared config against live state to produce a plan.
	ComputePlan(config any, live any, state *State) (*Plan, error)

	// ApplyPlan executes the planned changes against the external system.
	ApplyPlan(ctx context.Context, plan *Plan) ([]Result, error)

	// BuildState constructs state from live data (for snapshot/import).
	BuildState(config any, live any, existing *State) (*State, error)

	// Health returns the current three-axis status.
	Health() ResourceStatus
}

Reconcilable is the contract all resource providers implement. Each provider manages one resource type (Discord, Agent, Workspace, etc.) through the standard plan/apply/state lifecycle.

func GetProvider

func GetProvider(name string) (Reconcilable, error)

GetProvider returns the provider for the given resource type.

type Resource

type Resource struct {
	Address         string         `json:"address"`
	Type            string         `json:"type"`
	Mode            ResourceMode   `json:"mode"`
	ExternalID      string         `json:"external_id"`
	Name            string         `json:"name"`
	ParentAddress   string         `json:"parent_address,omitempty"`
	ParentID        string         `json:"parent_id,omitempty"`
	Attributes      map[string]any `json:"attributes,omitempty"`
	UnmanagedReason string         `json:"unmanaged_reason,omitempty"`
	LastRefreshed   string         `json:"last_refreshed"`
}

Resource describes a single tracked resource within state.

type ResourceMode

type ResourceMode string

ResourceMode indicates how a resource is managed.

const (
	ModeManaged   ResourceMode = "managed"
	ModeUnmanaged ResourceMode = "unmanaged"
	ModeData      ResourceMode = "data"
)

type ResourceStatus

type ResourceStatus struct {
	Sync      SyncStatus     `json:"sync"`
	Health    HealthStatus   `json:"health"`
	Operation OperationPhase `json:"operation"`
	Message   string         `json:"message,omitempty"`
}

ResourceStatus combines all three status axes for a single resource provider.

func NewResourceStatus

func NewResourceStatus(sync SyncStatus, health HealthStatus) ResourceStatus

NewResourceStatus creates a ResourceStatus with defaults.

type Result

type Result struct {
	Phase     string      `json:"phase"`
	Action    string      `json:"action"`
	Name      string      `json:"name"`
	Status    ApplyStatus `json:"status"`
	Error     string      `json:"error,omitempty"`
	CreatedID string      `json:"created_id,omitempty"`
}

Result records the outcome of executing a single plan action.

type State

type State struct {
	Version      int            `json:"version"`
	Lineage      string         `json:"lineage"`
	Serial       int            `json:"serial"`
	ResourceType string         `json:"resource_type"`
	GeneratedAt  string         `json:"generated_at"`
	Resources    []Resource     `json:"resources"`
	Metadata     map[string]any `json:"metadata,omitempty"`
}

State tracks the last-known state of managed resources. Modeled after Terraform state: version, lineage, serial, resources.

func LoadState

func LoadState(root, resourceType string) (*State, error)

LoadState loads the state file for a given resource type. Returns nil, nil if no state file exists yet.

func NewState

func NewState(resourceType string) *State

NewState creates a fresh state with a new lineage.

type Summary

type Summary struct {
	Creates int `json:"creates"`
	Updates int `json:"updates"`
	Deletes int `json:"deletes"`
	Skipped int `json:"skipped"`
}

Summary counts actions by type.

func (Summary) HasChanges

func (s Summary) HasChanges() bool

HasChanges returns true if there are any non-skip actions.

func (Summary) Total

func (s Summary) Total() int

Total returns the total number of actions.

type SyncStatus

type SyncStatus string

SyncStatus indicates whether declared config matches live state.

const (
	SyncStatusSynced    SyncStatus = "Synced"
	SyncStatusOutOfSync SyncStatus = "OutOfSync"
	SyncStatusUnknown   SyncStatus = "Unknown"
)

type Tokenable

type Tokenable interface {
	SetToken(token string)
}

Tokenable is an optional interface for providers that need auth tokens. Providers that implement this can receive tokens from --token flags or environment variables ({TYPE}_TOKEN, e.g. DISCORD_BOT_TOKEN).

Jump to

Keyboard shortcuts

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