Commit 4bdcfdd
authored
fix: derive the extends merge policy from each key's validator (#58)
* fix: derive the extends merge policy from each key's validator
resolve_extends runs ahead of validate(), so a merge that normalizes a value
decides what the gate then sees. The policy was a hand-maintained pair of key
sets, and it had drifted from the gate in both directions.
It laundered invalid input into valid: ulimits has no list form and the gate
refuses one, but _merge_map coerced `ulimits: ["nofile=2"]` into
{"nofile": "2"} before the gate ran. Same for every list-only key given a bare
scalar -- cap_add, devices, security_opt, group_add, volumes, secrets, configs
all refuse a scalar standalone and all accepted one via extends.
And it refused valid input: extra_hosts has a list form, accepted standalone,
but rejected on merge.
One rule now: a merge may normalize a value only through a form that key
actually has. Registry keys run spec.validate on both sides before spec.merge,
so the merge's accepted forms ARE the gate's, by construction. Structural
normalizers are narrowed to the forms Compose defines -- scalar only for
tmpfs/env_file, list form only for environment/extra_hosts/depends_on.
extra_hosts gets a real normalizer: its list form is colon-separated, so
pairs_to_mapping (which splits on '=') would have produced a single
{'host:ip': None} key. Splits on the first colon, so IPv6 survives.
A parametrized test pins the invariant for every mergeable key: a form the gate
refuses standalone must be refused through extends too. Verified to go red
without the fix.
* fix: attribute merge errors to the right service; make the invariant test real
The base-side spec.validate reported the base's malformed value under the
extending service's name. _merge now takes base_name and attributes each side's
failure to the service the value belongs to.
The parametrized invariant test was 10/11 vacuous: it paired the list-only keys
with a dict, which the old code already refused, instead of the bare scalar that
actually laundered. It now uses the laundering shape, covers all 17 mergeable
keys, and asserts its own completeness so a new key cannot be added without a
case. Against the pre-fix code it goes red on nine keys; before, only one.
* docs: correct the normalization list and attribution claim; pin structural attribution
The Extends section claimed 'nothing else is coerced' while omitting list-form
labels/annotations, which are legitimately normalized through their own
validator-approved list form.
The 'error always names the owning service' claim had one reachable exception:
spec.merge only receives the extending service's name, so a null ulimits in the
base is reported against the child. Stated rather than overclaimed.
Adds tests pinning base-side attribution on both structural paths (_as_mapping,
_as_concat_list), which were correct but unpinned.1 parent 7ccdd0c commit 4bdcfdd
4 files changed
Lines changed: 436 additions & 35 deletions
File tree
- architecture
- compose2pod
- planning/changes
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
234 | 234 | | |
235 | 235 | | |
236 | 236 | | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
241 | 258 | | |
242 | 259 | | |
243 | 260 | | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
257 | 273 | | |
258 | 274 | | |
259 | 275 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | | - | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
16 | 23 | | |
17 | 24 | | |
18 | 25 | | |
| |||
39 | 46 | | |
40 | 47 | | |
41 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
42 | 81 | | |
43 | 82 | | |
44 | 83 | | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
49 | 89 | | |
50 | 90 | | |
51 | 91 | | |
52 | 92 | | |
53 | 93 | | |
54 | 94 | | |
| 95 | + | |
| 96 | + | |
55 | 97 | | |
56 | 98 | | |
57 | 99 | | |
| |||
62 | 104 | | |
63 | 105 | | |
64 | 106 | | |
65 | | - | |
66 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
67 | 114 | | |
68 | 115 | | |
69 | 116 | | |
70 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
71 | 128 | | |
72 | 129 | | |
73 | | - | |
| 130 | + | |
74 | 131 | | |
75 | | - | |
| 132 | + | |
76 | 133 | | |
77 | 134 | | |
78 | 135 | | |
| |||
115 | 172 | | |
116 | 173 | | |
117 | 174 | | |
118 | | - | |
| 175 | + | |
119 | 176 | | |
120 | 177 | | |
121 | 178 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
0 commit comments