A carried peer is nameable, and the mesh answers for it (hq 112)
The tunnel the hub took over routes to machines the predecessor knows by name and the mesh knew only by address — taking the resolver in that state silences three machines at once. Now the operator states which machine a carried address is (overlay name <address> <name>), the statement rides tunnel_peer.named, and namesInTheMesh answers for named not-yet-enrolled peers — one reading, so the hosts fact, a container's hosts and the resolver cannot disagree. Enrolment verifies the word: a machine enrolling under a named peer's key with a different name is refused where the operator can read it, the stated name keeps the carried address, and an enrolled peer's name is the node's — naming it again refuses. The issue's rule holds: a name the predecessor answers for keeps resolving until the machine behind it is a node.
This commit is contained in:
@@ -85,6 +85,9 @@ type CarriedPeer struct {
|
||||
Address string
|
||||
// EnrolledAs names the node that enrolled with this key, or is empty while none has.
|
||||
EnrolledAs string
|
||||
// Named is what the operator said this peer is, before it enrolled (novox/hq issue 112) —
|
||||
// a statement the mesh records and cannot verify, which is why enrolment checks it.
|
||||
Named string
|
||||
}
|
||||
|
||||
// ErrNoTunnel is asking about a tunnel on a node that presented none.
|
||||
@@ -247,7 +250,7 @@ func (i *Inventory) AdoptedTunnel(ctx context.Context) (Tunnel, string, bool, er
|
||||
// adopted no tunnel.
|
||||
func (i *Inventory) CarriedPeers(ctx context.Context) ([]CarriedPeer, error) {
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
`select p.public_key, host(p.address), coalesce(n.name, '')
|
||||
`select p.public_key, host(p.address), coalesce(n.name, ''), coalesce(p.named, '')
|
||||
from tunnel_peer p
|
||||
join node hub on hub.id = p.node and hub.is_hub
|
||||
and hub.tunnel is not null and hub.overlay_key = hub.tunnel->>'public_key'
|
||||
@@ -260,7 +263,7 @@ func (i *Inventory) CarriedPeers(ctx context.Context) ([]CarriedPeer, error) {
|
||||
var out []CarriedPeer
|
||||
for rows.Next() {
|
||||
var p CarriedPeer
|
||||
if err := rows.Scan(&p.PublicKey, &p.Address, &p.EnrolledAs); err != nil {
|
||||
if err := rows.Scan(&p.PublicKey, &p.Address, &p.EnrolledAs, &p.Named); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, p)
|
||||
@@ -268,6 +271,46 @@ func (i *Inventory) CarriedPeers(ctx context.Context) ([]CarriedPeer, error) {
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// NamePeer records the operator's statement that a carried address is a particular machine
|
||||
// (novox/hq issue 112). Refused when nothing carried has that address, when a node of the mesh
|
||||
// already has the name — the statement would collide with something verified — and when another
|
||||
// peer was already named it. Naming an enrolled peer is refused too: its name is the node's now.
|
||||
func (i *Inventory) NamePeer(ctx context.Context, address, name string) error {
|
||||
peers, err := i.CarriedPeers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var at *CarriedPeer
|
||||
for idx := range peers {
|
||||
if peers[idx].Address == address {
|
||||
at = &peers[idx]
|
||||
continue
|
||||
}
|
||||
if peers[idx].Named == name {
|
||||
return fmt.Errorf("the carried peer at %s is already named %q — one machine per name",
|
||||
peers[idx].Address, name)
|
||||
}
|
||||
}
|
||||
if at == nil {
|
||||
return fmt.Errorf("no carried peer has the address %s — `overlay show` lists them", address)
|
||||
}
|
||||
if at.EnrolledAs != "" {
|
||||
return fmt.Errorf("the peer at %s enrolled as %q — its name is the node's now", address, at.EnrolledAs)
|
||||
}
|
||||
if _, err := i.NodeByName(ctx, name); err == nil {
|
||||
return fmt.Errorf("%q is a node of this mesh — a carried peer cannot be named after one", name)
|
||||
}
|
||||
tag, err := i.store.Pool().Exec(ctx,
|
||||
`update tunnel_peer set named = $2 where host(address) = $1`, address, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tag.RowsAffected() == 0 {
|
||||
return fmt.Errorf("no carried peer has the address %s", address)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FoundTunnel is a node's found tunnel with the node's mode, for composing: the takeover is
|
||||
// declared to an adopted node only, since only there is a found unit kept to be stopped.
|
||||
type FoundTunnel struct {
|
||||
|
||||
Reference in New Issue
Block a user