A take acts on the preview it showed; a setting is judged where it is stored; a kept network and a minted secret are said (hq ADR 0163)
take ends its preview with a digest and --yes names it, as the flip does; a changed preview or an account older than the flip allows is refused. A module the machine holds nothing for has nothing to compare, and --yes suffices. A published port's reach is said as the machine reported it. Every secret the module holds on the machine is listed with where it came from, and one the mesh minted for a service whose data was found refuses unless --mint names it. One judgement of a module's settings against its definition, in the catalogue: settings set refuses what cannot compose or reaches nothing, naming node, module, layer and key; Compose leaves out a module whose definition moved under a stored setting, the envelope says so (left_out), plan and push say it by name, and the machine is told everything else. A stray setting no longer refuses the whole machine where it is read (issue 096). The per-machine setting networks keeps a found network for a taken container, on an adopted machine only; the container's declaration carries it and the preview names it (rule 4).
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package catalogue
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A setting is judged where it is stored, and an impossible one costs a module, not a machine
|
||||
// (novox/hq ADR 0163, rule 6): the one judgement, used by SetSettings before storing and by
|
||||
// Compose when a definition has moved under a stored setting.
|
||||
func TestASettingThatCannotComposeIsRefusedByNameAndLeavesOnlyItsModuleOut(t *testing.T) {
|
||||
web := Manifest{Module: "hello-web",
|
||||
Listens: []Listening{{Port: 8080, From: FromEverywhere}},
|
||||
Resources: []map[string]any{{"id": "server", "type": "container", "name": "hello-web",
|
||||
"ports": []any{"8080"}}}}
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
layer map[string]any
|
||||
refuse string
|
||||
}{
|
||||
{"a port the module does not publish", map[string]any{PortsSetting: map[string]any{"9999": 10000}},
|
||||
"hello-web gives port 9999 a machine port, and no container of its publishes 9999"},
|
||||
{"a mesh-wide port", map[string]any{PortsSetting: map[string]any{"8080": 10000}},
|
||||
"a port is a fact about one machine"},
|
||||
} {
|
||||
from := "anchor"
|
||||
if c.name == "a mesh-wide port" {
|
||||
from = MeshWideLayer
|
||||
}
|
||||
err := JudgeSettings(web, []Layer{{From: from, Values: c.layer}}, true)
|
||||
if err == nil || !strings.Contains(err.Error(), c.refuse) {
|
||||
t.Errorf("%s: judged %v, want %q", c.name, err, c.refuse)
|
||||
}
|
||||
}
|
||||
if err := JudgeSettings(web, []Layer{{From: "anchor", Values: map[string]any{PortsSetting: map[string]any{"8080": 10000}}}}, true); err != nil {
|
||||
t.Fatalf("a port the module publishes was refused: %v", err)
|
||||
}
|
||||
|
||||
// Composed, a module whose stored setting no longer works is left out by name; the rest of
|
||||
// the machine is declared.
|
||||
r := anAdoptedAnchor()
|
||||
with := anchorRendering(false)
|
||||
with.Settings = SettingsBy{"hello-web": {{From: "anchor", Values: map[string]any{PortsSetting: map[string]any{"9999": 10000}}}}}
|
||||
composed, err := r.Compose(with)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
why, left := composed.LeftOut["hello-web"]
|
||||
if !left || !strings.Contains(why, "no container of its publishes 9999") {
|
||||
t.Fatalf("hello-web is not left out by name: %v", composed.LeftOut)
|
||||
}
|
||||
if len(composed.LeftOut) != 1 {
|
||||
t.Fatalf("more than hello-web is left out: %v", composed.LeftOut)
|
||||
}
|
||||
got := byID(composed.Resources)
|
||||
if _, declared := got["hello-web.server"]; declared {
|
||||
t.Fatal("the left-out module's container is still declared")
|
||||
}
|
||||
if _, declared := got["distribution.store"]; !declared {
|
||||
t.Fatal("the rest of the machine was not declared")
|
||||
}
|
||||
if left := r.LeftOut(with.Settings, false); len(left) != 1 || left["hello-web"] == "" {
|
||||
t.Fatalf("the judgement a plan reads differs from what compose did: %v", left)
|
||||
}
|
||||
}
|
||||
|
||||
// A taken container keeps a found network by a per-machine setting (novox/hq ADR 0163, rule 4):
|
||||
// on an adopted machine only, for a container the module declares, and it reaches the container's
|
||||
// declaration as the networks it also joins.
|
||||
func TestAKeptNetworkReachesTheContainerOnAnAdoptedMachineOnly(t *testing.T) {
|
||||
r := anAdoptedAnchor()
|
||||
keep := SettingsBy{"hello-web": {{From: "anchor",
|
||||
Values: map[string]any{NetworksSetting: map[string]any{"server": []any{"predecessor_default"}}}}}}
|
||||
|
||||
with := anchorRendering(true)
|
||||
with.Settings = keep
|
||||
composed, err := r.Compose(with)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(composed.LeftOut) != 0 {
|
||||
t.Fatalf("a kept network left a module out: %v", composed.LeftOut)
|
||||
}
|
||||
server := byID(composed.Resources)["hello-web.server"]
|
||||
networks, _ := server["networks"].([]any)
|
||||
if len(networks) != 1 || networks[0] != "predecessor_default" {
|
||||
t.Fatalf("the container does not join the kept network: %v", server)
|
||||
}
|
||||
if _, has := byID(composed.Resources)["distribution.store"]["networks"]; has {
|
||||
t.Fatal("another container joins a network nobody kept for it")
|
||||
}
|
||||
|
||||
// Converged, the setting reaches nothing it was for, and the module is left out saying so.
|
||||
with = anchorRendering(false)
|
||||
with.Settings = keep
|
||||
composed, err = r.Compose(with)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if why := composed.LeftOut["hello-web"]; !strings.Contains(why, "anchor is converged") {
|
||||
t.Fatalf("a kept network on a converged machine: %v", composed.LeftOut)
|
||||
}
|
||||
|
||||
web := r.Modules[4]
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
layer Layer
|
||||
want string
|
||||
}{
|
||||
{"mesh-wide", Layer{From: MeshWideLayer, Values: map[string]any{NetworksSetting: map[string]any{"server": []any{"x"}}}},
|
||||
"a found network is a fact about one machine"},
|
||||
{"an unknown container", Layer{From: "anchor", Values: map[string]any{NetworksSetting: map[string]any{"db": []any{"x"}}}},
|
||||
`names the container "db", which it does not declare`},
|
||||
{"not a list", Layer{From: "anchor", Values: map[string]any{NetworksSetting: map[string]any{"server": "x"}}},
|
||||
"is a list of network names"},
|
||||
{"not a network name", Layer{From: "anchor", Values: map[string]any{NetworksSetting: map[string]any{"server": []any{"a/b"}}}},
|
||||
"which is not a network name"},
|
||||
} {
|
||||
_, err := KeptNetworks(web, []Layer{c.layer}, true)
|
||||
if err == nil || !strings.Contains(err.Error(), c.want) {
|
||||
t.Errorf("%s: %v, want %q", c.name, err, c.want)
|
||||
}
|
||||
}
|
||||
if kept, err := KeptNetworks(web, nil, false); err != nil || kept != nil {
|
||||
t.Fatalf("no setting: %v %v", kept, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user