A module that puts nothing on a machine cannot be assigned to one
The image every module in the scripted toolchain is compiled on top of is registered as a module so the mesh can build, version and depend on it. It is not one: nothing about it belongs on a machine. Assigning it succeeded, the machine was sent a declaration containing nothing of it, and everything reported success — the operator had said run this here and the mesh had agreed to something it cannot do. A module whose resources are worked out per node is asked about separately, so it stays assignable, which is the point of it.
This commit is contained in:
@@ -431,6 +431,9 @@ func (i *Inventory) Assign(ctx context.Context, nodeName, module string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := i.runsSomewhere(ctx, module); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = i.store.Pool().Exec(ctx,
|
_, err = i.store.Pool().Exec(ctx,
|
||||||
`insert into assignment (node, module) values ($1, $2) on conflict do nothing`,
|
`insert into assignment (node, module) values ($1, $2) on conflict do nothing`,
|
||||||
node.ID, module)
|
node.ID, module)
|
||||||
@@ -871,3 +874,43 @@ func (i *Inventory) Running(ctx context.Context, module string) ([]string, error
|
|||||||
}
|
}
|
||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runsSomewhere refuses to put a module on a machine when it would put nothing there.
|
||||||
|
//
|
||||||
|
// **Not every thing the mesh builds is a thing a machine runs.** The image every module in the
|
||||||
|
// scripted toolchain is compiled on top of is built, versioned and depended upon like a module, and
|
||||||
|
// is registered as one so the mesh can track all three. It is not one: it declares no resources,
|
||||||
|
// because nothing about it belongs on a machine — its whole purpose is to be the starting point for
|
||||||
|
// other modules' builds.
|
||||||
|
//
|
||||||
|
// Without this, assigning it succeeds, the machine is sent a declaration containing nothing of it,
|
||||||
|
// and everything reports success. The operator has said "run this here" and the mesh has agreed to
|
||||||
|
// something it cannot do. Said at the assignment, which is where somebody is standing.
|
||||||
|
//
|
||||||
|
// A module whose resources are worked out per node declares none here and is still assignable —
|
||||||
|
// that is the point of it — so it is asked about separately rather than caught by the same test.
|
||||||
|
func (i *Inventory) runsSomewhere(ctx context.Context, module string) error {
|
||||||
|
var raw []byte
|
||||||
|
err := i.store.Pool().QueryRow(ctx,
|
||||||
|
`select manifest from module where name = $1`, module).Scan(&raw)
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
// Left to the insert, which already says this and says it the same way everywhere.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var m catalogue.Manifest
|
||||||
|
if err := json.Unmarshal(raw, &m); err != nil {
|
||||||
|
// Unreadable is not the same as empty. A manifest the mesh cannot parse is a separate
|
||||||
|
// fault and refusing the assignment here would report it as the wrong one.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if m.Computed != "" || len(m.Resources) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf(
|
||||||
|
"%s puts nothing on a machine, so there is nothing to assign. It is something this mesh "+
|
||||||
|
"builds and other modules are built on top of, not something a machine runs — "+
|
||||||
|
"`module list` shows what it produces", module)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user