Merge pull request 'The proxy is told its routes and the mesh on the bus, and serves internal names to the mesh only (hq issue 191, ADR 0167)' (#207) from jschoubben/an-internal-only-route into main
This commit was merged in pull request #207.
This commit is contained in:
@@ -241,15 +241,21 @@ func (r Resolution) Declaration(with Rendering) ([]map[string]any, error) {
|
||||
// Owner is kept beside the resources because a resource id cannot be split back into its module:
|
||||
// a module's name may itself contain a dot. What the mesh adds of its own — an opening, the guard —
|
||||
// has no owner.
|
||||
//
|
||||
// Received is what each module on the machine is given for each requirement it receives — the same
|
||||
// contributions its received file is written from, kept beside it so the mesh can also issue them
|
||||
// on the bus in the module's membership (novox/hq ADR 0167). By module, then requirement.
|
||||
type Composed struct {
|
||||
Resources []map[string]any
|
||||
Owner map[string]string
|
||||
Received map[string]map[string][]Contribution
|
||||
}
|
||||
|
||||
// Compose is Declaration with the owner of every resource said.
|
||||
func (r Resolution) Compose(with Rendering) (Composed, error) {
|
||||
owner := map[string]string{}
|
||||
resources, err := r.compose(with, owner)
|
||||
received := map[string]map[string][]Contribution{}
|
||||
resources, err := r.compose(with, owner, received)
|
||||
if err != nil {
|
||||
return Composed{}, err
|
||||
}
|
||||
@@ -261,7 +267,7 @@ func (r Resolution) Compose(with Rendering) (Composed, error) {
|
||||
"sealed": with.BusMembership, "mode": "0600",
|
||||
})
|
||||
}
|
||||
return Composed{Resources: resources, Owner: owner}, nil
|
||||
return Composed{Resources: resources, Owner: owner, Received: received}, nil
|
||||
}
|
||||
|
||||
// BusMembershipID names the resource carrying a machine's membership for the new bus, and
|
||||
@@ -270,7 +276,8 @@ func BusMembershipID() string { return "bus-membership" }
|
||||
|
||||
const BusMembershipPath = "/var/lib/mesh/membership-next.json"
|
||||
|
||||
func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[string]any, error) {
|
||||
func (r Resolution) compose(with Rendering, owner map[string]string,
|
||||
received map[string]map[string][]Contribution) ([]map[string]any, error) {
|
||||
// Every manifest is placed first (novox/hq ADR 0112): the maps naming where its bindings,
|
||||
// credentials and contributions land are resolved against this node's directories, so every
|
||||
// reader below — the binding files, the sealed secrets, the grant paths a contribution
|
||||
@@ -596,6 +603,12 @@ func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[stri
|
||||
return nil, err
|
||||
}
|
||||
first = append(first, file)
|
||||
if received[m.Module] == nil {
|
||||
received[m.Module] = map[string][]Contribution{}
|
||||
}
|
||||
// Empty rather than absent when nobody contributed, for the reason the file is
|
||||
// written empty: "nothing asked" and "never told" want different responses.
|
||||
received[m.Module][to] = append([]Contribution{}, given[to]...)
|
||||
}
|
||||
if m.Keeps != "" && with.Kept != nil {
|
||||
file, err := keptFile(m.Keeps, with.Kept)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package catalogue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// What a provider receives is composed once, and issued twice: as its received file, and in its
|
||||
// membership on the bus (novox/hq ADR 0167). The two are the same list, so a proxy reading the bus
|
||||
// and one reading the file serve the same routes — including the port the machine published, which
|
||||
// is the same-node fix the file already carries.
|
||||
func TestWhatAProviderReceivesIsTheSameOnTheBusAsInItsFile(t *testing.T) {
|
||||
gitea := Manifest{
|
||||
Module: "gitea", Version: "1",
|
||||
Listens: []Listening{{Port: 3000, Protocol: "tcp", From: FromMesh}},
|
||||
Contributes: map[string]map[string]any{"route": {"label": "git", "port": 3000}},
|
||||
Resources: []map[string]any{{
|
||||
"id": "server", "type": "container", "name": "gitea", "ports": []any{"3000"},
|
||||
}},
|
||||
}
|
||||
r, err := Resolve(shelf(gitea, routeProxy(), stepCA()),
|
||||
[]string{"gitea", "route-proxy", "step-ca"}, reachable(), World{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
composed, err := r.Compose(Rendering{Ports: map[string]map[int]int{"gitea": {3000: 20000}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
file := fileNamed(composed.Resources, "route-proxy.received-route")
|
||||
if file == nil {
|
||||
t.Fatal("the proxy was given no routes file")
|
||||
}
|
||||
var written struct {
|
||||
Given []Contribution `json:"given"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(file["content"].(string)), &written); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
issued, said := composed.Received["route-proxy"]["route"]
|
||||
if !said {
|
||||
t.Fatalf("nothing is issued for the proxy to receive on the bus: %v", composed.Received)
|
||||
}
|
||||
// Compared as JSON, which is what both are once they leave the controller.
|
||||
a, _ := json.Marshal(written.Given)
|
||||
b, _ := json.Marshal(issued)
|
||||
var fromFile, fromBus any
|
||||
_ = json.Unmarshal(a, &fromFile)
|
||||
_ = json.Unmarshal(b, &fromBus)
|
||||
if !reflect.DeepEqual(fromFile, fromBus) {
|
||||
t.Errorf("the bus and the file disagree about the routes:\nfile %s\nbus %s", a, b)
|
||||
}
|
||||
if len(issued) != 1 {
|
||||
t.Fatalf("expected one route on the bus, got %v", issued)
|
||||
}
|
||||
if port, ok := asPort(issued[0].Values["port"]); !ok || port != 20000 {
|
||||
t.Errorf("the bus carries a port nothing listens on: %v", issued[0].Values["port"])
|
||||
}
|
||||
|
||||
// A module that receives nothing is issued nothing to receive.
|
||||
if _, any := composed.Received["gitea"]; any {
|
||||
t.Errorf("a module that receives nothing was issued something: %v", composed.Received["gitea"])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user