package compose import ( "encoding/json" "sort" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // What an input says of its held modules on the wire (issue 774, the group check of feat/l3-final 278aa5f0ccbe). A held // module stands in the input as its stub (Stub), and the stub's mark (catalogue.Manifest.Stubbed) is no field of a // manifest's JSON: an input a node-engine sent the check's sandbox lost it, so the sandbox read node-tools, held by its // manifest's verdict, as a tool runner with no bundle and refused every module of ace, g14 and shanks for "its build // produced 0 bundle(s)" instead of naming the verdict. So the input carries the mark itself, by module, for its catalogue // and for each node's kept manifests, and a reader marks each again. An input from a node-engine before the mark (no // Held) is read by its contract: a module Refused names stands in Catalogue as its stub. // heldMarks are the modules an input holds as their stubs: those of its catalogue, and those each node keeps, by node. type heldMarks struct { Catalogue []string `json:",omitempty"` Kept map[string][]string `json:",omitempty"` } // inputFields is Input without its JSON methods. type inputFields Input // inputWire is an input as it crosses the bus: its fields, and the modules it holds as their stubs. type inputWire struct { inputFields Held *heldMarks `json:",omitempty"` } // MarshalJSON writes the input with the modules it holds as their stubs named beside it (heldMarks). func (in Input) MarshalJSON() ([]byte, error) { w := inputWire{inputFields: inputFields(in)} marks := heldMarks{Catalogue: stubbedOf(in.Catalogue)} for _, n := range in.Nodes { if kept := stubbedOf(n.Kept); len(kept) > 0 { if marks.Kept == nil { marks.Kept = map[string][]string{} } marks.Kept[n.Name] = kept } } if len(marks.Catalogue) > 0 || len(marks.Kept) > 0 { w.Held = &marks } return json.Marshal(w) } // UnmarshalJSON reads an input and marks again each module it holds as its stub: those it names held, and, by the // input's contract, every module Refused names that its catalogue holds. func (in *Input) UnmarshalJSON(raw []byte) error { var w inputWire if err := json.Unmarshal(raw, &w); err != nil { return err } *in = Input(w.inputFields) held := map[string]bool{} for m := range in.Refused { held[m] = true } if w.Held != nil { for _, m := range w.Held.Catalogue { held[m] = true } } for m := range held { if man, ok := in.Catalogue[m]; ok { man.Stubbed = true in.Catalogue[m] = man } } if w.Held != nil { for i := range in.Nodes { for _, m := range w.Held.Kept[in.Nodes[i].Name] { if man, ok := in.Nodes[i].Kept[m]; ok { man.Stubbed = true in.Nodes[i].Kept[m] = man } } } } return nil } // stubbedOf is each module of manifests held as its stub, sorted. func stubbedOf(manifests map[string]catalogue.Manifest) []string { var out []string for name, m := range manifests { if m.Stubbed { out = append(out, name) } } sort.Strings(out) return out }