Keep libraries under groups of their own, and give modules users in them (hq ADR 0328, issue 567)
ADR 0328 supersedes ADR 0325: shared data is a library with one home, kept usable by its group rather than by ACL entries. The engine now makes each library's group and each module's user in its libraries' groups; keeps a library's root and requested sub-paths in its group with group write and setgid on its home, making missing sub-paths as the root is; waits for the operator's word before touching a root that holds data, and on the take act walks it by descriptor (no link, same filesystem, bounded and resumed, files with other names left); holds the containers of a library whose disk or mount is not there; and puts the tool runner's account in the group. The ACL keeping, mask repair and watch are gone; an access is again as before ADR 0325.
This commit is contained in:
+87
-34
@@ -262,7 +262,7 @@ func ApplyMindingWindows(
|
||||
}
|
||||
report = Report{}
|
||||
|
||||
// **No module identity is root** (novox/hq ADR 0325 §11): an identity or a container told a root number refuses
|
||||
// **No module identity is root** (novox/hq ADR 0328 §15): an identity or a container told a root number refuses
|
||||
// the declaration whole, before anything of it is made or started.
|
||||
if err := refuseRootIdentities(d); err != nil {
|
||||
return report, known, &Error{Resource: "the declaration's identities", Err: err, Done: report}
|
||||
@@ -349,12 +349,8 @@ func ApplyMindingWindows(
|
||||
case declaration.TypeUser:
|
||||
action, detail, err = removeUser(ctx, sys, orphan, run, wanted, handed)
|
||||
case declaration.TypeAccess:
|
||||
// The folder is left as it is: what the mesh added to it is taken out by the walk once no access names
|
||||
// it (novox/hq ADR 0325 §8), never by removing the access's record.
|
||||
// The path is left as it is (novox/hq ADR 0051); what ADR 0312's grant put an account in is taken back.
|
||||
action, detail = "forgotten", "an operator-owned path is never the host's to remove"
|
||||
if _, kept := keptRecord(filepath.Clean(orphan.Target)); kept {
|
||||
detail += "; the entries the mesh added go once no access names it"
|
||||
}
|
||||
gave, left, said := takeBackGranted(ctx, sys, orphan, run, wanted, handed)
|
||||
if said != "" {
|
||||
detail = joinDetail(detail, said)
|
||||
@@ -539,13 +535,6 @@ func ApplyMindingWindows(
|
||||
// which declared directories were already here: one this apply makes is the mesh's, one found may not be.
|
||||
refreshRuntimeRoots(ctx)
|
||||
in.refused = refusedPlaces(d.Resources)
|
||||
// What every declared access asks of its folder, several accesses of one folder as one (novox/hq ADR 0325 §5),
|
||||
// and every accessed folder, which no container mounts while it is not there (§9).
|
||||
// Every tool runner's account that came with no number, read by name here (ADR 0325 §4).
|
||||
in.runners = ResolveRunners(ctx, d)
|
||||
in.folders = foldersOf(d.Resources, in.refused)
|
||||
in.identities = len(d.Identities) > 0
|
||||
in.accesses = accessPaths(d.Resources, in.refused, in.identities)
|
||||
in.agentHomes = rootNeverHomes(d)
|
||||
in.dirsBefore = map[string]bool{}
|
||||
for _, resource := range d.Resources {
|
||||
@@ -587,17 +576,46 @@ func ApplyMindingWindows(
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
// **Every module's identity is made before anything of it is applied** (novox/hq ADR 0325 §3): a directory
|
||||
// it owns is given to it, and a container is told to run as it. One that cannot be made — its name or numbers
|
||||
// another's here — fails, naming whose, and its module is not attempted; the rest of the machine is.
|
||||
// **Every library's group, then every module's identity, is made before anything of it is applied** (novox/hq
|
||||
// ADR 0328 §3, §4): a directory a module owns is given to it, and its user is in its libraries' groups. One that
|
||||
// cannot be made — its name or numbers another's here — fails, naming whose, and what needs it is not
|
||||
// attempted; the rest of the machine is.
|
||||
var identityFailures []*Error
|
||||
if len(d.Identities) > 0 {
|
||||
brokenGroups := map[int]bool{}
|
||||
if len(d.Groups) > 0 || len(d.Identities) > 0 {
|
||||
tool, toolErr := toolFor(sys)
|
||||
for _, id := range d.Identities {
|
||||
for _, g := range d.Groups {
|
||||
var outcome Outcome
|
||||
err := toolErr
|
||||
if err == nil {
|
||||
outcome, err = applyIdentity(ctx, tool, id, &known, run)
|
||||
outcome, err = applyGroup(ctx, tool, g, &known, run)
|
||||
}
|
||||
if err != nil {
|
||||
identityFailures = append(identityFailures, &Error{Resource: "group " + g.Name, Err: err})
|
||||
log(fmt.Sprintf(" failed group %s: %v", g.Name, err))
|
||||
brokenGroups[g.GID] = true
|
||||
continue
|
||||
}
|
||||
report.Outcomes = append(report.Outcomes, outcome)
|
||||
if outcome.Action != "unchanged" {
|
||||
log(fmt.Sprintf(" %s %s: %s", outcome.Action, outcome.ID, outcome.Detail))
|
||||
}
|
||||
}
|
||||
names := map[int]string{}
|
||||
for _, g := range d.Groups {
|
||||
names[g.GID] = g.Name
|
||||
}
|
||||
for _, id := range d.Identities {
|
||||
var outcome Outcome
|
||||
err := toolErr
|
||||
for _, gid := range append([]int{id.GID}, id.Groups...) {
|
||||
if brokenGroups[gid] && err == nil {
|
||||
err = fmt.Errorf("its library group %s could not be made; nothing of the module was attempted",
|
||||
names[gid])
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
outcome, err = applyIdentity(ctx, tool, id, names, &known, run)
|
||||
}
|
||||
if err != nil {
|
||||
// Counted with the others once the resources are through: here, before the guard, it would read
|
||||
@@ -615,6 +633,37 @@ func ApplyMindingWindows(
|
||||
}
|
||||
}
|
||||
}
|
||||
// **Every library this machine is reached by, before anything mounts it** (ADR 0328 §6, §9, §11): kept on its
|
||||
// home, its tool runner's account in its group, and the containers that mount one whose disk or mount is not
|
||||
// there held. A tool runner that joined a group is a change of `library:<name>`, which the tool runner's unit
|
||||
// names under restart-on to be restarted once.
|
||||
verdicts := map[string]libraryVerdict{}
|
||||
for _, l := range d.Libraries {
|
||||
outcome, v, err := applyLibrary(ctx, l)
|
||||
verdicts[l.Library] = v
|
||||
if err == nil {
|
||||
var moved bool
|
||||
var said string
|
||||
moved, said, err = joinRunner(ctx, sys, l, &known, run)
|
||||
if moved {
|
||||
changed[LibraryAccess(l.Library)] = true
|
||||
outcome.Detail = joinDetail(outcome.Detail, said)
|
||||
if outcome.Action == "unchanged" {
|
||||
outcome.Action = "updated"
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
identityFailures = append(identityFailures, &Error{Resource: LibraryAccess(l.Library), Err: err})
|
||||
log(fmt.Sprintf(" failed %s (%s): %v", LibraryAccess(l.Library), l.Root, err))
|
||||
continue
|
||||
}
|
||||
report.Outcomes = append(report.Outcomes, outcome)
|
||||
if outcome.Action != "unchanged" {
|
||||
log(fmt.Sprintf(" %s %s (%s): %s", outcome.Action, outcome.ID, outcome.Target, outcome.Detail))
|
||||
}
|
||||
}
|
||||
in.held = heldRoots(verdicts, d.Libraries)
|
||||
for i, resource := range ordered {
|
||||
if !orphansRemoved && i == guardFirst {
|
||||
// **Only a guard that is up may let the filter go.** Removing the derived filter's
|
||||
@@ -1001,14 +1050,22 @@ func ApplyMindingWindows(
|
||||
|
||||
// Only the mesh says what is assigned: a carried bundle's silence undeclares no identity and no folder.
|
||||
if origin == store.OriginDeclared {
|
||||
// A folder no access names any more has what the mesh added taken out by the next walk (ADR 0325 §8).
|
||||
forgetUndeclared(in.folders)
|
||||
// And an identity no longer declared goes, once what ran as it went above (ADR 0325 §3).
|
||||
// A tool runner no longer put in a library's group leaves it (ADR 0328 §11, ADR 0252 §3).
|
||||
for _, o := range leaveRunners(ctx, sys, d.Libraries, &known, run, wanted) {
|
||||
report.Outcomes = append(report.Outcomes, o)
|
||||
log(fmt.Sprintf(" %s %s: %s", o.Action, o.ID, o.Detail))
|
||||
}
|
||||
// And an identity, then a library group, no longer declared goes, once what ran as it went above (ADR 0328
|
||||
// §3, §4).
|
||||
if tool, err := toolFor(sys); err == nil {
|
||||
for _, o := range removeIdentities(ctx, tool, d.Identities, &known, run) {
|
||||
report.Outcomes = append(report.Outcomes, o)
|
||||
log(fmt.Sprintf(" %s %s: %s", o.Action, o.ID, o.Detail))
|
||||
}
|
||||
for _, o := range removeGroups(ctx, tool, d.Groups, &known, run) {
|
||||
report.Outcomes = append(report.Outcomes, o)
|
||||
log(fmt.Sprintf(" %s %s: %s", o.Action, o.ID, o.Detail))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1139,12 +1196,13 @@ func applyOne(ctx context.Context, sys system.System, r declaration.Resource, ru
|
||||
if err := refuseMounts(res, in.refused); err != nil {
|
||||
return begin(r), err
|
||||
}
|
||||
// Not created over an accessed folder not there, which the runtime would make as root (novox/hq ADR 0325 §9).
|
||||
if id := mountsMissing(ctx, res, in.accesses); id != "" {
|
||||
// Not created over a library whose disk or mount is not there: the runtime would make the root as root,
|
||||
// and the container's writes would land on the filesystem below (novox/hq ADR 0328 §9).
|
||||
if name := mountsHeld(res, in.held); name != "" {
|
||||
out := begin(r)
|
||||
out.Action = "waiting"
|
||||
out.Detail = "not created: it mounts the access " + id + ", whose folder or its disk is not there; " +
|
||||
"created once it is (novox/hq ADR 0325 §9)"
|
||||
out.Detail = "not created: it mounts the library " + name + ", whose disk or mount is not there; " +
|
||||
"created once it is (novox/hq ADR 0328 §9)"
|
||||
return out, nil
|
||||
}
|
||||
}
|
||||
@@ -2196,14 +2254,9 @@ type inputs struct {
|
||||
// dirsBefore is every declared directory that was on the machine when this apply began (novox/hq issue
|
||||
// 339): one the apply itself made — a file's parent — is the mesh's, one that was there may not be.
|
||||
dirsBefore map[string]bool
|
||||
// folders is what every declared access asks of its folder, by path (novox/hq ADR 0325 §5); accesses every
|
||||
// accessed folder with its access's id, which no container mounts while it is not there (§9).
|
||||
folders map[string]*folderWant
|
||||
// identities is that the declaration carries identities: its controller speaks ADR 0325 for every access.
|
||||
identities bool
|
||||
// runners is every access refused for its tool runner's account (not here, or root's), by id.
|
||||
runners map[string]error
|
||||
accesses map[string]string
|
||||
// held is the root of every library whose disk or mount is not there, with its name: no container that mounts
|
||||
// it is created (novox/hq ADR 0328 §9).
|
||||
held map[string]string
|
||||
// handed is every group a record that went this apply handed to a resource still asking for it.
|
||||
handed Handed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user