Look at what a container mounts directly, accept a pre-upgrade label, and write the genesis secret without a newline
Review of the first cut found four things. A directory mounted into a container is no longer looked inside, not even for the files this host wrote there. The controller records every provider's received and contributions file as a plain file under a mounted directory, so folding those in would have recreated the route proxy — which re-reads its routes live, by design — on every route change, and killed every provisioner sidecar, which polls what it receives, mid-reconcile on every grant. Whether a service reads a file under its directory once or watches it is the service's; restart-on is how a module says "once", and it stays the opt-in. Env-files and files mounted directly remain by content. Genesis wrote the superuser secret as `value\n`; `secret accept` strips the line ending by design, so the postgres module declared `value` — and with a mounted file's content in the spec, phase three would have recreated the store it meant to adopt in place, with the temporary control plane connected to it. Genesis now writes the value alone. readCredentialFile tolerated both endings already. Pinned with the bytes the genesis code path writes, then the module's declaration of the same container: it must reconcile. A container carrying a label from before the host folded in what it reads is accepted rather than recreated, when that label matches the spec as it used to be computed: what it reads is recorded then, a change is caught from that record from the next apply on, and the label is renewed at the next genuine recreate. Recreating them all would have been a restart storm across the mesh in declaration order, the store first. The trade-off is stated in the code: a container already stale at upgrade time is not caught, and could not have been either way. The record of what a container read is looked up by its name when its declared id has none — the bundle's `store` becomes `postgres.server` for the same container — so a change on the day it is adopted still names the file. The by-target lookup takes the most recently applied record, since the bundle's record for the same target is never removed by the mesh's. novox/hq 04-ISSUES/103
This commit is contained in:
+14
-13
@@ -18,7 +18,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -209,24 +208,26 @@ func (s State) Recorded(kind, target string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// FilesUnder returns every file this host has a record of writing at a path or beneath it, of any
|
||||
// origin and under any id, in path order.
|
||||
// At returns what this host has a record of putting at a target of this kind, under any id and of
|
||||
// any origin — Recorded, with the record.
|
||||
//
|
||||
// By path rather than by id because a container names what it reads by path: the id a file was
|
||||
// declared under may change — the bundle's, then a module's, for the same file — and the container
|
||||
// reading it does not care which.
|
||||
func (s State) FilesUnder(path string) []Applied {
|
||||
var out []Applied
|
||||
// By target rather than by id because the id a thing was declared under may change while the thing
|
||||
// does not: the bundle's `store` becomes a module's `postgres.server` for the same container, and
|
||||
// the file that container reads is the same file under either id. Both ids may then hold a record
|
||||
// for the one target — the bundle's is never removed by the mesh's declaration — and the most
|
||||
// recently applied is the one that says what is there now.
|
||||
func (s State) At(kind, target string) (Applied, bool) {
|
||||
var latest Applied
|
||||
found := false
|
||||
for _, r := range s.Resources {
|
||||
if r.Type != "file" {
|
||||
if r.Type != kind || r.Target != target {
|
||||
continue
|
||||
}
|
||||
if r.Target == path || strings.HasPrefix(r.Target, strings.TrimSuffix(path, "/")+"/") {
|
||||
out = append(out, r)
|
||||
if !found || r.AppliedAt.After(latest.AppliedAt) {
|
||||
latest, found = r, true
|
||||
}
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool { return out[i].Target < out[j].Target })
|
||||
return out
|
||||
return latest, found
|
||||
}
|
||||
|
||||
// HeldAt returns what is held under a resource id.
|
||||
|
||||
Reference in New Issue
Block a user