Networking is a module, and a domain module is how you avoid choosing
Connectivity was code beside the module system doing the module system's
job: every machine with an address was on the private network and there
was no way to keep one off.
A manifest can now say its resources are computed by the control plane,
which is what a peer list needs — it is derived from every machine at
once, so nothing could be written in advance. The network is a module
from there on: assigned, resolved, settled, and absent from a machine
nobody gave it to.
Three modules rather than one, because WireGuard is one VPN of several:
mesh-wireguard provides private-network, mesh-addressing
claims the-private-network, one per node
mesh-names provides name-resolution, requires mesh-addressing
networking requires both, and ships no files of its own
The last is the point. Most people want the network up and do not want
to choose a VPN, so `assign networking` takes the only answer to each
requirement silently. The day the catalogue holds a second one there are
two answers, the resolver refuses and names them, and choosing is
assigning the one you want. No flavor field, nothing to configure.
Names left the WireGuard declaration for their own module. They would be
identical over a different private network, and bundling them made one
module out of two things.
Three faults the walk found:
- choosing tailscale still installed WireGuard, dragged back in by the
names needing the mesh's own addresses. Caught now by a claim: running
two VPNs is fine, being *the* mesh network is singular.
- a requirement wanted by two modules was reported twice, identically.
- "this mesh has no hub" was reported when the real cause was that a
node could not be resolved at all. It now names the node and the why.
And a test that asserts the manifests actually shipped, after the claim
went missing from the real one while every test stayed green.
This commit is contained in:
@@ -173,8 +173,52 @@ func (i *Inventory) Catalogue(ctx context.Context) (map[string]catalogue.Manifes
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// ForgetModule removes a module, unless a machine is running it.
|
||||
// Provide records a module the control plane ships with itself.
|
||||
//
|
||||
// The mesh's own private network is one: what computes its files is in this binary, so the
|
||||
// manifest is too. Marked so it can be told apart from a module somebody wrote — not because it
|
||||
// behaves differently, but because "where did this come from" must have an answer for everything
|
||||
// in the catalogue, and "it came with the control plane" is that answer.
|
||||
func (i *Inventory) Provide(ctx context.Context, m catalogue.Manifest) error {
|
||||
raw, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = i.store.Pool().Exec(ctx,
|
||||
`insert into module (name, manifest, version, source)
|
||||
values ($1, $2, $3, 'the control plane')
|
||||
on conflict (name) do update set manifest = excluded.manifest,
|
||||
version = excluded.version, source = 'the control plane'`,
|
||||
m.Module, raw, m.Version)
|
||||
return err
|
||||
}
|
||||
|
||||
// Provided reports whether a module came with the control plane rather than from a repository.
|
||||
func (i *Inventory) Provided(ctx context.Context, name string) (bool, error) {
|
||||
var source *string
|
||||
err := i.store.Pool().QueryRow(ctx,
|
||||
`select source from module where name = $1`, name).Scan(&source)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return source != nil && *source == "the control plane", nil
|
||||
}
|
||||
|
||||
// ForgetModule removes a module, unless a machine is running it, and never one the control plane
|
||||
// provides.
|
||||
func (i *Inventory) ForgetModule(ctx context.Context, name string) error {
|
||||
provided, err := i.Provided(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if provided {
|
||||
// Refused rather than removed and re-created on the next migrate, which would look like
|
||||
// it worked and quietly come back. Taking it off a machine is what "I do not want this"
|
||||
// means, and that is what unassign is for.
|
||||
return fmt.Errorf(
|
||||
"%s comes with the control plane and cannot be forgotten; unassign it instead", name)
|
||||
}
|
||||
|
||||
var on []string
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
`select n.name from assignment a join node n on n.id = a.node where a.module = $1
|
||||
|
||||
Reference in New Issue
Block a user