resources: Improve AutoEdge API and pkg breakage

I previously broke the pkg auto edges because the package list wasn't
available by the time it was called. This fixes the pkg resource so that
it gets the necessary list of packages when needed. Since this means
that a possible failure could happen, we also update the AutoEdges API
to support errors. Errors can only be generated at AutoEdge struct
creation, once the struct has been returned (right before modification
of the graph structure) there is no possibility to return any errors.

It's important to remember that the AutoEdges stuff gets called because
the Init of each resource, so make sure it doesn't depend on anything
that happens there or that gets cached as a result of Init.

This is all much nicer now and has a test too :)
This commit is contained in:
James Shubin
2017-06-02 20:38:05 -04:00
parent 5f6c8545c6
commit 4d9d0d4548
20 changed files with 208 additions and 117 deletions

View File

@@ -379,7 +379,7 @@ if another resource can match a dependency to this one.
### AutoEdges ### AutoEdges
```golang ```golang
AutoEdges() AutoEdge AutoEdges() (AutoEdge, error)
``` ```
This returns a struct that implements the `AutoEdge` interface. This struct This returns a struct that implements the `AutoEdge` interface. This struct

View File

@@ -513,9 +513,22 @@ func (obj *Main) Run() error {
} }
continue continue
} }
// TODO: should we call each Res.Setup() here instead?
// add autoedges; modifies the graph only if no error
if err := resources.AutoEdges(oldGraph); err != nil {
log.Printf("Main: Error running auto edges: %v", err)
// unpause!
if !first {
graph.Start(first) // sync
converger.Start() // after Start()
}
continue
}
graph.Update(oldGraph) // copy in structure of new graph graph.Update(oldGraph) // copy in structure of new graph
resources.AutoEdges(graph.Graph) // add autoedges; modifies the graph
resources.AutoGroup(graph.Graph, &resources.NonReachabilityGrouper{}) // run autogroup; modifies the graph resources.AutoGroup(graph.Graph, &resources.NonReachabilityGrouper{}) // run autogroup; modifies the graph
// TODO: do we want to do a transitive reduction? // TODO: do we want to do a transitive reduction?
// FIXME: run a type checker that verifies all the send->recv relationships // FIXME: run a type checker that verifies all the send->recv relationships

View File

