A-342 engine-node-env: every process runs with its node's name as MESH_NODE
The apply gives each process the declaration's For as MESH_NODE beside its own env, so a process that reads MESH_NODE (mesh-sdk, the zfs follower's writer and its node-service-manager calls) names its node. Builds: design 47 G A-342 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -785,7 +785,7 @@ func applyScoped(
|
||||
// change one apply late, and never misses it.
|
||||
// And one patience with the artifact store for the whole apply (novox/hq issue 291): a fetch it
|
||||
// does not answer during a maintenance window waits for the window instead of failing.
|
||||
in := inputs{declares: map[string]string{}, known: &known, windows: windows, away: newStoreAway(windows, log),
|
||||
in := inputs{node: d.For, declares: map[string]string{}, known: &known, windows: windows, away: newStoreAway(windows, log),
|
||||
groups: wanted, handed: handed}
|
||||
// Where nothing is placed or mounted from, judged before anything is applied (novox/hq issue 339), and
|
||||
// which declared directories were already here: one this apply makes is the mesh's, one found may not be.
|
||||
@@ -1625,7 +1625,7 @@ func applyOne(ctx context.Context, sys system.System, r declaration.Resource, ru
|
||||
if err != nil {
|
||||
return begin(r), err
|
||||
}
|
||||
return applyProcess(ctx, res, run, changed, previous, held, in.away)
|
||||
return applyProcess(ctx, withNode(res, in.node), run, changed, previous, held, in.away)
|
||||
case *declaration.Action:
|
||||
return applyAction(ctx, res, run)
|
||||
case *declaration.Network:
|
||||
@@ -2816,6 +2816,9 @@ type inputs struct {
|
||||
// fetched is every archive's and process's bytes this apply fetched before anything was replaced (fetchFirst), each
|
||||
// taken by its applier once (artifact).
|
||||
fetched map[string]fetchedArtifact
|
||||
// node is the node's own name, the declaration's For: every process runs with it as MESH_NODE beside its own env
|
||||
// (design 47 G A-342). Empty where the declaration names none (the first node's carried bundle).
|
||||
node string
|
||||
}
|
||||
|
||||
// fileDigest is what a file the container reads holds, by digest.
|
||||
|
||||
@@ -95,7 +95,7 @@ func WriteFilledWith(
|
||||
"yet taken (%s), so nothing was written", path, held.Why)}
|
||||
}
|
||||
|
||||
in := inputs{declares: map[string]string{}, known: &known, windows: windows, away: newStoreAway(windows, log),
|
||||
in := inputs{node: d.For, declares: map[string]string{}, known: &known, windows: windows, away: newStoreAway(windows, log),
|
||||
groups: groupsWanted(d.Resources), handed: Handed{}}
|
||||
in.refused = refusedPlaces(d.Resources)
|
||||
in.agentHomes = rootNeverHomes(d)
|
||||
|
||||
@@ -274,6 +274,25 @@ func applyProcess(ctx context.Context, r *declaration.Process, run Runner,
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// NodeEnv is the variable every process the node-engine runs reads its node's name from (design 47 G A-342), the one
|
||||
// mesh-sdk reads (MESH_NODE).
|
||||
const NodeEnv = "MESH_NODE"
|
||||
|
||||
// withNode is the process as it runs on node: its own env with NodeEnv beside it (design 47 G A-342). The validator
|
||||
// refuses a resource that sets it, so the mesh's value is the only one; with no node named the process is as declared.
|
||||
func withNode(r *declaration.Process, node string) *declaration.Process {
|
||||
if node == "" {
|
||||
return r
|
||||
}
|
||||
p := *r
|
||||
p.Env = make(map[string]string, len(r.Env)+1)
|
||||
for k, v := range r.Env {
|
||||
p.Env[k] = v
|
||||
}
|
||||
p.Env[NodeEnv] = node
|
||||
return &p
|
||||
}
|
||||
|
||||
// unitFor is the unit the mesh writes for a daemon.
|
||||
//
|
||||
// **Generated whole and never edited in place**, the same rule as every other managed file: an
|
||||
|
||||
@@ -319,11 +319,17 @@ func TestAProcessAppliedAgainIsUnchangedAndNotRestarted(t *testing.T) {
|
||||
}
|
||||
d := declare(t, `{"id":"node-tools.runtime","type":"process","name":"node-tools","source":"`+serving(t, body)+
|
||||
`","digest":"`+digest+`","run":["node","main.js"],"env":{"MESH_TOOL_MODULES":"a=/x/index.js"}}`)
|
||||
d.For = "anchor"
|
||||
|
||||
first, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginDeclared, run, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Design 47 G A-342: the process runs with its node's name as MESH_NODE beside its own env.
|
||||
if b, err := os.ReadFile(filepath.Join(units, "node-tools.service")); err != nil || !strings.Contains(string(b), `Environment="MESH_NODE=anchor"`) ||
|
||||
!strings.Contains(string(b), `Environment="MESH_TOOL_MODULES=`) {
|
||||
t.Errorf("the unit does not carry the node's name beside its env (%v):\n%s", err, b)
|
||||
}
|
||||
if o := outcomeOf(first, "node-tools.runtime"); o.Action != "created" {
|
||||
t.Fatalf("first apply: %+v, want created", o)
|
||||
}
|
||||
@@ -360,6 +366,7 @@ func TestAProcessAppliedAgainIsUnchangedAndNotRestarted(t *testing.T) {
|
||||
// An input of its unit that differs restarts it, and the line says which (issue 1966).
|
||||
changed := declare(t, `{"id":"node-tools.runtime","type":"process","name":"node-tools","source":"`+serving(t, body)+
|
||||
`","digest":"`+digest+`","run":["node","main.js"],"env":{"MESH_TOOL_MODULES":"a=/x/index.js,b=/y/index.js"}}`)
|
||||
changed.For = "anchor"
|
||||
fourth, _, err := Apply(context.Background(), archHost(t), changed, state, store.OriginDeclared, run, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user