Documentation
¶
Overview ¶
Package app provides application bootstrap, lifecycle management, and configuration management for muster.
This package implements the central application lifecycle control following the API Service Locator Pattern and clean separation of concerns. It handles initialization, configuration loading and management, service setup, API adapter registration, and execution mode determination.
Architecture Overview ¶
The app package serves as the application's bootstrap layer and configuration bridge, with five core components:
1. **Bootstrap (`bootstrap.go`)**: Application initialization and lifecycle management 2. **Configuration (`config.go`)**: Application runtime configuration structure 3. **Configuration Adapter (`config_adapter.go`)**: API integration and MCP configuration tools 4. **Services (`services.go`)**: Service initialization, registration, and dependency management 5. **Modes (`modes.go`)**: Execution mode handlers
Core Components ¶
## Bootstrap (bootstrap.go)
The bootstrap component handles the complete application initialization sequence:
- **Logging Configuration**: Sets up logging based on debug flags and execution mode
- **Configuration Loading**: Supports both layered and single-path configuration strategies
- **Service Initialization**: Creates and initializes all required services and API adapters
- **Mode Selection**: Determines and executes appropriate execution mode based on configuration
### Configuration Loading Strategies
**Layered Configuration (Default)**:
- Default configuration (embedded in binary)
- User configuration (~/.config/muster/config.yaml)
- Project configuration (./.muster/config.yaml)
**Single Path Configuration**:
- Loads from specified directory only
- Useful for testing and deployment scenarios
## Configuration Management (config.go & config_adapter.go)
The configuration system has two layers:
**Application Configuration (`config.go`)**:
- Runtime settings: debug flags, safety settings
- Configuration loading behavior control
- Bootstrap args and preferences
**Configuration Adapter (`config_adapter.go`)**:
- Implements `api.ConfigHandler` interface
- Provides thread-safe configuration access and updates
- Exposes MCP tools for external configuration management
- Handles configuration persistence and reloading
- Supports both project-local and user-global configuration files
### MCP Configuration Tools
The ConfigAdapter exposes the following MCP tools for external clients:
- `config_get`: Retrieve complete muster configuration
- `config_get_aggregator`: Get aggregator-specific settings
- `config_get_global_settings`: Get global configuration settings
- `config_update_aggregator`: Update aggregator configuration
- `config_update_global_settings`: Update global settings
- `config_save`: Persist current configuration to disk
- `config_reload`: Reload configuration from disk and trigger component reloads
## Service Management (services.go)
The Services component implements comprehensive service initialization following the API Service Locator Pattern:
### Initialization Sequence
- **Storage Creation**: Shared configuration storage for persistence
- **API Interfaces**: Tool checker and caller for service integration
- **Orchestrator Setup**: Core service lifecycle manager initialization
- **Service Registry**: Dependency injection and service discovery setup
- **API Adapter Registration**: Register all service adapters with API layer (CRITICAL)
- **Manager Creation**: Workflow and MCPServer managers
- **Definition Loading**: Load component definitions from configuration directories
- **Service Instantiation**: Create concrete service instances from definitions
- **Aggregator Service**: MCP aggregator for external tool access (when enabled)
### Service Dependencies and Registration
**Critical Ordering**: API adapters MUST be registered before API interfaces are created. This ensures handlers are available when APIs attempt to locate them.
**Auto-Start Services**: Services with `AutoStart=true` are automatically registered with the orchestrator and started during application launch.
**Service Types Managed**:
- MCP Server services (external MCP protocol servers)
- Aggregator service (tool aggregation and MCP endpoint)
- Workflow execution services
## Execution Modes (modes.go)
### Server Mode Activated by default:
- **Purpose**: Separation of concerns between client integration and actual application logic
- **Logging**: Text-based output to stdout/stderr
- **Lifecycle**: Start services → Wait for signals → Graceful shutdown
- **Signals**: SIGINT (Ctrl+C), SIGTERM handled for graceful shutdown
- **Use Cases**: systemd services, run in a Kubernetes cluster
Configuration Persistence Strategy ¶
The ConfigAdapter implements intelligent configuration file management:
**Path Resolution Priority**:
- Custom path (if specified via `ConfigPath`)
- Project configuration (`./.muster/config.yaml`)
- User configuration (`~/.config/muster/config.yaml`)
**Automatic Directory Creation**: Creates necessary directories when saving configuration
**Thread Safety**: All configuration access is protected with read-write mutex
Usage Patterns ¶
## Standard Application Startup
cfg := app.NewConfig(true, false, "") // debug enabled
application, err := app.NewApplication(cfg)
if err != nil {
return fmt.Errorf("bootstrap failed: %w", err)
}
return application.Run(ctx)
## Custom Configuration Path
cfg := app.NewConfig(false, false, "/opt/muster/config")
application, err := app.NewApplication(cfg)
if err != nil {
return fmt.Errorf("bootstrap failed: %w", err)
}
return application.Run(ctx)
## Debug Mode for Development
cfg := app.NewConfig(true, true, "") // debug, yolo mode
application, err := app.NewApplication(cfg)
if err != nil {
return fmt.Errorf("bootstrap failed: %w", err)
}
return application.Run(ctx)
API Service Locator Pattern Compliance ¶
The app package strictly follows the architectural principle that all inter-package communication goes through the central API layer:
**Adapter Registration**: Each service creates an API adapter that implements the corresponding handler interface and registers itself with the API layer.
**Service Discovery**: Components retrieve other services through `api.GetXXX()` methods rather than direct package imports.
**Dependency Flow**: app → api ← other packages (one-way dependency)
Error Handling and Resilience ¶
**Fail-Fast Approach**: Critical components (storage, orchestrator, API registration) cause immediate initialization failure if they cannot be set up properly.
**Graceful Degradation**: Optional components (Workflow definitions) log warnings but don't halt initialization.
**Configuration Recovery**: Config reload functionality allows recovery from configuration errors without application restart.
**Signal Handling**: Proper SIGINT/SIGTERM handling ensures graceful shutdown with service cleanup.
Testing Strategy ¶
The package includes comprehensive test coverage with patterns for:
**Unit Testing**: Configuration validation, mode selection, service structure validation
**Integration Testing**: Service initialization sequences, API adapter registration
**Mock-Friendly Design**: Pre-populated configurations in tests to avoid global dependencies
**Test Coverage Focus**: Configuration handling, service creation, mode selection logic
Dependencies and Integration ¶
**Core Dependencies**:
- `internal/config`: Environment configuration and entity persistence
- `internal/orchestrator`: Service lifecycle management
- `internal/api`: Central API layer and service locator
- `internal/aggregator`: MCP tool aggregation service
- `internal/services`: Service abstractions and registry
- `pkg/logging`: Logging system initialization
**Service Components**:
- `internal/workflow`: Workflow definition and execution
- `internal/mcpserver`: MCP server process management
**API Integration**: All service interactions use the API layer interfaces, maintaining clean architectural boundaries and enabling independent testing.
Benefits of This Architecture ¶
**Separation of Concerns**: Clear boundaries between bootstrap, configuration, services, and execution
**Testability**: Each component can be tested independently with mocked dependencies
**Flexibility**: Easy to add new services, modify behavior, or change execution modes
**Configuration Management**: Comprehensive configuration handling with persistence and MCP integration
**Service Isolation**: Services are loosely coupled through the API layer
**Operational Readiness**: Proper signal handling, logging, and error management for production use
Index ¶
- type Application
- type Config
- func (c *Config) WithEvents(enabled bool) *Config
- func (c *Config) WithExtraCAFile(path string) *Config
- func (c *Config) WithOAuthMCPClient(enabled bool, publicURL, clientID string) *Config
- func (c *Config) WithOAuthServer(enabled bool, baseURL string) *Config
- func (c *Config) WithVersion(version string) *Config
- type ConfigAdapter
- func (a *ConfigAdapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
- func (a *ConfigAdapter) GetAggregatorConfig(ctx context.Context) (*config.AggregatorConfig, error)
- func (a *ConfigAdapter) GetConfig(ctx context.Context) (*config.MusterConfig, error)
- func (a *ConfigAdapter) GetTools() []api.ToolMetadata
- func (a *ConfigAdapter) Register()
- func (a *ConfigAdapter) ReloadConfig(ctx context.Context) error
- func (a *ConfigAdapter) SaveConfig(ctx context.Context) error
- func (a *ConfigAdapter) UpdateAggregatorConfig(ctx context.Context, aggregator config.AggregatorConfig) error
- type Services
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Application ¶
type Application struct {
// contains filtered or unexported fields
}
Application represents the main application structure that bootstraps and runs muster. It encapsulates all necessary configuration and services required for the application's lifecycle, including initialization, service management, and execution mode handling.
The Application follows a two-phase initialization pattern:
- Bootstrap phase: Load configuration, initialize logging, setup services
- Execution phase: Run the orchestrator
Example usage:
cfg := app.NewConfig(true, false, "") // debug enabled
app, err := app.NewApplication(cfg)
if err != nil {
return fmt.Errorf("failed to create application: %w", err)
}
return app.Run(ctx)
func NewApplication ¶
func NewApplication(cfg *Config) (*Application, error)
NewApplication creates and initializes a new application instance with the provided configuration. This function performs the complete bootstrap sequence:
- Configures logging based on debug settings
- Loads muster configuration (layered or single-path)
- Initializes all required services and API handlers
- Sets up service dependencies and registrations
Configuration Loading Behavior:
- If cfg.ConfigPath is set: loads from the specified directory only
- If cfg.ConfigPath is empty: uses layered loading (defaults + user + project)
The function returns an error if any critical initialization step fails, including configuration loading or service initialization failures.
Example:
cfg := app.NewConfig(true, false, "/custom/config") // CLI mode, custom config
app, err := app.NewApplication(cfg)
if err != nil {
log.Fatalf("Bootstrap failed: %v", err)
}
func (*Application) Run ¶
func (a *Application) Run(ctx context.Context) error
Run executes the application
Handles graceful shutdown via context cancellation and system signals. The method blocks until the application is terminated or encounters an error.
Returns an error if the selected execution mode fails to start or encounters a runtime error during execution.
type Config ¶
type Config struct {
// Version is the muster build version (e.g., "v0.1.0").
// This is passed to the aggregator to report in the MCP protocol handshake.
Version string
// Debug settings
Debug bool
// Yolo enables "you only live once" mode with relaxed safety checks.
// This setting reduces confirmation prompts and safety validations.
// Use with caution in production environments.
Yolo bool
// ConfigPath specifies a custom configuration directory path.
// When set, disables layered configuration loading and loads from this path only.
// When empty, uses standard layered configuration loading strategy.
ConfigPath string
// MusterConfig holds the loaded muster environment configuration.
// This field is populated during application bootstrap after configuration loading.
MusterConfig *config.MusterConfig
// OAuth MCP Client/Proxy settings (ADR 004 - for authenticating TO remote MCP servers)
OAuthMCPClientEnabled bool // Enable OAuth MCP client/proxy for remote MCP server authentication
OAuthMCPClientPublicURL string // Publicly accessible URL of the Muster Server
OAuthMCPClientID string // OAuth client identifier (CIMD URL)
// OAuth Server settings (ADR 005 - for protecting the Muster Server ITSELF)
OAuthServerEnabled bool // Enable OAuth 2.1 protection for Muster Server
OAuthServerBaseURL string // Base URL of the Muster Server for OAuth issuer
// Events settings
EnableEvents bool // Enable Kubernetes event emission (alpha, disabled by default)
// ExtraCAFile is the path to a PEM file whose certificates are appended to
// the system trust pool at startup. The augmented pool becomes the default
// for outbound HTTP (MCP backends, token exchange, OAuth proxy) by
// overriding http.DefaultTransport.TLSClientConfig.RootCAs.
//
// Use this when muster talks to internal services served behind a private
// CA — e.g. tunnelport's SPIFFE-issued certificates on tunnel pods.
ExtraCAFile string
}
Config holds the application configuration that controls bootstrap behavior and execution modes. This struct encapsulates all settings needed during application initialization and runtime, including debugging options, safety settings, and configuration loading behavior.
The configuration supports both layered and single-path configuration loading strategies:
- Layered: Merges configuration from defaults, user config, and project config
- Single-path: Loads configuration from a specific directory only
Field descriptions:
- Debug: Enables debug-level logging and additional diagnostic output
- Yolo: Enables "you only live once" mode with relaxed safety checks
- ConfigPath: Optional custom configuration directory path
- MusterConfig: Loaded muster configuration (populated during bootstrap)
func NewConfig ¶
NewConfig creates a new application configuration with the specified settings. This is the primary constructor for application configuration, taking all essential runtime args needed for application bootstrap and execution.
Args:
- debug: enables debug logging and verbose output
- yolo: enables relaxed safety checks and reduced confirmations
- configPath: custom config directory (empty string for default layered loading)
Returns a fully initialized Config struct ready for use with NewApplication.
Example:
// Standard mode with debug enabled cfg := app.NewConfig(true, false, "") // Custom configuration path cfg := app.NewConfig(false, false, "/opt/muster/config")
func (*Config) WithEvents ¶ added in v0.0.233
WithEvents enables or disables Kubernetes event emission. Events are an alpha feature and disabled by default. When enabled, muster emits Kubernetes Events for CRD lifecycle operations and service management.
Args:
- enabled: whether event emission is enabled
Returns the modified Config for method chaining.
func (*Config) WithExtraCAFile ¶ added in v0.1.198
WithExtraCAFile sets the path to a PEM file appended to the system trust pool at startup. See Config.ExtraCAFile for the rationale.
func (*Config) WithOAuthMCPClient ¶
WithOAuthMCPClient adds OAuth MCP client/proxy configuration to the Config. This method enables OAuth MCP client/proxy functionality for authenticating TO remote MCP servers.
Args:
- enabled: whether OAuth MCP client/proxy is enabled
- publicURL: the publicly accessible URL of the Muster Server
- clientID: the OAuth client identifier (CIMD URL)
Returns the modified Config for method chaining.
func (*Config) WithOAuthServer ¶
WithOAuthServer adds OAuth server protection configuration to the Config. This method enables OAuth 2.1 protection for the Muster Server itself (ADR 005). When enabled, clients (like muster agent) must authenticate with OAuth before accessing MCP endpoints.
Note: Full OAuth server configuration (provider, storage, etc.) should be done via the config file. These flags provide convenience overrides for enabling the feature and setting the base URL.
Args:
- enabled: whether OAuth server protection is enabled
- baseURL: the base URL of the Muster Server (used as OAuth issuer)
Returns the modified Config for method chaining.
func (*Config) WithVersion ¶
WithVersion sets the muster build version on the Config. This version is passed to the aggregator to report in the MCP protocol handshake, allowing clients to discover the server version during initialization.
Args:
- version: the build version string (e.g., "v0.1.0", "dev")
Returns the modified Config for method chaining.
type ConfigAdapter ¶
type ConfigAdapter struct {
// contains filtered or unexported fields
}
ConfigAdapter adapts the config system to implement api.ConfigHandler. It provides a thread-safe interface for reading and updating muster configuration and serves as the bridge between the application layer and the API system.
func NewConfigAdapter ¶
func NewConfigAdapter(cfg *config.MusterConfig, configPath string) *ConfigAdapter
NewConfigAdapter creates a new config adapter instance. The configPath arg specifies where to save configuration changes. If empty, the adapter will auto-detect an appropriate path.
func (*ConfigAdapter) ExecuteTool ¶
func (a *ConfigAdapter) ExecuteTool(ctx context.Context, toolName string, args map[string]interface{}) (*api.CallToolResult, error)
ExecuteTool executes a configuration management tool by name with the provided arguments. This is the main entry point for MCP clients to interact with configuration.
func (*ConfigAdapter) GetAggregatorConfig ¶
func (a *ConfigAdapter) GetAggregatorConfig(ctx context.Context) (*config.AggregatorConfig, error)
GetAggregatorConfig returns the aggregator-specific configuration section.
func (*ConfigAdapter) GetConfig ¶
func (a *ConfigAdapter) GetConfig(ctx context.Context) (*config.MusterConfig, error)
GetConfig returns the current muster configuration. This method is thread-safe and returns a copy of the configuration.
func (*ConfigAdapter) GetTools ¶
func (a *ConfigAdapter) GetTools() []api.ToolMetadata
GetTools returns metadata for all configuration management tools provided by this adapter. These tools are exposed through the MCP aggregator for external clients.
func (*ConfigAdapter) Register ¶
func (a *ConfigAdapter) Register()
Register registers the adapter with the API layer. This must be called during application initialization to make the config handler available to other components through the API system.
func (*ConfigAdapter) ReloadConfig ¶
func (a *ConfigAdapter) ReloadConfig(ctx context.Context) error
ReloadConfig reloads the configuration from disk using the centralized loader. This replaces the current in-memory configuration with the version from disk.
func (*ConfigAdapter) SaveConfig ¶
func (a *ConfigAdapter) SaveConfig(ctx context.Context) error
SaveConfig persists the current configuration to disk. If no config path was specified during creation, it attempts to auto-detect an appropriate location (project directory first, then user directory).
func (*ConfigAdapter) UpdateAggregatorConfig ¶
func (a *ConfigAdapter) UpdateAggregatorConfig(ctx context.Context, aggregator config.AggregatorConfig) error
UpdateAggregatorConfig updates the aggregator configuration section. Changes are immediately saved to disk if a valid config path is available.
type Services ¶
type Services struct {
// Orchestrator manages the lifecycle of all registered services.
// It handles service startup, shutdown, dependency resolution, and health monitoring.
Orchestrator *orchestrator.Orchestrator
// OrchestratorAPI provides programmatic access to orchestrator operations.
// This interface allows other components to interact with service management
// functionality through the central API layer.
OrchestratorAPI api.OrchestratorAPI
// ConfigAPI provides programmatic access to configuration management.
// This interface enables runtime configuration updates, persistence,
// and retrieval through the central API layer.
ConfigAPI api.ConfigAPI
// AggregatorPort specifies the port number for the MCP aggregator service.
// This port is used by external MCP clients to connect to the aggregator
// for tool discovery and execution.
AggregatorPort int
// ReconcileManager handles automatic detection and reconciliation of
// configuration changes for MCPServers and Workflows.
// This enables automatic synchronization between desired state (YAML/CRDs)
// and actual state (running services).
ReconcileManager *reconciler.Manager
// StateChangeBridge bridges service state changes from the orchestrator to
// the reconciliation system. This enables status sync when services change
// state at runtime (e.g., crash, health check failure, restart).
StateChangeBridge *reconciler.StateChangeBridge
}
Services holds all initialized services and APIs used by the application. This struct serves as the central registry for all core application components, providing access to service management, API interfaces, and runtime configuration.
The Services struct follows the dependency injection pattern, ensuring that all components are properly initialized and registered before being made available to the application runtime.
Field descriptions:
- Orchestrator: Core service orchestrator responsible for service lifecycle management
- OrchestratorAPI: API interface for orchestrator operations (start, stop, status)
- AggregatorPort: Port number where the MCP aggregator service is listening
- ReconcileManager: Reconciliation manager for automatic change detection
Service Dependencies: The services are initialized in a specific order to handle dependencies:
- Storage and tool interfaces (shared dependencies)
- Service adapters and API registrations
- Manager instances (Workflow, MCPServer)
- Concrete service instances
- Aggregator service (when enabled)
- Reconciliation manager (for automatic change detection)
func InitializeServices ¶
InitializeServices creates and registers all required services for the application. This function implements the complete service initialization sequence, following the API Service Locator Pattern for clean separation of concerns.
Initialization Sequence:
- **Storage Setup**: Creates shared configuration storage for persistence
- **API Interfaces**: Creates tool checker and caller for service integration
- **Orchestrator**: Initializes the core service orchestrator
- **Service Registry**: Sets up the service registry for dependency injection
- **API Adapters**: Creates and registers all service adapters with the API layer
- **Manager Initialization**: Creates managers for Workflow, MCPServer
- **Definition Loading**: Loads component definitions from configuration directories
- **Service Creation**: Creates concrete service instances based on definitions
- **Aggregator Setup**: Initializes MCP aggregator service (when enabled)
Configuration Handling:
- If cfg.ConfigPath is set: uses single-directory configuration loading
- If cfg.ConfigPath is empty: uses layered configuration approach
Service Auto-registration: Services marked with AutoStart=true in their definitions are automatically registered with the orchestrator and will be started when the orchestrator starts.
Error Handling: The function uses a fail-fast approach for critical components but continues initialization for optional components (logging warnings for failures). Critical failures include storage creation, orchestrator setup, and API registration.
Aggregator Service: The MCP aggregator is enabled by default unless explicitly disabled in configuration. It provides MCP protocol support for external tool integration and discovery.
Returns a fully initialized Services struct or an error if critical initialization fails.