mesh/delivery closed: a newer head of the same pull request
mesh/check checking 3968849b1b36 on a7a1fbd34e1d | novox/mesh-sdk#98 in group feat/1126-nodes-compose
112 lines
4.2 KiB
Go
112 lines
4.2 KiB
Go
package frombus
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/compose"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// Export is one node's placement file as the composition input the controller fills says it (novox/hq ADR 0555 §6,
|
|
// issue 1126): the inverse of Input for what a person decides, so the controller's one read-only verb
|
|
// `placement-export` answers, from its own store by its own code, exactly what the seed writes into the catalogue.
|
|
// What the machine observes (its record) is not in it.
|
|
func Export(in compose.Input, node string) (delivery.Placement, error) {
|
|
var n *compose.Node
|
|
for i := range in.Nodes {
|
|
if in.Nodes[i].Name == node {
|
|
n = &in.Nodes[i]
|
|
}
|
|
}
|
|
if n == nil {
|
|
return delivery.Placement{}, fmt.Errorf("frombus: the input has no node %q", node)
|
|
}
|
|
// At the version the placement file is read at, with a list of modules even when none is placed: the export is the
|
|
// file the seed writes (cmd/placement-seed), and the reader refuses a value of version 0 or without its modules.
|
|
p := delivery.Placement{V: delivery.Version, Node: node, Modules: []delivery.PlacedModule{}, Decided: delivery.NodeDecided{
|
|
Endpoint: n.Place.Endpoint, Site: n.Place.Site, Hub: n.Place.Hub, Address: n.Place.Address,
|
|
PublicDomain: n.PublicDomain, Account: n.Account, AccountHome: n.AccountHome, AgentAccount: n.AgentAccount,
|
|
AgentHome: n.AgentAccountHome, Adopted: n.Adopted, Taken: n.Taken}}
|
|
// The tunnel found at the node's adoption: the one its private network took over, or, on the hub, the mesh's adopted
|
|
// one whether or not the hub took it; and the names a person gave the hub's carried peers.
|
|
if t, ok := in.Tunnels[node]; ok {
|
|
rt := recordTunnelOf(t.Tunnel)
|
|
p.Decided.Tunnel = &rt
|
|
} else if in.Adopted != nil && in.Adopted.Hub == node {
|
|
rt := recordTunnelOf(in.Adopted.Tunnel)
|
|
p.Decided.Tunnel = &rt
|
|
}
|
|
if n.Place.Hub {
|
|
for _, c := range in.CarriedPeers {
|
|
if c.Named != "" {
|
|
if p.Decided.PeerNames == nil {
|
|
p.Decided.PeerNames = map[string]string{}
|
|
}
|
|
p.Decided.PeerNames[c.PublicKey] = c.Named
|
|
}
|
|
}
|
|
}
|
|
for _, module := range n.Assigned {
|
|
m := delivery.PlacedModule{Module: module}
|
|
for port, at := range n.Ports[module] {
|
|
if m.Ports == nil {
|
|
m.Ports = map[string]int{}
|
|
}
|
|
m.Ports[strconv.Itoa(port)] = at
|
|
}
|
|
for provision, to := range n.Bound[module] {
|
|
if m.Bindings == nil {
|
|
m.Bindings = map[string]delivery.Provider{}
|
|
}
|
|
m.Bindings[provision] = delivery.Provider{Node: to.Node, Module: to.Module}
|
|
}
|
|
// A module in the settings form keeps its config values in its layers, not in mesh-config: they are exported with
|
|
// the placement. A module in the config form has mesh-config's values laid into its layer, which are not.
|
|
settingsForm := !in.Catalogue[module].DeclaresConfig()
|
|
for _, layer := range n.Settings[module] {
|
|
if layer.From == catalogue.MeshWideLayer {
|
|
m.HasMesh, m.MeshWide = true, layer.Placement
|
|
if settingsForm && len(layer.Values) > 0 {
|
|
m.MeshValues = layer.Values
|
|
}
|
|
} else {
|
|
m.HasLayer, m.Layer = true, layer.Placement
|
|
if settingsForm && len(layer.Values) > 0 {
|
|
m.Values = layer.Values
|
|
}
|
|
}
|
|
}
|
|
p.Modules = append(p.Modules, m)
|
|
}
|
|
for provision, to := range n.Pins {
|
|
if p.Pins == nil {
|
|
p.Pins = map[string]delivery.Provider{}
|
|
}
|
|
p.Pins[provision] = delivery.Provider{Node: to.Node, Module: to.Module}
|
|
}
|
|
for _, h := range in.Holdings {
|
|
if h.Node == node {
|
|
p.Holds = append(p.Holds, delivery.Holding{Claim: h.Claim, Scope: h.Scope, Module: h.Module, Site: h.Site, Kind: h.Kind})
|
|
}
|
|
}
|
|
sort.SliceStable(p.Holds, func(i, j int) bool {
|
|
if p.Holds[i].Claim != p.Holds[j].Claim {
|
|
return p.Holds[i].Claim < p.Holds[j].Claim
|
|
}
|
|
return p.Holds[i].Module < p.Holds[j].Module
|
|
})
|
|
return p, nil
|
|
}
|
|
|
|
func recordTunnelOf(t compose.Tunnel) delivery.RecordTunnel {
|
|
out := delivery.RecordTunnel{Interface: t.Interface, Unit: t.Unit, Config: t.Config, Port: t.Port, MTU: t.MTU,
|
|
Address: t.Address, Range: t.Range, PublicKey: t.PublicKey}
|
|
for _, peer := range t.Peers {
|
|
out.Peers = append(out.Peers, delivery.RecordTunnelPeer{PublicKey: peer.PublicKey, Address: peer.Address})
|
|
}
|
|
return out
|
|
}
|