The host applies the newest declaration, a file may be created once, the foundation filters first
031: a window of unacknowledged declarations is drained to the newest; the rest are set aside and reported as superseded. 035: a file resource may say create-once — written when absent, kept untouched when present (ADR 0087). 054: the bundle installs nftables and loads a base ruleset before the store and broker, in the table the filter module later replaces (ADR 0088).
This commit is contained in:
@@ -470,6 +470,18 @@ func applyFile(r *declaration.File, previous store.Applied, unseal Unseal) (Outc
|
||||
if readErr != nil && !errors.Is(readErr, os.ErrNotExist) {
|
||||
return out, readErr
|
||||
}
|
||||
// A seed that is already there is left exactly as it is — whatever has grown in it since is
|
||||
// not the mesh's to put back (novox/hq issue 035). What this host records is what it once
|
||||
// wrote, so a later declaration that changes the seed is not mistaken for drift either.
|
||||
if r.CreateOnce && existed {
|
||||
out.wrote = previous.Wrote
|
||||
if out.wrote == "" {
|
||||
out.wrote = digestOf(string(existing))
|
||||
}
|
||||
out.Action = "kept"
|
||||
out.Detail = "created once, and present; what is in it now is not the mesh's to change"
|
||||
return out, nil
|
||||
}
|
||||
|
||||
var beforeMode os.FileMode
|
||||
if existed {
|
||||
|
||||
@@ -1558,3 +1558,40 @@ func TestAContainerStaleFromAnEarlierApplyIsReplaced(t *testing.T) {
|
||||
"(removed=%v created=%v)", removed, created)
|
||||
}
|
||||
}
|
||||
|
||||
// A seed is written once. What grows in it afterwards is somebody else's work the mesh asked for,
|
||||
// and a reconcile leaves it alone — content, mode and owner — and says so (novox/hq issue 035).
|
||||
func TestASeedIsCreatedOnceAndWhatGrowsInItIsKept(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "acl.conf")
|
||||
d := parse(t, fmt.Sprintf(`{"declaration":1,"resources":[
|
||||
{"id":"acl","type":"file","path":%q,"content":"user default on\n","mode":"0600","create-once":true}
|
||||
]}`, path))
|
||||
|
||||
report, state, err := Apply(context.Background(), archHost(t), d, store.State{},
|
||||
store.OriginCarried, noServices, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := report.Outcomes[0].Action; got != "created" {
|
||||
t.Fatalf("first apply: %q", got)
|
||||
}
|
||||
|
||||
// The program persists into it.
|
||||
if err := os.WriteFile(path, []byte("user default on\nuser app-one on >secret\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
report, _, err = Apply(context.Background(), archHost(t), d, state,
|
||||
store.OriginCarried, noServices, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := report.Outcomes[0].Action; got != "kept" {
|
||||
t.Fatalf("second apply: %q — a seed was reconciled", got)
|
||||
}
|
||||
grown, _ := os.ReadFile(path)
|
||||
if string(grown) != "user default on\nuser app-one on >secret\n" {
|
||||
t.Fatalf("what grew in the seed was wiped: %q", grown)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user