- CLIConfig gains optional [master] section with address field - dialMaster() creates McpMasterServiceClient (same TLS/token pattern) - deploy: routes through master when [master] configured, --direct flag bypasses master for v1-style agent deployment - undeploy: same master/direct routing pattern - Master responses show per-step results (deploy, dns, edge) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
126 lines
3.4 KiB
Go
126 lines
3.4 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
toml "github.com/pelletier/go-toml/v2"
|
|
)
|
|
|
|
// CLIConfig is the configuration for the mcp CLI binary.
|
|
type CLIConfig struct {
|
|
Services ServicesConfig `toml:"services"`
|
|
Build BuildConfig `toml:"build"`
|
|
MCIAS MCIASConfig `toml:"mcias"`
|
|
Auth AuthConfig `toml:"auth"`
|
|
Nodes []NodeConfig `toml:"nodes"`
|
|
Master *CLIMasterConfig `toml:"master,omitempty"`
|
|
}
|
|
|
|
// CLIMasterConfig holds the optional master connection settings.
|
|
// When configured, deploy/undeploy/status go through the master
|
|
// instead of directly to agents.
|
|
type CLIMasterConfig struct {
|
|
Address string `toml:"address"` // master gRPC address (e.g. "100.95.252.120:9555")
|
|
}
|
|
|
|
// BuildConfig holds settings for building container images.
|
|
type BuildConfig struct {
|
|
Workspace string `toml:"workspace"`
|
|
}
|
|
|
|
// ServicesConfig defines where service definition files live.
|
|
type ServicesConfig struct {
|
|
Dir string `toml:"dir"`
|
|
}
|
|
|
|
// MCIASConfig holds MCIAS connection settings, shared by CLI and agent.
|
|
type MCIASConfig struct {
|
|
ServerURL string `toml:"server_url"`
|
|
CACert string `toml:"ca_cert"`
|
|
ServiceName string `toml:"service_name"`
|
|
}
|
|
|
|
// AuthConfig holds authentication settings for the CLI.
|
|
type AuthConfig struct {
|
|
TokenPath string `toml:"token_path"`
|
|
Username string `toml:"username"` // optional, for unattended operation
|
|
PasswordFile string `toml:"password_file"` // optional, for unattended operation
|
|
}
|
|
|
|
// NodeConfig defines a managed node that the CLI connects to.
|
|
type NodeConfig struct {
|
|
Name string `toml:"name"`
|
|
Address string `toml:"address"`
|
|
}
|
|
|
|
// LoadCLIConfig reads and validates a CLI configuration file.
|
|
// Environment variables override file values for select fields.
|
|
func LoadCLIConfig(path string) (*CLIConfig, error) {
|
|
data, err := os.ReadFile(path) //nolint:gosec // config path from trusted CLI flag
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read config %q: %w", path, err)
|
|
}
|
|
|
|
var cfg CLIConfig
|
|
if err := toml.Unmarshal(data, &cfg); err != nil {
|
|
return nil, fmt.Errorf("parse config %q: %w", path, err)
|
|
}
|
|
|
|
applyCLIEnvOverrides(&cfg)
|
|
|
|
if err := validateCLIConfig(&cfg); err != nil {
|
|
return nil, fmt.Errorf("validate config: %w", err)
|
|
}
|
|
|
|
return &cfg, nil
|
|
}
|
|
|
|
func applyCLIEnvOverrides(cfg *CLIConfig) {
|
|
if v := os.Getenv("MCP_SERVICES_DIR"); v != "" {
|
|
cfg.Services.Dir = v
|
|
}
|
|
if v := os.Getenv("MCP_BUILD_WORKSPACE"); v != "" {
|
|
cfg.Build.Workspace = v
|
|
}
|
|
if v := os.Getenv("MCP_MCIAS_SERVER_URL"); v != "" {
|
|
cfg.MCIAS.ServerURL = v
|
|
}
|
|
if v := os.Getenv("MCP_MCIAS_CA_CERT"); v != "" {
|
|
cfg.MCIAS.CACert = v
|
|
}
|
|
if v := os.Getenv("MCP_MCIAS_SERVICE_NAME"); v != "" {
|
|
cfg.MCIAS.ServiceName = v
|
|
}
|
|
if v := os.Getenv("MCP_AUTH_TOKEN_PATH"); v != "" {
|
|
cfg.Auth.TokenPath = v
|
|
}
|
|
}
|
|
|
|
func validateCLIConfig(cfg *CLIConfig) error {
|
|
if cfg.Services.Dir == "" {
|
|
return fmt.Errorf("services.dir is required")
|
|
}
|
|
if cfg.MCIAS.ServerURL == "" {
|
|
return fmt.Errorf("mcias.server_url is required")
|
|
}
|
|
if cfg.MCIAS.ServiceName == "" {
|
|
return fmt.Errorf("mcias.service_name is required")
|
|
}
|
|
if cfg.Auth.TokenPath == "" {
|
|
return fmt.Errorf("auth.token_path is required")
|
|
}
|
|
|
|
// Expand ~ in workspace path.
|
|
if strings.HasPrefix(cfg.Build.Workspace, "~/") {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return fmt.Errorf("expand workspace path: %w", err)
|
|
}
|
|
cfg.Build.Workspace = home + cfg.Build.Workspace[1:]
|
|
}
|
|
|
|
return nil
|
|
}
|