Merge pull request 'The profile names the network manager that is running, and travels in every report (hq ADR 0161)' (#61) from feat/the-profile-names-the-uplink-and-travels-in-the-report into main
This commit was merged in pull request #61.
This commit is contained in:
+13
-5
@@ -818,10 +818,7 @@ func enrol(ctx context.Context, opts options) error {
|
|||||||
// control plane cannot decide what a node should run without it, so it travels with the
|
// control plane cannot decide what a node should run without it, so it travels with the
|
||||||
// request instead of being asked for in a second round trip.
|
// request instead of being asked for in a second round trip.
|
||||||
detected := profile.Detect(ctx, profile.Default(nil), opts.timeout)
|
detected := profile.Detect(ctx, profile.Default(nil), opts.timeout)
|
||||||
reported := map[string]any{}
|
reported := profileAsReported(detected)
|
||||||
if raw, err := json.Marshal(detected); err == nil {
|
|
||||||
_ = json.Unmarshal(raw, &reported)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signed with the identity just generated, so the mesh can tell this machine from anyone else
|
// Signed with the identity just generated, so the mesh can tell this machine from anyone else
|
||||||
// who knows its public key (novox/hq issue 083).
|
// who knows its public key (novox/hq issue 083).
|
||||||
@@ -1418,7 +1415,8 @@ func applyAndKeep(ctx context.Context, opts options, raw []byte, signed *store.D
|
|||||||
sched.Sync(declared, held)
|
sched.Sync(declared, held)
|
||||||
}
|
}
|
||||||
|
|
||||||
report := link.Report{Carried: carriedPorts(updated), Declared: digestOf(raw), Host: runningVersion()}
|
report := link.Report{Carried: carriedPorts(updated), Declared: digestOf(raw), Host: runningVersion(),
|
||||||
|
Profile: profileAsReported(profile.Detect(ctx, profile.Default(nil), opts.timeout))}
|
||||||
// Which of this machine's links face outside, for the filter the mesh writes around them
|
// Which of this machine's links face outside, for the filter the mesh writes around them
|
||||||
// (novox/hq ADR 0140). Reported whatever the node's mode: a converged node's filter needs it,
|
// (novox/hq ADR 0140). Reported whatever the node's mode: a converged node's filter needs it,
|
||||||
// and an adopted one becomes converged without a further round trip. A machine that cannot read
|
// and an adopted one becomes converged without a further round trip. A machine that cannot read
|
||||||
@@ -1630,3 +1628,13 @@ func refuseOlder(kept store.Declared, keptErr error, sequence int64) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// profileAsReported is the profile as the mesh reads it — the same bytes enrolment sends, so a
|
||||||
|
// report's profile and an enrolment's are one shape on the controller's side (novox/hq ADR 0161).
|
||||||
|
func profileAsReported(detected profile.Profile) map[string]any {
|
||||||
|
reported := map[string]any{}
|
||||||
|
if raw, err := json.Marshal(detected); err == nil {
|
||||||
|
_ = json.Unmarshal(raw, &reported)
|
||||||
|
}
|
||||||
|
return reported
|
||||||
|
}
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ type Report struct {
|
|||||||
// and the mesh's up in its place, and where the found configuration's original was kept.
|
// and the mesh's up in its place, and where the found configuration's original was kept.
|
||||||
Tunnel *CarriedTunnel `json:"tunnel,omitempty"`
|
Tunnel *CarriedTunnel `json:"tunnel,omitempty"`
|
||||||
|
|
||||||
|
// Profile is what this machine can do, detected again by the apply that reports (novox/hq
|
||||||
|
// ADR 0161) — the same shape enrolment sends — so a capability gained or lost since enrolment,
|
||||||
|
// a network manager switched, reaches the mesh at the next push rather than never.
|
||||||
|
Profile map[string]any `json:"profile,omitempty"`
|
||||||
|
|
||||||
// Host is the version of the host that produced this report (novox/hq ADR 0141).
|
// Host is the version of the host that produced this report (novox/hq ADR 0141).
|
||||||
//
|
//
|
||||||
// Without it nothing can say a machine is behind, so "every machine current with its source"
|
// Without it nothing can say a machine is behind, so "every machine current with its source"
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ const (
|
|||||||
// state: whether one IS running. Assignment needs the first.
|
// state: whether one IS running. Assignment needs the first.
|
||||||
CapSeat = "seat"
|
CapSeat = "seat"
|
||||||
CapPrivileged = "privileged"
|
CapPrivileged = "privileged"
|
||||||
|
|
||||||
|
// The network manager this machine runs, one capability per dialect (novox/hq ADR 0161): the
|
||||||
|
// uplink seat's holder declares its own, so the holder for a manager the machine does not run
|
||||||
|
// is refused the way any missing capability is, naming it. Active, not installed — a machine
|
||||||
|
// may have two of these on disk and runs one.
|
||||||
|
CapUplinkNetworkManager = "uplink-networkmanager"
|
||||||
|
CapUplinkSystemdNetworkd = "uplink-systemd-networkd"
|
||||||
|
CapUplinkDhcpcd = "uplink-dhcpcd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// commandCapability is the shape most detectors take: run something, and treat a working
|
// commandCapability is the shape most detectors take: run something, and treat a working
|
||||||
@@ -202,6 +210,21 @@ func Default(runner Runner) []Detector {
|
|||||||
why: "asks the kernel for interfaces — needs the module, not just the tool",
|
why: "asks the kernel for interfaces — needs the module, not just the tool",
|
||||||
runner: runner,
|
runner: runner,
|
||||||
},
|
},
|
||||||
|
commandCapability{
|
||||||
|
name: CapUplinkNetworkManager, command: "systemctl", args: []string{"is-active", "NetworkManager.service"},
|
||||||
|
why: "asks the init whether NetworkManager is running — the dialect the uplink seat's holder must speak",
|
||||||
|
runner: runner,
|
||||||
|
},
|
||||||
|
commandCapability{
|
||||||
|
name: CapUplinkSystemdNetworkd, command: "systemctl", args: []string{"is-active", "systemd-networkd.service"},
|
||||||
|
why: "asks the init whether systemd-networkd is running — the dialect the uplink seat's holder must speak",
|
||||||
|
runner: runner,
|
||||||
|
},
|
||||||
|
commandCapability{
|
||||||
|
name: CapUplinkDhcpcd, command: "systemctl", args: []string{"is-active", "dhcpcd.service"},
|
||||||
|
why: "asks the init whether dhcpcd is running — the dialect the uplink seat's holder must speak",
|
||||||
|
runner: runner,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package profile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The uplink seat's holder must be the dialect the machine runs (novox/hq ADR 0161): the profile
|
||||||
|
// names the network manager found active, one capability per manager, and nothing for one that is
|
||||||
|
// merely installed.
|
||||||
|
func TestTheProfileNamesTheNetworkManagerThatIsRunning(t *testing.T) {
|
||||||
|
runner := func(_ context.Context, name string, args ...string) (string, error) {
|
||||||
|
if name == "systemctl" && len(args) == 2 && args[0] == "is-active" {
|
||||||
|
if args[1] == "NetworkManager.service" {
|
||||||
|
return "active\n", nil
|
||||||
|
}
|
||||||
|
return "inactive\n", errors.New("exit status 3")
|
||||||
|
}
|
||||||
|
return "", errors.New("not here")
|
||||||
|
}
|
||||||
|
var have []Detector
|
||||||
|
for _, d := range Default(Runner(runner)) {
|
||||||
|
switch d.Name() {
|
||||||
|
case CapUplinkNetworkManager, CapUplinkSystemdNetworkd, CapUplinkDhcpcd:
|
||||||
|
have = append(have, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(have) != 3 {
|
||||||
|
t.Fatalf("expected a detector per manager, found %d", len(have))
|
||||||
|
}
|
||||||
|
for _, d := range have {
|
||||||
|
v := d.Detect(context.Background())
|
||||||
|
want := d.Name() == CapUplinkNetworkManager
|
||||||
|
if v.Present != want {
|
||||||
|
t.Errorf("%s: present=%v, want %v (%s)", d.Name(), v.Present, want, v.Detail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user