func appendConstraint(constraints *versionConstraint, cons string) { if constraintPresent(*constraints, cons) { return } newcon, _ := gversion.NewConstraint(cons) *constraints = append(*constraints, newcon...) }
func (cbv *CookbookVersion) getDependencies(g *depgraph.Graph, nodes map[string]*depgraph.Noun, cbShelf map[string]*Cookbook) { depList := cbv.Metadata["dependencies"].(map[string]interface{}) for r, c2 := range depList { if _, ok := nodes[r]; ok { if nodes[r].Meta.(*depMeta).noVersion || nodes[r].Meta.(*depMeta).notFound { continue } } c := c2.(string) var depCb *Cookbook var err util.Gerror var found bool if _, ok := nodes[r]; !ok { nodes[r] = &depgraph.Noun{Name: r, Meta: &depMeta{}} } dep, depPos, dt := checkDependency(nodes[cbv.CookbookName], r) if dep == nil { dep = &depgraph.Dependency{Name: fmt.Sprintf("%s-%s", cbv.CookbookName, r), Source: nodes[cbv.CookbookName], Target: nodes[r]} } depCons, _ := gversion.NewConstraint(c) dep.Constraints = []depgraph.Constraint{versionConstraint(depCons)} if !dt || nodes[cbv.CookbookName].Deps == nil { nodes[cbv.CookbookName].Deps = append(nodes[cbv.CookbookName].Deps, dep) } else { nodes[cbv.CookbookName].Deps[depPos] = dep } if depCb, found = cbShelf[r]; !found { depCb, err = Get(r) if err != nil { nodes[r].Meta.(*depMeta).notFound = true appendConstraint(&nodes[r].Meta.(*depMeta).constraint, c) continue } } else { // see if this constraint and a dependency for this // cookbook is already in place. If it is, go ahead and // move along, we've already been here. if dt && constraintPresent(nodes[r].Meta.(*depMeta).constraint, c) { continue } } appendConstraint(&nodes[r].Meta.(*depMeta).constraint, c) cbShelf[r] = depCb depCbv := depCb.latestMultiConstraint(nodes[r].Meta.(*depMeta).constraint) if depCbv == nil { nodes[r].Meta.(*depMeta).noVersion = true continue } if nodes[r].Meta.(*depMeta).version != "" && nodes[r].Meta.(*depMeta).version != depCbv.Version { // Remove any dependencies for this cookbook's node. // They'll be filled in nodes[r].Deps = make([]*depgraph.Dependency, 0) } nodes[r].Meta.(*depMeta).version = depCbv.Version depCbv.getDependencies(g, nodes, cbShelf) } }
// DependsCookbooks will, for the given run list and environment constraints, // return the cookbook dependencies. func DependsCookbooks(runList []string, envConstraints map[string]string) (map[string]interface{}, error) { nodes := make(map[string]*depgraph.Noun) runListRef := make([]string, len(runList)) for i, cbV := range runList { var cbName string var constraint string cx := strings.Split(cbV, "@") cbName = strings.Split(cx[0], "::")[0] if len(cx) == 2 { constraint = fmt.Sprintf("= %s", cx[1]) } nodes[cbName] = &depgraph.Noun{Name: cbName} meta := &depMeta{} if constraint != "" { q, _ := gversion.NewConstraint(constraint) meta.constraint = versionConstraint(q) } nodes[cbName].Meta = meta runListRef[i] = cbName } for k, ec := range envConstraints { if _, found := nodes[k]; !found { continue } appendConstraint(&nodes[k].Meta.(*depMeta).constraint, ec) } graphRoot := &depgraph.Noun{Name: "^runlist_root^"} g := &depgraph.Graph{Name: "runlist", Root: graphRoot} // fill in constraints for runlist deps now for k, n := range nodes { d := &depgraph.Dependency{Name: fmt.Sprintf("%s-%s", g.Name, k), Source: graphRoot, Target: n, Constraints: []depgraph.Constraint{versionConstraint(n.Meta.(*depMeta).constraint)}} graphRoot.Deps = append(graphRoot.Deps, d) } cbShelf := make(map[string]*Cookbook) for _, cbName := range runListRef { if _, found := cbShelf[cbName]; found || nodes[cbName].Meta.(*depMeta).notFound { continue } cb, err := Get(cbName) if err != nil { nodes[cbName].Meta.(*depMeta).notFound = true continue } cbShelf[cbName] = cb cbv := cb.latestMultiConstraint(nodes[cbName].Meta.(*depMeta).constraint) if cbv == nil { nodes[cbName].Meta.(*depMeta).noVersion = true continue } nodes[cbName].Meta.(*depMeta).version = cbv.Version cbv.getDependencies(g, nodes, cbShelf) } nouns := make([]*depgraph.Noun, 1) nouns[0] = graphRoot g.Nouns = nouns cerr := g.CheckConstraints() if cerr != nil { err := &DependsError{cerr.(*depgraph.ConstraintError)} return nil, err } cookbookDeps := make(map[string]interface{}, len(cbShelf)) for k, c := range cbShelf { constraints := nodes[k].Meta.(*depMeta).constraint cbv := c.latestMultiConstraint(constraints) if cbv == nil { err := fmt.Errorf("Somehow, and this shouldn't have beenable to happen at this stage, no versions of %s satisfied the constraints '%s'!", c.Name, constraints.String()) return nil, err } gcbvJSON := cbv.ToJSON("POST") for _, cd := range chkDiv { if gcbvJSON[cd] == nil { gcbvJSON[cd] = make([]map[string]interface{}, 0) } } cookbookDeps[cbv.CookbookName] = gcbvJSON } return cookbookDeps, nil }