325 lines
15 KiB
Go
325 lines
15 KiB
Go
// Package compose is the controller's composition of a machine, as a function over a plain input (novox/hq ADR 0453
|
|
// clause 3, ADR 0446 clause 4): what the rest of the mesh offers and holds, the private network's generator, one
|
|
// node's resolution and, in the issues after, its rendering and its declaration.
|
|
//
|
|
// **It never allocates, makes, writes, logs or raises.** The controller composes with a store behind it; this
|
|
// package is its Reading and Foreseeing modes over data. Everything the controller reads from its store is a field of
|
|
// Input, and everything a send would make or record (a port, a credential, a seat passed on, a node left out) is
|
|
// returned for the caller to act on, never done. Input is never changed by a call. No field holds a secret value
|
|
// the composition needs: sealed values are optional inputs, and without them the composition uses stand-ins named
|
|
// foreseen. The logic is the controller's, ported from mesh-controller cmd/mesh-controller at commit
|
|
// 6c2a8d62100cb7d491f8eb9a623e1eeea5ec0de1 (plan.go, network.go, holdings.go, seat_pass.go), in the same order, with the
|
|
// same refusals in the same words, so that a comparison node for node is a fair one.
|
|
//
|
|
// It imports the standard library and mesh-sdk's own packages only.
|
|
// It reads no environment variable: the range the mesh allocates from and the suffix of its internal names are fields of Input.
|
|
package compose
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// Input is everything the composition reads. Each field is what one read of the controller's inventory answers, named
|
|
// beside it; the controller's adapter fills it from its stores and the assigner from the mesh's facts and buckets
|
|
// (ADR 0446 clause 2).
|
|
type Input struct {
|
|
// Catalogue is the shelf: every module's manifest by name (inv.Catalogue), as it is to be composed. A recorded
|
|
// module kept at the build a machine runs (keepRecorded) is that node's Kept, applied to its own resolution only (never to the rest of the mesh).
|
|
Catalogue map[string]catalogue.Manifest
|
|
// Nodes is every node the mesh has (inv.Nodes and inv.Overlays together, one row per node).
|
|
Nodes []Node
|
|
// Holdings is every seat whose holder is on record (inv.Holdings).
|
|
Holdings []catalogue.Held
|
|
// Licences is every licence the mesh holds, with the machines that use it (open.Licences); none for a mesh with no
|
|
// licence.
|
|
Licences []Licence
|
|
|
|
// OverlayCIDR is the range the mesh allocates from when no tunnel was adopted, as genesis was told it (the
|
|
// controller's OverlayCIDRVar); empty means DefaultOverlayCIDR. The package reads no environment.
|
|
OverlayCIDR string
|
|
// InternalSuffix is what the mesh's internal names end in (the controller's MESH_INTERNAL_SUFFIX), with or without a leading
|
|
// dot; empty means overlay.DefaultSuffix. A fact of the whole mesh, so it is in the Input and never read from the environment.
|
|
InternalSuffix string
|
|
// Tunnels is, by node name, the found tunnel whose key is the node's overlay key (inv.Tunnels).
|
|
Tunnels map[string]FoundTunnel
|
|
// Adopted is the hub's found tunnel and the hub's name, whether or not the hub took it (inv.AdoptedTunnel); nil
|
|
// when no hub has one.
|
|
Adopted *AdoptedTunnel
|
|
// CarriedPeers is every peer of the adopted tunnel (inv.CarriedPeers).
|
|
CarriedPeers []CarriedPeer
|
|
// Joining is the nodes that hold a live enrolment token (inv.NodesWithALiveToken).
|
|
Joining []string
|
|
|
|
// Credentials is how each pair credential a node takes from elsewhere stands, never its value (what inv.SecretFor,
|
|
// SharedSecretFor and GivenPairSecret would answer): held, to be made by the next send, only a person's to give, or
|
|
// refused. A need with no entry here is one the next send would make.
|
|
Credentials []Credential
|
|
|
|
// Built is every repository the mesh has built (the keys of inv.Held): what tells a reference recorded with an address
|
|
// from an image a module runs straight from a public registry.
|
|
Built []string
|
|
// OperatorExport is every operator-sealed secret in the mesh, for a module that keeps them (inv.OperatorExport): sealed
|
|
// values the composition carries without opening. Nil when the mesh has no operator key.
|
|
OperatorExport *catalogue.KeptExport
|
|
|
|
// Issued is the credentials made for the consumers of each provider (inv.SecretsFrom): one row for each pair credential
|
|
// that exists, by the provider node it is for. The grants a provider must create are read from these, so a credential not
|
|
// made yet has no grant until the send that makes it.
|
|
Issued []Issued
|
|
// OwnSecrets is the own secrets held on each machine (the module_secret rows): who made each, and the key it is sealed to.
|
|
// Their sealed values are optional.
|
|
OwnSecrets []OwnSecretRow
|
|
// KeptCoreBoxes is the vault's box last kept for each core credential on each machine (inv.KeptCoreBoxes).
|
|
KeptCoreBoxes []CoreBox
|
|
// BusUsers is the bus's user list as the controller composes it from the bus records and the hashes it holds (composeBusUsers),
|
|
// for the machine that runs the bus: names and hashes, never passwords. Empty when the Input does not carry it, and then
|
|
// the composition uses a stand-in, named foreseen. BusMissing are the users left out of it for want of a credential.
|
|
BusUsers string
|
|
BusMissing []string
|
|
// BusMinted are the bus users the mesh has minted a password hash for (inv.BusUserHash): `<node>.<module>` for a module and
|
|
// `provisioner.<node>` for a machine's provisioner client.
|
|
BusMinted []string
|
|
// BusMemberships is, by node, the membership sealed to it for the bus the mesh is moving to (inv.BusMemberships).
|
|
BusMemberships map[string]string
|
|
// Authority is the mesh's own certificate (identity.EstablishAuthority), public. Optional.
|
|
Authority string
|
|
|
|
// CurrentBuilds is, by module, the commit of the build the mesh holds for it (inv.CurrentBuilds, the commit it was built from);
|
|
// BuildIDs the build made from a commit of a module (inv.BuildOf), by module then commit. Read only to name the builds a
|
|
// declaration carries to a node-engine that reads them.
|
|
CurrentBuilds map[string]string
|
|
BuildIDs map[string]map[string]string
|
|
}
|
|
|
|
// Issued is one pair credential made for a consumer of a provider (inv.Secret): ForProvider is its copy sealed to the
|
|
// provider, optional.
|
|
type Issued struct {
|
|
Provision string
|
|
Consumer string
|
|
ConsumerModule string
|
|
Local string
|
|
Provider string
|
|
ForProvider string
|
|
}
|
|
|
|
// OwnSecretRow is one own secret held on a machine: Origin is `made` (the mesh generated it) or `accepted` (a person gave it),
|
|
// SealedTo the sealing key it is sealed to, and Sealed its value sealed to that key, optional.
|
|
type OwnSecretRow struct {
|
|
Node string
|
|
Module string
|
|
Name string
|
|
Origin string
|
|
SealedTo string
|
|
Sealed string
|
|
}
|
|
|
|
// CoreBox is the vault's box for one core credential of one machine, as last kept (inv.CoreBox).
|
|
type CoreBox struct {
|
|
Node string
|
|
Module string
|
|
Name string
|
|
Generation int
|
|
SealedTo string
|
|
Box json.RawMessage
|
|
}
|
|
|
|
// Node is one node of the mesh and what the composition reads about it.
|
|
type Node struct {
|
|
Name string
|
|
// Place is where it is on the private network (inv.Overlays).
|
|
Place Place
|
|
// Assigned is the modules assigned to it, in the order the controller reads them (inv.Assigned).
|
|
Assigned []string
|
|
// Capabilities are the ones present on it (inv.ProfileOf).
|
|
Capabilities map[string]bool
|
|
// PublicDomain is the domain it composes its routed names under (inv.PublicDomainOf).
|
|
PublicDomain string
|
|
// Account, AccountHome, AgentAccount and AgentAccountHome are its operator and agent logins (inv.NodeByName).
|
|
Account, AccountHome, AgentAccount, AgentAccountHome string
|
|
// Adopted is whether it is adopted rather than converged.
|
|
Adopted bool
|
|
// Pins is the provider each provision was pinned to for it (inv.PinsFor).
|
|
Pins map[string]catalogue.Chosen
|
|
// Bound is where each of its consumers of a provision that keeps data was last sent (inv.BindingsFor), by consumer
|
|
// module and provision.
|
|
Bound map[string]map[string]catalogue.Chosen
|
|
// Settings is its settings layers by module (inv.SettingsFor); a module with none is absent.
|
|
Settings map[string][]catalogue.Layer
|
|
// Ports is the machine port each module's software port was given on it (inv.PortsFor), by module then port.
|
|
Ports map[string]map[int]int
|
|
// SealingKey is the public key its secrets are sealed to (inv.SealingKeyOf); empty when it has none. A public key, so
|
|
// nothing secret.
|
|
SealingKey string
|
|
// Taken is the modules taken on it, for an adopted node (inv.Taken).
|
|
Taken []string
|
|
// OutwardLinks are the links it reported as facing outside it (inv.OutwardLinksOf).
|
|
OutwardLinks []string
|
|
// Networks are the networks it reported being attached to, as link and network (inv.MachineOf); NetworksSaid is whether
|
|
// its node-engine said any at all, which is not the same as saying none.
|
|
Networks []catalogue.AttachedNetwork
|
|
NetworksSaid bool
|
|
// ServingKey is the key the machine serves with, which a certificate is issued for (identity.ServingKeyOf); empty when it has
|
|
// never reported one. Certificate is the certificate the mesh issued for its internal name, public and optional.
|
|
ServingKey string
|
|
Certificate string
|
|
// Sequence, Epoch and Generation are what the declaration is sent under (inv.Sequence, SentEpoch, SentGeneration): the order
|
|
// against every other send to the node, the lease epoch and the assignment generation it was last sent. Zero is not sent.
|
|
Sequence int64
|
|
Epoch uint64
|
|
Generation int64
|
|
// ReadsModules says its node-engine reads a module per resource and a build per module (inv.ReadsModules, issue 1145); only
|
|
// then are they sent. SentBuilds is the build of each module it was last sent, by module to commit, and SentKnown whether
|
|
// that is known at all (inv.SentBuilds); Runs is what each of its assignments runs (inv.AssignmentRuns), by module.
|
|
ReadsModules bool
|
|
SentBuilds map[string]string
|
|
SentKnown bool
|
|
Runs map[string]Run
|
|
// Kept is, by module, the manifest of a recorded or core module kept at the build this machine runs (plan.go keepRecorded:
|
|
// the caller reads it with recordedKept and ManifestAt), and KeptBuilds the commit of that build. They apply to this node's
|
|
// own resolution only, never to another node's, and a declaration carries the kept commit for the module.
|
|
Kept map[string]catalogue.Manifest
|
|
KeptBuilds map[string]string
|
|
// Contract is the contract of its node-engine's newest statement (inv.HealthOf); Stated is whether it ever stated one.
|
|
Contract int
|
|
Stated bool
|
|
}
|
|
|
|
// Place is where a node is, as its placement says (inv.Overlay).
|
|
type Place struct {
|
|
Key string
|
|
Endpoint string
|
|
Site string
|
|
Hub bool
|
|
Address string
|
|
}
|
|
|
|
// Reachable says whether the node can be dialled.
|
|
func (p Place) Reachable() bool { return strings.TrimSpace(p.Endpoint) != "" }
|
|
|
|
// Tunnel is a tunnel found on a node (inv.Tunnel).
|
|
type Tunnel struct {
|
|
Interface string
|
|
Unit string
|
|
Config string
|
|
Port int
|
|
MTU int
|
|
// Address is the interface's own address with its prefix length, Range the network that prefix names.
|
|
Address string
|
|
Range string
|
|
PublicKey string
|
|
Peers []TunnelPeer
|
|
}
|
|
|
|
// TunnelPeer is one peer of a found tunnel.
|
|
type TunnelPeer struct {
|
|
PublicKey string
|
|
Address string
|
|
}
|
|
|
|
// FoundTunnel is a node's tunnel and whether the node is adopted (inv.FoundTunnel).
|
|
type FoundTunnel struct {
|
|
Tunnel
|
|
NodeAdopted bool
|
|
}
|
|
|
|
// AdoptedTunnel is the hub's tunnel, the hub's name, and whether the hub's overlay key is the tunnel's, which is
|
|
// whether the private network took the tunnel over.
|
|
type AdoptedTunnel struct {
|
|
Tunnel Tunnel
|
|
Hub string
|
|
Adopted bool
|
|
}
|
|
|
|
// CarriedPeer is a peer of the adopted tunnel (inv.CarriedPeer).
|
|
type CarriedPeer struct {
|
|
PublicKey string
|
|
Address string
|
|
EnrolledAs string
|
|
Named string
|
|
}
|
|
|
|
// Licence is one licence the mesh holds: its name, what a consumer may know of it, and the machines and modules
|
|
// that use it.
|
|
type Licence struct {
|
|
Name string
|
|
Serves map[string]any
|
|
Holders []Holder
|
|
// Keys is, by holder, the licence's key sealed to that holder's machine (held.KeyFor), empty where the mesh holds none:
|
|
// the plaintext was discarded when it was supplied. Optional: nil means not given, and the composition uses a stand-in named
|
|
// foreseen; given (even empty), a holder with no entry is one the mesh holds no key for.
|
|
Keys map[Holder]string
|
|
// Manager is the holder of a refreshable-grant licence that manages it (held.ManagerOf); the zero Holder when none.
|
|
Manager Holder
|
|
}
|
|
|
|
// Holder is a module on a node that uses a licence.
|
|
type Holder struct {
|
|
Node string
|
|
Module string
|
|
}
|
|
|
|
// ErrNoSuchNode is what the controller's inventory answers for a node it does not have.
|
|
var ErrNoSuchNode = errors.New("no node of that name")
|
|
|
|
// node is the node of that name, or the refusal the controller's inventory gives for one it does not have.
|
|
func (in Input) node(name string) (Node, error) {
|
|
for _, n := range in.Nodes {
|
|
if n.Name == name {
|
|
return n, nil
|
|
}
|
|
}
|
|
return Node{}, fmt.Errorf("%w: %s", ErrNoSuchNode, name)
|
|
}
|
|
|
|
// sorted is the nodes by name, the order the controller reads them in.
|
|
func (in Input) sorted() []Node {
|
|
out := append([]Node(nil), in.Nodes...)
|
|
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
|
|
return out
|
|
}
|
|
|
|
// CredentialState is how one pair credential stands.
|
|
type CredentialState string
|
|
|
|
const (
|
|
// CredentialHeld is a credential held for both ends as they stand now. Sealed, when given, is the consumer's copy; a held
|
|
// credential with no value is composed with a stand-in, named foreseen.
|
|
CredentialHeld CredentialState = "held"
|
|
// CredentialWouldMake is a credential none is held for: the next send makes it, and the composition uses a stand-in,
|
|
// named foreseen. It is also what a need with no entry is.
|
|
CredentialWouldMake CredentialState = "would-make"
|
|
// CredentialNotGiven is a credential only a person gives (novox/hq ADR 0337 clause 4) that nobody has given, or that was given
|
|
// under a key one end no longer has: the consumer still resolves, without it. Why is the controller's words for it.
|
|
CredentialNotGiven CredentialState = "not-given"
|
|
// CredentialRefused is a credential the send would refuse to make, for the reason Why gives in the controller's words: a
|
|
// value a person gave sealed to a key the machine no longer has, a machine with no sealing key.
|
|
CredentialRefused CredentialState = "refused"
|
|
)
|
|
|
|
// Credential is the state of one pair credential, by the ends it joins: the provision, the consumer's node and module, the
|
|
// provider's node, and the local name where a module keeps several (inv.Secret's key).
|
|
type Credential struct {
|
|
Provision string
|
|
Consumer string
|
|
ConsumerModule string
|
|
Provider string
|
|
Local string
|
|
State CredentialState
|
|
// Sealed is the consumer's copy as it is sealed to the consumer's key; optional, and only the controller's adapter passes it.
|
|
Sealed string
|
|
// Why is the words of a CredentialNotGiven or CredentialRefused.
|
|
Why string
|
|
}
|
|
|
|
// Run is the build an assignment names: the commit it is of and the build made from it (chain.Ref).
|
|
type Run struct {
|
|
Commit string
|
|
Build string
|
|
}
|