package main import ( "fmt" "os" "path/filepath" toml "github.com/pelletier/go-toml/v2" ) // Config is the top-level deployment configuration. type Config struct { Workspace string `toml:"workspace"` Registry string `toml:"registry"` MCDSL MCDSLConfig `toml:"mcdsl"` Services []ServiceConfig `toml:"services"` Nodes map[string]*NodeConfig `toml:"nodes"` } // MCDSLConfig points to the shared mcdsl library. type MCDSLConfig struct { Path string `toml:"path"` // relative to workspace } // ServiceConfig describes a deployable service. type ServiceConfig struct { Name string `toml:"name"` Path string `toml:"path"` // relative to workspace Images []string `toml:"images"` Dockerfiles map[string]string `toml:"dockerfiles"` // image name -> Dockerfile path UsesMCDSL bool `toml:"uses_mcdsl"` } // NodeConfig describes a deployment target machine. type NodeConfig struct { Host string `toml:"host"` User string `toml:"user"` Containers map[string]*ContainerConfig `toml:"containers"` } // ContainerConfig describes a container to run on a node. type ContainerConfig struct { Image string `toml:"image"` Network string `toml:"network"` User string `toml:"user"` Volumes []string `toml:"volumes"` Ports []string `toml:"ports"` Restart string `toml:"restart"` Cmd []string `toml:"cmd"` } // LoadConfig reads and parses a TOML config file. func LoadConfig(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config %s: %w", path, err) } var cfg Config if err := toml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parse config %s: %w", path, err) } return &cfg, nil } // FindService looks up a service by name. func (c *Config) FindService(name string) (*ServiceConfig, error) { for i := range c.Services { if c.Services[i].Name == name { return &c.Services[i], nil } } return nil, fmt.Errorf("service %q not found in config", name) } // FindNode looks up a node by name. func (c *Config) FindNode(name string) (*NodeConfig, error) { node, ok := c.Nodes[name] if !ok { return nil, fmt.Errorf("node %q not found in config", name) } return node, nil } // ServicePath returns the absolute path to a service directory. func (c *Config) ServicePath(svc *ServiceConfig) string { return filepath.Join(c.Workspace, svc.Path) } // ImageRef returns the full registry reference for an image // (e.g. "mcr.svc.mcp.metacircular.net:8443/mc-proxy"). func (c *Config) ImageRef(image string) string { return c.Registry + "/" + image }