Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22a836812f | |||
| 9918859705 |
@@ -51,12 +51,23 @@ func (m *Master) Deploy(ctx context.Context, req *mcpv1.MasterDeployRequest) (*m
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Parse the node's Tailnet IP from its address (host:port).
|
||||
// Resolve the node's address to an IP for DNS registration.
|
||||
// Node addresses may be Tailscale DNS names (e.g., rift.scylla-hammerhead.ts.net:9444)
|
||||
// but MCNS needs an IP address for A records.
|
||||
nodeHost, _, err := net.SplitHostPort(node.Address)
|
||||
if err != nil {
|
||||
resp.Error = fmt.Sprintf("invalid node address %q: %v", node.Address, err)
|
||||
return resp, nil
|
||||
}
|
||||
// If nodeHost is not an IP, resolve it.
|
||||
if net.ParseIP(nodeHost) == nil {
|
||||
ips, lookupErr := net.LookupHost(nodeHost)
|
||||
if lookupErr != nil || len(ips) == 0 {
|
||||
m.Logger.Warn("cannot resolve node address", "host", nodeHost, "err", lookupErr)
|
||||
} else {
|
||||
nodeHost = ips[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Forward deploy to the agent.
|
||||
client, err := m.Pool.Get(nodeName)
|
||||
|
||||
@@ -16,8 +16,10 @@ import (
|
||||
// ServiceDef is the top-level TOML structure for a service definition file.
|
||||
type ServiceDef struct {
|
||||
Name string `toml:"name"`
|
||||
Node string `toml:"node"`
|
||||
Node string `toml:"node,omitempty"`
|
||||
Tier string `toml:"tier,omitempty"`
|
||||
Active *bool `toml:"active,omitempty"`
|
||||
Comment string `toml:"comment,omitempty"`
|
||||
Path string `toml:"path,omitempty"`
|
||||
Build *BuildDef `toml:"build,omitempty"`
|
||||
Components []ComponentDef `toml:"components"`
|
||||
@@ -36,6 +38,7 @@ type RouteDef struct {
|
||||
Port int `toml:"port"`
|
||||
Mode string `toml:"mode,omitempty"`
|
||||
Hostname string `toml:"hostname,omitempty"`
|
||||
Public bool `toml:"public,omitempty"`
|
||||
}
|
||||
|
||||
// ComponentDef describes a single container component within a service.
|
||||
@@ -129,8 +132,9 @@ func validate(def *ServiceDef) error {
|
||||
if def.Name == "" {
|
||||
return fmt.Errorf("service name is required")
|
||||
}
|
||||
if def.Node == "" {
|
||||
return fmt.Errorf("service node is required")
|
||||
// v2: either node or tier must be set. Tier defaults to "worker" if both empty.
|
||||
if def.Node == "" && def.Tier == "" {
|
||||
def.Tier = "worker"
|
||||
}
|
||||
if len(def.Components) == 0 {
|
||||
return fmt.Errorf("service %q must have at least one component", def.Name)
|
||||
@@ -191,8 +195,11 @@ func validateRoutes(compName, svcName string, routes []RouteDef) error {
|
||||
// ToProto converts a ServiceDef to a proto ServiceSpec.
|
||||
func ToProto(def *ServiceDef) *mcpv1.ServiceSpec {
|
||||
spec := &mcpv1.ServiceSpec{
|
||||
Name: def.Name,
|
||||
Active: def.Active != nil && *def.Active,
|
||||
Name: def.Name,
|
||||
Active: def.Active != nil && *def.Active,
|
||||
Comment: def.Comment,
|
||||
Tier: def.Tier,
|
||||
Node: def.Node,
|
||||
}
|
||||
|
||||
for _, c := range def.Components {
|
||||
@@ -213,6 +220,7 @@ func ToProto(def *ServiceDef) *mcpv1.ServiceSpec {
|
||||
Port: int32(r.Port), //nolint:gosec // port range validated
|
||||
Mode: r.Mode,
|
||||
Hostname: r.Hostname,
|
||||
Public: r.Public,
|
||||
})
|
||||
}
|
||||
spec.Components = append(spec.Components, cs)
|
||||
@@ -227,9 +235,11 @@ func ToProto(def *ServiceDef) *mcpv1.ServiceSpec {
|
||||
func FromProto(spec *mcpv1.ServiceSpec, node string) *ServiceDef {
|
||||
active := spec.GetActive()
|
||||
def := &ServiceDef{
|
||||
Name: spec.GetName(),
|
||||
Node: node,
|
||||
Active: &active,
|
||||
Name: spec.GetName(),
|
||||
Node: node,
|
||||
Tier: spec.GetTier(),
|
||||
Active: &active,
|
||||
Comment: spec.GetComment(),
|
||||
}
|
||||
|
||||
for _, c := range spec.GetComponents() {
|
||||
@@ -250,6 +260,7 @@ func FromProto(spec *mcpv1.ServiceSpec, node string) *ServiceDef {
|
||||
Port: int(r.GetPort()),
|
||||
Mode: r.GetMode(),
|
||||
Hostname: r.GetHostname(),
|
||||
Public: r.GetPublic(),
|
||||
})
|
||||
}
|
||||
def.Components = append(def.Components, cd)
|
||||
|
||||
@@ -119,14 +119,8 @@ func TestValidation(t *testing.T) {
|
||||
},
|
||||
wantErr: "service name is required",
|
||||
},
|
||||
{
|
||||
name: "missing node",
|
||||
def: &ServiceDef{
|
||||
Name: "svc",
|
||||
Components: []ComponentDef{{Name: "api", Image: "img:v1"}},
|
||||
},
|
||||
wantErr: "service node is required",
|
||||
},
|
||||
// v2: missing node no longer errors — defaults to tier=worker.
|
||||
// Tested separately in TestValidationNodeTierDefault.
|
||||
{
|
||||
name: "empty components",
|
||||
def: &ServiceDef{
|
||||
|
||||
Reference in New Issue
Block a user