Documentation
¶
Overview ¶
Package orchestrator provides the core service orchestration functionality for muster.
The orchestrator is responsible for managing the lifecycle of all services in muster, including both static services (Kubernetes connections, port forwards, MCP servers) and dynamic ServiceClass-based service instances. It ensures services are started in the correct dependency order and handles automatic recovery when dependencies fail.
Architecture ¶
The orchestrator has been enhanced with ServiceClass support and now uses:
- **Service Registry Pattern**: Unified management of static and dynamic services
- **Dependency Graph**: Complex dependency relationships across service types
- **ServiceClass Integration**: Dynamic service creation and lifecycle management
- **Event-Driven Updates**: Real-time state and health monitoring
- **API Service Locator**: Clean integration through the central API layer
- **Tool Caller Interface**: Integration with aggregator for tool execution
Service Types ¶
The orchestrator manages both traditional and ServiceClass-based services:
## Static Services (Traditional)
- **K8s Connections**: Establish and maintain connections to Kubernetes clusters
- **Port Forwards**: Create kubectl port-forward tunnels to cluster services
- **MCP Servers**: Run Model Context Protocol servers for AI assistant integration
## ServiceClass-Based Services (Dynamic)
- **ServiceClass Instances**: Runtime-configurable services created from YAML definitions
- **Tool-Driven Lifecycle**: Operations executed through aggregator tool integration
- **Template-Based Configuration**: Dynamic arg substitution and mapping
- **Event Streaming**: Real-time instance state and lifecycle events
- **Persistence Support**: Optional persistence of service instance definitions
ServiceClass Integration ¶
The orchestrator provides comprehensive ServiceClass instance management:
- **CreateServiceClassInstance**: Creates new instances from ServiceClass definitions
- **DeleteServiceClassInstance**: Cleanup and lifecycle management
- **GetServiceClassInstance**: Instance status and data retrieval
- **ListServiceClassInstances**: Full instance inventory
- **Event Subscription**: Real-time instance lifecycle events
## ServiceClass Instance Lifecycle
- **ServiceClass Validation**: Verify ServiceClass exists and is available
- **Tool Availability Check**: Ensure required tools are accessible through aggregator
- **Instance Creation**: Create GenericServiceInstance with ServiceClass reference
- **Arg Validation**: Validate args against ServiceClass schema
- **Tool Execution**: Execute ServiceClass create tool with templated args
- **Registration**: Register instance with unified service registry
- **Health Monitoring**: Periodic health checks using ServiceClass health tools
- **Event Propagation**: Broadcast instance state changes and lifecycle events
- **Persistence**: Optional persistence of instance definitions to YAML files
Enhanced Dependency Management ¶
The dependency system now supports complex relationships:
## Traditional Dependencies
- **K8s connections** (foundation - no dependencies)
- **Port forwards** (depend on K8s connections)
- **MCP servers** (may depend on port forwards)
## ServiceClass Dependencies
- **YAML-Defined Dependencies**: Specified in ServiceClass definitions
- **Runtime Dependencies**: Added during instance creation
- **Cross-Type Dependencies**: ServiceClass instances can depend on static services
- **Tool Dependencies**: ServiceClass availability depends on aggregator tools
## Dependency Features
- **Cascade Operations**: Failure in one service stops all dependents
- **Dependency Restoration**: Automatic restart of dependents when dependencies recover
- **Circular Dependency Detection**: Prevents invalid dependency configurations
- **Dependency Validation**: Ensures all dependencies exist and are valid
Health Monitoring ¶
Enhanced health monitoring supports both service types:
## Static Service Health
- Periodic health checks for traditional service types
- Automatic recovery attempts for failed services
- Cascade failure handling for dependent services
## ServiceClass Health
- Tool-driven health checking through ServiceClass health tools
- Configurable health check intervals and thresholds
- Template-based arg substitution for health check tools
- Response mapping for health status extraction
- Failure threshold tracking and recovery detection
State Management ¶
Comprehensive state management with ServiceClass awareness:
- **Unified State Tracking**: Both static and ServiceClass services
- **Event-Driven Updates**: Real-time state change propagation
- **ServiceClass Instance Events**: Detailed lifecycle event streaming
- **State Correlation**: Track related operations across service lifecycle
- **Health Status Integration**: Combined state and health monitoring
Service Instance Persistence ¶
ServiceClass instances can be persisted to YAML files:
- **Automatic Persistence**: Optional persistence during instance creation
- **Auto-Start Support**: Instances can be configured to start automatically
- **Definition Loading**: Persisted instances loaded on orchestrator startup
- **YAML Management**: Create, update, and delete persisted definitions
API Integration ¶
Following the Service Locator Pattern, the orchestrator provides:
- **Unified Service Management**: Single interface for all service operations
- **ServiceClass APIs**: Complete ServiceClass instance management
- **Event Subscription**: Real-time state and instance event streaming
- **Tool Provider Integration**: Aggregator tool execution capabilities
- **Clean Separation**: No direct inter-package dependencies
Usage Examples ¶
## Traditional Orchestrator Usage
cfg := orchestrator.Config{
Aggregator: aggregatorConfig,
ToolCaller: toolCaller,
Storage: storage,
Yolo: false,
}
orch := orchestrator.New(cfg)
if err := orch.Start(ctx); err != nil {
log.Fatal(err)
}
defer orch.Stop()
## ServiceClass Instance Management
// Create ServiceClass instance
req := orchestrator.CreateServiceRequest{
ServiceClassName: "kubernetes_port_forward",
Name: "my-app-forward",
Args: map[string]interface{}{
"namespace": "default",
"service_name": "my-app",
"local_port": "8080",
"remote_port": "80",
},
Persist: true,
AutoStart: true,
}
instance, err := orch.CreateServiceClassInstance(ctx, req)
if err != nil {
log.Fatal(err)
}
// Monitor instance lifecycle
events := orch.SubscribeToServiceInstanceEvents()
go func() {
for event := range events {
fmt.Printf("Instance %s: %s -> %s\n",
event.Name, event.OldState, event.NewState)
}
}()
// Get instance status
status, err := orch.GetServiceClassInstance(instance.Name)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Instance state: %s, health: %s\n", status.State, status.Health)
Service Names ¶
Services are identified by names following these conventions:
## Static Services
- **K8s connections**: "k8s-mc-{cluster}" or "k8s-wc-{cluster}"
- **Port forwards**: "{name}" (from configuration)
- **MCP servers**: "mcp-{name}" (from configuration)
## ServiceClass Instances
- **User-defined names** specified during instance creation
- Must be unique within the service registry
- Can use ServiceClass default name templates with arg substitution
Error Handling ¶
Enhanced error handling for ServiceClass operations:
- **ServiceClass Validation Errors**: Invalid or unavailable ServiceClass definitions
- **Tool Execution Errors**: Aggregator tool failures and response mapping errors
- **Arg Template Errors**: Template substitution and validation failures
- **Dependency Errors**: Invalid dependencies and circular dependency detection
- **Instance Management Errors**: Creation, deletion, and lifecycle management failures
- **Persistence Errors**: YAML file operations and storage failures
Thread Safety ¶
All orchestrator operations are thread-safe:
- **Concurrent service operations**
- **Thread-safe service registry access**
- **Atomic state updates and event propagation**
- **Safe dependency graph manipulation**
- **Concurrent ServiceClass instance management**
- **Protected access to persistence layer**
Index ¶
- Constants
- type Adapter
- func (a *Adapter) CreateService(ctx context.Context, req api.CreateServiceInstanceRequest) (*api.ServiceInstance, error)
- func (a *Adapter) CreateServiceClassInstance(ctx context.Context, req api.CreateServiceInstanceRequest) (*api.ServiceInstance, error)
- func (a *Adapter) DeleteService(ctx context.Context, name string) error
- func (a *Adapter) DeleteServiceClassInstance(ctx context.Context, name string) error
- func (a *Adapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
- func (a *Adapter) GetAllServices() []api.ServiceStatus
- func (a *Adapter) GetService(name string) (*api.ServiceInstance, error)
- func (a *Adapter) GetServiceClassInstance(name string) (*api.ServiceInstance, error)
- func (a *Adapter) GetServiceStatus(name string) (*api.ServiceStatus, error)
- func (a *Adapter) GetTools() []api.ToolMetadata
- func (a *Adapter) ListServiceClassInstances() []api.ServiceInstance
- func (a *Adapter) Register()
- func (a *Adapter) RestartService(name string) error
- func (a *Adapter) StartService(name string) error
- func (a *Adapter) StopService(name string) error
- func (a *Adapter) SubscribeToServiceInstanceEvents() <-chan api.ServiceInstanceEvent
- func (a *Adapter) SubscribeToStateChanges() <-chan api.ServiceStateChangedEvent
- type Config
- type CreateServiceRequest
- type Orchestrator
- func (o *Orchestrator) CreateServiceClassInstance(ctx context.Context, req CreateServiceRequest) (*ServiceInstanceInfo, error)
- func (o *Orchestrator) DeleteServiceClassInstance(ctx context.Context, name string) error
- func (o *Orchestrator) GetAllServices() []ServiceStatus
- func (o *Orchestrator) GetServiceClassInstance(name string) (*ServiceInstanceInfo, error)
- func (o *Orchestrator) GetServiceRegistry() services.ServiceRegistry
- func (o *Orchestrator) GetServiceStatus(name string) (*ServiceStatus, error)
- func (o *Orchestrator) GetToolCaller() ToolCaller
- func (o *Orchestrator) ListServiceClassInstances() []ServiceInstanceInfo
- func (o *Orchestrator) RestartService(name string) error
- func (o *Orchestrator) SetToolCaller(toolCaller ToolCaller)
- func (o *Orchestrator) Start(ctx context.Context) error
- func (o *Orchestrator) StartService(name string) error
- func (o *Orchestrator) Stop() error
- func (o *Orchestrator) StopService(name string) error
- func (o *Orchestrator) SubscribeToServiceInstanceEvents() <-chan ServiceInstanceEvent
- func (o *Orchestrator) SubscribeToStateChanges() <-chan ServiceStateChangedEvent
- type ServiceInstanceEvent
- type ServiceInstanceInfo
- type ServiceStateChangedEvent
- type ServiceStatus
- type StopReason
- type ToolCaller
Constants ¶
const MaxConcurrentRetries = 5
MaxConcurrentRetries limits the number of MCPServers that can be retried simultaneously. This prevents a "thundering herd" scenario where many failed servers retry at once, potentially overwhelming the system or upstream services.
const RetryInterval = 30 * time.Second
RetryInterval is the interval at which the orchestrator checks for failed servers to retry.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter adapts the orchestrator to implement api.ServiceManagerHandler
func NewAPIAdapter ¶
func NewAPIAdapter(orchestrator *Orchestrator) *Adapter
NewAPIAdapter creates a new orchestrator adapter
func (*Adapter) CreateService ¶
func (a *Adapter) CreateService(ctx context.Context, req api.CreateServiceInstanceRequest) (*api.ServiceInstance, error)
CreateService creates a new ServiceClass-based service instance (unified method)
func (*Adapter) CreateServiceClassInstance ¶
func (a *Adapter) CreateServiceClassInstance(ctx context.Context, req api.CreateServiceInstanceRequest) (*api.ServiceInstance, error)
CreateServiceClassInstance is an alias that delegates to CreateService for backward compatibility
func (*Adapter) DeleteService ¶
DeleteService deletes a service (works for ServiceClass instances by name)
func (*Adapter) DeleteServiceClassInstance ¶
DeleteServiceClassInstance deletes a ServiceClass-based service instance
func (*Adapter) ExecuteTool ¶
func (a *Adapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
ExecuteTool executes a tool by name
func (*Adapter) GetAllServices ¶
func (a *Adapter) GetAllServices() []api.ServiceStatus
func (*Adapter) GetService ¶
func (a *Adapter) GetService(name string) (*api.ServiceInstance, error)
GetService returns detailed service information by name
func (*Adapter) GetServiceClassInstance ¶
func (a *Adapter) GetServiceClassInstance(name string) (*api.ServiceInstance, error)
GetServiceClassInstance returns service instance info by ID
func (*Adapter) GetServiceStatus ¶
func (a *Adapter) GetServiceStatus(name string) (*api.ServiceStatus, error)
Service status
func (*Adapter) GetTools ¶
func (a *Adapter) GetTools() []api.ToolMetadata
GetTools returns all tools this provider offers
func (*Adapter) ListServiceClassInstances ¶
func (a *Adapter) ListServiceClassInstances() []api.ServiceInstance
ListServiceClassInstances returns all service class instances
func (*Adapter) RestartService ¶
func (*Adapter) StartService ¶
Service lifecycle management
func (*Adapter) StopService ¶
func (*Adapter) SubscribeToServiceInstanceEvents ¶
func (a *Adapter) SubscribeToServiceInstanceEvents() <-chan api.ServiceInstanceEvent
SubscribeToServiceInstanceEvents returns a channel for service instance events
func (*Adapter) SubscribeToStateChanges ¶
func (a *Adapter) SubscribeToStateChanges() <-chan api.ServiceStateChangedEvent
type Config ¶
type Config struct {
Aggregator config.AggregatorConfig
Yolo bool
ToolCaller ToolCaller // Optional: for ServiceClass-based services
}
Config holds the configuration for the orchestrator.
type CreateServiceRequest ¶
type CreateServiceRequest struct {
// ServiceClass to use
ServiceClassName string `json:"serviceClassName"`
// Name for the service instance (must be unique)
Name string `json:"name"`
// Arguments for service creation
Args map[string]interface{} `json:"args"`
// Whether to persist this service instance definition to YAML files
Persist bool `json:"persist,omitempty"`
// Optional: Whether this instance should be started automatically on system startup
AutoStart bool `json:"autoStart,omitempty"`
// Override default timeouts (future use)
CreateTimeout *time.Duration `json:"createTimeout,omitempty"`
DeleteTimeout *time.Duration `json:"deleteTimeout,omitempty"`
}
CreateServiceRequest represents a request to create a new ServiceClass-based service instance
type Orchestrator ¶
type Orchestrator struct {
// contains filtered or unexported fields
}
Orchestrator manages services using the unified service registry architecture. It serves as the single source of truth for all active services, both static and dynamic.
func (*Orchestrator) CreateServiceClassInstance ¶
func (o *Orchestrator) CreateServiceClassInstance(ctx context.Context, req CreateServiceRequest) (*ServiceInstanceInfo, error)
CreateServiceClassInstance creates a new ServiceClass-based service instance
func (*Orchestrator) DeleteServiceClassInstance ¶
func (o *Orchestrator) DeleteServiceClassInstance(ctx context.Context, name string) error
DeleteServiceClassInstance deletes a ServiceClass-based service instance
func (*Orchestrator) GetAllServices ¶
func (o *Orchestrator) GetAllServices() []ServiceStatus
GetAllServices returns status for all services (both static and ServiceClass-based).
func (*Orchestrator) GetServiceClassInstance ¶
func (o *Orchestrator) GetServiceClassInstance(name string) (*ServiceInstanceInfo, error)
GetServiceClassInstance returns information about a ServiceClass-based service instance
func (*Orchestrator) GetServiceRegistry ¶
func (o *Orchestrator) GetServiceRegistry() services.ServiceRegistry
GetServiceRegistry returns the service registry.
func (*Orchestrator) GetServiceStatus ¶
func (o *Orchestrator) GetServiceStatus(name string) (*ServiceStatus, error)
GetServiceStatus returns the status of a specific service.
func (*Orchestrator) GetToolCaller ¶
func (o *Orchestrator) GetToolCaller() ToolCaller
GetToolCaller returns the current ToolCaller
func (*Orchestrator) ListServiceClassInstances ¶
func (o *Orchestrator) ListServiceClassInstances() []ServiceInstanceInfo
ListServiceClassInstances returns information about all ServiceClass-based service instances
func (*Orchestrator) RestartService ¶
func (o *Orchestrator) RestartService(name string) error
RestartService restarts a specific service by name
func (*Orchestrator) SetToolCaller ¶
func (o *Orchestrator) SetToolCaller(toolCaller ToolCaller)
SetToolCaller sets the ToolCaller for ServiceClass-based services This is called after the aggregator is available
func (*Orchestrator) Start ¶
func (o *Orchestrator) Start(ctx context.Context) error
Start initializes and starts all services (both static and ServiceClass-based).
func (*Orchestrator) StartService ¶
func (o *Orchestrator) StartService(name string) error
StartService starts a specific service by name. For MCP servers, this method waits for the server to be fully registered with the aggregator before returning, ensuring that tools are available.
func (*Orchestrator) Stop ¶
func (o *Orchestrator) Stop() error
Stop gracefully stops all services (both static and ServiceClass-based).
func (*Orchestrator) StopService ¶
func (o *Orchestrator) StopService(name string) error
StopService stops a specific service by name
func (*Orchestrator) SubscribeToServiceInstanceEvents ¶
func (o *Orchestrator) SubscribeToServiceInstanceEvents() <-chan ServiceInstanceEvent
SubscribeToServiceInstanceEvents returns a channel for receiving ServiceClass-based service instance events
func (*Orchestrator) SubscribeToStateChanges ¶
func (o *Orchestrator) SubscribeToStateChanges() <-chan ServiceStateChangedEvent
SubscribeToStateChanges returns a channel for state change events.
type ServiceInstanceEvent ¶
type ServiceInstanceEvent struct {
Name string `json:"name"`
ServiceType string `json:"serviceType"`
OldState string `json:"oldState"`
NewState string `json:"newState"`
OldHealth string `json:"oldHealth"`
NewHealth string `json:"newHealth"`
Error string `json:"error,omitempty"`
Timestamp time.Time `json:"timestamp"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
ServiceInstanceEvent represents a service instance state change event
type ServiceInstanceInfo ¶
type ServiceInstanceInfo struct {
Name string `json:"name"`
ServiceClassName string `json:"serviceClassName"`
ServiceClassType string `json:"serviceClassType"`
State string `json:"state"`
Health string `json:"health"`
LastError string `json:"lastError,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
LastChecked *time.Time `json:"lastChecked,omitempty"`
ServiceData map[string]interface{} `json:"serviceData,omitempty"`
CreationArgs map[string]interface{} `json:"creationArgs"`
Outputs map[string]interface{} `json:"outputs,omitempty"`
}
ServiceInstanceInfo provides information about a ServiceClass-based service instance
type ServiceStateChangedEvent ¶
type ServiceStateChangedEvent struct {
Name string
ServiceType string
OldState string
NewState string
Health string
Error error
Timestamp int64
}
ServiceStateChangedEvent represents a service state change event.
type ServiceStatus ¶
ServiceStatus represents the status of a service.
type StopReason ¶
type StopReason int
StopReason tracks why a service was stopped.
const ( StopReasonManual StopReason = iota StopReasonDependency )