Declare openings and a refusal-only guard on an adopted node in place of the filter (hq ADR 0100)
This commit is contained in:
@@ -128,6 +128,11 @@ type Rendering struct {
|
||||
// set, for what a consumer is told, and for what the runtime publishes — and nothing checked
|
||||
// that the three agreed. They are all derived from this.
|
||||
Ports map[string]map[int]int
|
||||
|
||||
// Adopted says the node is adopted (novox/hq ADR 0100): the firewall found on it stays in
|
||||
// force, so no module that loads a filter is declared there, and what the mesh needs
|
||||
// reachable is declared as openings, with its own ports guarded by a table that only refuses.
|
||||
Adopted bool
|
||||
}
|
||||
|
||||
// machinePort is where a module's port lives on this machine, or the port itself when the mesh has
|
||||
@@ -257,6 +262,13 @@ func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[stri
|
||||
|
||||
var out []map[string]any
|
||||
for _, m := range r.Modules {
|
||||
if with.Adopted && m.Filtering != nil {
|
||||
// Nothing of a module that loads a filter, on an adopted node: its table would drop
|
||||
// by default and hold accepts, and the found firewall stays in force. Every resource,
|
||||
// not only the rule set — its service must not run, and a node returned to adopted
|
||||
// stops it by the ordinary removal of what is no longer declared.
|
||||
continue
|
||||
}
|
||||
resources := m.Resources
|
||||
|
||||
// What the mesh computes for this module goes FIRST, before the module's own resources.
|
||||
@@ -567,9 +579,54 @@ func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[stri
|
||||
out = append(out, fact)
|
||||
}
|
||||
}
|
||||
if with.Adopted {
|
||||
// First, before anything a module declares: what the mesh needs reachable, then its guard.
|
||||
// The order a machine applies is the order written here.
|
||||
ours := Openings(rules, with.Foundation, Published(out))
|
||||
ours = append(ours, GuardResources(r.guarded(out, owner, with))...)
|
||||
out = append(ours, out...)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// guarded is the machine ports of every guarded port of the modules here: where each module's
|
||||
// container publishes it, as composed — or where the machine put it when no container does.
|
||||
func (r Resolution) guarded(out []map[string]any, owner map[string]string, with Rendering) []int {
|
||||
seen := map[int]bool{}
|
||||
var ports []int
|
||||
for _, m := range r.Modules {
|
||||
for _, want := range m.Guards {
|
||||
at := with.machinePort(m.Module, want)
|
||||
for _, resource := range out {
|
||||
if owner[fmt.Sprint(resource["id"])] != m.Module ||
|
||||
fmt.Sprint(resource["type"]) != "container" {
|
||||
continue
|
||||
}
|
||||
listed, _ := resource["ports"].([]any)
|
||||
for _, entry := range listed {
|
||||
parts := strings.Split(strings.TrimSpace(fmt.Sprint(entry)), ":")
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
inner, err := strconv.Atoi(strings.SplitN(parts[len(parts)-1], "/", 2)[0])
|
||||
if err != nil || inner != want {
|
||||
continue
|
||||
}
|
||||
if outer, err := strconv.Atoi(parts[len(parts)-2]); err == nil {
|
||||
at = outer
|
||||
}
|
||||
}
|
||||
}
|
||||
if !seen[at] {
|
||||
seen[at] = true
|
||||
ports = append(ports, at)
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Ints(ports)
|
||||
return ports
|
||||
}
|
||||
|
||||
// Contribution is one module telling the answer to a requirement what it needs from it.
|
||||
type Contribution struct {
|
||||
// From is the module that said it, so the provider and a person reading the file can tell
|
||||
|
||||
Reference in New Issue
Block a user