package compose import ( "encoding/json" "fmt" "sort" "git.novox.be/novox/mesh-sdk/go/declaration" "git.novox.be/novox/mesh-sdk/go/delivery" ) // Compositions is one node's compositions (novox/hq ADR 0539 clauses 1 and 2): its declaration composed over in, as // the controller composes it, split into each module's composition at the fingerprint fps gives it and the node's own // (`.node`), by key (delivery.ComposedKey). Each resource says its module, whatever the node reported it reads. // A module fps gives no fingerprint for is not composed and is named in skipped, so a caller composing one module // (mesh-compose) gets that one. Each module's Data says whether its manifest declares data. The compositions are not // signed and not yet by digest: the writer does both (delivery.SignComposed, Composed.ByDigest). func Compositions(in Input, node string, fps map[string]string, mode Mode) (out map[string]delivery.Composed, skipped []string, err error) { reading := in reading.Nodes = append([]Node(nil), in.Nodes...) found := false for i := range reading.Nodes { if reading.Nodes[i].Name == node { reading.Nodes[i].ReadsModules = true found = true } } if !found { return nil, nil, fmt.Errorf("compose: the mesh has no node %q", node) } d, problems, err := ComposeIn(reading, node, mode) if err != nil { return nil, nil, err } if len(problems) > 0 { return nil, nil, fmt.Errorf("compose: %s's declaration is refused by the node-engine's validator: %v", node, problems) } body, err := d.Body() if err != nil { return nil, nil, err } var envelope struct { Resources []json.RawMessage `json:"resources"` Adoption *declaration.Adoption `json:"adoption"` Filled []string `json:"filled_files"` Provisioner string `json:"provisioner_account"` } if err := json.Unmarshal(body, &envelope); err != nil { return nil, nil, err } var kept []json.RawMessage keptPaths := map[string]bool{} left := map[string]bool{} for _, raw := range envelope.Resources { var head struct { Module string `json:"module"` Type string `json:"type"` Path string `json:"path"` } if err := json.Unmarshal(raw, &head); err != nil { return nil, nil, err } if _, ok := fps[head.Module]; head.Module != "" && !ok { left[head.Module] = true continue } if head.Type == string(declaration.TypeFile) { keptPaths[head.Path] = true } kept = append(kept, raw) } var filled []string for _, p := range envelope.Filled { if keptPaths[p] { filled = append(filled, p) } } out, err = delivery.SplitComposed(node, kept, fps, filled, delivery.NodeOwn{Adoption: envelope.Adoption, Provisioner: envelope.Provisioner}) if err != nil { return nil, nil, err } for key, c := range out { if m, ok := in.Catalogue[c.Module]; ok && c.Module != "" { c.Data = len(m.DataItems()) > 0 out[key] = c } } for m := range left { skipped = append(skipped, m) } sort.Strings(skipped) return out, skipped, nil }