package main import ( "context" "fmt" "github.com/novox/mesh-control/internal/catalogue" ) // The things the mesh can be asked to do, separated from how it was asked. // // **A surface is an adapter with no decisions in it** (novox/hq ADR 0035). The command line and // the command API call the same functions here, so an assignment refused at one is refused at the // other for the same reason and in the same words. The moment a surface can accept something // another would reject, the mesh has two answers to one question and people learn which to trust. // // Each returns what happened as text a person can read and a caller can pass on. Neither surface // composes its own explanation, because two explanations of one refusal drift. // assign puts a module on a node, and says at once whether the whole set still resolves. // // The assignment is kept even when it does not: it is what a person meant, and the refusal is // about the set rather than about this one. That is a decision, so it lives here rather than in // whichever surface asked. func assign(ctx context.Context, open *stores, node, module string) (string, error) { if err := open.inventory.Assign(ctx, node, module); err != nil { return "", err } said := fmt.Sprintf("%s is assigned %s", node, module) plan, _, err := planFor(ctx, open, node) if err != nil { // Kept, and still refused. Both halves are the answer. return said, err } // Kept, and cannot be hosted here. Said at once rather than discovered at push: a module whose // capability the machine lacks is on the wrong machine, and the assignment records what a person // meant while this line says it will not run until it moves. The rest of the node still pushes. for _, u := range plan.Unhostable { if u.Module != module { continue } for _, c := range u.Missing { said += "\n but " + catalogue.WrongMachine(u.Module, c, node) } } return said + fmt.Sprintf("\n run `push %s` to send it", node), nil } // unassign takes a module off a node. What it leaves behind is the host's business: a directory // holding anything the mesh did not put there is kept (novox/hq ADR 0030). func unassign(ctx context.Context, open *stores, node, module string) (string, error) { if err := open.inventory.Unassign(ctx, node, module); err != nil { return "", err } return fmt.Sprintf("%s no longer runs %s — run `push %s` to make it so", node, module, node), nil }