From 9f56e4a582473840418794c2f916f4e22cbf4213 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Sat, 14 May 2016 12:03:32 -0400 Subject: [PATCH] Add global --noop support This is part two of the earlier patch in 6bbce039aa6ac7b1fa9ea617663e7ad6b5a5cffa We also rename GetMeta to just Meta to clean up the API. --- DOCUMENTATION.md | 5 +++++ config.go | 17 ++++++++++++----- exec.go | 4 ++++ file.go | 4 ++++ main.go | 7 ++++++- noop.go | 4 ++++ pgraph.go | 4 ++-- pgraph_test.go | 2 +- pkg.go | 4 ++++ resources.go | 39 ++++++++++++++++++++++++++------------- svc.go | 4 ++++ 11 files changed, 72 insertions(+), 22 deletions(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 334b081c..b9608d03 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -179,6 +179,11 @@ Exit if the machine has converged for approximately this many seconds. Exit when the agent has run for approximately this many seconds. This is not generally recommended, but may be useful for users who know what they're doing. +####`--noop` +Globally force all resources into no-op mode. This also disables the export to +etcd functionality, but does not disable resource collection, however all +resources that are collected will have their individual noop settings set. + ##Examples For example configurations, please consult the [examples/](https://github.com/purpleidea/mgmt/tree/master/examples) directory in the git source repository. It is available from: diff --git a/config.go b/config.go index 87f9e35f..ed4c5f62 100644 --- a/config.go +++ b/config.go @@ -85,7 +85,7 @@ func ParseConfigFromFile(filename string) *GraphConfig { // NewGraphFromConfig returns a new graph from existing input, such as from the // existing graph, and a GraphConfig struct. -func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, hostname string) (*Graph, error) { +func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, hostname string, noop bool) (*Graph, error) { var graph *Graph // new graph to return if g == nil { // FIXME: how can we check for an empty graph? @@ -122,7 +122,9 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host if !ok { return nil, fmt.Errorf("Error: Config: Can't convert: %v of type: %T to Res.", x, x) } - + if noop { + obj.Meta().Noop = noop + } if _, exists := lookup[kind]; !exists { lookup[kind] = make(map[string]*Vertex) } @@ -141,7 +143,7 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host lookup[kind][obj.GetName()] = v // used for constructing edges keep = append(keep, v) // append - } else { + } else if !noop { // do not export any resources if noop // XXX: do this in a different function... // add to etcd storage... obj.SetName(obj.GetName()[2:]) //slice off @@ @@ -177,6 +179,11 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host continue } + // collect resources but add the noop metaparam + if noop { + obj.Meta().Noop = noop + } + if t.Pattern != "" { // XXX: simplistic for now obj.CollectPattern(t.Pattern) // obj.Dirname = t.Pattern } @@ -271,7 +278,7 @@ func (g *Graph) addEdgesByMatchingUUIDS(v *Vertex, uuids []ResUUID) []bool { func (g *Graph) AutoEdges() { log.Println("Compile: Adding AutoEdges...") for _, v := range g.GetVertices() { // for each vertexes autoedges - if !v.GetMeta().AutoEdge { // is the metaparam true? + if !v.Meta().AutoEdge { // is the metaparam true? continue } autoEdgeObj := v.AutoEdges() @@ -398,7 +405,7 @@ func (ag *baseGrouper) vertexCmp(v1, v2 *Vertex) error { return fmt.Errorf("The two resources aren't the same kind!") } // someone doesn't want to group! - if !v1.GetMeta().AutoGroup || !v2.GetMeta().AutoGroup { + if !v1.Meta().AutoGroup || !v2.Meta().AutoGroup { return fmt.Errorf("One of the autogroup flags is false!") } if v1.Res.IsGrouped() { // already grouped! diff --git a/exec.go b/exec.go index 9d9e7cdb..56f6b23b 100644 --- a/exec.go +++ b/exec.go @@ -391,6 +391,10 @@ func (obj *ExecRes) Compare(res Res) bool { switch res.(type) { case *ExecRes: res := res.(*ExecRes) + if !obj.BaseRes.Compare(res) { // call base Compare + return false + } + if obj.Name != res.Name { return false } diff --git a/file.go b/file.go index 65f9a7d6..a2dfba1e 100644 --- a/file.go +++ b/file.go @@ -478,6 +478,10 @@ func (obj *FileRes) Compare(res Res) bool { switch res.(type) { case *FileRes: res := res.(*FileRes) + if !obj.BaseRes.Compare(res) { // call base Compare + return false + } + if obj.Name != res.Name { return false } diff --git a/main.go b/main.go index fb6761ec..5da96f31 100644 --- a/main.go +++ b/main.go @@ -103,6 +103,7 @@ func run(c *cli.Context) error { if hostname == "" { hostname, _ = os.Hostname() // etcd watch key // XXX: this is not the correct key name this is the set key name... WOOPS } + noop := c.Bool("noop") exitchan := make(chan Event) // exit event go func() { @@ -157,7 +158,7 @@ func run(c *cli.Context) error { // build graph from yaml file on events (eg: from etcd) // we need the vertices to be paused to work on them - if newFullgraph, err := fullGraph.NewGraphFromConfig(config, etcdO, hostname); err == nil { // keep references to all original elements + if newFullgraph, err := fullGraph.NewGraphFromConfig(config, etcdO, hostname, noop); err == nil { // keep references to all original elements fullGraph = newFullgraph } else { log.Printf("Config: Error making new graph from config: %v", err) @@ -295,6 +296,10 @@ func main() { Usage: "exit after a maximum of approximately this many seconds", EnvVar: "MGMT_MAX_RUNTIME", }, + cli.BoolFlag{ + Name: "noop", + Usage: "globally force all resources into no-op mode", + }, }, }, } diff --git a/noop.go b/noop.go index f4551e91..e0740dd1 100644 --- a/noop.go +++ b/noop.go @@ -133,6 +133,10 @@ func (obj *NoopRes) Compare(res Res) bool { // we can only compare NoopRes to others of the same resource case *NoopRes: res := res.(*NoopRes) + // calling base Compare is unneeded for the noop res + //if !obj.BaseRes.Compare(res) { // call base Compare + // return false + //} if obj.Name != res.Name { return false } diff --git a/pgraph.go b/pgraph.go index 6eb98c7e..957314c6 100644 --- a/pgraph.go +++ b/pgraph.go @@ -729,7 +729,7 @@ func (g *Graph) Process(v *Vertex) { obj.SetState(resStateCheckApply) // if this fails, don't UpdateTimestamp() - checkok, err := obj.CheckApply(!obj.GetMeta().Noop) + checkok, err := obj.CheckApply(!obj.Meta().Noop) if checkok && err != nil { // should never return this way log.Fatalf("%v[%v]: CheckApply(): %t, %+v", obj.Kind(), obj.GetName(), checkok, err) } @@ -746,7 +746,7 @@ func (g *Graph) Process(v *Vertex) { } // when noop is true we always want to update timestamp - if obj.GetMeta().Noop && err == nil { + if obj.Meta().Noop && err == nil { ok = true } diff --git a/pgraph_test.go b/pgraph_test.go index 3cfa0085..9a616f29 100644 --- a/pgraph_test.go +++ b/pgraph_test.go @@ -638,7 +638,7 @@ func NewNoopResTest(name string) *NoopResTest { NoopRes: NoopRes{ BaseRes: BaseRes{ Name: name, - Meta: MetaParams{ + MetaParams: MetaParams{ AutoGroup: true, // always autogroup }, }, diff --git a/pkg.go b/pkg.go index 0dfce5cc..5e159272 100644 --- a/pkg.go +++ b/pkg.go @@ -507,6 +507,10 @@ func (obj *PkgRes) Compare(res Res) bool { switch res.(type) { case *PkgRes: res := res.(*PkgRes) + if !obj.BaseRes.Compare(res) { // call base Compare + return false + } + if obj.Name != res.Name { return false } diff --git a/resources.go b/resources.go index a1d7131f..3f21c7f9 100644 --- a/resources.go +++ b/resources.go @@ -69,7 +69,7 @@ type Base interface { GetName() string // can't be named "Name()" because of struct field SetName(string) Kind() string - GetMeta() MetaParams + Meta() *MetaParams AssociateData(Converger) IsWatching() bool SetWatching(bool) @@ -99,16 +99,16 @@ type Res interface { } type BaseRes struct { - Name string `yaml:"name"` - Meta MetaParams `yaml:"meta"` // struct of all the metaparams - kind string - events chan Event - converger Converger // converged tracking - state resState - watching bool // is Watch() loop running ? - isStateOK bool // whether the state is okay based on events or not - isGrouped bool // am i contained within a group? - grouped []Res // list of any grouped resources + Name string `yaml:"name"` + MetaParams MetaParams `yaml:"meta"` // struct of all the metaparams + kind string + events chan Event + converger Converger // converged tracking + state resState + watching bool // is Watch() loop running ? + isStateOK bool // whether the state is okay based on events or not + isGrouped bool // am i contained within a group? + grouped []Res // list of any grouped resources } // wraps the IFF method when used with a list of UUID's @@ -167,8 +167,8 @@ func (obj *BaseRes) Kind() string { return obj.kind } -func (obj *BaseRes) GetMeta() MetaParams { - return obj.Meta +func (obj *BaseRes) Meta() *MetaParams { + return &obj.MetaParams } // AssociateData associates some data with the object in question @@ -292,6 +292,19 @@ func (obj *BaseRes) SetGroup(g []Res) { obj.grouped = g } +// Compare is the base compare method, which also handles the metaparams cmp +func (obj *BaseRes) Compare(res Res) bool { + if obj.Meta().Noop != res.Meta().Noop { + // obj is the existing res, res is the *new* resource + // if we go from no-noop -> noop, we can re-use the obj + // if we go from noop -> no-noop, we need to regenerate + if obj.Meta().Noop { // asymmetrical + return false // going from noop to no-noop! + } + } + return true +} + func (obj *BaseRes) CollectPattern(pattern string) { // XXX: default method is empty } diff --git a/svc.go b/svc.go index c0204738..d63a869f 100644 --- a/svc.go +++ b/svc.go @@ -424,6 +424,10 @@ func (obj *SvcRes) Compare(res Res) bool { switch res.(type) { case *SvcRes: res := res.(*SvcRes) + if !obj.BaseRes.Compare(res) { // call base Compare + return false + } + if obj.Name != res.Name { return false }