Documentation
¶
Index ¶
- Variables
- func BuildResourceController[ClientT any](ctx context.Context, cfg ResourcePluginConfig[ClientT]) (*resourceController[ClientT], error)
- func ConnectionFromContext(ctx context.Context) *types.Connection
- func PtrFloat64(v float64) *float64
- func WithSession(ctx context.Context, s *Session) context.Context
- func WithWatchScope(ctx context.Context, scope *WatchScope) context.Context
- type ActionDescriptor
- type ActionEvent
- type ActionInput
- type ActionProvider
- type ActionResourcer
- type ActionResult
- type ActionScope
- type ClientRefresher
- type ColumnDefinition
- type ConnectionLifecycleProvider
- type ConnectionProvider
- type ConnectionWatcher
- type CreateInput
- type CreateResult
- type DefinitionProvider
- type DeleteInput
- type DeleteResult
- type DiscoveryProvider
- type EdgeDirection
- type EditorSchema
- type EditorSchemaProvider
- type ErrorClassifier
- type EventRetriever
- type EventSeverity
- type FilterExpression
- type FilterField
- type FilterFieldType
- type FilterLogic
- type FilterOperator
- type FilterPredicate
- type FilterableProvider
- type FindInput
- type FindResult
- type GetInput
- type GetResult
- type HealthAssessor
- type HealthCondition
- type HealthProvider
- type HealthStatus
- type ListInput
- type ListResult
- type OperationProvider
- type OrderField
- type PaginationParams
- type Provider
- type RelationshipDeclarer
- type RelationshipDescriptor
- type RelationshipExtractor
- type RelationshipProvider
- type RelationshipResolver
- type RelationshipType
- type ResolvedRelationship
- type ResourceCapabilities
- type ResourceDefinition
- type ResourceEvent
- type ResourceGroup
- type ResourceHealth
- type ResourceLink
- type ResourceMeta
- type ResourceMetadata
- type ResourceOperationError
- type ResourcePluginConfig
- type ResourceRef
- type ResourceRegistration
- type ResourceSchemaProvider
- type Resourcer
- type ScaleHint
- type ScaleHintProvider
- type ScaleLevel
- type Schema
- type SchemaProperty
- type SchemaProvider
- type SchemaType
- type ScopeMode
- type ScopeProvider
- type Session
- type SyncPolicy
- type SyncPolicyDeclarer
- type TextSearchProvider
- type TypeProvider
- type UpdateInput
- type UpdateResult
- type WatchAddPayload
- type WatchConnectionSummary
- type WatchDeletePayload
- type WatchEventSink
- type WatchProvider
- type WatchScope
- type WatchState
- type WatchStateEvent
- type WatchUpdatePayload
- type Watcher
Constants ¶
This section is empty.
Variables ¶
var AllScopeModes = []struct { Value ScopeMode TSName string }{ {ScopeModeAll, "ALL"}, {ScopeModeExplicit, "EXPLICIT"}, {ScopeModeAutoDiscover, "AUTO_DISCOVER"}, }
AllScopeModes lists all scope modes for Wails enum binding.
var AllSyncPolicies = []struct { Value SyncPolicy TSName string }{ {SyncOnConnect, "ON_CONNECT"}, {SyncOnFirstQuery, "ON_FIRST_QUERY"}, {SyncNever, "NEVER"}, }
AllSyncPolicies is a list of all sync policies. Necessary for Wails to bind the enums.
var AllWatchStates = []struct { Value WatchState TSName string }{ {WatchStateIdle, "IDLE"}, {WatchStateSyncing, "SYNCING"}, {WatchStateSynced, "SYNCED"}, {WatchStateError, "ERROR"}, {WatchStateStopped, "STOPPED"}, {WatchStateFailed, "FAILED"}, {WatchStateForbidden, "FORBIDDEN"}, {WatchStateSkipped, "SKIPPED"}, }
AllWatchStates is a list of all watch states. Necessary for Wails to bind the enums.
var ErrConnectionUnchanged = errors.New("connection unchanged")
ErrConnectionUnchanged is returned by UpdateConnection when the incoming connection data is identical to the stored connection. Callers can use errors.Is(err, ErrConnectionUnchanged) to detect the no-op case.
Functions ¶
func BuildResourceController ¶
func BuildResourceController[ClientT any](ctx context.Context, cfg ResourcePluginConfig[ClientT]) (*resourceController[ClientT], error)
BuildResourceController creates a fully wired resourceController from config. Returns an error if the config fails validation.
func ConnectionFromContext ¶
func ConnectionFromContext(ctx context.Context) *types.Connection
ConnectionFromContext is a convenience helper that retrieves the Connection from the Session stored in the context. Returns nil if no Session or no Connection is present.
func PtrFloat64 ¶
PtrFloat64 is a convenience helper for setting Minimum/Maximum in schema literals.
func WithSession ¶
WithSession stores a Session in the context.
func WithWatchScope ¶
func WithWatchScope(ctx context.Context, scope *WatchScope) context.Context
WithWatchScope attaches a WatchScope to a context.
Types ¶
type ActionDescriptor ¶
type ActionDescriptor struct {
ID string `json:"id"`
Label string `json:"label"`
Description string `json:"description"`
Icon string `json:"icon"`
Scope ActionScope `json:"scope"`
Streaming bool `json:"streaming"`
// ParamsSchema describes the action's input parameters as a typed JSON Schema.
// Serialized to JSON Schema bytes for gRPC and MCP tool generators.
ParamsSchema *Schema `json:"paramsSchema,omitempty"`
// OutputSchema describes the action's result structure as a typed JSON Schema.
// Serialized to JSON Schema bytes for gRPC and MCP tool generators.
OutputSchema *Schema `json:"outputSchema,omitempty"`
// Dangerous indicates this action has destructive side effects.
// AI agents should confirm before executing.
Dangerous bool `json:"dangerous,omitempty"`
}
ActionDescriptor describes an available action on a resource type.
type ActionEvent ¶
type ActionEvent struct {
Type string `json:"type"` // "progress", "output", "error", "complete"
Data map[string]interface{} `json:"data"`
}
ActionEvent represents a streaming event from a long-running action.
type ActionInput ¶
type ActionInput struct {
ID string `json:"id"`
Namespace string `json:"namespace"`
Params map[string]interface{} `json:"params"`
}
ActionInput contains the parameters for executing an action.
type ActionProvider ¶
type ActionProvider interface {
// GetActions returns available actions for a resource type.
GetActions(ctx context.Context, key string) ([]ActionDescriptor, error)
// ExecuteAction executes a named action.
ExecuteAction(ctx context.Context, key string, actionID string, input ActionInput) (*ActionResult, error)
// StreamAction executes a streaming action, sending progress events on the channel.
StreamAction(ctx context.Context, key string, actionID string, input ActionInput, stream chan<- ActionEvent) error
}
ActionProvider handles resource actions across the gRPC boundary.
type ActionResourcer ¶
type ActionResourcer[ClientT any] interface { // GetActions returns available actions for a resource type. GetActions(ctx context.Context, client *ClientT, meta ResourceMeta) ([]ActionDescriptor, error) // ExecuteAction executes a named action and returns the result. ExecuteAction(ctx context.Context, client *ClientT, meta ResourceMeta, actionID string, input ActionInput) (*ActionResult, error) // StreamAction executes a streaming action, sending events on the channel. // The channel is closed by the caller when the context is cancelled. StreamAction(ctx context.Context, client *ClientT, meta ResourceMeta, actionID string, input ActionInput, stream chan<- ActionEvent) error }
ActionResourcer adds named actions beyond CRUD (restart, scale, drain, etc.). Optional — type-asserted on Resourcer implementations.
type ActionResult ¶
type ActionResult struct {
Success bool `json:"success"`
Data map[string]interface{} `json:"data"`
Message string `json:"message"`
}
ActionResult contains the result of executing an action.
type ActionScope ¶
type ActionScope string
ActionScope defines whether an action operates on a specific resource instance or on the resource type as a whole.
const ( ActionScopeInstance ActionScope = "instance" ActionScopeType ActionScope = "type" )
type ClientRefresher ¶
type ClientRefresher[ClientT any] interface { RefreshClient(ctx context.Context, client *ClientT) error }
ClientRefresher refreshes credentials without recreating the client. Optional — type-asserted on the ConnectionProvider implementation.
type ColumnDefinition ¶
type ColumnDefinition struct {
// ID is the unique identifier for this column.
ID string `json:"id"`
// Header is the display header text.
Header string `json:"header"`
// Accessors is a comma-separated list of JSON path accessors.
Accessors string `json:"accessor"`
// AccessorPriority controls which value to return when multiple
// accessors match. Values: "ALL", "FIRST", "LAST".
AccessorPriority string `json:"accessorPriority,omitempty"`
// ColorMap maps cell values to color variants.
ColorMap map[string]string `json:"colorMap,omitempty"`
// Color is the default color variant for the cell.
Color string `json:"color,omitempty"`
// Alignment is the column alignment: "LEFT", "CENTER", "RIGHT".
Alignment string `json:"align,omitempty"`
// Hidden controls whether the column is visible by default.
Hidden bool `json:"hidden,omitempty"`
// Width is the column width in pixels. 0 means auto-size.
Width int `json:"width,omitempty"`
// Formatter is the value formatter: "NONE", "BYTES", "DURATION", "AGE", etc.
Formatter string `json:"formatter,omitempty"`
// Component is the cell renderer component name.
Component string `json:"component,omitempty"`
// ComponentParams are parameters passed to the cell component.
ComponentParams interface{} `json:"componentParams,omitempty"`
// ResourceLink creates a link to another resource.
ResourceLink *ResourceLink `json:"resourceLink,omitempty"`
// ValueMap maps values via regex replacement.
ValueMap map[string]string `json:"valueMap,omitempty"`
}
ColumnDefinition describes a single table column for resource display.
type ConnectionLifecycleProvider ¶
type ConnectionLifecycleProvider interface {
// StartConnection starts a connection and returns its status.
StartConnection(ctx context.Context, connectionID string) (types.ConnectionStatus, error)
// StopConnection stops a connection and returns its final state.
StopConnection(ctx context.Context, connectionID string) (types.Connection, error)
// CheckConnection validates that an active connection is still healthy.
CheckConnection(ctx context.Context, connectionID string) (types.ConnectionStatus, error)
// LoadConnections reads connections from plugin configuration (e.g., kubeconfig files).
// Called on plugin start and when config changes.
LoadConnections(ctx context.Context) ([]types.Connection, error)
// ListConnections returns the current runtime state of all managed connections.
ListConnections(ctx context.Context) ([]types.Connection, error)
// GetConnection returns a single connection by ID.
GetConnection(ctx context.Context, id string) (types.Connection, error)
// GetConnectionNamespaces returns available namespaces for a connection.
GetConnectionNamespaces(ctx context.Context, id string) ([]string, error)
// UpdateConnection updates a connection's configuration.
UpdateConnection(ctx context.Context, connection types.Connection) (types.Connection, error)
// DeleteConnection removes a connection.
DeleteConnection(ctx context.Context, id string) error
// WatchConnections watches for external connection changes.
// Blocks until ctx is cancelled, sending updates on the stream channel.
WatchConnections(ctx context.Context, stream chan<- []types.Connection) error
}
ConnectionLifecycleProvider manages connection lifecycle over the gRPC boundary. Named differently from the plugin-author ConnectionProvider[ClientT] to avoid confusion.
type ConnectionProvider ¶
type ConnectionProvider[ClientT any] interface { // CreateClient creates a typed client for a connection. // ctx carries Session with connection data. Deadline applies to creation. CreateClient(ctx context.Context) (*ClientT, error) // DestroyClient tears down a client. Called once per CreateClient. // Use for cleanup (close sockets, cancel watches, etc.). DestroyClient(ctx context.Context, client *ClientT) error // LoadConnections returns all connections from plugin configuration. // Called on plugin start and when config changes. LoadConnections(ctx context.Context) ([]types.Connection, error) // CheckConnection verifies a connection is alive and healthy. // Returns structured status (CONNECTED, UNAUTHORIZED, TIMEOUT, etc.). CheckConnection(ctx context.Context, conn *types.Connection, client *ClientT) (types.ConnectionStatus, error) // GetNamespaces returns namespaces for a connection. // Return nil if the backend doesn't support namespaces. GetNamespaces(ctx context.Context, client *ClientT) ([]string, error) }
ConnectionProvider manages connections and their typed clients. All resource plugins must implement this interface.
The SDK's connectionManager calls these methods to manage the full connection lifecycle: load from config, create typed clients, check health, and retrieve namespaces.
type ConnectionWatcher ¶
type ConnectionWatcher interface {
WatchConnections(ctx context.Context) (<-chan []types.Connection, error)
}
ConnectionWatcher watches for external connection changes (e.g., kubeconfig file modifications). Optional — type-asserted on the ConnectionProvider implementation at registration time.
type CreateInput ¶
type CreateInput struct {
// Input is the resource data to create.
Input json.RawMessage `json:"input"`
// Namespace is an optional namespace for the new resource.
Namespace string `json:"namespace"`
}
CreateInput is the input to the Create operation.
type CreateResult ¶
type CreateResult struct {
// Result is the created resource as pre-serialized JSON.
Result json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
}
CreateResult is the result of a Create operation.
type DefinitionProvider ¶
type DefinitionProvider interface {
Definition() ResourceDefinition
}
DefinitionProvider provides column defs, ID/namespace accessors for a resource type. Optional — if not implemented, the SDK uses the Definition from ResourceRegistration, falling back to the DefaultDefinition from ResourcePluginConfig.
type DeleteInput ¶
type DeleteInput struct {
// ID is the unique identifier of the resource to delete.
ID string `json:"id"`
// Namespace is an optional namespace identifier.
Namespace string `json:"namespace"`
// GracePeriodSeconds is an optional grace period before deletion.
// nil means use the default.
GracePeriodSeconds *int64 `json:"gracePeriodSeconds,omitempty"`
}
DeleteInput is the input to the Delete operation.
type DeleteResult ¶
type DeleteResult struct {
// Result is the deleted resource as pre-serialized JSON (if available).
Result json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
}
DeleteResult is the result of a Delete operation.
type DiscoveryProvider ¶
type DiscoveryProvider interface {
// Discover returns resource types available for a connection (e.g., CRDs in K8s).
// Called when a connection starts and periodically to refresh.
Discover(ctx context.Context, conn *types.Connection) ([]ResourceMeta, error)
// OnConnectionRemoved cleans up any cached discovery state for a removed connection.
OnConnectionRemoved(ctx context.Context, conn *types.Connection) error
}
DiscoveryProvider discovers resource types available for a connection at runtime. Optional — without it, the plugin uses statically registered types only.
Note: Discover takes an explicit *types.Connection rather than reading from Session context. This is intentional — discovery is a connection-lifecycle operation called by the SDK's typeManager during connection setup, not a user-initiated request.
type EdgeDirection ¶ added in v0.3.1
type EdgeDirection string
EdgeDirection controls whether an extracted edge points from the declaring resource to the target (outgoing) or from the target back to the declaring resource (incoming). Incoming is used for ownership edges where the child declares its parent (e.g., Pod ownerRef → ReplicaSet).
const ( // EdgeOutgoing is the default: declaring resource → extracted target. EdgeOutgoing EdgeDirection = "" // EdgeIncoming reverses the edge: extracted target → declaring resource. EdgeIncoming EdgeDirection = "incoming" )
type EditorSchema ¶
type EditorSchema struct {
ResourceKey string `json:"resourceKey"`
FileMatch string `json:"fileMatch"`
URI string `json:"uri"`
URL string `json:"url,omitempty"`
Content []byte `json:"content,omitempty"`
Language string `json:"language"`
}
EditorSchema provides schema information for Monaco editor validation.
type EditorSchemaProvider ¶
type EditorSchemaProvider interface {
// GetEditorSchemas returns editor schemas for a connection.
GetEditorSchemas(ctx context.Context, connectionID string) ([]EditorSchema, error)
}
EditorSchemaProvider provides editor schemas across the gRPC boundary.
type ErrorClassifier ¶
ErrorClassifier classifies raw errors into structured ResourceOperationErrors. Can be implemented on a Resourcer (per-resource classification) or provided at the plugin level via ResourcePluginConfig.ErrorClassifier.
type EventRetriever ¶
type EventRetriever[ClientT any] interface { GetEvents(ctx context.Context, client *ClientT, meta ResourceMeta, id string, namespace string, limit int32) ([]ResourceEvent, error) }
EventRetriever can be implemented by a Resourcer to retrieve diagnostic events for a resource instance.
type EventSeverity ¶
type EventSeverity string
EventSeverity classifies diagnostic events.
const ( SeverityNormal EventSeverity = "normal" SeverityWarning EventSeverity = "warning" SeverityError EventSeverity = "error" )
type FilterExpression ¶
type FilterExpression struct {
Logic FilterLogic `json:"logic,omitempty"`
Predicates []FilterPredicate `json:"predicates,omitempty"`
Groups []FilterExpression `json:"groups,omitempty"`
}
FilterExpression combines predicates with a logical operator. Supports one level of nesting (AND of ORs, or OR of ANDs).
type FilterField ¶
type FilterField struct {
// Path is the dot-separated field path (e.g., "metadata.name", "status.phase").
Path string `json:"path"`
// DisplayName is the human-readable name for UI and MCP tool descriptions.
DisplayName string `json:"displayName"`
// Description explains what this field represents.
Description string `json:"description"`
// Type declares the value type.
Type FilterFieldType `json:"type"`
// Operators lists valid comparison operators for this field.
// If empty, defaults to [OpEqual, OpNotEqual].
Operators []FilterOperator `json:"operators"`
// AllowedValues is the fixed set of valid values (only for FilterFieldEnum).
AllowedValues []string `json:"allowedValues,omitempty"`
// Required indicates this field must be provided in filter queries.
Required bool `json:"required,omitempty"`
}
FilterField declares a field that can be used in filter predicates. This is the introspection/discovery type for AI agents and MCP tool generators.
type FilterFieldType ¶
type FilterFieldType string
FilterFieldType declares the value type for a filterable field.
const ( FilterFieldString FilterFieldType = "string" FilterFieldInt FilterFieldType = "integer" FilterFieldFloat FilterFieldType = "number" FilterFieldBool FilterFieldType = "boolean" FilterFieldTime FilterFieldType = "datetime" FilterFieldEnum FilterFieldType = "enum" FilterFieldMap FilterFieldType = "map" )
type FilterLogic ¶
type FilterLogic string
FilterLogic is the logical operator for combining predicates.
const ( FilterAnd FilterLogic = "and" FilterOr FilterLogic = "or" )
type FilterOperator ¶
type FilterOperator string
FilterOperator is a comparison operator for filter predicates.
const ( // Equality. OpEqual FilterOperator = "eq" OpNotEqual FilterOperator = "neq" // Comparison (numeric, time). OpGreaterThan FilterOperator = "gt" OpGreaterOrEqual FilterOperator = "gte" OpLessThan FilterOperator = "lt" OpLessOrEqual FilterOperator = "lte" // String matching. OpContains FilterOperator = "contains" OpPrefix FilterOperator = "prefix" OpSuffix FilterOperator = "suffix" OpRegex FilterOperator = "regex" // Set membership. OpIn FilterOperator = "in" OpNotIn FilterOperator = "notin" // Existence. OpExists FilterOperator = "exists" OpNotExists FilterOperator = "notexists" // Map/label-specific. OpHasKey FilterOperator = "haskey" )
type FilterPredicate ¶
type FilterPredicate struct {
// Field is the filter field path (must match a FilterField.Path).
Field string `json:"field"`
// Operator is the comparison operator.
Operator FilterOperator `json:"operator"`
// Value is the comparison value. Type depends on field and operator:
// - OpIn/OpNotIn: []string
// - OpExists/OpNotExists: ignored (nil)
// - All others: scalar matching the field's FilterFieldType
Value interface{} `json:"value,omitempty"`
}
FilterPredicate is a single condition in a query.
type FilterableProvider ¶
type FilterableProvider interface {
FilterFields(ctx context.Context, connectionID string) ([]FilterField, error)
}
FilterableProvider declares filter fields available for a resource type. Optional — type-asserted on Resourcer implementations.
If NOT implemented, Find() still works but callers cannot discover valid filter fields. MCP tool generators omit filter parameters.
connectionID is provided because some backends have different filterable fields per connection (e.g., CRD custom columns).
type FindInput ¶
type FindInput struct {
// Filters is a typed filter expression replacing the old untyped Conditions.
Filters *FilterExpression `json:"filters,omitempty"`
// TextQuery is a free-text search string.
TextQuery string `json:"textQuery,omitempty"`
// Namespaces limits the search scope.
Namespaces []string `json:"namespaces"`
// Order specifies multi-field ordering.
Order []OrderField `json:"order"`
// Pagination controls pagination.
Pagination PaginationParams `json:"pagination"`
}
FindInput is the input to the Find operation.
type FindResult ¶
type FindResult struct {
// Result is the list of matching resources as pre-serialized JSON.
Result []json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
// TotalCount is the total number of matching resources.
// -1 if unknown.
TotalCount int `json:"totalCount"`
// NextCursor is the continuation token for cursor-based pagination.
NextCursor string `json:"nextCursor,omitempty"`
}
FindResult is the result of a Find operation.
type GetInput ¶
type GetInput struct {
// ID is the unique identifier of the resource.
ID string `json:"id"`
// Namespace is an optional namespace identifier.
Namespace string `json:"namespace"`
}
GetInput is the input to the Get operation.
type GetResult ¶
type GetResult struct {
// Result is the resource data as pre-serialized JSON.
Result json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
}
GetResult is the result of a Get operation.
type HealthAssessor ¶
type HealthAssessor[ClientT any] interface { AssessHealth(ctx context.Context, client *ClientT, meta ResourceMeta, data json.RawMessage) (*ResourceHealth, error) }
HealthAssessor can be implemented by a Resourcer to assess resource health from raw resource data.
type HealthCondition ¶
type HealthCondition struct {
Type string `json:"type"`
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"`
LastProbeTime *time.Time `json:"lastProbeTime,omitempty"`
LastTransitionTime *time.Time `json:"lastTransitionTime,omitempty"`
}
HealthCondition represents a single condition (Ready, Scheduled, etc.).
type HealthProvider ¶
type HealthProvider interface {
// GetHealth assesses health for a resource from its raw data.
GetHealth(ctx context.Context, connectionID string, resourceKey string, data json.RawMessage) (*ResourceHealth, error)
// GetResourceEvents returns diagnostic events for a resource instance.
GetResourceEvents(ctx context.Context, connectionID string, resourceKey string, id string, namespace string, limit int32) ([]ResourceEvent, error)
}
HealthProvider provides resource health assessment across the gRPC boundary.
type HealthStatus ¶
type HealthStatus string
HealthStatus represents the normalized health of a resource.
const ( HealthHealthy HealthStatus = "healthy" HealthDegraded HealthStatus = "degraded" HealthUnhealthy HealthStatus = "unhealthy" HealthPending HealthStatus = "pending" HealthUnknown HealthStatus = "unknown" )
type ListInput ¶
type ListInput struct {
// Namespaces limits listing to these namespaces.
// Empty means all namespaces.
Namespaces []string `json:"namespaces"`
// Order specifies multi-field ordering.
Order []OrderField `json:"order"`
// Pagination controls pagination.
Pagination PaginationParams `json:"pagination"`
}
ListInput is the input to the List operation.
type ListResult ¶
type ListResult struct {
// Result is the list of resources as pre-serialized JSON.
Result []json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
// TotalCount is the total number of resources (for pagination).
// -1 if unknown.
TotalCount int `json:"totalCount"`
// NextCursor is the continuation token for cursor-based pagination.
NextCursor string `json:"nextCursor,omitempty"`
}
ListResult is the result of a List operation.
type OperationProvider ¶
type OperationProvider interface {
Get(ctx context.Context, key string, input GetInput) (*GetResult, error)
List(ctx context.Context, key string, input ListInput) (*ListResult, error)
Find(ctx context.Context, key string, input FindInput) (*FindResult, error)
Create(ctx context.Context, key string, input CreateInput) (*CreateResult, error)
Update(ctx context.Context, key string, input UpdateInput) (*UpdateResult, error)
Delete(ctx context.Context, key string, input DeleteInput) (*DeleteResult, error)
}
OperationProvider handles CRUD operations on resources across the gRPC boundary. The key parameter is the resource type key (e.g., "core::v1::Pod").
type OrderField ¶
type OrderField struct {
// Field is the dot-separated path to the field to order by.
Field string `json:"field"`
// Descending controls sort direction. false = ascending (default).
Descending bool `json:"descending"`
}
OrderField specifies a single field in a multi-field ordering clause.
type PaginationParams ¶
type PaginationParams struct {
// Page is the 1-based page number (for page-based pagination).
Page int `json:"page"`
// PageSize is the maximum number of results per page.
// 0 means return all results.
PageSize int `json:"pageSize"`
// Cursor is the continuation token from a previous response
// (for cursor-based pagination). Mutually exclusive with Page.
Cursor string `json:"cursor,omitempty"`
}
PaginationParams controls pagination for List and Find operations.
type Provider ¶
type Provider interface {
OperationProvider
ConnectionLifecycleProvider
WatchProvider
TypeProvider
ActionProvider
EditorSchemaProvider
RelationshipProvider
HealthProvider
}
Provider is the composite interface that crosses the gRPC boundary. The SDK's resourceController[ClientT] satisfies this on the plugin side. The engine's gRPC client stub also satisfies this on the engine side.
type RelationshipDeclarer ¶
type RelationshipDeclarer interface {
DeclareRelationships() []RelationshipDescriptor
}
RelationshipDeclarer can be implemented by a Resourcer to declare its relationship descriptors (static metadata about resource type edges).
type RelationshipDescriptor ¶
type RelationshipDescriptor struct {
Type RelationshipType `json:"type"`
TargetResourceKey string `json:"targetResourceKey"`
Label string `json:"label"`
InverseLabel string `json:"inverseLabel,omitempty"`
Cardinality string `json:"cardinality,omitempty"`
Direction EdgeDirection `json:"direction,omitempty"`
Extractor *RelationshipExtractor `json:"extractor,omitempty"`
// TargetNamespaced is a tri-state flag: nil = default to namespaced (common case),
// true = explicitly namespaced, false = cluster-scoped target (e.g., Node, PV,
// StorageClass). Pointer type distinguishes "unspecified" from explicit values;
// callers must check for nil before dereferencing.
TargetNamespaced *bool `json:"targetNamespaced,omitempty"`
}
RelationshipDescriptor declares a relationship from one resource type to another.
type RelationshipExtractor ¶
type RelationshipExtractor struct {
Method string `json:"method"`
FieldPath string `json:"fieldPath,omitempty"`
LabelSelector map[string]string `json:"labelSelector,omitempty"`
}
RelationshipExtractor defines how to find related resource IDs from source data.
type RelationshipProvider ¶
type RelationshipProvider interface {
// GetRelationships returns the declared relationship descriptors for a resource type.
GetRelationships(ctx context.Context, resourceKey string) ([]RelationshipDescriptor, error)
// ResolveRelationships resolves actual relationship instances for a specific resource.
ResolveRelationships(ctx context.Context, connectionID string, resourceKey string, id string, namespace string) ([]ResolvedRelationship, error)
}
RelationshipProvider provides resource relationship information across the gRPC boundary.
type RelationshipResolver ¶
type RelationshipResolver[ClientT any] interface { ResolveRelationships(ctx context.Context, client *ClientT, meta ResourceMeta, id string, namespace string) ([]ResolvedRelationship, error) }
RelationshipResolver can be implemented by a Resourcer to resolve relationships for a specific resource instance.
type RelationshipType ¶
type RelationshipType string
RelationshipType classifies the kind of relationship between resources.
const ( RelOwns RelationshipType = "owns" RelRunsOn RelationshipType = "runs_on" RelUses RelationshipType = "uses" RelExposes RelationshipType = "exposes" RelManages RelationshipType = "manages" RelMemberOf RelationshipType = "member_of" RelSelects RelationshipType = "selects" )
type ResolvedRelationship ¶
type ResolvedRelationship struct {
Descriptor RelationshipDescriptor `json:"descriptor"`
Targets []ResourceRef `json:"targets"`
}
ResolvedRelationship holds actual relationship instances for a resource.
type ResourceCapabilities ¶
type ResourceCapabilities struct {
// CRUD flags.
CanGet bool `json:"canGet"`
CanList bool `json:"canList"`
CanFind bool `json:"canFind"`
CanCreate bool `json:"canCreate"`
CanUpdate bool `json:"canUpdate"`
CanDelete bool `json:"canDelete"`
// Extended capabilities.
Watchable bool `json:"watchable"`
Filterable bool `json:"filterable"`
Searchable bool `json:"searchable"`
HasActions bool `json:"hasActions"`
HasSchema bool `json:"hasSchema"`
NamespaceScoped bool `json:"namespaceScoped"`
HasRelationships bool `json:"hasRelationships"`
HasHealth bool `json:"hasHealth"`
HasEvents bool `json:"hasEvents"`
// ScaleHint indicates expected cardinality.
Scale *ScaleHint `json:"scaleHint,omitempty"`
}
ResourceCapabilities describes what operations and features a resource type supports. Auto-derived by the SDK from type assertions on registered Resourcers at registration time.
type ResourceDefinition ¶
type ResourceDefinition struct {
// IDAccessor is the JSON path to extract the resource ID.
IDAccessor string `json:"id_accessor"`
// NamespaceAccessor is the JSON path to extract the namespace.
NamespaceAccessor string `json:"namespace_accessor"`
// MemoizerAccessor is the JSON path to extract a memoization key.
MemoizerAccessor string `json:"memoizer_accessor"`
// ColumnDefs defines the table columns for this resource type.
ColumnDefs []ColumnDefinition `json:"columnDefs"`
}
ResourceDefinition describes the table rendering configuration for a resource type.
type ResourceEvent ¶
type ResourceEvent struct {
Type EventSeverity `json:"type"`
Reason string `json:"reason"`
Message string `json:"message"`
Source string `json:"source,omitempty"`
Count int32 `json:"count,omitempty"`
FirstSeen time.Time `json:"firstSeen"`
LastSeen time.Time `json:"lastSeen"`
}
ResourceEvent is a diagnostic event associated with a resource.
type ResourceGroup ¶
type ResourceGroup struct {
// ID is the unique identifier of the resource group.
ID string `json:"id"`
// Name is the display name of the resource group.
Name string `json:"name"`
// Description is a human-readable description.
Description string `json:"description"`
// Icon is an optional icon for the resource group.
Icon string `json:"icon"`
// Resources is a map of resource versions to the resources in that version.
Resources map[string][]ResourceMeta `json:"resources"`
}
ResourceGroup is a categorization of resources within a plugin.
type ResourceHealth ¶
type ResourceHealth struct {
Status HealthStatus `json:"status"`
Reason string `json:"reason,omitempty"`
Message string `json:"message,omitempty"`
Since *time.Time `json:"since,omitempty"`
Conditions []HealthCondition `json:"conditions,omitempty"`
}
ResourceHealth is a normalized health assessment for a resource.
type ResourceLink ¶
type ResourceLink struct {
IDAccessor string `json:"idAccessor"`
NamespaceAccessor string `json:"namespaceAccessor"`
Namespaced bool `json:"namespaced"`
Key string `json:"resourceKey"`
KeyAccessor string `json:"keyAccessor"`
KeyMap map[string]string `json:"keyMap"`
DetailExtractors map[string]string `json:"detailExtractors"`
DisplayID bool `json:"displayId"`
}
ResourceLink creates links to other resources from table cells.
type ResourceMeta ¶
type ResourceMeta struct {
// Group is the group of the resource (e.g., "core", "apps", "ec2").
Group string `json:"group"`
// Version is the version of the resource (e.g., "v1", "v1beta1").
Version string `json:"version"`
// Kind is the kind of the resource (e.g., "Pod", "Deployment", "EC2Instance").
Kind string `json:"kind"`
// Label is a human-readable label. Defaults to Kind if not provided.
Label string `json:"label"`
// Icon is an optional icon (icon name, data URI, or URL).
Icon string `json:"icon"`
// Description is a human-readable description of the resource.
Description string `json:"description"`
// Category is the category for grouping (e.g., "Workloads", "Networking").
// Defaults to "Uncategorized" if empty.
Category string `json:"category"`
}
ResourceMeta contains information about the categorization of a resource. Used to identify resource types across plugins and route operations to the correct Resourcer implementation.
func ResourceMetaFromString ¶
func ResourceMetaFromString(s string) ResourceMeta
ResourceMetaFromString parses a "group::version::kind" string into a ResourceMeta.
func (ResourceMeta) Key ¶
func (r ResourceMeta) Key() string
Key is an alias for String — the canonical resource key.
func (ResourceMeta) String ¶
func (r ResourceMeta) String() string
String returns the canonical string representation: "group::version::kind".
type ResourceMetadata ¶ added in v0.3.1
type ResourceMetadata struct {
UID string `json:"uid"`
Labels map[string]string `json:"labels,omitempty"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
}
ResourceMetadata carries structured metadata extracted by the plugin from its typed objects. The engine stores this in the registry without parsing raw JSON.
type ResourceOperationError ¶
type ResourceOperationError struct {
Err error `json:"-"`
Code string `json:"code"`
Title string `json:"title"`
Message string `json:"message"`
Suggestions []string `json:"suggestions,omitempty"`
}
ResourceOperationError is a structured error for resource operations. Its Error() method returns a JSON string so the structured fields survive the Wails IPC boundary.
func ErrFilterInvalidOperator ¶
func ErrFilterInvalidOperator(field string, op FilterOperator, allowed []FilterOperator) *ResourceOperationError
ErrFilterInvalidOperator returns a structured error for an unsupported operator on a field.
func ErrFilterUnknownField ¶
func ErrFilterUnknownField(field string) *ResourceOperationError
ErrFilterUnknownField returns a structured error for an unknown filter field path.
func (*ResourceOperationError) Error ¶
func (e *ResourceOperationError) Error() string
Error returns a JSON-encoded representation of the structured error.
func (*ResourceOperationError) Unwrap ¶
func (e *ResourceOperationError) Unwrap() error
Unwrap returns the underlying error for use with errors.Is / errors.As.
type ResourcePluginConfig ¶
type ResourcePluginConfig[ClientT any] struct { // Logger is an optional logger for the resource controller subsystem. // nil → logging.NewNop(). Logger logging.Logger // Connections is the required connection provider. // All plugins must supply this. Connections ConnectionProvider[ClientT] // Resources is the list of resource registrations. // Each entry binds a resource type to its Resourcer implementation. // At least one of Resources or Patterns must be non-empty. Resources []ResourceRegistration[ClientT] // Patterns is a map of wildcard patterns to fallback Resourcers. // The key "*" matches any resource type not registered in Resources. // Used for dynamic resource types like CRDs. Patterns map[string]Resourcer[ClientT] // Groups defines the resource groups for sidebar organization. Groups []ResourceGroup // DefaultDefinition is the fallback resource definition used when // neither the Resourcer (via DefinitionProvider) nor the // ResourceRegistration.Definition provides one. DefaultDefinition ResourceDefinition // Discovery is an optional provider for dynamic resource type discovery. // nil means static types only. Discovery DiscoveryProvider // ErrorClassifier is an optional plugin-wide error classifier. // nil means no classification (raw errors pass through). // Per-resource ErrorClassifier on a Resourcer takes precedence. ErrorClassifier ErrorClassifier }
ResourcePluginConfig holds all configuration for a resource plugin. Passed to RegisterResourcePlugin to register the resource capability.
func (ResourcePluginConfig[ClientT]) Validate ¶
func (c ResourcePluginConfig[ClientT]) Validate() error
Validate checks documented invariants and returns a descriptive error if the config is invalid. Uses reflect-based checks to catch typed-nil interfaces (e.g., (*T)(nil)) that pass simple == nil comparisons.
type ResourceRef ¶
type ResourceRef struct {
PluginID string `json:"pluginId,omitempty"`
ConnectionID string `json:"connectionId"`
ResourceKey string `json:"resourceKey"`
ID string `json:"id"`
Namespace string `json:"namespace,omitempty"`
DisplayName string `json:"displayName,omitempty"`
}
ResourceRef is a reference to a specific resource instance.
type ResourceRegistration ¶
type ResourceRegistration[ClientT any] struct { // Meta identifies the resource type (group, version, kind). Meta ResourceMeta // Resourcer is the implementation that handles CRUD for this resource type. // May also implement optional interfaces (Watcher, ActionResourcer, // DefinitionProvider, etc.) which are detected via type assertion. Resourcer Resourcer[ClientT] // Definition is an optional fallback resource definition (column defs, ID accessor, etc.). // Precedence: if the Resourcer implements DefinitionProvider, that wins. // Otherwise, this Definition is used. If both are nil, the config's // DefaultDefinition applies. Definition *ResourceDefinition }
ResourceRegistration binds a resource type to its implementation. Co-locates metadata, resourcer, and definition.
type ResourceSchemaProvider ¶
type ResourceSchemaProvider[ClientT any] interface { GetResourceSchema(ctx context.Context, client *ClientT, meta ResourceMeta) (json.RawMessage, error) }
ResourceSchemaProvider provides raw JSON Schema for a resource type. Optional — describes the full resource data structure (all fields, types). Distinct from EditorSchema (which wraps schema in Monaco-specific metadata). Used by MCP tool generators as outputSchema.
type Resourcer ¶
type Resourcer[ClientT any] interface { // Get retrieves a single resource by ID (and optionally namespace). Get(ctx context.Context, client *ClientT, meta ResourceMeta, input GetInput) (*GetResult, error) // List returns all resources matching the input criteria. List(ctx context.Context, client *ClientT, meta ResourceMeta, input ListInput) (*ListResult, error) // Find searches for resources matching a filter expression or text query. Find(ctx context.Context, client *ClientT, meta ResourceMeta, input FindInput) (*FindResult, error) // Create creates a new resource. Create(ctx context.Context, client *ClientT, meta ResourceMeta, input CreateInput) (*CreateResult, error) // Update modifies an existing resource. Update(ctx context.Context, client *ClientT, meta ResourceMeta, input UpdateInput) (*UpdateResult, error) // Delete removes a resource. Delete(ctx context.Context, client *ClientT, meta ResourceMeta, input DeleteInput) (*DeleteResult, error) }
Resourcer handles CRUD for a single resource type (or pattern of types). This is the core interface that all resource implementations must satisfy.
Static resourcers (bound to one type at registration) may ignore the ResourceMeta parameter. Pattern resourcers (registered with wildcard patterns like "*") use it to determine the concrete resource being operated on.
type ScaleHint ¶
type ScaleHint struct {
// Level is the expected scale: "few", "moderate", "many".
Level ScaleLevel `json:"level"`
// ExpectedCount is the approximate expected count (optional).
ExpectedCount int `json:"expectedCount,omitempty"`
// DefaultPageSize is the recommended page size for this resource.
DefaultPageSize int `json:"defaultPageSize,omitempty"`
}
ScaleHint indicates the expected cardinality of a resource type.
type ScaleHintProvider ¶
type ScaleHintProvider interface {
ScaleHint() *ScaleHint
}
ScaleHintProvider declares expected cardinality for a resource type. Optional — helps AI agents decide list-all vs. paginate vs. filter-first.
type ScaleLevel ¶
type ScaleLevel string
ScaleLevel represents expected resource cardinality.
const ( // ScaleFew means <100 resources (list-all is fine). ScaleFew ScaleLevel = "few" // ScaleModerate means 100-10K resources (pagination recommended). ScaleModerate ScaleLevel = "moderate" // ScaleMany means 10K+ resources (filter-first approach required). ScaleMany ScaleLevel = "many" )
type Schema ¶
type Schema struct {
Properties map[string]SchemaProperty `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
}
Schema describes the shape of an action's parameters or output. Always serializes as a JSON Schema object with "type":"object".
func (Schema) MarshalJSON ¶
MarshalJSON produces a JSON Schema with "type":"object" added automatically.
func (*Schema) UnmarshalJSON ¶
UnmarshalJSON reads a JSON Schema object, discarding the "type" field.
type SchemaProperty ¶
type SchemaProperty struct {
Type SchemaType `json:"type"`
Description string `json:"description,omitempty"`
Enum []string `json:"enum,omitempty"`
Default any `json:"default,omitempty"`
Minimum *float64 `json:"minimum,omitempty"`
Maximum *float64 `json:"maximum,omitempty"`
Properties map[string]SchemaProperty `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
}
SchemaProperty describes a single property within a Schema.
type SchemaProvider ¶
type SchemaProvider[ClientT any] interface { GetEditorSchemas(ctx context.Context, client *ClientT) ([]EditorSchema, error) }
SchemaProvider provides editor schemas for a connection (e.g., OpenAPI schemas). Optional — type-asserted on the ConnectionProvider implementation. Connection-level, not per-resource — schemas are fetched once per connection.
type SchemaType ¶
type SchemaType string
SchemaType represents a JSON Schema type.
const ( SchemaString SchemaType = "string" SchemaInteger SchemaType = "integer" SchemaNumber SchemaType = "number" SchemaBoolean SchemaType = "boolean" SchemaObject SchemaType = "object" SchemaArray SchemaType = "array" )
type ScopeMode ¶
type ScopeMode int
ScopeMode controls how partitions are resolved for a connection.
const ( // ScopeModeAll means no partitioning — watch all partitions (default). ScopeModeAll ScopeMode = iota // ScopeModeExplicit means the user has configured a fixed partition list. ScopeModeExplicit // ScopeModeAutoDiscover means the plugin discovers accessible partitions dynamically. ScopeModeAutoDiscover )
type ScopeProvider ¶
type ScopeProvider[ClientT any] interface { ResolveScope(ctx context.Context, client *ClientT) (ScopeMode, []string, error) }
ScopeProvider resolves the watch scope for a connection. Optional — type-asserted on ConnectionProvider at connection start. If not implemented or returns ScopeModeAll, watches are unscoped.
type Session ¶
type Session struct {
Connection *types.Connection
PluginConfig settings.Provider
GlobalConfig *config.GlobalConfig
RequestID string
RequesterID string
}
Session carries per-request metadata through context.Context values. Set by the SDK framework before calling into plugin code. Replaces the old *PluginContext — Go convention is context.Context first.
func SessionFromContext ¶
SessionFromContext retrieves the Session from the context. Returns nil if no Session is present.
type SyncPolicy ¶
type SyncPolicy int
SyncPolicy controls when watches start for a resource type.
const ( // SyncOnConnect starts watching as soon as a connection is established. SyncOnConnect SyncPolicy = iota // SyncOnFirstQuery starts watching on the first List/Get call. SyncOnFirstQuery // SyncNever disables watching entirely (CRUD-only). SyncNever )
type SyncPolicyDeclarer ¶
type SyncPolicyDeclarer interface {
SyncPolicy() SyncPolicy
}
SyncPolicyDeclarer declares the sync policy for this resource type. Only meaningful if the Resourcer also implements Watcher. If not implemented, defaults to SyncOnConnect.
type TextSearchProvider ¶
type TextSearchProvider[ClientT any] interface { Search(ctx context.Context, client *ClientT, meta ResourceMeta, query string, limit int) (*FindResult, error) }
TextSearchProvider adds free-text search to a Resourcer. Optional — for command palette, AI natural language queries, global search. Separate from FilterableProvider (structured predicates vs. text matching).
type TypeProvider ¶
type TypeProvider interface {
// GetResourceGroups returns all resource groups for a connection.
GetResourceGroups(ctx context.Context, connectionID string) map[string]ResourceGroup
// GetResourceGroup returns a single resource group by ID.
GetResourceGroup(ctx context.Context, id string) (ResourceGroup, error)
// GetResourceTypes returns all resource types for a connection.
GetResourceTypes(ctx context.Context, connectionID string) map[string]ResourceMeta
// GetResourceType returns a single resource type by key.
GetResourceType(ctx context.Context, id string) (*ResourceMeta, error)
// HasResourceType checks whether a resource type exists.
HasResourceType(ctx context.Context, id string) bool
// GetResourceDefinition returns the table rendering definition for a resource type.
GetResourceDefinition(ctx context.Context, id string) (ResourceDefinition, error)
// GetResourceCapabilities returns the auto-derived capabilities for a resource type.
GetResourceCapabilities(ctx context.Context, resourceKey string) (*ResourceCapabilities, error)
// GetResourceSchema returns the raw JSON Schema for a resource type.
GetResourceSchema(ctx context.Context, connectionID string, resourceKey string) (json.RawMessage, error)
// GetFilterFields returns the declared filter fields for a resource type.
GetFilterFields(ctx context.Context, connectionID string, resourceKey string) ([]FilterField, error)
}
TypeProvider provides resource type metadata and introspection across the gRPC boundary.
type UpdateInput ¶
type UpdateInput struct {
// Input is the updated resource data.
Input json.RawMessage `json:"input"`
// ID is the unique identifier of the resource to update.
ID string `json:"id"`
// Namespace is an optional namespace identifier.
Namespace string `json:"namespace"`
}
UpdateInput is the input to the Update operation.
type UpdateResult ¶
type UpdateResult struct {
// Result is the updated resource as pre-serialized JSON.
Result json.RawMessage `json:"result"`
// Success indicates whether the operation succeeded.
Success bool `json:"success"`
}
UpdateResult is the result of an Update operation.
type WatchAddPayload ¶
type WatchAddPayload struct {
// Data is the resource data as pre-serialized JSON.
Data json.RawMessage `json:"data"`
// PluginID identifies the source plugin.
PluginID string `json:"pluginId"`
// Key is the resource type key (e.g., "core::v1::Pod").
Key string `json:"key"`
// Connection is the connection ID that produced this event.
Connection string `json:"connection"`
// ID is the resource instance identifier.
ID string `json:"id"`
// Namespace is the resource namespace (empty for cluster-scoped resources).
Namespace string `json:"namespace"`
// Metadata contains structured metadata extracted by the plugin.
Metadata ResourceMetadata `json:"metadata"`
}
WatchAddPayload represents a resource addition event.
type WatchConnectionSummary ¶
type WatchConnectionSummary struct {
ConnectionID string `json:"connectionId"`
Resources map[string]WatchState `json:"resources"`
ResourceCounts map[string]int `json:"resourceCounts"`
Scope *WatchScope `json:"scope,omitempty"`
}
WatchConnectionSummary provides a snapshot of all watch states for a connection.
type WatchDeletePayload ¶
type WatchDeletePayload struct {
// Data is the deleted resource's last-known state as pre-serialized JSON.
Data json.RawMessage `json:"data"`
// PluginID identifies the source plugin.
PluginID string `json:"pluginId"`
// Key is the resource type key.
Key string `json:"key"`
// Connection is the connection ID that produced this event.
Connection string `json:"connection"`
// ID is the resource instance identifier.
ID string `json:"id"`
// Namespace is the resource namespace.
Namespace string `json:"namespace"`
}
WatchDeletePayload represents a resource deletion event.
type WatchEventSink ¶
type WatchEventSink interface {
OnAdd(payload WatchAddPayload)
OnUpdate(payload WatchUpdatePayload)
OnDelete(payload WatchDeletePayload)
OnStateChange(event WatchStateEvent)
}
WatchEventSink receives all events from a Watch. The SDK provides the implementation — plugin authors never implement this.
Thread safety: All methods are safe for concurrent use. Multiple Watch goroutines (one per resource type per connection) may call methods simultaneously. The SDK implementation serialises event delivery to the engine via an internal channel, so callers do not need external locking.
Ordering: Events are delivered in the order received per resource type. No cross-resource-type ordering is guaranteed. Within a single Watch goroutine, OnAdd/OnUpdate/OnDelete calls are sequenced by the informer's event handler and will arrive in informer order.
OnStateChange calls may interleave with data events. Consumers should treat state events as advisory — e.g., a brief ERROR→SYNCING transition during a retry does not invalidate previously received data.
type WatchProvider ¶
type WatchProvider interface {
// StartConnectionWatch starts all watches for a connection.
// Resources with SyncOnConnect policy begin watching immediately.
// Resources with SyncOnFirstQuery are registered but not started.
StartConnectionWatch(ctx context.Context, connectionID string) error
// StopConnectionWatch stops all watches for a connection.
// All active watches transition to WatchStateStopped.
StopConnectionWatch(ctx context.Context, connectionID string) error
// HasWatch returns whether any watches are active for a connection.
HasWatch(ctx context.Context, connectionID string) bool
// GetWatchState returns a snapshot of all watch states for a connection.
GetWatchState(ctx context.Context, connectionID string) (*WatchConnectionSummary, error)
// ListenForEvents opens a long-lived event stream.
// Blocks until ctx is cancelled, delivering events via the sink.
// Must be called after StartConnectionWatch. Events that arrive before
// ListenForEvents is called are buffered internally.
ListenForEvents(ctx context.Context, sink WatchEventSink) error
// EnsureResourceWatch ensures a watch is running for a specific resource type.
// No-op if already running. Used by SyncOnFirstQuery resources and for
// restarting failed watches.
EnsureResourceWatch(ctx context.Context, connectionID string, resourceKey string) error
// StopResourceWatch stops the watch for a specific resource type.
// Transitions the watch to WatchStateStopped.
StopResourceWatch(ctx context.Context, connectionID string, resourceKey string) error
// RestartResourceWatch restarts the watch for a specific resource type.
// Stops the current watch (if any) and starts a fresh one.
// Useful for recovering from WatchStateFailed.
RestartResourceWatch(ctx context.Context, connectionID string, resourceKey string) error
// IsResourceWatchRunning returns whether a watch is running for a specific resource type.
IsResourceWatchRunning(ctx context.Context, connectionID string, resourceKey string) (bool, error)
}
WatchProvider manages watch lifecycle and event streaming over the gRPC boundary.
Lifecycle ¶
A typical watch lifecycle proceeds as follows:
- The engine calls StartConnectionWatch after a connection is established. This starts watches for all resource types whose SyncPolicy is SyncOnConnect.
- The engine calls ListenForEvents to open a long-lived event stream. The WatchEventSink receives ADD/UPDATE/DELETE data events and STATE change notifications. ListenForEvents blocks until the provided context is cancelled.
- For resource types with SyncPolicy SyncOnFirstQuery, the engine calls EnsureResourceWatch on the first List or Get call for that resource type.
- On shutdown or disconnect, the engine calls StopConnectionWatch, which cancels all active watches and transitions them to WatchStateStopped.
SyncPolicy Interaction ¶
- SyncOnConnect: Watch starts immediately in step 1. The initial LIST+WATCH runs in the background; ADD events arrive via the sink before the first user query completes.
- SyncOnFirstQuery: Watch is deferred until EnsureResourceWatch is called. The first user query triggers the watch; subsequent queries hit the cache.
- SyncNever: No watch is started. All reads go through direct API calls.
Thread Safety ¶
All methods are safe for concurrent use. StartConnectionWatch and StopConnectionWatch are serialised internally. EnsureResourceWatch is idempotent — concurrent calls for the same resource type result in a single watch.
Error Handling and Retries ¶
When a watch encounters an error (API server disconnect, timeout), the implementation transitions to WatchStateError and retries with exponential backoff. After exhausting the retry budget, the state moves to WatchStateFailed (terminal). A failed watch can be manually restarted via RestartResourceWatch.
Individual Resource Watch Management ¶
EnsureResourceWatch, StopResourceWatch, and RestartResourceWatch allow fine-grained control over individual resource type watches within a connection. This is useful for on-demand resource types (SyncOnFirstQuery) and for manual recovery after WatchStateFailed.
type WatchScope ¶
type WatchScope struct {
Partitions []string `json:"partitions,omitempty"` // empty = unscoped
}
WatchScope configures the scope/partitioning of a Watch invocation. Passed via context so the Watcher[ClientT] interface doesn't change.
"Partitions" are backend-defined divisions of the resource space. K8s: partitions = namespaces. AWS: partitions = regions. GCP: partitions = projects.
func WatchScopeFromContext ¶
func WatchScopeFromContext(ctx context.Context) *WatchScope
WatchScopeFromContext retrieves the WatchScope from a context, or nil if none.
type WatchState ¶
type WatchState int
WatchState represents the current state of a watch.
State Machine:
┌─────────────────────────────┐
│ │
Idle ──► Syncing ──► Synced ──► Error ──► Syncing │ (retry)
│ │ │
│ ▼ │
│ Failed │ (terminal: max retries)
│ │
▼ │
Error ──────────────────────────────────►│
│
▼
Stopped (terminal: context cancelled)
Transition rules:
- Idle → Syncing: StartConnectionWatch or EnsureResourceWatch is called.
- Syncing → Synced: Initial list completed and cache populated. ResourceCount is set.
- Syncing → Error: Initial list or informer setup failed. Error and Message are set.
- Synced → Error: Watch stream returned an error during live operation.
- Error → Syncing: Automatic retry after backoff (if retries remain).
- Error → Failed: Max retry attempts exhausted. Terminal state.
- Error → Stopped: Context cancelled during backoff. Terminal state.
- Any → Stopped: Context cancelled (explicit StopConnectionWatch or shutdown).
- Idle → Forbidden: Backend detects 401/403 on initial sync. Terminal — no retry.
- Idle → Skipped: Resource excluded by scope configuration. Terminal.
const ( // WatchStateIdle means the watch is registered but not started. // Entered: on registration. Exited: when watch startup begins (→ Syncing). // Not terminal. WatchStateIdle WatchState = iota // WatchStateSyncing means the watch is running but initial sync is in progress. // Entered: on first startup or retry. Exited: cache sync completes (→ Synced) // or fails (→ Error). // WatchStateEvent.ResourceCount is not yet meaningful in this state. // Not terminal. WatchStateSyncing // WatchStateSynced means the watch is running and the cache is fully populated. // Entered: when cache sync completes successfully. // Exited: watch stream error (→ Error) or context cancelled (→ Stopped). // WatchStateEvent.ResourceCount is set to the number of resources observed. // Not terminal. WatchStateSynced // WatchStateError means an error occurred during watching. // Entered: when the watch stream or initial list returns an error. // Exited: automatic retry (→ Syncing), max retries (→ Failed), or // context cancelled (→ Stopped). // WatchStateEvent.Error and Message are set. // Not terminal. WatchStateError // WatchStateStopped means the watch was explicitly stopped. // Entered: when context is cancelled (user-initiated stop or shutdown). // Terminal — no further transitions occur. WatchStateStopped // WatchStateFailed means the watch failed after exhausting retry attempts. // Entered: when max retries are exhausted after repeated errors. // WatchStateEvent.Error and Message are set. // Terminal — requires explicit restart via RestartResourceWatch. WatchStateFailed // WatchStateForbidden means the watch was denied due to 401/403 permissions. // Entered: when the backend detects a permission error (e.g., K8s 403 on List/Watch). // Terminal — stable, no auto-retry. User must fix permissions and reconnect. WatchStateForbidden // WatchStateSkipped means the watch was intentionally not started. // Entered: when the resource is excluded by scope configuration or other policy. // Terminal — no further transitions occur unless scope changes. WatchStateSkipped )
type WatchStateEvent ¶
type WatchStateEvent struct {
// PluginID identifies the source plugin.
PluginID string `json:"pluginId"`
// Connection is the connection ID that produced this event.
Connection string `json:"connection"`
// ResourceKey is the resource type key (e.g., "core::v1::Pod").
ResourceKey string `json:"resourceKey"`
// State is the new watch state.
State WatchState `json:"state"`
// Error is the error that caused the state change (if any).
// Only set when State is WatchStateError or WatchStateFailed.
Error error `json:"-"`
// Message is a human-readable description of the state change.
Message string `json:"message,omitempty"`
// ResourceCount is the number of resources observed (if known).
ResourceCount int `json:"resourceCount,omitempty"`
// ErrorCode is a machine-readable error classification (e.g., "FORBIDDEN", "TIMEOUT").
// Only set when State is WatchStateError, WatchStateFailed, or WatchStateForbidden.
ErrorCode string `json:"errorCode,omitempty"`
}
WatchStateEvent represents a state change in a watch.
type WatchUpdatePayload ¶
type WatchUpdatePayload struct {
// Data is the new resource state as pre-serialized JSON.
Data json.RawMessage `json:"data"`
// PluginID identifies the source plugin.
PluginID string `json:"pluginId"`
// Key is the resource type key.
Key string `json:"key"`
// Connection is the connection ID that produced this event.
Connection string `json:"connection"`
// ID is the resource instance identifier.
ID string `json:"id"`
// Namespace is the resource namespace.
Namespace string `json:"namespace"`
// Metadata contains structured metadata extracted by the plugin.
Metadata ResourceMetadata `json:"metadata"`
}
WatchUpdatePayload represents a resource update event. Carries only the new state — OldData is dropped (frontend doesn't use it).
type Watcher ¶
type Watcher[ClientT any] interface { Watch(ctx context.Context, client *ClientT, meta ResourceMeta, sink WatchEventSink) error }
Watcher adds real-time event streaming to a Resourcer. Optional — type-asserted on Resourcer implementations.
The Watch method MUST:
- Block until ctx is cancelled (clean shutdown) or an unrecoverable error occurs
- Emit events via the sink as they arrive (OnAdd, OnUpdate, OnDelete)
- Emit state changes via the sink (OnStateChange: Syncing -> Synced, Error, etc.)
- Return nil on clean shutdown (ctx cancelled), non-nil on failure
The SDK WILL:
- Call Watch() in a goroutine — plugin authors never call it themselves
- Cancel ctx to stop watching (connection disconnect, resource unsubscribed, etc.)
- Restart Watch() on failure (with backoff) or when explicitly requested
- Track per-resource running state
- Honor SyncPolicyDeclarer to decide WHEN to start watching
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package plugintest provides a test harness for plugin authors to mount their ResourcePluginConfig and assert behavior (CRUD, watch events, health, relationships) without needing gRPC or process spawning.
|
Package plugintest provides a test harness for plugin authors to mount their ResourcePluginConfig and assert behavior (CRUD, watch events, health, relationships) without needing gRPC or process spawning. |