V3 judge-config-json: a file holding ${config-json} places every config value of its module

Builds: design 42 zfs-owns-zfs §9; answers A-15, A-24
This commit is contained in:
2026-11-13 01:27:58 +01:00
parent ff76ee95ad
commit e9eac06e5d
2 changed files with 28 additions and 0 deletions
@@ -875,6 +875,14 @@ func configPlaced(m catalogue.Manifest) map[string]bool {
for _, u := range configLinesUses(m) {
placed[u.key] = true
}
// A file holding ${config-json} writes every config value of the module (design 42 zfs-owns-zfs §9, A-15).
for _, r := range m.Resources {
if content, _ := r["content"].(string); fmt.Sprint(r["type"]) == "file" && ofConfigJSON.MatchString(content) {
for key := range m.Settings {
placed[key] = true
}
}
}
return placed
}
@@ -3594,6 +3594,25 @@ func caseConfigLinesNamesADeclaredValueAndAPlainPrefix(t *testing.T) {
refused(t, withLines("${config-lines:nowhere:o=}"), `no value "nowhere"`)
}
// Design 42 zfs-owns-zfs §9, V3/AC1 (A-15, A-24): a file holding ${config-json} places every config value.
func caseConfigJSONPlacesEveryValueOfTheModule(t *testing.T) {
m := map[string]any{"module": "m", "version": "1",
"config": map[string]any{
"a": map[string]any{"type": "string", "description": "a word nothing else says", "default": "x"},
"b": map[string]any{"type": "number", "description": "a count nothing else says", "default": 1},
},
"resources": []any{map[string]any{"id": "c", "type": "file", "path": "/x/c.json", "content": "# none\n"}}}
refused(t, m, `"a"`, `"b"`, "placed nowhere")
resourceOf(m, "c")["content"] = "${config-json}"
if _, err := parseRaw(t, m); err != nil {
t.Fatal(err)
}
// Only in a file's content.
m["resources"] = append(m["resources"].([]any), map[string]any{"id": "u", "type": "service", "unit": "u.service", "restart-on": []any{"c"}})
resourceOf(m, "u")["unit"] = "x ${config-json}"
refused(t, m, "${config-json}")
}
// Consumer data said to live in a provision the module requires is protected only as well as that
// provision's provider protects its consumers' data.
func caseConsumerDataInARequiredProvisionIsJudgedAgainstItsProvider(t *testing.T) {
@@ -6190,6 +6209,7 @@ func TestRulesConfig(t *testing.T) {
t.Run("ConfigStillRefusesAValueNoItemPlaces", caseConfigStillRefusesAValueNoItemPlaces)
t.Run("IfConfigNamesADeclaredValueAndPlacesIt", caseIfConfigNamesADeclaredValueAndPlacesIt)
t.Run("ConfigLinesNamesADeclaredValueAndAPlainPrefix", caseConfigLinesNamesADeclaredValueAndAPlainPrefix)
t.Run("ConfigJSONPlacesEveryValueOfTheModule", caseConfigJSONPlacesEveryValueOfTheModule)
}
// TestRulesClaims runs the tests of one kind as subtests, each by its former name.