Add global --noop support

This is part two of the earlier patch in
6bbce039aa

We also rename GetMeta to just Meta to clean up the API.
This commit is contained in:
James Shubin
2016-05-14 12:03:32 -04:00
parent 12ea860eba
commit 9f56e4a582
11 changed files with 72 additions and 22 deletions

View File

@@ -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 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. 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 ##Examples
For example configurations, please consult the [examples/](https://github.com/purpleidea/mgmt/tree/master/examples) directory in the git 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: source repository. It is available from:

View File

@@ -85,7 +85,7 @@ func ParseConfigFromFile(filename string) *GraphConfig {
// NewGraphFromConfig returns a new graph from existing input, such as from the // NewGraphFromConfig returns a new graph from existing input, such as from the
// existing graph, and a GraphConfig struct. // 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 var graph *Graph // new graph to return
if g == nil { // FIXME: how can we check for an empty graph? 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 { if !ok {
return nil, fmt.Errorf("Error: Config: Can't convert: %v of type: %T to Res.", x, x) 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 { if _, exists := lookup[kind]; !exists {
lookup[kind] = make(map[string]*Vertex) 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 lookup[kind][obj.GetName()] = v // used for constructing edges
keep = append(keep, v) // append keep = append(keep, v) // append
} else { } else if !noop { // do not export any resources if noop
// XXX: do this in a different function... // XXX: do this in a different function...
// add to etcd storage... // add to etcd storage...
obj.SetName(obj.GetName()[2:]) //slice off @@ obj.SetName(obj.GetName()[2:]) //slice off @@
@@ -177,6 +179,11 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host
continue continue
} }
// collect resources but add the noop metaparam
if noop {
obj.Meta().Noop = noop
}
if t.Pattern != "" { // XXX: simplistic for now if t.Pattern != "" { // XXX: simplistic for now
obj.CollectPattern(t.Pattern) // obj.Dirname = t.Pattern 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() { func (g *Graph) AutoEdges() {
log.Println("Compile: Adding AutoEdges...") log.Println("Compile: Adding AutoEdges...")
for _, v := range g.GetVertices() { // for each vertexes 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 continue
} }
autoEdgeObj := v.AutoEdges() 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!") return fmt.Errorf("The two resources aren't the same kind!")
} }
// someone doesn't want to group! // 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!") return fmt.Errorf("One of the autogroup flags is false!")
} }
if v1.Res.IsGrouped() { // already grouped! if v1.Res.IsGrouped() { // already grouped!

View File

@@ -391,6 +391,10 @@ func (obj *ExecRes) Compare(res Res) bool {
switch res.(type) { switch res.(type) {
case *ExecRes: case *ExecRes:
res := res.(*ExecRes) res := res.(*ExecRes)
if !obj.BaseRes.Compare(res) { // call base Compare
return false
}
if obj.Name != res.Name { if obj.Name != res.Name {
return false return false
} }

View File

@@ -478,6 +478,10 @@ func (obj *FileRes) Compare(res Res) bool {
switch res.(type) { switch res.(type) {
case *FileRes: case *FileRes:
res := res.(*FileRes) res := res.(*FileRes)
if !obj.BaseRes.Compare(res) { // call base Compare
return false
}
if obj.Name != res.Name { if obj.Name != res.Name {
return false return false
} }

View File

@@ -103,6 +103,7 @@ func run(c *cli.Context) error {
if hostname == "" { if hostname == "" {
hostname, _ = os.Hostname() // etcd watch key // XXX: this is not the correct key name this is the set key name... WOOPS 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 exitchan := make(chan Event) // exit event
go func() { go func() {
@@ -157,7 +158,7 @@ func run(c *cli.Context) error {
// build graph from yaml file on events (eg: from etcd) // build graph from yaml file on events (eg: from etcd)
// we need the vertices to be paused to work on them // 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 fullGraph = newFullgraph
} else { } else {
log.Printf("Config: Error making new graph from config: %v", err) 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", Usage: "exit after a maximum of approximately this many seconds",
EnvVar: "MGMT_MAX_RUNTIME", EnvVar: "MGMT_MAX_RUNTIME",
}, },
cli.BoolFlag{
Name: "noop",
Usage: "globally force all resources into no-op mode",
},
}, },
}, },
} }

View File

@@ -133,6 +133,10 @@ func (obj *NoopRes) Compare(res Res) bool {
// we can only compare NoopRes to others of the same resource // we can only compare NoopRes to others of the same resource
case *NoopRes: case *NoopRes:
res := res.(*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 { if obj.Name != res.Name {
return false return false
} }

View File

@@ -729,7 +729,7 @@ func (g *Graph) Process(v *Vertex) {
obj.SetState(resStateCheckApply) obj.SetState(resStateCheckApply)
// if this fails, don't UpdateTimestamp() // 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 if checkok && err != nil { // should never return this way
log.Fatalf("%v[%v]: CheckApply(): %t, %+v", obj.Kind(), obj.GetName(), checkok, err) 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 // when noop is true we always want to update timestamp
if obj.GetMeta().Noop && err == nil { if obj.Meta().Noop && err == nil {
ok = true ok = true
} }

View File

@@ -638,7 +638,7 @@ func NewNoopResTest(name string) *NoopResTest {
NoopRes: NoopRes{ NoopRes: NoopRes{
BaseRes: BaseRes{ BaseRes: BaseRes{
Name: name, Name: name,
Meta: MetaParams{ MetaParams: MetaParams{
AutoGroup: true, // always autogroup AutoGroup: true, // always autogroup
}, },
}, },

4
pkg.go
View File

@@ -507,6 +507,10 @@ func (obj *PkgRes) Compare(res Res) bool {
switch res.(type) { switch res.(type) {
case *PkgRes: case *PkgRes:
res := res.(*PkgRes) res := res.(*PkgRes)
if !obj.BaseRes.Compare(res) { // call base Compare
return false
}
if obj.Name != res.Name { if obj.Name != res.Name {
return false return false
} }

View File

@@ -69,7 +69,7 @@ type Base interface {
GetName() string // can't be named "Name()" because of struct field GetName() string // can't be named "Name()" because of struct field
SetName(string) SetName(string)
Kind() string Kind() string
GetMeta() MetaParams Meta() *MetaParams
AssociateData(Converger) AssociateData(Converger)
IsWatching() bool IsWatching() bool
SetWatching(bool) SetWatching(bool)
@@ -99,16 +99,16 @@ type Res interface {
} }
type BaseRes struct { type BaseRes struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Meta MetaParams `yaml:"meta"` // struct of all the metaparams MetaParams MetaParams `yaml:"meta"` // struct of all the metaparams
kind string kind string
events chan Event events chan Event
converger Converger // converged tracking converger Converger // converged tracking
state resState state resState
watching bool // is Watch() loop running ? watching bool // is Watch() loop running ?
isStateOK bool // whether the state is okay based on events or not isStateOK bool // whether the state is okay based on events or not
isGrouped bool // am i contained within a group? isGrouped bool // am i contained within a group?
grouped []Res // list of any grouped resources grouped []Res // list of any grouped resources
} }
// wraps the IFF method when used with a list of UUID's // wraps the IFF method when used with a list of UUID's
@@ -167,8 +167,8 @@ func (obj *BaseRes) Kind() string {
return obj.kind return obj.kind
} }
func (obj *BaseRes) GetMeta() MetaParams { func (obj *BaseRes) Meta() *MetaParams {
return obj.Meta return &obj.MetaParams
} }
// AssociateData associates some data with the object in question // AssociateData associates some data with the object in question
@@ -292,6 +292,19 @@ func (obj *BaseRes) SetGroup(g []Res) {
obj.grouped = g 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) { func (obj *BaseRes) CollectPattern(pattern string) {
// XXX: default method is empty // XXX: default method is empty
} }

4
svc.go
View File

@@ -424,6 +424,10 @@ func (obj *SvcRes) Compare(res Res) bool {
switch res.(type) { switch res.(type) {
case *SvcRes: case *SvcRes:
res := res.(*SvcRes) res := res.(*SvcRes)
if !obj.BaseRes.Compare(res) { // call base Compare
return false
}
if obj.Name != res.Name { if obj.Name != res.Name {
return false return false
} }