The engine reads the group owning the accessed path at apply and gives it to the containers and the tools' account an access's new `grant` names: --group-add for a container (recreated with it), an account group for the account (recorded, taken back as ADR 0252 takes back). The path is never changed; an access whose group cannot write is stated unhealthy for the operator to decide; group 0 and the root-granting groups are refused by name. The tool runner restarts through the restart-on the controller gives it, because the access reports updated exactly when the account's groups moved. Health says GrantContract (4), which tells the controller it may send `grant`.
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, nil) == containerSpecReading(moved, nil, 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, nil) != containerSpecReading(reordered, nil, 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, nil) == containerSpecReading(was, nil, 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)
|
|
}
|