diff --git a/examples/lib/libmgmt2.go b/examples/lib/libmgmt2.go index bbd6d007..0a6a2543 100644 --- a/examples/lib/libmgmt2.go +++ b/examples/lib/libmgmt2.go @@ -59,7 +59,10 @@ func (obj *MyGAPI) Graph() (*pgraph.Graph, error) { return nil, fmt.Errorf("libmgmt: MyGAPI is not initialized") } - g := pgraph.NewGraph(obj.Name) + g, err := pgraph.NewGraph(obj.Name) + if err != nil { + return nil, err + } var vertex *pgraph.Vertex for i := uint(0); i < obj.Count; i++ { n := &resources.NoopRes{ diff --git a/examples/lib/libmgmt3.go b/examples/lib/libmgmt3.go index 329acdb9..184f7619 100644 --- a/examples/lib/libmgmt3.go +++ b/examples/lib/libmgmt3.go @@ -56,7 +56,10 @@ func (obj *MyGAPI) Graph() (*pgraph.Graph, error) { return nil, fmt.Errorf("libmgmt: MyGAPI is not initialized") } - g := pgraph.NewGraph(obj.Name) + g, err := pgraph.NewGraph(obj.Name) + if err != nil { + return nil, err + } // FIXME: these are being specified temporarily until it's the default! metaparams := resources.DefaultMetaParams diff --git a/pgraph/actions.go b/pgraph/actions.go index a4ec7196..17f8e87e 100644 --- a/pgraph/actions.go +++ b/pgraph/actions.go @@ -87,7 +87,7 @@ func (g *Graph) Poke(v *Vertex) error { wg.Add(1) go func(nn *Vertex) error { defer wg.Done() - //edge := g.Adjacency[v][nn] // lookup + //edge := g.adjacency[v][nn] // lookup //notify := edge.Notify && edge.Refresh() return nn.SendEvent(event.EventPoke, nil) }(n) diff --git a/pgraph/autogroup.go b/pgraph/autogroup.go index aa4faaca..4a1b173a 100644 --- a/pgraph/autogroup.go +++ b/pgraph/autogroup.go @@ -204,11 +204,11 @@ func (g *Graph) VertexMerge(v1, v2 *Vertex, vertexMergeFn func(*Vertex, *Vertex) // methodology // 1) edges between v1 and v2 are removed //Loop: - for k1 := range g.Adjacency { - for k2 := range g.Adjacency[k1] { + for k1 := range g.adjacency { + for k2 := range g.adjacency[k1] { // v1 -> v2 || v2 -> v1 if (k1 == v1 && k2 == v2) || (k1 == v2 && k2 == v1) { - delete(g.Adjacency[k1], k2) // delete map & edge + delete(g.adjacency[k1], k2) // delete map & edge // NOTE: if we assume this is a DAG, then we can // assume only v1 -> v2 OR v2 -> v1 exists, and // we can break out of these loops immediately! @@ -220,10 +220,10 @@ func (g *Graph) VertexMerge(v1, v2 *Vertex, vertexMergeFn func(*Vertex, *Vertex) // 2) edges that point towards v2 from X now point to v1 from X (no dupes) for _, x := range g.IncomingGraphVertices(v2) { // all to vertex v (??? -> v) - e := g.Adjacency[x][v2] // previous edge + e := g.adjacency[x][v2] // previous edge r := g.Reachability(x, v1) - // merge e with ex := g.Adjacency[x][v1] if it exists! - if ex, exists := g.Adjacency[x][v1]; exists && edgeMergeFn != nil && len(r) == 0 { + // merge e with ex := g.adjacency[x][v1] if it exists! + if ex, exists := g.adjacency[x][v1]; exists && edgeMergeFn != nil && len(r) == 0 { e = edgeMergeFn(e, ex) } if len(r) == 0 { // if not reachable, add it @@ -236,21 +236,21 @@ func (g *Graph) VertexMerge(v1, v2 *Vertex, vertexMergeFn func(*Vertex, *Vertex) continue } // this edge is from: prev, to: next - ex, _ := g.Adjacency[prev][next] // get + ex, _ := g.adjacency[prev][next] // get ex = edgeMergeFn(ex, e) - g.Adjacency[prev][next] = ex // set + g.adjacency[prev][next] = ex // set prev = next } } - delete(g.Adjacency[x], v2) // delete old edge + delete(g.adjacency[x], v2) // delete old edge } // 3) edges that point from v2 to X now point from v1 to X (no dupes) for _, x := range g.OutgoingGraphVertices(v2) { // all from vertex v (v -> ???) - e := g.Adjacency[v2][x] // previous edge + e := g.adjacency[v2][x] // previous edge r := g.Reachability(v1, x) - // merge e with ex := g.Adjacency[v1][x] if it exists! - if ex, exists := g.Adjacency[v1][x]; exists && edgeMergeFn != nil && len(r) == 0 { + // merge e with ex := g.adjacency[v1][x] if it exists! + if ex, exists := g.adjacency[v1][x]; exists && edgeMergeFn != nil && len(r) == 0 { e = edgeMergeFn(e, ex) } if len(r) == 0 { @@ -263,13 +263,13 @@ func (g *Graph) VertexMerge(v1, v2 *Vertex, vertexMergeFn func(*Vertex, *Vertex) continue } // this edge is from: prev, to: next - ex, _ := g.Adjacency[prev][next] + ex, _ := g.adjacency[prev][next] ex = edgeMergeFn(ex, e) - g.Adjacency[prev][next] = ex + g.adjacency[prev][next] = ex prev = next } } - delete(g.Adjacency[v2], x) + delete(g.adjacency[v2], x) } // 4) merge and then remove the (now merged/grouped) vertex diff --git a/pgraph/autogroup_test.go b/pgraph/autogroup_test.go index 2a0046f4..7c6d6dd4 100644 --- a/pgraph/autogroup_test.go +++ b/pgraph/autogroup_test.go @@ -30,19 +30,19 @@ import ( // empty graph func TestPgraphGrouping1(t *testing.T) { - g1 := NewGraph("g1") // original graph - g2 := NewGraph("g2") // expected result + g1, _ := NewGraph("g1") // original graph + g2, _ := NewGraph("g2") // expected result runGraphCmp(t, g1, g2) } // single vertex func TestPgraphGrouping2(t *testing.T) { - g1 := NewGraph("g1") // original graph - { // grouping to limit variable scope + g1, _ := NewGraph("g1") // original graph + { // grouping to limit variable scope a1 := NewVertex(NewNoopResTest("a1")) g1.AddVertex(a1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) g2.AddVertex(a1) @@ -52,13 +52,13 @@ func TestPgraphGrouping2(t *testing.T) { // two vertices func TestPgraphGrouping3(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) g1.AddVertex(a1, b1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) @@ -69,13 +69,13 @@ func TestPgraphGrouping3(t *testing.T) { // two vertices merge func TestPgraphGrouping4(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) g1.AddVertex(a1, a2) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) g2.AddVertex(a) @@ -85,14 +85,14 @@ func TestPgraphGrouping4(t *testing.T) { // three vertices merge func TestPgraphGrouping5(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) a3 := NewVertex(NewNoopResTest("a3")) g1.AddVertex(a1, a2, a3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2,a3")) g2.AddVertex(a) @@ -102,14 +102,14 @@ func TestPgraphGrouping5(t *testing.T) { // three vertices, two merge func TestPgraphGrouping6(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) b1 := NewVertex(NewNoopResTest("b1")) g1.AddVertex(a1, a2, b1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b1 := NewVertex(NewNoopResTest("b1")) @@ -120,7 +120,7 @@ func TestPgraphGrouping6(t *testing.T) { // four vertices, three merge func TestPgraphGrouping7(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -128,7 +128,7 @@ func TestPgraphGrouping7(t *testing.T) { b1 := NewVertex(NewNoopResTest("b1")) g1.AddVertex(a1, a2, a3, b1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2,a3")) b1 := NewVertex(NewNoopResTest("b1")) @@ -139,7 +139,7 @@ func TestPgraphGrouping7(t *testing.T) { // four vertices, two&two merge func TestPgraphGrouping8(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -147,7 +147,7 @@ func TestPgraphGrouping8(t *testing.T) { b2 := NewVertex(NewNoopResTest("b2")) g1.AddVertex(a1, a2, b1, b2) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b := NewVertex(NewNoopResTest("b1,b2")) @@ -158,7 +158,7 @@ func TestPgraphGrouping8(t *testing.T) { // five vertices, two&three merge func TestPgraphGrouping9(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -167,7 +167,7 @@ func TestPgraphGrouping9(t *testing.T) { b3 := NewVertex(NewNoopResTest("b3")) g1.AddVertex(a1, a2, b1, b2, b3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b := NewVertex(NewNoopResTest("b1,b2,b3")) @@ -178,14 +178,14 @@ func TestPgraphGrouping9(t *testing.T) { // three unique vertices func TestPgraphGrouping10(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) c1 := NewVertex(NewNoopResTest("c1")) g1.AddVertex(a1, b1, c1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) @@ -197,7 +197,7 @@ func TestPgraphGrouping10(t *testing.T) { // three unique vertices, two merge func TestPgraphGrouping11(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) @@ -205,7 +205,7 @@ func TestPgraphGrouping11(t *testing.T) { c1 := NewVertex(NewNoopResTest("c1")) g1.AddVertex(a1, b1, b2, c1) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) b := NewVertex(NewNoopResTest("b1,b2")) @@ -220,7 +220,7 @@ func TestPgraphGrouping11(t *testing.T) { // \ / >>> | (arrows point downwards) // b b func TestPgraphGrouping12(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -230,7 +230,7 @@ func TestPgraphGrouping12(t *testing.T) { g1.AddEdge(a1, b1, e1) g1.AddEdge(a2, b1, e2) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b1 := NewVertex(NewNoopResTest("b1")) @@ -245,7 +245,7 @@ func TestPgraphGrouping12(t *testing.T) { // / \ >>> | (arrows point downwards) // a1 a2 a1,a2 func TestPgraphGrouping13(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -255,7 +255,7 @@ func TestPgraphGrouping13(t *testing.T) { g1.AddEdge(b1, a1, e1) g1.AddEdge(b1, a2, e2) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b1 := NewVertex(NewNoopResTest("b1")) @@ -270,7 +270,7 @@ func TestPgraphGrouping13(t *testing.T) { // \ | / >>> | (arrows point downwards) // b b func TestPgraphGrouping14(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -283,7 +283,7 @@ func TestPgraphGrouping14(t *testing.T) { g1.AddEdge(a2, b1, e2) g1.AddEdge(a3, b1, e3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2,a3")) b1 := NewVertex(NewNoopResTest("b1")) @@ -300,7 +300,7 @@ func TestPgraphGrouping14(t *testing.T) { // \ / | // c1 c1 func TestPgraphGrouping15(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) @@ -315,7 +315,7 @@ func TestPgraphGrouping15(t *testing.T) { g1.AddEdge(b1, c1, e3) g1.AddEdge(b2, c1, e4) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) b := NewVertex(NewNoopResTest("b1,b2")) @@ -337,7 +337,7 @@ func TestPgraphGrouping15(t *testing.T) { // | / | | / // c1 c1 c1 func TestPgraphGrouping16(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -350,7 +350,7 @@ func TestPgraphGrouping16(t *testing.T) { g1.AddEdge(b1, c1, e2) g1.AddEdge(a2, c1, e3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b1 := NewVertex(NewNoopResTest("b1")) @@ -370,7 +370,7 @@ func TestPgraphGrouping16(t *testing.T) { // | / | // c1 c1 func TestPgraphGrouping17(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b1 := NewVertex(NewNoopResTest("b1")) @@ -383,7 +383,7 @@ func TestPgraphGrouping17(t *testing.T) { g1.AddEdge(b1, c1, e2) g1.AddEdge(b2, c1, e3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a1 := NewVertex(NewNoopResTest("a1")) b := NewVertex(NewNoopResTest("b1,b2")) @@ -404,7 +404,7 @@ func TestPgraphGrouping17(t *testing.T) { // \ | / | // c1 c1 func TestPgraphGrouping18(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -420,7 +420,7 @@ func TestPgraphGrouping18(t *testing.T) { g1.AddEdge(a2, c1, e3) g1.AddEdge(b2, c1, e4) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a := NewVertex(NewNoopResTest("a1,a2")) b := NewVertex(NewNoopResTest("b1,b2")) @@ -438,14 +438,14 @@ func TestPgraphGrouping18(t *testing.T) { // \ >>> \ (arrows point downwards) // a2 a2 func TestPgraphGroupingConnected0(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) e1 := NewEdge("e1") g1.AddEdge(a1, a2, e1) } - g2 := NewGraph("g2") // expected result ? + g2, _ := NewGraph("g2") // expected result ? { a1 := NewVertex(NewNoopResTest("a1")) a2 := NewVertex(NewNoopResTest("a2")) @@ -462,7 +462,7 @@ func TestPgraphGroupingConnected0(t *testing.T) { // \ \ // a2 a2 func TestPgraphGroupingConnected1(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTest("a1")) b := NewVertex(NewNoopResTest("b")) @@ -472,7 +472,7 @@ func TestPgraphGroupingConnected1(t *testing.T) { g1.AddEdge(a1, b, e1) g1.AddEdge(b, a2, e2) } - g2 := NewGraph("g2") // expected result ? + g2, _ := NewGraph("g2") // expected result ? { a1 := NewVertex(NewNoopResTest("a1")) b := NewVertex(NewNoopResTest("b")) diff --git a/pgraph/graphviz.go b/pgraph/graphviz.go index 9e6143c3..e9b97876 100644 --- a/pgraph/graphviz.go +++ b/pgraph/graphviz.go @@ -45,10 +45,10 @@ func (g *Graph) Graphviz() (out string) { out += fmt.Sprintf("\tlabel=\"%s\";\n", g.GetName()) //out += "\tnode [shape=box];\n" str := "" - for i := range g.Adjacency { // reverse paths + for i := range g.adjacency { // reverse paths out += fmt.Sprintf("\t\"%s\" [label=\"%s[%s]\"];\n", i.GetName(), i.GetKind(), i.GetName()) - for j := range g.Adjacency[i] { - k := g.Adjacency[i][j] + for j := range g.adjacency[i] { + k := g.adjacency[i][j] // use str for clearer output ordering if k.Notify { str += fmt.Sprintf("\t\"%s\" -> \"%s\" [label=\"%s\",style=bold];\n", i.GetName(), j.GetName(), k.Name) diff --git a/pgraph/pgraph.go b/pgraph/pgraph.go index 201a1f1c..78582b7b 100644 --- a/pgraph/pgraph.go +++ b/pgraph/pgraph.go @@ -54,8 +54,12 @@ type Flags struct { // * IOW, you might see package -> file -> service (where package runs first) // * This is also the direction that the notify should happen in... type Graph struct { - Name string - Adjacency map[*Vertex]map[*Vertex]*Edge // *Vertex -> *Vertex (edge) + Name string + + adjacency map[*Vertex]map[*Vertex]*Edge // *Vertex -> *Vertex (edge) + kv map[string]interface{} // some values associated with the graph + + // legacy Flags Flags state graphState fastPause bool // used to disable pokes for a fast pause @@ -81,18 +85,34 @@ type Edge struct { refresh bool // is there a notify pending for the dest vertex ? } -// NewGraph builds a new graph. -func NewGraph(name string) *Graph { - return &Graph{ - Name: name, - Adjacency: make(map[*Vertex]map[*Vertex]*Edge), - state: graphStateNil, - // ptr b/c: Mutex/WaitGroup must not be copied after first use - mutex: &sync.Mutex{}, - wg: &sync.WaitGroup{}, - semas: make(map[string]*semaphore.Semaphore), - slock: &sync.Mutex{}, +// Init initializes the graph which populates all the internal structures. +func (g *Graph) Init() error { + if g.Name == "" { + return fmt.Errorf("can't initialize graph with empty name") } + + g.adjacency = make(map[*Vertex]map[*Vertex]*Edge) + g.kv = make(map[string]interface{}) + + // legacy + g.state = graphStateNil + // ptr b/c: Mutex/WaitGroup must not be copied after first use + g.mutex = &sync.Mutex{} + g.wg = &sync.WaitGroup{} + g.semas = make(map[string]*semaphore.Semaphore) + g.slock = &sync.Mutex{} + return nil +} + +// NewGraph builds a new graph. +func NewGraph(name string) (*Graph, error) { + g := &Graph{ + Name: name, + } + if err := g.Init(); err != nil { + return nil, err + } + return g, nil } // NewVertex returns a new graph vertex struct with a contained resource. @@ -119,11 +139,25 @@ func (obj *Edge) SetRefresh(b bool) { obj.refresh = b } +// Value returns a value stored alongside the graph in a particular key. +func (g *Graph) Value(key string) (interface{}, bool) { + val, exists := g.kv[key] + return val, exists +} + +// SetValue sets a value to be stored alongside the graph in a particular key. +func (g *Graph) SetValue(key string, val interface{}) { + g.kv[key] = val +} + // Copy makes a copy of the graph struct func (g *Graph) Copy() *Graph { newGraph := &Graph{ Name: g.Name, - Adjacency: make(map[*Vertex]map[*Vertex]*Edge, len(g.Adjacency)), + adjacency: make(map[*Vertex]map[*Vertex]*Edge, len(g.adjacency)), + kv: g.kv, + + // legacy Flags: g.Flags, state: g.state, mutex: g.mutex, @@ -134,8 +168,8 @@ func (g *Graph) Copy() *Graph { prometheus: g.prometheus, } - for k, v := range g.Adjacency { - newGraph.Adjacency[k] = v // copy + for k, v := range g.adjacency { + newGraph.adjacency[k] = v // copy } return newGraph } @@ -171,17 +205,17 @@ func (g *Graph) setState(state graphState) graphState { // AddVertex uses variadic input to add all listed vertices to the graph func (g *Graph) AddVertex(xv ...*Vertex) { for _, v := range xv { - if _, exists := g.Adjacency[v]; !exists { - g.Adjacency[v] = make(map[*Vertex]*Edge) + if _, exists := g.adjacency[v]; !exists { + g.adjacency[v] = make(map[*Vertex]*Edge) } } } // DeleteVertex deletes a particular vertex from the graph. func (g *Graph) DeleteVertex(v *Vertex) { - delete(g.Adjacency, v) - for k := range g.Adjacency { - delete(g.Adjacency[k], v) + delete(g.adjacency, v) + for k := range g.adjacency { + delete(g.adjacency[k], v) } } @@ -191,16 +225,16 @@ func (g *Graph) AddEdge(v1, v2 *Vertex, e *Edge) { g.AddVertex(v1, v2) // supports adding N vertices now // TODO: check if an edge exists to avoid overwriting it! // NOTE: VertexMerge() depends on overwriting it at the moment... - g.Adjacency[v1][v2] = e + g.adjacency[v1][v2] = e } // DeleteEdge deletes a particular edge from the graph. // FIXME: add test cases func (g *Graph) DeleteEdge(e *Edge) { - for v1 := range g.Adjacency { - for v2, edge := range g.Adjacency[v1] { + for v1 := range g.adjacency { + for v2, edge := range g.adjacency[v1] { if e == edge { - delete(g.Adjacency[v1], v2) + delete(g.adjacency[v1], v2) } } } @@ -209,7 +243,7 @@ func (g *Graph) DeleteEdge(e *Edge) { // CompareMatch searches for an equivalent resource in the graph and returns the // vertex it is found in, or nil if not found. func (g *Graph) CompareMatch(obj resources.Res) *Vertex { - for v := range g.Adjacency { + for v := range g.adjacency { if v.Res.Compare(obj) { return v } @@ -219,7 +253,7 @@ func (g *Graph) CompareMatch(obj resources.Res) *Vertex { // TODO: consider adding a mutate API. //func (g *Graph) MutateMatch(obj resources.Res) *Vertex { -// for v := range g.Adjacency { +// for v := range g.adjacency { // if err := v.Res.Mutate(obj); err == nil { // // transmogrified! // return v @@ -230,7 +264,7 @@ func (g *Graph) CompareMatch(obj resources.Res) *Vertex { // HasVertex returns if the input vertex exists in the graph. func (g *Graph) HasVertex(v *Vertex) bool { - if _, exists := g.Adjacency[v]; exists { + if _, exists := g.adjacency[v]; exists { return true } return false @@ -238,14 +272,14 @@ func (g *Graph) HasVertex(v *Vertex) bool { // NumVertices returns the number of vertices in the graph. func (g *Graph) NumVertices() int { - return len(g.Adjacency) + return len(g.adjacency) } // NumEdges returns the number of edges in the graph. func (g *Graph) NumEdges() int { count := 0 - for k := range g.Adjacency { - count += len(g.Adjacency[k]) + for k := range g.adjacency { + count += len(g.adjacency[k]) } return count } @@ -254,7 +288,7 @@ func (g *Graph) NumEdges() int { // The order is random, because the map implementation is intentionally so! func (g *Graph) GetVertices() []*Vertex { var vertices []*Vertex - for k := range g.Adjacency { + for k := range g.adjacency { vertices = append(vertices, k) } return vertices @@ -264,7 +298,7 @@ func (g *Graph) GetVertices() []*Vertex { func (g *Graph) GetVerticesChan() chan *Vertex { ch := make(chan *Vertex) go func(ch chan *Vertex) { - for k := range g.Adjacency { + for k := range g.adjacency { ch <- k } close(ch) @@ -283,7 +317,7 @@ func (vs VertexSlice) Less(i, j int) bool { return vs[i].String() < vs[j].String // The order is sorted by String() to avoid the non-determinism in the map type func (g *Graph) GetVerticesSorted() []*Vertex { var vertices []*Vertex - for k := range g.Adjacency { + for k := range g.adjacency { vertices = append(vertices, k) } sort.Sort(VertexSlice(vertices)) // add determinism @@ -306,8 +340,8 @@ func (g *Graph) IncomingGraphVertices(v *Vertex) []*Vertex { // TODO: we might be able to implement this differently by reversing // the Adjacency graph and then looping through it again... var s []*Vertex - for k := range g.Adjacency { // reverse paths - for w := range g.Adjacency[k] { + for k := range g.adjacency { // reverse paths + for w := range g.adjacency[k] { if w == v { s = append(s, k) } @@ -320,7 +354,7 @@ func (g *Graph) IncomingGraphVertices(v *Vertex) []*Vertex { // points to (v -> ???). Poke should probably use this. func (g *Graph) OutgoingGraphVertices(v *Vertex) []*Vertex { var s []*Vertex - for k := range g.Adjacency[v] { // forward paths + for k := range g.adjacency[v] { // forward paths s = append(s, k) } return s @@ -338,8 +372,8 @@ func (g *Graph) GraphVertices(v *Vertex) []*Vertex { // IncomingGraphEdges returns all of the edges that point to vertex v (??? -> v). func (g *Graph) IncomingGraphEdges(v *Vertex) []*Edge { var edges []*Edge - for v1 := range g.Adjacency { // reverse paths - for v2, e := range g.Adjacency[v1] { + for v1 := range g.adjacency { // reverse paths + for v2, e := range g.adjacency[v1] { if v2 == v { edges = append(edges, e) } @@ -351,7 +385,7 @@ func (g *Graph) IncomingGraphEdges(v *Vertex) []*Edge { // OutgoingGraphEdges returns all of the edges that point from vertex v (v -> ???). func (g *Graph) OutgoingGraphEdges(v *Vertex) []*Edge { var edges []*Edge - for _, e := range g.Adjacency[v] { // forward paths + for _, e := range g.adjacency[v] { // forward paths edges = append(edges, e) } return edges @@ -370,7 +404,7 @@ func (g *Graph) GraphEdges(v *Vertex) []*Edge { func (g *Graph) DFS(start *Vertex) []*Vertex { var d []*Vertex // discovered var s []*Vertex // stack - if _, exists := g.Adjacency[start]; !exists { + if _, exists := g.adjacency[start]; !exists { return nil // TODO: error } v := start @@ -390,64 +424,65 @@ func (g *Graph) DFS(start *Vertex) []*Vertex { } // FilterGraph builds a new graph containing only vertices from the list. -func (g *Graph) FilterGraph(name string, vertices []*Vertex) *Graph { - newgraph := NewGraph(name) - for k1, x := range g.Adjacency { +func (g *Graph) FilterGraph(name string, vertices []*Vertex) (*Graph, error) { + newGraph := &Graph{Name: name} + if err := newGraph.Init(); err != nil { + return nil, errwrap.Wrapf(err, "could not run FilterGraph() properly") + } + for k1, x := range g.adjacency { for k2, e := range x { //log.Printf("Filter: %s -> %s # %s", k1.Name, k2.Name, e.Name) if VertexContains(k1, vertices) || VertexContains(k2, vertices) { - newgraph.AddEdge(k1, k2, e) + newGraph.AddEdge(k1, k2, e) } } } - return newgraph + return newGraph, nil } -// GetDisconnectedGraphs returns a channel containing the N disconnected graphs -// in our main graph. We can then process each of these in parallel. -func (g *Graph) GetDisconnectedGraphs() chan *Graph { - ch := make(chan *Graph) - go func() { - var start *Vertex - var d []*Vertex // discovered - c := g.NumVertices() - for len(d) < c { +// GetDisconnectedGraphs returns a list containing the N disconnected graphs. +func (g *Graph) GetDisconnectedGraphs() ([]*Graph, error) { + graphs := []*Graph{} + var start *Vertex + var d []*Vertex // discovered + c := g.NumVertices() + for len(d) < c { - // get an undiscovered vertex to start from - for _, s := range g.GetVertices() { - if !VertexContains(s, d) { - start = s - } + // get an undiscovered vertex to start from + for _, s := range g.GetVertices() { + if !VertexContains(s, d) { + start = s } - - // dfs through the graph - dfs := g.DFS(start) - // filter all the collected elements into a new graph - newgraph := g.FilterGraph(g.Name, dfs) - - // add number of elements found to found variable - d = append(d, dfs...) // extend - - // return this new graph to the channel - ch <- newgraph - - // if we've found all the elements, then we're done - // otherwise loop through to continue... } - close(ch) - }() - return ch + + // dfs through the graph + dfs := g.DFS(start) + // filter all the collected elements into a new graph + newgraph, err := g.FilterGraph(g.Name, dfs) + if err != nil { + return nil, errwrap.Wrapf(err, "could not run GetDisconnectedGraphs() properly") + } + // add number of elements found to found variable + d = append(d, dfs...) // extend + + // append this new graph to the list + graphs = append(graphs, newgraph) + + // if we've found all the elements, then we're done + // otherwise loop through to continue... + } + return graphs, nil } // InDegree returns the count of vertices that point to me in one big lookup map. func (g *Graph) InDegree() map[*Vertex]int { result := make(map[*Vertex]int) - for k := range g.Adjacency { + for k := range g.adjacency { result[k] = 0 // initialize } - for k := range g.Adjacency { - for z := range g.Adjacency[k] { + for k := range g.adjacency { + for z := range g.adjacency[k] { result[z]++ } } @@ -458,9 +493,9 @@ func (g *Graph) InDegree() map[*Vertex]int { func (g *Graph) OutDegree() map[*Vertex]int { result := make(map[*Vertex]int) - for k := range g.Adjacency { + for k := range g.adjacency { result[k] = 0 // initialize - for range g.Adjacency[k] { + for range g.adjacency[k] { result[k]++ } } @@ -490,7 +525,7 @@ func (g *Graph) TopologicalSort() ([]*Vertex, error) { // kahn's algorithm v := S[last] S = S[:last] L = append(L, v) // add v to tail of L - for n := range g.Adjacency[v] { + for n := range g.adjacency[v] { // for each node n remaining in the graph, consume from // remaining, so for remaining[n] > 0 if remaining[n] > 0 { @@ -505,7 +540,7 @@ func (g *Graph) TopologicalSort() ([]*Vertex, error) { // kahn's algorithm // if graph has edges, eg if any value in rem is > 0 for c, in := range remaining { if in > 0 { - for n := range g.Adjacency[c] { + for n := range g.adjacency[c] { if remaining[n] > 0 { return nil, fmt.Errorf("not a dag") } @@ -563,7 +598,11 @@ func (g *Graph) Reachability(a, b *Vertex) []*Vertex { func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { if oldGraph == nil { - oldGraph = NewGraph(g.GetName()) // copy over the name + var err error + oldGraph, err = NewGraph(g.GetName()) // copy over the name + if err != nil { + return nil, errwrap.Wrapf(err, "could not run GraphSync() properly") + } } oldGraph.SetName(g.GetName()) // overwrite the name @@ -571,7 +610,7 @@ func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { var vertexKeep []*Vertex // list of vertices which are the same in new graph var edgeKeep []*Edge // list of vertices which are the same in new graph - for v := range g.Adjacency { // loop through the vertices (resources) + for v := range g.adjacency { // loop through the vertices (resources) res := v.Res // resource var vertex *Vertex @@ -598,7 +637,7 @@ func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { } // get rid of any vertices we shouldn't keep (that aren't in new graph) - for v := range oldGraph.Adjacency { + for v := range oldGraph.adjacency { if !VertexContains(v, vertexKeep) { // wait for exit before starting new graph! v.SendEvent(event.EventExit, nil) // sync @@ -608,8 +647,8 @@ func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { } // compare edges - for v1 := range g.Adjacency { // loop through the vertices (resources) - for v2, e := range g.Adjacency[v1] { + for v1 := range g.adjacency { // loop through the vertices (resources) + for v2, e := range g.adjacency[v1] { // we have an edge! // lookup vertices (these should exist now) @@ -624,18 +663,18 @@ func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { return nil, fmt.Errorf("new vertices weren't found") // programming error } - edge, exists := oldGraph.Adjacency[vertex1][vertex2] + edge, exists := oldGraph.adjacency[vertex1][vertex2] if !exists || edge.Name != e.Name { // TODO: edgeCmp edge = e // use or overwrite edge } - oldGraph.Adjacency[vertex1][vertex2] = edge // store it (AddEdge) + oldGraph.adjacency[vertex1][vertex2] = edge // store it (AddEdge) edgeKeep = append(edgeKeep, edge) // mark as saved } } // delete unused edges - for v1 := range oldGraph.Adjacency { - for _, e := range oldGraph.Adjacency[v1] { + for v1 := range oldGraph.adjacency { + for _, e := range oldGraph.adjacency[v1] { // we have an edge! if !EdgeContains(e, edgeKeep) { oldGraph.DeleteEdge(e) @@ -649,7 +688,7 @@ func (g *Graph) GraphSync(oldGraph *Graph) (*Graph, error) { // GraphMetas returns a list of pointers to each of the resource MetaParams. func (g *Graph) GraphMetas() []*resources.MetaParams { metas := []*resources.MetaParams{} - for v := range g.Adjacency { // loop through the vertices (resources)) + for v := range g.adjacency { // loop through the vertices (resources)) res := v.Res // resource meta := res.Meta() metas = append(metas, meta) @@ -662,7 +701,7 @@ func (g *Graph) AssociateData(data *resources.Data) { // prometheus needs to be associated to this graph as well g.prometheus = data.Prometheus - for k := range g.Adjacency { + for k := range g.adjacency { *k.Res.Data() = *data } } diff --git a/pgraph/pgraph_test.go b/pgraph/pgraph_test.go index 3cd8a322..8b4f313f 100644 --- a/pgraph/pgraph_test.go +++ b/pgraph/pgraph_test.go @@ -42,7 +42,7 @@ func NV(s string) *Vertex { func TestPgraphT1(t *testing.T) { - G := NewGraph("g1") + G, _ := NewGraph("g1") if i := G.NumVertices(); i != 0 { t.Errorf("should have 0 vertices instead of: %d", i) @@ -68,7 +68,7 @@ func TestPgraphT1(t *testing.T) { func TestPgraphT2(t *testing.T) { - G := NewGraph("g2") + G, _ := NewGraph("g2") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -95,7 +95,7 @@ func TestPgraphT2(t *testing.T) { func TestPgraphT3(t *testing.T) { - G := NewGraph("g3") + G, _ := NewGraph("g3") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -136,7 +136,7 @@ func TestPgraphT3(t *testing.T) { func TestPgraphT4(t *testing.T) { - G := NewGraph("g4") + G, _ := NewGraph("g4") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -158,7 +158,7 @@ func TestPgraphT4(t *testing.T) { } func TestPgraphT5(t *testing.T) { - G := NewGraph("g5") + G, _ := NewGraph("g5") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -180,14 +180,18 @@ func TestPgraphT5(t *testing.T) { //G.AddEdge(v6, v4, e6) save := []*Vertex{v1, v2, v3} - out := G.FilterGraph("new g5", save) + out, err := G.FilterGraph("new g5", save) + if err != nil { + t.Errorf("failed with: %v", err) + } + if i := out.NumVertices(); i != 3 { t.Errorf("should have 3 vertices instead of: %d", i) } } func TestPgraphT6(t *testing.T) { - G := NewGraph("g6") + G, _ := NewGraph("g6") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -208,24 +212,19 @@ func TestPgraphT6(t *testing.T) { G.AddEdge(v5, v6, e5) //G.AddEdge(v6, v4, e6) - graphs := G.GetDisconnectedGraphs() - HeisenbergGraphCount := func(ch chan *Graph) int { - c := 0 - for x := range ch { - _ = x - c++ - } - return c + graphs, err := G.GetDisconnectedGraphs() + if err != nil { + t.Errorf("failed with: %v", err) } - if i := HeisenbergGraphCount(graphs); i != 2 { + if i := len(graphs); i != 2 { t.Errorf("should have 2 graphs instead of: %d", i) } } func TestPgraphT7(t *testing.T) { - G := NewGraph("g7") + G, _ := NewGraph("g7") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -296,7 +295,7 @@ func TestPgraphT8(t *testing.T) { func TestPgraphT9(t *testing.T) { - G := NewGraph("g9") + G, _ := NewGraph("g9") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -372,7 +371,7 @@ func TestPgraphT9(t *testing.T) { func TestPgraphT10(t *testing.T) { - G := NewGraph("g10") + G, _ := NewGraph("g10") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -400,7 +399,7 @@ func TestPgraphT10(t *testing.T) { // empty func TestPgraphReachability0(t *testing.T) { { - G := NewGraph("g") + G, _ := NewGraph("g") result := G.Reachability(nil, nil) if result != nil { t.Logf("reachability failed") @@ -412,7 +411,7 @@ func TestPgraphReachability0(t *testing.T) { } } { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v6 := NV("v6") @@ -429,7 +428,7 @@ func TestPgraphReachability0(t *testing.T) { } } { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -463,7 +462,7 @@ func TestPgraphReachability0(t *testing.T) { // simple linear path func TestPgraphReachability1(t *testing.T) { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -497,7 +496,7 @@ func TestPgraphReachability1(t *testing.T) { // pick one of two correct paths func TestPgraphReachability2(t *testing.T) { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -534,7 +533,7 @@ func TestPgraphReachability2(t *testing.T) { // pick shortest path func TestPgraphReachability3(t *testing.T) { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -569,7 +568,7 @@ func TestPgraphReachability3(t *testing.T) { // direct path func TestPgraphReachability4(t *testing.T) { - G := NewGraph("g") + G, _ := NewGraph("g") v1 := NV("v1") v2 := NV("v2") v3 := NV("v3") @@ -693,7 +692,7 @@ func GraphCmp(g1, g2 *Graph) error { var m = make(map[*Vertex]*Vertex) // g1 to g2 vertex correspondence Loop: // check vertices - for v1 := range g1.Adjacency { // for each vertex in g1 + for v1 := range g1.adjacency { // for each vertex in g1 l1 := strings.Split(v1.GetName(), ",") // make list of everyone's names... for _, x1 := range v1.GetGroup() { @@ -703,7 +702,7 @@ Loop: sort.Strings(l1) // inner loop - for v2 := range g2.Adjacency { // does it match in g2 ? + for v2 := range g2.adjacency { // does it match in g2 ? l2 := strings.Split(v2.GetName(), ",") for _, x2 := range v2.GetGroup() { @@ -723,16 +722,16 @@ Loop: // vertices (and groups) match :) // check edges - for v1 := range g1.Adjacency { // for each vertex in g1 + for v1 := range g1.adjacency { // for each vertex in g1 v2 := m[v1] // lookup in map to get correspondance - // g1.Adjacency[v1] corresponds to g2.Adjacency[v2] - if e1, e2 := len(g1.Adjacency[v1]), len(g2.Adjacency[v2]); e1 != e2 { + // g1.adjacency[v1] corresponds to g2.adjacency[v2] + if e1, e2 := len(g1.adjacency[v1]), len(g2.adjacency[v2]); e1 != e2 { return fmt.Errorf("graph g1, vertex(%v) has %d edges, while g2, vertex(%v) has %d", v1.GetName(), e1, v2.GetName(), e2) } - for vv1, ee1 := range g1.Adjacency[v1] { + for vv1, ee1 := range g1.adjacency[v1] { vv2 := m[vv1] - ee2 := g2.Adjacency[v2][vv2] + ee2 := g2.adjacency[v2][vv2] // these are edges from v1 -> vv1 via ee1 (graph 1) // to cmp to edges from v2 -> vv2 via ee2 (graph 2) @@ -765,8 +764,8 @@ Loop: } // check meta parameters - for v1 := range g1.Adjacency { // for each vertex in g1 - for v2 := range g2.Adjacency { // does it match in g2 ? + for v1 := range g1.adjacency { // for each vertex in g1 + for v2 := range g2.adjacency { // does it match in g2 ? s1, s2 := v1.Meta().Sema, v2.Meta().Sema sort.Strings(s1) sort.Strings(s2) @@ -816,7 +815,7 @@ func (ag *testGrouper) edgeMerge(e1, e2 *Edge) *Edge { func (g *Graph) fullPrint() (str string) { str += "\n" - for v := range g.Adjacency { + for v := range g.adjacency { if semas := v.Meta().Sema; len(semas) > 0 { str += fmt.Sprintf("* v: %v; sema: %v\n", v.GetName(), semas) } else { @@ -824,8 +823,8 @@ func (g *Graph) fullPrint() (str string) { } // TODO: add explicit grouping data? } - for v1 := range g.Adjacency { - for v2, e := range g.Adjacency[v1] { + for v1 := range g.adjacency { + for v2, e := range g.adjacency[v1] { str += fmt.Sprintf("* e: %v -> %v # %v\n", v1.GetName(), v2.GetName(), e.Name) } } diff --git a/pgraph/semaphore_test.go b/pgraph/semaphore_test.go index 940fd44e..c2e6ae05 100644 --- a/pgraph/semaphore_test.go +++ b/pgraph/semaphore_test.go @@ -52,7 +52,7 @@ func NewNoopResTestSema(name string, semas []string) *NoopResTest { } func TestPgraphSemaphoreGrouping1(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTestSema("a1", []string{"s:1"})) a2 := NewVertex(NewNoopResTestSema("a2", []string{"s:2"})) @@ -61,7 +61,7 @@ func TestPgraphSemaphoreGrouping1(t *testing.T) { g1.AddVertex(a2) g1.AddVertex(a3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a123 := NewVertex(NewNoopResTestSema("a1,a2,a3", []string{"s:1", "s:2", "s:3"})) g2.AddVertex(a123) @@ -70,7 +70,7 @@ func TestPgraphSemaphoreGrouping1(t *testing.T) { } func TestPgraphSemaphoreGrouping2(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTestSema("a1", []string{"s:10", "s:11"})) a2 := NewVertex(NewNoopResTestSema("a2", []string{"s:2"})) @@ -79,7 +79,7 @@ func TestPgraphSemaphoreGrouping2(t *testing.T) { g1.AddVertex(a2) g1.AddVertex(a3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a123 := NewVertex(NewNoopResTestSema("a1,a2,a3", []string{"s:10", "s:11", "s:2", "s:3"})) g2.AddVertex(a123) @@ -88,7 +88,7 @@ func TestPgraphSemaphoreGrouping2(t *testing.T) { } func TestPgraphSemaphoreGrouping3(t *testing.T) { - g1 := NewGraph("g1") // original graph + g1, _ := NewGraph("g1") // original graph { a1 := NewVertex(NewNoopResTestSema("a1", []string{"s:1", "s:2"})) a2 := NewVertex(NewNoopResTestSema("a2", []string{"s:2"})) @@ -97,7 +97,7 @@ func TestPgraphSemaphoreGrouping3(t *testing.T) { g1.AddVertex(a2) g1.AddVertex(a3) } - g2 := NewGraph("g2") // expected result + g2, _ := NewGraph("g2") // expected result { a123 := NewVertex(NewNoopResTestSema("a1,a2,a3", []string{"s:1", "s:2", "s:3"})) g2.AddVertex(a123) diff --git a/test/shell/libmgmt-change1.go b/test/shell/libmgmt-change1.go index 086d8985..9f8d86da 100644 --- a/test/shell/libmgmt-change1.go +++ b/test/shell/libmgmt-change1.go @@ -57,7 +57,10 @@ func (obj *MyGAPI) Graph() (*pgraph.Graph, error) { } // FIXME: these are being specified temporarily until it's the default! metaparams := resources.DefaultMetaParams - g := pgraph.NewGraph(obj.Name) + g, err := pgraph.NewGraph(obj.Name) + if err != nil { + return nil, err + } n0 := &resources.NoopRes{ BaseRes: resources.BaseRes{ diff --git a/yamlgraph/gconfig.go b/yamlgraph/gconfig.go index 5311e4f1..5d557e87 100644 --- a/yamlgraph/gconfig.go +++ b/yamlgraph/gconfig.go @@ -29,6 +29,7 @@ import ( "github.com/purpleidea/mgmt/pgraph" "github.com/purpleidea/mgmt/resources" + errwrap "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -95,8 +96,12 @@ func (c *GraphConfig) Parse(data []byte) error { func (c *GraphConfig) NewGraphFromConfig(hostname string, world resources.World, noop bool) (*pgraph.Graph, error) { // hostname is the uuid for the host - var graph *pgraph.Graph // new graph to return - graph = pgraph.NewGraph("Graph") // give graph a default name + var graph *pgraph.Graph // new graph to return + var err error + graph, err = pgraph.NewGraph("Graph") // give graph a default name + if err != nil { + return nil, errwrap.Wrapf(err, "could not run NewGraphFromConfig() properly") + } var lookup = make(map[string]map[string]*pgraph.Vertex) diff --git a/yamlgraph2/gconfig.go b/yamlgraph2/gconfig.go index 73e6f179..f52843ee 100644 --- a/yamlgraph2/gconfig.go +++ b/yamlgraph2/gconfig.go @@ -28,6 +28,7 @@ import ( "github.com/purpleidea/mgmt/pgraph" "github.com/purpleidea/mgmt/resources" + errwrap "github.com/pkg/errors" "gopkg.in/yaml.v2" ) @@ -155,8 +156,12 @@ func (c *GraphConfig) Parse(data []byte) error { func (c *GraphConfig) NewGraphFromConfig(hostname string, world resources.World, noop bool) (*pgraph.Graph, error) { // hostname is the uuid for the host - var graph *pgraph.Graph // new graph to return - graph = pgraph.NewGraph("Graph") // give graph a default name + var graph *pgraph.Graph // new graph to return + var err error + graph, err = pgraph.NewGraph("Graph") // give graph a default name + if err != nil { + return nil, errwrap.Wrapf(err, "could not run NewGraphFromConfig() properly") + } var lookup = make(map[string]map[string]*pgraph.Vertex)