engine: resources: exec: AutoEdge to User/Group/File
Fixes https://github.com/purpleidea/mgmt/issues/221 Signed-off-by: Joe Groocock <me@frebib.net>
This commit is contained in:
committed by
James Shubin
parent
2d7deef4e2
commit
fe2b8c9fee
@@ -570,26 +570,38 @@ type ExecUID struct {
|
|||||||
|
|
||||||
// ExecResAutoEdges holds the state of the auto edge generator.
|
// ExecResAutoEdges holds the state of the auto edge generator.
|
||||||
type ExecResAutoEdges struct {
|
type ExecResAutoEdges struct {
|
||||||
edges []engine.ResUID
|
edges []engine.ResUID
|
||||||
|
pointer int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next automatic edge.
|
// Next returns the next automatic edge.
|
||||||
func (obj *ExecResAutoEdges) Next() []engine.ResUID {
|
func (obj *ExecResAutoEdges) Next() []engine.ResUID {
|
||||||
return obj.edges
|
if len(obj.edges) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := obj.edges[obj.pointer]
|
||||||
|
obj.pointer++
|
||||||
|
return []engine.ResUID{value}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test gets results of the earlier Next() call, & returns if we should
|
// Test gets results of the earlier Next() call, & returns if we should
|
||||||
// continue!
|
// continue!
|
||||||
func (obj *ExecResAutoEdges) Test(input []bool) bool {
|
func (obj *ExecResAutoEdges) Test(input []bool) bool {
|
||||||
return false // never keep going
|
if len(obj.edges) <= obj.pointer {
|
||||||
// TODO: we could return false if we find as many edges as the number of different path's in cmdFiles()
|
return false
|
||||||
|
}
|
||||||
|
if len(input) != 1 { // in case we get given bad data
|
||||||
|
panic(fmt.Sprintf("Expecting a single value!"))
|
||||||
|
}
|
||||||
|
return true // keep going
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoEdges returns the AutoEdge interface. In this case the systemd units.
|
// AutoEdges returns the AutoEdge interface. In this case the systemd units.
|
||||||
func (obj *ExecRes) AutoEdges() (engine.AutoEdge, error) {
|
func (obj *ExecRes) AutoEdges() (engine.AutoEdge, error) {
|
||||||
var data []engine.ResUID
|
var data []engine.ResUID
|
||||||
|
var reversed = true
|
||||||
|
|
||||||
for _, x := range obj.cmdFiles() {
|
for _, x := range obj.cmdFiles() {
|
||||||
var reversed = true
|
|
||||||
data = append(data, &PkgFileUID{
|
data = append(data, &PkgFileUID{
|
||||||
BaseUID: engine.BaseUID{
|
BaseUID: engine.BaseUID{
|
||||||
Name: obj.Name(),
|
Name: obj.Name(),
|
||||||
@@ -598,9 +610,39 @@ func (obj *ExecRes) AutoEdges() (engine.AutoEdge, error) {
|
|||||||
},
|
},
|
||||||
path: x, // what matters
|
path: x, // what matters
|
||||||
})
|
})
|
||||||
|
data = append(data, &FileUID{
|
||||||
|
BaseUID: engine.BaseUID{
|
||||||
|
Name: obj.Name(),
|
||||||
|
Kind: obj.Kind(),
|
||||||
|
Reversed: &reversed,
|
||||||
|
},
|
||||||
|
path: x,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
if obj.User != "" {
|
||||||
|
data = append(data, &UserUID{
|
||||||
|
BaseUID: engine.BaseUID{
|
||||||
|
Name: obj.Name(),
|
||||||
|
Kind: obj.Kind(),
|
||||||
|
Reversed: &reversed,
|
||||||
|
},
|
||||||
|
name: obj.User,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if obj.Group != "" {
|
||||||
|
data = append(data, &GroupUID{
|
||||||
|
BaseUID: engine.BaseUID{
|
||||||
|
Name: obj.Name(),
|
||||||
|
Kind: obj.Kind(),
|
||||||
|
Reversed: &reversed,
|
||||||
|
},
|
||||||
|
name: obj.Group,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return &ExecResAutoEdges{
|
return &ExecResAutoEdges{
|
||||||
edges: data,
|
edges: data,
|
||||||
|
pointer: 0,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/purpleidea/mgmt/engine"
|
"github.com/purpleidea/mgmt/engine"
|
||||||
|
"github.com/purpleidea/mgmt/engine/graph/autoedge"
|
||||||
|
"github.com/purpleidea/mgmt/pgraph"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fakeExecInit(t *testing.T) (*engine.Init, *ExecSends) {
|
func fakeExecInit(t *testing.T) (*engine.Init, *ExecSends) {
|
||||||
@@ -257,3 +259,77 @@ func TestExecTimeoutBehaviour(t *testing.T) {
|
|||||||
|
|
||||||
// no error
|
// no error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecAutoEdge1(t *testing.T) {
|
||||||
|
g, err := pgraph.NewGraph("TestGraph")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating graph: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resUser, err := engine.NewNamedResource("user", "someuser")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating user resource: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resGroup, err := engine.NewNamedResource("group", "somegroup")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating group resource: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resFile, err := engine.NewNamedResource("file", "/somefile")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating group resource: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resExec, err := engine.NewNamedResource("exec", "somefile")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating exec resource: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
exc := resExec.(*ExecRes)
|
||||||
|
exc.Cmd = resFile.Name()
|
||||||
|
exc.User = resUser.Name()
|
||||||
|
exc.Group = resGroup.Name()
|
||||||
|
|
||||||
|
g.AddVertex(resUser, resGroup, resFile, resExec)
|
||||||
|
|
||||||
|
if i := g.NumEdges(); i != 0 {
|
||||||
|
t.Errorf("should have 0 edges instead of: %d", i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug := testing.Verbose() // set via the -test.v flag to `go test`
|
||||||
|
logf := func(format string, v ...interface{}) {
|
||||||
|
t.Logf("test: "+format, v...)
|
||||||
|
}
|
||||||
|
if err := autoedge.AutoEdge(g, debug, logf); err != nil {
|
||||||
|
t.Errorf("error running autoedges: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expected, err := pgraph.NewGraph("Expected")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error creating graph: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expectEdge := func(from, to pgraph.Vertex) {
|
||||||
|
edge := &engine.Edge{Name: fmt.Sprintf("%s -> %s (expected)", from, to)}
|
||||||
|
expected.AddEdge(from, to, edge)
|
||||||
|
}
|
||||||
|
expectEdge(resFile, resExec)
|
||||||
|
expectEdge(resUser, resExec)
|
||||||
|
expectEdge(resGroup, resExec)
|
||||||
|
|
||||||
|
vertexCmp := func(v1, v2 pgraph.Vertex) (bool, error) { return v1 == v2, nil } // pointer compare is sufficient
|
||||||
|
edgeCmp := func(e1, e2 pgraph.Edge) (bool, error) { return true, nil } // we don't care about edges here
|
||||||
|
|
||||||
|
if err := expected.GraphCmp(g, vertexCmp, edgeCmp); err != nil {
|
||||||
|
t.Errorf("graph doesn't match expected: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -333,6 +333,26 @@ func (obj *UserRes) Cmp(r engine.Res) error {
|
|||||||
type UserUID struct {
|
type UserUID struct {
|
||||||
engine.BaseUID
|
engine.BaseUID
|
||||||
name string
|
name string
|
||||||
|
uid *uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFF aka if and only if they are equivalent, return true. If not, false.
|
||||||
|
func (obj *UserUID) IFF(uid engine.ResUID) bool {
|
||||||
|
res, ok := uid.(*UserUID)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if obj.uid != nil && res.uid != nil {
|
||||||
|
if *obj.uid != *res.uid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obj.name != "" && res.name != "" {
|
||||||
|
if obj.name != res.name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserResAutoEdges holds the state of the auto edge generator.
|
// UserResAutoEdges holds the state of the auto edge generator.
|
||||||
@@ -411,6 +431,7 @@ func (obj *UserRes) UIDs() []engine.ResUID {
|
|||||||
x := &UserUID{
|
x := &UserUID{
|
||||||
BaseUID: engine.BaseUID{Name: obj.Name(), Kind: obj.Kind()},
|
BaseUID: engine.BaseUID{Name: obj.Name(), Kind: obj.Kind()},
|
||||||
name: obj.Name(),
|
name: obj.Name(),
|
||||||
|
uid: obj.UID,
|
||||||
}
|
}
|
||||||
return []engine.ResUID{x}
|
return []engine.ResUID{x}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user