From eaab1aae283d43a6f6d81ba10137549de50fada1 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Fri, 25 Oct 2019 09:36:27 -0400 Subject: [PATCH] engine: graph, resources: Add filtered graph function This lets a resource query the resource graph in a controlled way. --- engine/graph/state.go | 45 ++++++++++++++++++++++++++++++ engine/resources.go | 9 ++++++ engine/resources/resources_test.go | 13 +++++++++ 3 files changed, 67 insertions(+) diff --git a/engine/graph/state.go b/engine/graph/state.go index 742e8b4b..d50046f9 100644 --- a/engine/graph/state.go +++ b/engine/graph/state.go @@ -200,6 +200,51 @@ func (obj *State) Init() error { // return obj.Graph // we return in a func so it's fresh! //}, + FilteredGraph: func() (*pgraph.Graph, error) { + graph, err := pgraph.NewGraph("filtered") + if err != nil { + return nil, errwrap.Wrapf(err, "could not create graph") + } + + // filter graph and build a new one... + adjacency := obj.Graph.Adjacency() + for v1 := range adjacency { + // check we're allowed + r1, ok := v1.(engine.GraphQueryableRes) + if !ok { + continue + } + // pass in information on requestor... + if err := r1.GraphQueryAllowed( + engine.GraphQueryableOptionKind(res.Kind()), + engine.GraphQueryableOptionName(res.Name()), + // TODO: add more information... + ); err != nil { + continue + } + graph.AddVertex(v1) + + for v2, edge := range adjacency[v1] { + r2, ok := v2.(engine.GraphQueryableRes) + if !ok { + continue + } + // pass in information on requestor... + if err := r2.GraphQueryAllowed( + engine.GraphQueryableOptionKind(res.Kind()), + engine.GraphQueryableOptionName(res.Name()), + // TODO: add more information... + ); err != nil { + continue + } + //graph.AddVertex(v2) // redundant + graph.AddEdge(v1, v2, edge) + } + } + + return graph, nil // we return in a func so it's fresh! + }, + World: obj.World, VarDir: obj.varDir, diff --git a/engine/resources.go b/engine/resources.go index 043a5e1e..401bfdec 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -21,6 +21,7 @@ import ( "encoding/gob" "fmt" + "github.com/purpleidea/mgmt/pgraph" "github.com/purpleidea/mgmt/util/errwrap" "gopkg.in/yaml.v2" @@ -126,6 +127,14 @@ type Init struct { // FIXME: it might be better to offer a safer, more limited, GraphQuery? //Graph func() *pgraph.Graph // TODO: not implemented, use FilteredGraph + // FilteredGraph is a function that returns a filtered variant of the + // current graph. Only resource that have allowed themselves to be added + // into this graph will appear. If they did not consent, then those + // vertices and any associated edges, will not be present. + FilteredGraph func() (*pgraph.Graph, error) + + // TODO: GraphQuery offers an interface to query the resource graph. + // World provides a connection to the outside world. This is most often // used for communicating with the distributed database. World World diff --git a/engine/resources/resources_test.go b/engine/resources/resources_test.go index 35d63ddd..281da247 100644 --- a/engine/resources/resources_test.go +++ b/engine/resources/resources_test.go @@ -603,6 +603,19 @@ func TestResources2(t *testing.T) { Recv: func() map[string]*engine.Send { return map[string]*engine.Send{} }, + + // Copied from state.go + FilteredGraph: func() (*pgraph.Graph, error) { + graph, err := pgraph.NewGraph("filtered") + if err != nil { + return nil, errwrap.Wrapf(err, "could not create graph") + } + // Hack: We just add ourself as allowed since + // we're just a one-vertex test suite... + graph.AddVertex(res) // hack! + + return graph, nil // we return in a func so it's fresh! + }, } // run Init return func() error {