Every module.json already declares a why for each port under listens, but plan only ever used it to build the firewall's rule set — nothing printed it. An operator deciding whether to assign a module had no way to see what it would open without reading the manifest by hand. plan <node> now prints each assigned module's listens entries — port, protocol, source, and its why — right under the module line, so the same text that feeds the firewall is visible at the point someone is actually deciding whether to open it.
38 lines
1.3 KiB
Go
38 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// `plan` tells a person what a module would open and why, from the same `why` every listens
|
|
// entry already carries for the firewall (novox/hq ADR 0007) — so deciding whether to assign a
|
|
// module does not need reading its manifest first.
|
|
func TestListensLinesShowWhatAModuleWouldOpenAndWhy(t *testing.T) {
|
|
m := catalogue.Manifest{Module: "minio", Listens: []catalogue.Listening{
|
|
{Port: 9000, From: catalogue.FromMesh, Why: "the S3 endpoint"},
|
|
{Port: 9001, From: catalogue.FromMesh},
|
|
}}
|
|
got := listensLines(m)
|
|
if len(got) != 2 {
|
|
t.Fatalf("two listens entries, got %d: %v", len(got), got)
|
|
}
|
|
if !strings.Contains(got[0], "9000/tcp") || !strings.Contains(got[0], "the S3 endpoint") {
|
|
t.Errorf("the port and its why did not both appear: %q", got[0])
|
|
}
|
|
if strings.Contains(got[1], "—") {
|
|
t.Errorf("a listens entry with no why should not print a dash: %q", got[1])
|
|
}
|
|
if !strings.Contains(got[1], "9001/tcp") {
|
|
t.Errorf("the port still appears without a why: %q", got[1])
|
|
}
|
|
}
|
|
|
|
func TestListensLinesAreEmptyForAModuleWithNothingToListenOn(t *testing.T) {
|
|
if got := listensLines(catalogue.Manifest{Module: "board"}); len(got) != 0 {
|
|
t.Errorf("a module with no listens should print nothing, got %v", got)
|
|
}
|
|
}
|