pgraph, resources: Major refactor to remove pgraph to resource dep

This is the mechanical port of the remaining bits. Next to clean it up a
bit.
This commit is contained in:
James Shubin
2017-05-16 11:23:26 -04:00
parent 4490c3ed1a
commit 3cf9639e99
15 changed files with 1241 additions and 1216 deletions

View File

@@ -19,9 +19,13 @@ package resources
import (
"fmt"
"log"
"sync"
"github.com/purpleidea/mgmt/event"
"github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util"
errwrap "github.com/pkg/errors"
)
//go:generate stringer -type=graphState -output=graphstate_stringer.go
@@ -43,7 +47,7 @@ func getState(g *pgraph.Graph) graphState {
//mutex.Lock()
//defer mutex.Unlock()
if u, ok := g.Value("state"); ok {
return util.Uint(u)
return graphState(util.Uint(u))
}
return graphStateNil
}
@@ -54,7 +58,7 @@ func setState(g *pgraph.Graph, state graphState) graphState {
mutex.Lock()
defer mutex.Unlock()
prev := getState(g)
g.SetValue("state", state)
g.SetValue("state", uint(state))
return prev
}
@@ -73,3 +77,113 @@ func StateLockFromGraph(g *pgraph.Graph) *sync.Mutex {
}
return m
}
// VtoR casts the Vertex into a Res for use. It panics if it can't convert.
func VtoR(v pgraph.Vertex) Res {
res, ok := v.(Res)
if !ok {
panic("not a Res")
}
return res
}
// GraphSync updates the oldGraph so that it matches the newGraph receiver. It
// leaves identical elements alone so that they don't need to be refreshed. It
// tries to mutate existing elements into new ones, if they support this.
// FIXME: add test cases
func GraphSync(g *pgraph.Graph, oldGraph *pgraph.Graph) (*pgraph.Graph, error) {
if oldGraph == nil {
var err error
oldGraph, err = pgraph.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
var lookup = make(map[pgraph.Vertex]pgraph.Vertex)
var vertexKeep []pgraph.Vertex // list of vertices which are the same in new graph
var edgeKeep []*pgraph.Edge // list of vertices which are the same in new graph
for v := range g.Adjacency() { // loop through the vertices (resources)
res := VtoR(v) // resource
var vertex pgraph.Vertex
// step one, direct compare with res.Compare
if vertex == nil { // redundant guard for consistency
fn := func(v pgraph.Vertex) (bool, error) {
return VtoR(v).Compare(res), nil
}
var err error
vertex, err = oldGraph.VertexMatchFn(fn)
if err != nil {
return nil, errwrap.Wrapf(err, "could not VertexMatchFn() resource")
}
}
// TODO: consider adding a mutate API.
// step two, try and mutate with res.Mutate
//if vertex == nil { // not found yet...
// vertex = oldGraph.MutateMatch(res)
//}
if vertex == nil { // no match found yet
if err := res.Validate(); err != nil {
return nil, errwrap.Wrapf(err, "could not Validate() resource")
}
vertex = v
oldGraph.AddVertex(vertex) // call standalone in case not part of an edge
}
lookup[v] = vertex // used for constructing edges
vertexKeep = append(vertexKeep, vertex) // append
}
// get rid of any vertices we shouldn't keep (that aren't in new graph)
for v := range oldGraph.Adjacency() {
if !pgraph.VertexContains(v, vertexKeep) {
// wait for exit before starting new graph!
VtoR(v).SendEvent(event.EventExit, nil) // sync
VtoR(v).WaitGroup().Wait()
oldGraph.DeleteVertex(v)
}
}
// compare edges
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)
//res1 := v1.Res // resource
//res2 := v2.Res
//vertex1 := oldGraph.CompareMatch(res1) // now: VertexMatchFn
//vertex2 := oldGraph.CompareMatch(res2) // now: VertexMatchFn
vertex1, exists1 := lookup[v1]
vertex2, exists2 := lookup[v2]
if !exists1 || !exists2 { // no match found, bug?
//if vertex1 == nil || vertex2 == nil { // no match found
return nil, fmt.Errorf("new vertices weren't found") // programming error
}
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)
edgeKeep = append(edgeKeep, edge) // mark as saved
}
}
// delete unused edges
for v1 := range oldGraph.Adjacency() {
for _, e := range oldGraph.Adjacency()[v1] {
// we have an edge!
if !pgraph.EdgeContains(e, edgeKeep) {
oldGraph.DeleteEdge(e)
}
}
}
return oldGraph, nil
}