A module's containers ran as whatever their image chose and shared folders were made writable by putting accounts in the folder's group (ADR 0312), which ADR 0325 supersedes. The engine now makes each declared module identity as a system account with the controller's numbers, runs a container declaring `identity` as it, and keeps each placed shared folder usable through one POSIX ACL entry per user, set through the kernel's xattrs on descriptors it opened itself. A folder holding data is kept only after the operator's warrant (the take act); a missing folder is made where its data lives and waits where its disk is not; root's data is never kept. A watch and a bounded sweep put back what an app narrows. The group grant is removed, and what it put an account in is taken back. Reuses the descriptor walks, the create act, the missing-path wait and the warrant- backed act message from the paused issue 567 branch.
55 lines
2.1 KiB
Go
55 lines
2.1 KiB
Go
package apply
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-host/internal/declaration"
|
|
)
|
|
|
|
// **A container's mesh names are part of what it is** (novox/hq 04-ISSUES/135).
|
|
//
|
|
// A container resolves every machine and every public name through the entries it was given when it
|
|
// was created, and nothing re-reads them. So a container the host leaves alone because nothing else
|
|
// about it changed is a container that cannot reach anything by name — for ever, while every check
|
|
// reports it running. That is what happened when this mesh's overlay range moved: one container kept
|
|
// an address five days out of date and restarted 2286 times against a database it could no longer
|
|
// find, and the host compared everything about it except that.
|
|
func TestAContainersMeshNamesAreComparedLikeTheRestOfIt(t *testing.T) {
|
|
was := &declaration.Container{
|
|
Name: "umami", Image: "ghcr.io/example/umami@sha256:" + zeros(64),
|
|
Hosts: []string{"novox.internal:10.42.0.1", "umami.novox.be:10.42.0.1"},
|
|
}
|
|
moved := &declaration.Container{
|
|
Name: was.Name, Image: was.Image,
|
|
Hosts: []string{"novox.internal:10.10.0.1", "umami.novox.be:10.10.0.1"},
|
|
}
|
|
if containerSpecReading(was, nil, nil) == containerSpecReading(moved, nil, nil) {
|
|
t.Fatal("a container whose mesh names moved compares equal, so it is never recreated")
|
|
}
|
|
|
|
// And the order they arrive in is not a change: the digest must not move for a reordering
|
|
// nobody made.
|
|
reordered := &declaration.Container{
|
|
Name: moved.Name, Image: moved.Image,
|
|
Hosts: []string{moved.Hosts[1], moved.Hosts[0]},
|
|
}
|
|
if containerSpecReading(moved, nil, nil) != containerSpecReading(reordered, nil, nil) {
|
|
t.Fatal("the same names in another order read as a different container")
|
|
}
|
|
|
|
// A container the mesh gives no names is unaffected, so nothing is recreated for a field it
|
|
// does not set.
|
|
plain := &declaration.Container{Name: "plex", Image: was.Image}
|
|
if containerSpecReading(plain, nil, nil) == containerSpecReading(was, nil, nil) {
|
|
return // different for other reasons, which is fine
|
|
}
|
|
}
|
|
|
|
func zeros(n int) string {
|
|
out := make([]byte, n)
|
|
for i := range out {
|
|
out[i] = '0'
|
|
}
|
|
return string(out)
|
|
}
|