@@ -248,11 +248,6 @@ type AugeasUID struct {
name string name string
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *AugeasRes) AutoEdges() AutoEdge {
return nil
}
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
func (obj *AugeasRes) UIDs() []ResUID { func (obj *AugeasRes) UIDs() []ResUID {
x := &AugeasUID{ x := &AugeasUID{

View File

@@ -23,6 +23,9 @@ import (
"github.com/purpleidea/mgmt/pgraph" "github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/util" "github.com/purpleidea/mgmt/util"
multierr "github.com/hashicorp/go-multierror"
errwrap "github.com/pkg/errors"
) )
// The AutoEdge interface is used to implement the autoedges feature. // The AutoEdge interface is used to implement the autoedges feature.
@@ -56,7 +59,7 @@ func addEdgesByMatchingUIDS(g *pgraph.Graph, v pgraph.Vertex, uids []ResUID) []b
continue continue
} }
if b, ok := g.Value("debug"); ok && util.Bool(b) { if b, ok := g.Value("debug"); ok && util.Bool(b) {
log.Printf("Compile: AutoEdge: Match: %s with UID: %s", VtoR(vv).String(), uid) log.Printf("Compile: AutoEdge: Match: %s with UID: %s", vv, uid)
} }
// we must match to an effective UID for the resource, // we must match to an effective UID for the resource,
// that is to say, the name value of a res is a helpful // that is to say, the name value of a res is a helpful
@@ -65,12 +68,12 @@ func addEdgesByMatchingUIDS(g *pgraph.Graph, v pgraph.Vertex, uids []ResUID) []b
if UIDExistsInUIDs(uid, VtoR(vv).UIDs()) { if UIDExistsInUIDs(uid, VtoR(vv).UIDs()) {
// add edge from: vv -> v // add edge from: vv -> v
if uid.IsReversed() { if uid.IsReversed() {
txt := fmt.Sprintf("AutoEdge: %s -> %s", VtoR(vv).String(), VtoR(v).String()) txt := fmt.Sprintf("AutoEdge: %s -> %s", vv, v)
log.Printf("Compile: Adding %s", txt) log.Printf("Compile: Adding %s", txt)
edge := &Edge{Name: txt} edge := &Edge{Name: txt}
g.AddEdge(vv, v, edge) g.AddEdge(vv, v, edge)
} else { // edges go the "normal" way, eg: pkg resource } else { // edges go the "normal" way, eg: pkg resource
txt := fmt.Sprintf("AutoEdge: %s -> %s", VtoR(v).String(), VtoR(vv).String()) txt := fmt.Sprintf("AutoEdge: %s -> %s", v, vv)
log.Printf("Compile: Adding %s", txt) log.Printf("Compile: Adding %s", txt)
edge := &Edge{Name: txt} edge := &Edge{Name: txt}
g.AddEdge(v, vv, edge) g.AddEdge(v, vv, edge)
@@ -85,22 +88,39 @@ func addEdgesByMatchingUIDS(g *pgraph.Graph, v pgraph.Vertex, uids []ResUID) []b
} }
// AutoEdges adds the automatic edges to the graph. // AutoEdges adds the automatic edges to the graph.
func AutoEdges(g *pgraph.Graph) { func AutoEdges(g *pgraph.Graph) error {
log.Println("Compile: Adding AutoEdges...") log.Println("Compile: Adding AutoEdges...")
for _, v := range g.Vertices() { // for each vertexes autoedges
// initially get all of the autoedges to seek out all possible errors
var err error
autoEdgeObjVertexMap := make(map[pgraph.Vertex]AutoEdge)
for _, v := range g.VerticesSorted() { // for each vertexes autoedges
if !VtoR(v).Meta().AutoEdge { // is the metaparam true? if !VtoR(v).Meta().AutoEdge { // is the metaparam true?
continue continue
} }
autoEdgeObj := VtoR(v).AutoEdges() autoEdgeObj, e := VtoR(v).AutoEdges()
if e != nil {
err = multierr.Append(err, e) // collect all errors
continue
}
if autoEdgeObj == nil { if autoEdgeObj == nil {
log.Printf("%s: Config: No auto edges were found!", VtoR(v).String()) log.Printf("%s: No auto edges were found!", v)
continue // next vertex continue // next vertex
} }
autoEdgeObjVertexMap[v] = autoEdgeObj // save for next loop
}
if err != nil {
return errwrap.Wrapf(err, "the auto edges had errors")
}
// now that we're guaranteed error free, we can modify the graph safely
// TODO: loop through this in a sorted order for stable log output...
for v, autoEdgeObj := range autoEdgeObjVertexMap {
for { // while the autoEdgeObj has more uids to add... for { // while the autoEdgeObj has more uids to add...
uids := autoEdgeObj.Next() // get some! uids := autoEdgeObj.Next() // get some!
if uids == nil { if uids == nil {
log.Printf("%s: Config: The auto edge list is empty!", VtoR(v).String()) log.Printf("%s: The auto edge list is empty!", v)
break // inner loop break // inner loop
} }
if b, ok := g.Value("debug"); ok && util.Bool(b) { if b, ok := g.Value("debug"); ok && util.Bool(b) {
@@ -119,4 +139,5 @@ func AutoEdges(g *pgraph.Graph) {
} }
} }
} }
return nil
} }

View File

@@ -335,10 +335,10 @@ type ExecUID struct {
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used. // AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *ExecRes) AutoEdges() AutoEdge { func (obj *ExecRes) AutoEdges() (AutoEdge, error) {
// TODO: parse as many exec params to look for auto edges, for example // TODO: parse as many exec params to look for auto edges, for example
// the path of the binary in the Cmd variable might be from in a pkg // the path of the binary in the Cmd variable might be from in a pkg
return nil return nil, nil
} }
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.

View File

@@ -898,10 +898,11 @@ func (obj *FileResAutoEdges) Test(input []bool) bool {
// AutoEdges generates a simple linear sequence of each parent directory from // AutoEdges generates a simple linear sequence of each parent directory from
// the bottom up! // the bottom up!
func (obj *FileRes) AutoEdges() AutoEdge { func (obj *FileRes) AutoEdges() (AutoEdge, error) {
var data []ResUID // store linear result chain here... var data []ResUID // store linear result chain here...
values := util.PathSplitFullReversed(obj.path) // build it // build it, but don't use obj.path because this gets called before Init
_, values = values[0], values[1:] // get rid of first value which is me! values := util.PathSplitFullReversed(obj.GetPath())
_, values = values[0], values[1:] // get rid of first value which is me!
for _, x := range values { for _, x := range values {
var reversed = true // cheat by passing a pointer var reversed = true // cheat by passing a pointer
data = append(data, &FileUID{ data = append(data, &FileUID{
@@ -917,7 +918,7 @@ func (obj *FileRes) AutoEdges() AutoEdge {
data: data, data: data,
pointer: 0, pointer: 0,
found: false, found: false,
} }, nil
} }
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
@@ -925,7 +926,7 @@ func (obj *FileRes) AutoEdges() AutoEdge {
func (obj *FileRes) UIDs() []ResUID { func (obj *FileRes) UIDs() []ResUID {
x := &FileUID{ x := &FileUID{
BaseUID: BaseUID{Name: obj.GetName(), Kind: obj.GetKind()}, BaseUID: BaseUID{Name: obj.GetName(), Kind: obj.GetKind()},
path: obj.path, path: obj.GetPath(), // not obj.path b/c we didn't init yet!
} }
return []ResUID{x} return []ResUID{x}
} }

79
resources/file_test.go Normal file
View File

@@ -0,0 +1,79 @@
// Mgmt
// Copyright (C) 2013-2017+ James Shubin and the project contributors
// Written by James Shubin <james@shubin.ca> and the project contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package resources
import (
"testing"
"github.com/purpleidea/mgmt/pgraph"
)
func TestFileAutoEdge1(t *testing.T) {
g, err := pgraph.NewGraph("TestGraph")
if err != nil {
t.Errorf("error creating graph: %v", err)
return
}
r1 := &FileRes{
BaseRes: BaseRes{
Name: "file1",
Kind: "file",
MetaParams: MetaParams{
AutoEdge: true,
},
},
Path: "/tmp/a/b/", // some dir
}
r2 := &FileRes{
BaseRes: BaseRes{
Name: "file2",
Kind: "file",
MetaParams: MetaParams{
AutoEdge: true,
},
},
Path: "/tmp/a/", // some parent dir
}
r3 := &FileRes{
BaseRes: BaseRes{
Name: "file3",
Kind: "file",
MetaParams: MetaParams{
AutoEdge: true,
},
},
Path: "/tmp/a/b/c", // some child file
}
g.AddVertex(r1, r2, r3)
if i := g.NumEdges(); i != 0 {
t.Errorf("should have 0 edges instead of: %d", i)
}
// run artificially without the entire engine
if err := AutoEdges(g); err != nil {
t.Errorf("error running autoedges: %v", err)
}
// two edges should have been added
if i := g.NumEdges(); i != 2 {
t.Errorf("should have 2 edges instead of: %d", i)
}
}

View File

@@ -165,11 +165,6 @@ func (obj *GraphRes) UIDs() []ResUID {
// XXX: hook up the autogrouping magic! // XXX: hook up the autogrouping magic!
// AutoEdges returns the AutoEdges. In this case none are used.
func (obj *GraphRes) AutoEdges() AutoEdge {
return nil
}
// Compare two resources and return if they are equivalent. // Compare two resources and return if they are equivalent.
func (obj *GraphRes) Compare(r Res) bool { func (obj *GraphRes) Compare(r Res) bool {
// we can only compare GraphRes to others of the same resource kind // we can only compare GraphRes to others of the same resource kind

View File

@@ -228,11 +228,6 @@ type HostnameUID struct {
transientHostname string transientHostname string
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *HostnameRes) AutoEdges() AutoEdge {
return nil
}
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
// Most resources only return one, although some resources can return multiple. // Most resources only return one, although some resources can return multiple.
func (obj *HostnameRes) UIDs() []ResUID { func (obj *HostnameRes) UIDs() []ResUID {

View File

@@ -226,11 +226,6 @@ type KVUID struct {
name string name string
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *KVRes) AutoEdges() AutoEdge {
return nil
}
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
// Most resources only return one, although some resources can return multiple. // Most resources only return one, although some resources can return multiple.
func (obj *KVRes) UIDs() []ResUID { func (obj *KVRes) UIDs() []ResUID {

View File

@@ -204,11 +204,6 @@ func (obj *MsgRes) UIDs() []ResUID {
return []ResUID{x} return []ResUID{x}
} }
// AutoEdges returns the AutoEdges. In this case none are used.
func (obj *MsgRes) AutoEdges() AutoEdge {
return nil
}
// Compare two resources and return if they are equivalent. // Compare two resources and return if they are equivalent.
func (obj *MsgRes) Compare(r Res) bool { func (obj *MsgRes) Compare(r Res) bool {
// we can only compare MsgRes to others of the same resource kind // we can only compare MsgRes to others of the same resource kind

View File

@@ -94,11 +94,6 @@ type NoopUID struct {
name string name string
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *NoopRes) AutoEdges() AutoEdge {
return nil
}
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
// Most resources only return one, although some resources can return multiple. // Most resources only return one, although some resources can return multiple.
func (obj *NoopRes) UIDs() []ResUID { func (obj *NoopRes) UIDs() []ResUID {

View File

@@ -295,11 +295,6 @@ func (obj *NspawnRes) Compare(r Res) bool {
return true return true
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *NspawnRes) AutoEdges() AutoEdge {
return nil
}
// UnmarshalYAML is the custom unmarshal handler for this struct. // UnmarshalYAML is the custom unmarshal handler for this struct.
// It is primarily useful for setting the defaults. // It is primarily useful for setting the defaults.
func (obj *NspawnRes) UnmarshalYAML(unmarshal func(interface{}) error) error { func (obj *NspawnRes) UnmarshalYAML(unmarshal func(interface{}) error) error {

View File

@@ -295,11 +295,6 @@ type PasswordUID struct {
name string name string
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *PasswordRes) AutoEdges() AutoEdge {
return nil
}
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
// Most resources only return one, although some resources can return multiple. // Most resources only return one, although some resources can return multiple.
func (obj *PasswordRes) UIDs() []ResUID { func (obj *PasswordRes) UIDs() []ResUID {

View File

@@ -72,31 +72,12 @@ func (obj *PkgRes) Init() error {
return err return err
} }
bus := packagekit.NewBus() if obj.fileList == nil {
if bus == nil { if err := obj.populateFileList(); err != nil {
return fmt.Errorf("can't connect to PackageKit bus") return errwrap.Wrapf(err, "error populating file list in init")
} }
defer bus.Close()
result, err := obj.pkgMappingHelper(bus)
if err != nil {
return errwrap.Wrapf(err, "the pkgMappingHelper failed")
} }
data, ok := result[obj.Name] // lookup single package (init does just one)
// package doesn't exist, this is an error!
if !ok || !data.Found {
return fmt.Errorf("can't find package named '%s'", obj.Name)
}
packageIDs := []string{data.PackageID} // just one for now
filesMap, err := bus.GetFilesByPackageID(packageIDs)
if err != nil {
return errwrap.Wrapf(err, "can't run GetFilesByPackageID")
}
if files, ok := filesMap[data.PackageID]; ok {
obj.fileList = util.DirifyFileList(files, false)
}
return nil return nil
} }
@@ -223,6 +204,39 @@ func (obj *PkgRes) pkgMappingHelper(bus *packagekit.Conn) (map[string]*packageki
return result, nil return result, nil
} }
// populateFileList fills in the fileList structure with what is in the package.
// TODO: should this work properly if pkg has been autogrouped ?
func (obj *PkgRes) populateFileList() error {
bus := packagekit.NewBus()
if bus == nil {
return fmt.Errorf("can't connect to PackageKit bus")
}
defer bus.Close()
result, err := obj.pkgMappingHelper(bus)
if err != nil {
return errwrap.Wrapf(err, "the pkgMappingHelper failed")
}
data, ok := result[obj.Name] // lookup single package (init does just one)
// package doesn't exist, this is an error!
if !ok || !data.Found {
return fmt.Errorf("can't find package named '%s'", obj.Name)
}
packageIDs := []string{data.PackageID} // just one for now
filesMap, err := bus.GetFilesByPackageID(packageIDs)
if err != nil {
return errwrap.Wrapf(err, "can't run GetFilesByPackageID")
}
if files, ok := filesMap[data.PackageID]; ok {
obj.fileList = util.DirifyFileList(files, false)
}
return nil
}
// CheckApply checks the resource state and applies the resource if the bool // CheckApply checks the resource state and applies the resource if the bool
// input is true. It returns error info and if the state check passed or not. // input is true. It returns error info and if the state check passed or not.
func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) { func (obj *PkgRes) CheckApply(apply bool) (checkOK bool, err error) {
@@ -419,10 +433,16 @@ func (obj *PkgResAutoEdges) Test(input []bool) bool {
// AutoEdges produces an object which generates a minimal pkg file optimization // AutoEdges produces an object which generates a minimal pkg file optimization
// sequence of edges. // sequence of edges.
func (obj *PkgRes) AutoEdges() AutoEdge { func (obj *PkgRes) AutoEdges() (AutoEdge, error) {
// in contrast with the FileRes AutoEdges() function which contains // in contrast with the FileRes AutoEdges() function which contains
// more of the mechanics, most of the AutoEdge mechanics for the PkgRes // more of the mechanics, most of the AutoEdge mechanics for the PkgRes
// is contained in the Test() method! This design is completely okay! // are contained in the Test() method! This design is completely okay!
if obj.fileList == nil {
if err := obj.populateFileList(); err != nil {
return nil, errwrap.Wrapf(err, "error populating file list for automatic edges")
}
}
// add matches for any svc resources found in pkg definition! // add matches for any svc resources found in pkg definition!
var svcUIDs []ResUID var svcUIDs []ResUID
@@ -444,7 +464,7 @@ func (obj *PkgRes) AutoEdges() AutoEdge {
testIsNext: false, // start with Next() call testIsNext: false, // start with Next() call
name: obj.GetName(), // save data for PkgResAutoEdges obj name: obj.GetName(), // save data for PkgResAutoEdges obj
kind: obj.GetKind(), kind: obj.GetKind(),
} }, nil
} }
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.
@@ -511,25 +531,6 @@ func (obj *PkgRes) Compare(r Res) bool {
return true return true
} }
// ReturnSvcInFileList returns a list of svc names for matches like: `/usr/lib/systemd/system/*.service`.
func ReturnSvcInFileList(fileList []string) []string {
result := []string{}
for _, x := range fileList {
dirname, basename := path.Split(path.Clean(x))
// TODO: do we also want to look for /etc/systemd/system/ ?
if dirname != "/usr/lib/systemd/system/" {
continue
}
if !strings.HasSuffix(basename, ".service") {
continue
}
if s := strings.TrimSuffix(basename, ".service"); !util.StrInList(s, result) {
result = append(result, s)
}
}
return result
}
// UnmarshalYAML is the custom unmarshal handler for this struct. // UnmarshalYAML is the custom unmarshal handler for this struct.
// It is primarily useful for setting the defaults. // It is primarily useful for setting the defaults.
func (obj *PkgRes) UnmarshalYAML(unmarshal func(interface{}) error) error { func (obj *PkgRes) UnmarshalYAML(unmarshal func(interface{}) error) error {
@@ -549,3 +550,22 @@ func (obj *PkgRes) UnmarshalYAML(unmarshal func(interface{}) error) error {
*obj = PkgRes(raw) // restore from indirection with type conversion! *obj = PkgRes(raw) // restore from indirection with type conversion!
return nil return nil
} }
// ReturnSvcInFileList returns a list of svc names for matches like: `/usr/lib/systemd/system/*.service`.
func ReturnSvcInFileList(fileList []string) []string {
result := []string{}
for _, x := range fileList {
dirname, basename := path.Split(path.Clean(x))
// TODO: do we also want to look for /etc/systemd/system/ ?
if dirname != "/usr/lib/systemd/system/" {
continue
}
if !strings.HasSuffix(basename, ".service") {
continue
}
if s := strings.TrimSuffix(basename, ".service"); !util.StrInList(s, result) {
result = append(result, s)
}
}
return result
}

View File

@@ -157,7 +157,7 @@ type Res interface {
UIDs() []ResUID // most resources only return one UIDs() []ResUID // most resources only return one
Watch() error // send on channel to signal process() events Watch() error // send on channel to signal process() events
CheckApply(apply bool) (checkOK bool, err error) CheckApply(apply bool) (checkOK bool, err error)
AutoEdges() AutoEdge AutoEdges() (AutoEdge, error)
Compare(Res) bool Compare(Res) bool
CollectPattern(string) // XXX: temporary until Res collection is more advanced CollectPattern(string) // XXX: temporary until Res collection is more advanced
//UnmarshalYAML(unmarshal func(interface{}) error) error // optional //UnmarshalYAML(unmarshal func(interface{}) error) error // optional
@@ -463,6 +463,13 @@ func (obj *BaseRes) SetGroup(g []Res) {
obj.grouped = g obj.grouped = g
} }
// AutoEdges returns the AutoEdge interface. By default, none are created. This
// should be implemented by the specific resource to be used. This base method
// does not need to be called by the resource specific implementing method.
func (obj *BaseRes) AutoEdges() (AutoEdge, error) {
return nil, nil
}
// Compare is the base compare method, which also handles the metaparams cmp. // Compare is the base compare method, which also handles the metaparams cmp.
func (obj *BaseRes) Compare(res Res) bool { func (obj *BaseRes) Compare(res Res) bool {
// TODO: should the AutoEdge values be compared? // TODO: should the AutoEdge values be compared?

View File

@@ -380,7 +380,7 @@ func (obj *SvcResAutoEdges) Test(input []bool) bool {
} }
// AutoEdges returns the AutoEdge interface. In this case the systemd units. // AutoEdges returns the AutoEdge interface. In this case the systemd units.
func (obj *SvcRes) AutoEdges() AutoEdge { func (obj *SvcRes) AutoEdges() (AutoEdge, error) {
var data []ResUID var data []ResUID
svcFiles := []string{ svcFiles := []string{
fmt.Sprintf("/etc/systemd/system/%s.service", obj.Name), // takes precedence fmt.Sprintf("/etc/systemd/system/%s.service", obj.Name), // takes precedence
@@ -401,7 +401,7 @@ func (obj *SvcRes) AutoEdges() AutoEdge {
data: data, data: data,
pointer: 0, pointer: 0,
found: false, found: false,
} }, nil
} }
// UIDs includes all params to make a unique identification of this object. // UIDs includes all params to make a unique identification of this object.

View File

@@ -129,11 +129,6 @@ func (obj *TimerRes) UIDs() []ResUID {
return []ResUID{x} return []ResUID{x}
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *TimerRes) AutoEdges() AutoEdge {
return nil
}
// Compare two resources and return if they are equivalent. // Compare two resources and return if they are equivalent.
func (obj *TimerRes) Compare(r Res) bool { func (obj *TimerRes) Compare(r Res) bool {
// we can only compare TimerRes to others of the same resource kind // we can only compare TimerRes to others of the same resource kind

View File

@@ -1070,11 +1070,6 @@ func (obj *VirtRes) GroupCmp(r Res) bool {
return false // not possible atm return false // not possible atm
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used.
func (obj *VirtRes) AutoEdges() AutoEdge {
return nil
}
// Compare two resources and return if they are equivalent. // Compare two resources and return if they are equivalent.
func (obj *VirtRes) Compare(r Res) bool { func (obj *VirtRes) Compare(r Res) bool {
// we can only compare VirtRes to others of the same resource kind // we can only compare VirtRes to others of the same resource kind

View File

@@ -128,6 +128,7 @@ func (c *GraphConfig) NewGraphFromConfig(hostname string, world resources.World,
if !ok { if !ok {
return nil, fmt.Errorf("Config: Error: Can't convert: %v of type: %T to Res", x, x) return nil, fmt.Errorf("Config: Error: Can't convert: %v of type: %T to Res", x, x)
} }
res.SetKind(kind) // cheap init
//if noop { // now done in mgmtmain //if noop { // now done in mgmtmain
// res.Meta().Noop = noop // res.Meta().Noop = noop
//} //}
@@ -154,7 +155,6 @@ func (c *GraphConfig) NewGraphFromConfig(hostname string, world resources.World,
} else if !noop { // do not export any resources if noop } else if !noop { // do not export any resources if noop
// store for addition to backend storage... // store for addition to backend storage...
res.SetName(res.GetName()[2:]) //slice off @@ res.SetName(res.GetName()[2:]) //slice off @@
res.SetKind(kind) // cheap init
resourceList = append(resourceList, res) resourceList = append(resourceList, res)
} }
} }