all: Rename UUID to UID.

Felix pointed out that these ID's are unique, but not universally unique
across the cluster, which might be confusing to new programmers. As a
result, rename them all.
This commit is contained in:
James Shubin
2016-10-18 23:03:55 -04:00
parent 1c1e8127d8
commit b26322fc20
15 changed files with 307 additions and 307 deletions

View File

@@ -334,7 +334,7 @@ starting up, and as a result, a default endpoint never gets added. The solution
is to either reconcile the mistake, and if there is no important data saved, you is to either reconcile the mistake, and if there is no important data saved, you
can remove the etcd dataDir. This is typically `/var/lib/mgmt/etcd/member/`. can remove the etcd dataDir. This is typically `/var/lib/mgmt/etcd/member/`.
###Why do resources have both a `Compare` method and an `IFF` (on the UUID) method? ###Why do resources have both a `Compare` method and an `IFF` (on the UID) method?
The `Compare()` methods are for determining if two resources are effectively the The `Compare()` methods are for determining if two resources are effectively the
same, which is used to make graph change delta's efficient. This is when we want same, which is used to make graph change delta's efficient. This is when we want
@@ -343,9 +343,9 @@ vertices. Since we want to make this process efficient, we only update the parts
that are different, and leave everything else alone. This `Compare()` method can that are different, and leave everything else alone. This `Compare()` method can
tell us if two resources are the same. tell us if two resources are the same.
The `IFF()` method is part of the whole UUID system, which is for discerning if The `IFF()` method is part of the whole UID system, which is for discerning if a
a resource meets the requirements another expects for an automatic edge. This is resource meets the requirements another expects for an automatic edge. This is
because the automatic edge system assumes a unified UUID pattern to test for because the automatic edge system assumes a unified UID pattern to test for
equality. In the future it might be helpful or sane to merge the two similar equality. In the future it might be helpful or sane to merge the two similar
comparison functions although for now they are separate because they are comparison functions although for now they are separate because they are
actually answer different questions. actually answer different questions.

View File

@@ -27,26 +27,26 @@ import (
) )
// TODO: we could make a new function that masks out the state of certain // TODO: we could make a new function that masks out the state of certain
// UUID's, but at the moment the new Timer code has obsoleted the need... // UID's, but at the moment the new Timer code has obsoleted the need...
// Converger is the general interface for implementing a convergence watcher // Converger is the general interface for implementing a convergence watcher
type Converger interface { // TODO: need a better name type Converger interface { // TODO: need a better name
Register() ConvergerUUID Register() ConvergerUID
IsConverged(ConvergerUUID) bool // is the UUID converged ? IsConverged(ConvergerUID) bool // is the UID converged ?
SetConverged(ConvergerUUID, bool) error // set the converged state of the UUID SetConverged(ConvergerUID, bool) error // set the converged state of the UID
Unregister(ConvergerUUID) Unregister(ConvergerUID)
Start() Start()
Pause() Pause()
Loop(bool) Loop(bool)
ConvergedTimer(ConvergerUUID) <-chan time.Time ConvergedTimer(ConvergerUID) <-chan time.Time
Status() map[uint64]bool Status() map[uint64]bool
Timeout() int // returns the timeout that this was created with Timeout() int // returns the timeout that this was created with
SetStateFn(func(bool) error) // sets the stateFn SetStateFn(func(bool) error) // sets the stateFn
} }
// ConvergerUUID is the interface resources can use to notify with if converged // ConvergerUID is the interface resources can use to notify with if converged
// you'll need to use part of the Converger interface to Register initially too // you'll need to use part of the Converger interface to Register initially too
type ConvergerUUID interface { type ConvergerUID interface {
ID() uint64 // get Id ID() uint64 // get Id
Name() string // get a friendly name Name() string // get a friendly name
SetName(string) SetName(string)
@@ -73,8 +73,8 @@ type converger struct {
status map[uint64]bool status map[uint64]bool
} }
// convergerUUID is an implementation of the ConvergerUUID interface // convergerUID is an implementation of the ConvergerUID interface
type convergerUUID struct { type convergerUID struct {
converger Converger converger Converger
id uint64 id uint64
name string // user defined, friendly name name string // user defined, friendly name
@@ -95,13 +95,13 @@ func NewConverger(timeout int, stateFn func(bool) error) *converger {
} }
} }
// Register assigns a ConvergerUUID to the caller // Register assigns a ConvergerUID to the caller
func (obj *converger) Register() ConvergerUUID { func (obj *converger) Register() ConvergerUID {
obj.mutex.Lock() obj.mutex.Lock()
defer obj.mutex.Unlock() defer obj.mutex.Unlock()
obj.lastid++ obj.lastid++
obj.status[obj.lastid] = false // initialize as not converged obj.status[obj.lastid] = false // initialize as not converged
return &convergerUUID{ return &convergerUID{
converger: obj, converger: obj,
id: obj.lastid, id: obj.lastid,
name: fmt.Sprintf("%d", obj.lastid), // some default name: fmt.Sprintf("%d", obj.lastid), // some default
@@ -110,32 +110,32 @@ func (obj *converger) Register() ConvergerUUID {
} }
} }
// IsConverged gets the converged status of a uuid // IsConverged gets the converged status of a uid
func (obj *converger) IsConverged(uuid ConvergerUUID) bool { func (obj *converger) IsConverged(uid ConvergerUID) bool {
if !uuid.IsValid() { if !uid.IsValid() {
panic(fmt.Sprintf("Id of ConvergerUUID(%s) is nil!", uuid.Name())) panic(fmt.Sprintf("Id of ConvergerUID(%s) is nil!", uid.Name()))
} }
obj.mutex.RLock() obj.mutex.RLock()
isConverged, found := obj.status[uuid.ID()] // lookup isConverged, found := obj.status[uid.ID()] // lookup
obj.mutex.RUnlock() obj.mutex.RUnlock()
if !found { if !found {
panic("Id of ConvergerUUID is unregistered!") panic("Id of ConvergerUID is unregistered!")
} }
return isConverged return isConverged
} }
// SetConverged updates the converger with the converged state of the UUID // SetConverged updates the converger with the converged state of the UID
func (obj *converger) SetConverged(uuid ConvergerUUID, isConverged bool) error { func (obj *converger) SetConverged(uid ConvergerUID, isConverged bool) error {
if !uuid.IsValid() { if !uid.IsValid() {
return fmt.Errorf("Id of ConvergerUUID(%s) is nil!", uuid.Name()) return fmt.Errorf("Id of ConvergerUID(%s) is nil!", uid.Name())
} }
obj.mutex.Lock() obj.mutex.Lock()
if _, found := obj.status[uuid.ID()]; !found { if _, found := obj.status[uid.ID()]; !found {
panic("Id of ConvergerUUID is unregistered!") panic("Id of ConvergerUID is unregistered!")
} }
obj.status[uuid.ID()] = isConverged // set obj.status[uid.ID()] = isConverged // set
obj.mutex.Unlock() // unlock *before* poke or deadlock! obj.mutex.Unlock() // unlock *before* poke or deadlock!
if isConverged != obj.converged { // only poke if it would be helpful if isConverged != obj.converged { // only poke if it would be helpful
// run in a go routine so that we never block... just queue up! // run in a go routine so that we never block... just queue up!
// this allows us to send events, even if we haven't started... // this allows us to send events, even if we haven't started...
go func() { obj.channel <- struct{}{} }() go func() { obj.channel <- struct{}{} }()
@@ -143,7 +143,7 @@ func (obj *converger) SetConverged(uuid ConvergerUUID, isConverged bool) error {
return nil return nil
} }
// isConverged returns true if *every* registered uuid has converged // isConverged returns true if *every* registered uid has converged
func (obj *converger) isConverged() bool { func (obj *converger) isConverged() bool {
obj.mutex.RLock() // take a read lock obj.mutex.RLock() // take a read lock
defer obj.mutex.RUnlock() defer obj.mutex.RUnlock()
@@ -155,16 +155,16 @@ func (obj *converger) isConverged() bool {
return true return true
} }
// Unregister dissociates the ConvergedUUID from the converged checking // Unregister dissociates the ConvergedUID from the converged checking
func (obj *converger) Unregister(uuid ConvergerUUID) { func (obj *converger) Unregister(uid ConvergerUID) {
if !uuid.IsValid() { if !uid.IsValid() {
panic(fmt.Sprintf("Id of ConvergerUUID(%s) is nil!", uuid.Name())) panic(fmt.Sprintf("Id of ConvergerUID(%s) is nil!", uid.Name()))
} }
obj.mutex.Lock() obj.mutex.Lock()
uuid.StopTimer() // ignore any errors uid.StopTimer() // ignore any errors
delete(obj.status, uuid.ID()) delete(obj.status, uid.ID())
obj.mutex.Unlock() obj.mutex.Unlock()
uuid.InvalidateID() uid.InvalidateID()
} }
// Start causes a Converger object to start or resume running // Start causes a Converger object to start or resume running
@@ -245,18 +245,18 @@ func (obj *converger) Loop(startPaused bool) {
// ConvergedTimer adds a timeout to a select call and blocks until then // ConvergedTimer adds a timeout to a select call and blocks until then
// TODO: this means we could eventually have per resource converged timeouts // TODO: this means we could eventually have per resource converged timeouts
func (obj *converger) ConvergedTimer(uuid ConvergerUUID) <-chan time.Time { func (obj *converger) ConvergedTimer(uid ConvergerUID) <-chan time.Time {
// be clever: if i'm already converged, this timeout should block which // be clever: if i'm already converged, this timeout should block which
// avoids unnecessary new signals being sent! this avoids fast loops if // avoids unnecessary new signals being sent! this avoids fast loops if
// we have a low timeout, or in particular a timeout == 0 // we have a low timeout, or in particular a timeout == 0
if uuid.IsConverged() { if uid.IsConverged() {
// blocks the case statement in select forever! // blocks the case statement in select forever!
return util.TimeAfterOrBlock(-1) return util.TimeAfterOrBlock(-1)
} }
return util.TimeAfterOrBlock(obj.timeout) return util.TimeAfterOrBlock(obj.timeout)
} }
// Status returns a map of the converged status of each UUID. // Status returns a map of the converged status of each UID.
func (obj *converger) Status() map[uint64]bool { func (obj *converger) Status() map[uint64]bool {
status := make(map[uint64]bool) status := make(map[uint64]bool)
obj.mutex.RLock() // take a read lock obj.mutex.RLock() // take a read lock
@@ -279,53 +279,53 @@ func (obj *converger) SetStateFn(stateFn func(bool) error) {
obj.stateFn = stateFn obj.stateFn = stateFn
} }
// Id returns the unique id of this UUID object // Id returns the unique id of this UID object
func (obj *convergerUUID) ID() uint64 { func (obj *convergerUID) ID() uint64 {
return obj.id return obj.id
} }
// Name returns a user defined name for the specific convergerUUID. // Name returns a user defined name for the specific convergerUID.
func (obj *convergerUUID) Name() string { func (obj *convergerUID) Name() string {
return obj.name return obj.name
} }
// SetName sets a user defined name for the specific convergerUUID. // SetName sets a user defined name for the specific convergerUID.
func (obj *convergerUUID) SetName(name string) { func (obj *convergerUID) SetName(name string) {
obj.name = name obj.name = name
} }
// IsValid tells us if the id is valid or has already been destroyed // IsValid tells us if the id is valid or has already been destroyed
func (obj *convergerUUID) IsValid() bool { func (obj *convergerUID) IsValid() bool {
return obj.id != 0 // an id of 0 is invalid return obj.id != 0 // an id of 0 is invalid
} }
// InvalidateID marks the id as no longer valid // InvalidateID marks the id as no longer valid
func (obj *convergerUUID) InvalidateID() { func (obj *convergerUID) InvalidateID() {
obj.id = 0 // an id of 0 is invalid obj.id = 0 // an id of 0 is invalid
} }
// IsConverged is a helper function to the regular IsConverged method // IsConverged is a helper function to the regular IsConverged method
func (obj *convergerUUID) IsConverged() bool { func (obj *convergerUID) IsConverged() bool {
return obj.converger.IsConverged(obj) return obj.converger.IsConverged(obj)
} }
// SetConverged is a helper function to the regular SetConverged notification // SetConverged is a helper function to the regular SetConverged notification
func (obj *convergerUUID) SetConverged(isConverged bool) error { func (obj *convergerUID) SetConverged(isConverged bool) error {
return obj.converger.SetConverged(obj, isConverged) return obj.converger.SetConverged(obj, isConverged)
} }
// Unregister is a helper function to unregister myself // Unregister is a helper function to unregister myself
func (obj *convergerUUID) Unregister() { func (obj *convergerUID) Unregister() {
obj.converger.Unregister(obj) obj.converger.Unregister(obj)
} }
// ConvergedTimer is a helper around the regular ConvergedTimer method // ConvergedTimer is a helper around the regular ConvergedTimer method
func (obj *convergerUUID) ConvergedTimer() <-chan time.Time { func (obj *convergerUID) ConvergedTimer() <-chan time.Time {
return obj.converger.ConvergedTimer(obj) return obj.converger.ConvergedTimer(obj)
} }
// StartTimer runs an invisible timer that automatically converges on timeout. // StartTimer runs an invisible timer that automatically converges on timeout.
func (obj *convergerUUID) StartTimer() (func() error, error) { func (obj *convergerUID) StartTimer() (func() error, error) {
obj.mutex.Lock() obj.mutex.Lock()
if !obj.running { if !obj.running {
obj.timer = make(chan struct{}) obj.timer = make(chan struct{})
@@ -359,7 +359,7 @@ func (obj *convergerUUID) StartTimer() (func() error, error) {
} }
// ResetTimer resets the counter to zero if using a StartTimer internally. // ResetTimer resets the counter to zero if using a StartTimer internally.
func (obj *convergerUUID) ResetTimer() error { func (obj *convergerUID) ResetTimer() error {
obj.mutex.Lock() obj.mutex.Lock()
defer obj.mutex.Unlock() defer obj.mutex.Unlock()
if obj.running { if obj.running {
@@ -370,7 +370,7 @@ func (obj *convergerUUID) ResetTimer() error {
} }
// StopTimer stops the running timer permanently until a StartTimer is run. // StopTimer stops the running timer permanently until a StartTimer is run.
func (obj *convergerUUID) StopTimer() error { func (obj *convergerUID) StopTimer() error {
obj.mutex.Lock() obj.mutex.Lock()
defer obj.mutex.Unlock() defer obj.mutex.Unlock()
if !obj.running { if !obj.running {

View File

@@ -692,22 +692,22 @@ func (obj *EmbdEtcd) CtxError(ctx context.Context, err error) (context.Context,
// CbLoop is the loop where callback execution is serialized // CbLoop is the loop where callback execution is serialized
func (obj *EmbdEtcd) CbLoop() { func (obj *EmbdEtcd) CbLoop() {
cuuid := obj.converger.Register() cuid := obj.converger.Register()
cuuid.SetName("Etcd: CbLoop") cuid.SetName("Etcd: CbLoop")
defer cuuid.Unregister() defer cuid.Unregister()
if e := obj.Connect(false); e != nil { if e := obj.Connect(false); e != nil {
return // fatal return // fatal
} }
// we use this timer because when we ignore un-converge events and loop, // we use this timer because when we ignore un-converge events and loop,
// we reset the ConvergedTimer case statement, ruining the timeout math! // we reset the ConvergedTimer case statement, ruining the timeout math!
cuuid.StartTimer() cuid.StartTimer()
for { for {
ctx := context.Background() // TODO: inherit as input argument? ctx := context.Background() // TODO: inherit as input argument?
select { select {
// etcd watcher event // etcd watcher event
case re := <-obj.wevents: case re := <-obj.wevents:
if !re.skipConv { // if we want to count it... if !re.skipConv { // if we want to count it...
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
} }
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: CbLoop: Event: StartLoop") log.Printf("Trace: Etcd: CbLoop: Event: StartLoop")
@@ -740,7 +740,7 @@ func (obj *EmbdEtcd) CbLoop() {
// exit loop commit // exit loop commit
case <-obj.exitTimeout: case <-obj.exitTimeout:
log.Println("Etcd: Exiting callback loop!") log.Println("Etcd: Exiting callback loop!")
cuuid.StopTimer() // clean up nicely cuid.StopTimer() // clean up nicely
return return
} }
} }
@@ -748,19 +748,19 @@ func (obj *EmbdEtcd) CbLoop() {
// Loop is the main loop where everything is serialized // Loop is the main loop where everything is serialized
func (obj *EmbdEtcd) Loop() { func (obj *EmbdEtcd) Loop() {
cuuid := obj.converger.Register() cuid := obj.converger.Register()
cuuid.SetName("Etcd: Loop") cuid.SetName("Etcd: Loop")
defer cuuid.Unregister() defer cuid.Unregister()
if e := obj.Connect(false); e != nil { if e := obj.Connect(false); e != nil {
return // fatal return // fatal
} }
cuuid.StartTimer() cuid.StartTimer()
for { for {
ctx := context.Background() // TODO: inherit as input argument? ctx := context.Background() // TODO: inherit as input argument?
// priority channel... // priority channel...
select { select {
case aw := <-obj.awq: case aw := <-obj.awq:
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: PriorityAW: StartLoop") log.Printf("Trace: Etcd: Loop: PriorityAW: StartLoop")
} }
@@ -776,7 +776,7 @@ func (obj *EmbdEtcd) Loop() {
select { select {
// add watcher // add watcher
case aw := <-obj.awq: case aw := <-obj.awq:
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: AW: StartLoop") log.Printf("Trace: Etcd: Loop: AW: StartLoop")
} }
@@ -787,7 +787,7 @@ func (obj *EmbdEtcd) Loop() {
// set kv pair // set kv pair
case kv := <-obj.setq: case kv := <-obj.setq:
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: Set: StartLoop") log.Printf("Trace: Etcd: Loop: Set: StartLoop")
} }
@@ -812,7 +812,7 @@ func (obj *EmbdEtcd) Loop() {
// get value // get value
case gq := <-obj.getq: case gq := <-obj.getq:
if !gq.skipConv { if !gq.skipConv {
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
} }
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: Get: StartLoop") log.Printf("Trace: Etcd: Loop: Get: StartLoop")
@@ -838,7 +838,7 @@ func (obj *EmbdEtcd) Loop() {
// delete value // delete value
case dl := <-obj.delq: case dl := <-obj.delq:
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: Delete: StartLoop") log.Printf("Trace: Etcd: Loop: Delete: StartLoop")
} }
@@ -863,7 +863,7 @@ func (obj *EmbdEtcd) Loop() {
// run txn // run txn
case tn := <-obj.txnq: case tn := <-obj.txnq:
cuuid.ResetTimer() // activity! cuid.ResetTimer() // activity!
if global.TRACE { if global.TRACE {
log.Printf("Trace: Etcd: Loop: Txn: StartLoop") log.Printf("Trace: Etcd: Loop: Txn: StartLoop")
} }
@@ -898,7 +898,7 @@ func (obj *EmbdEtcd) Loop() {
// exit loop commit // exit loop commit
case <-obj.exitTimeout: case <-obj.exitTimeout:
log.Println("Etcd: Exiting loop!") log.Println("Etcd: Exiting loop!")
cuuid.StopTimer() // clean up nicely cuid.StopTimer() // clean up nicely
return return
} }
} }
@@ -2114,7 +2114,7 @@ func EtcdWatch(obj *EmbdEtcd) chan bool {
// EtcdSetResources exports all of the resources which we pass in to etcd // EtcdSetResources exports all of the resources which we pass in to etcd
func EtcdSetResources(obj *EmbdEtcd, hostname string, resourceList []resources.Res) error { func EtcdSetResources(obj *EmbdEtcd, hostname string, resourceList []resources.Res) error {
// key structure is /$NS/exported/$hostname/resources/$uuid = $data // key structure is /$NS/exported/$hostname/resources/$uid = $data
var kindFilter []string // empty to get from everyone var kindFilter []string // empty to get from everyone
hostnameFilter := []string{hostname} hostnameFilter := []string{hostname}
@@ -2135,8 +2135,8 @@ func EtcdSetResources(obj *EmbdEtcd, hostname string, resourceList []resources.R
if res.Kind() == "" { if res.Kind() == "" {
log.Fatalf("Etcd: SetResources: Error: Empty kind: %v", res.GetName()) log.Fatalf("Etcd: SetResources: Error: Empty kind: %v", res.GetName())
} }
uuid := fmt.Sprintf("%s/%s", res.Kind(), res.GetName()) uid := fmt.Sprintf("%s/%s", res.Kind(), res.GetName())
path := fmt.Sprintf("/%s/exported/%s/resources/%s", NS, hostname, uuid) path := fmt.Sprintf("/%s/exported/%s/resources/%s", NS, hostname, uid)
if data, err := resources.ResToB64(res); err == nil { if data, err := resources.ResToB64(res); err == nil {
ifs = append(ifs, etcd.Compare(etcd.Value(path), "=", data)) // desired state ifs = append(ifs, etcd.Compare(etcd.Value(path), "=", data)) // desired state
ops = append(ops, etcd.OpPut(path, data)) ops = append(ops, etcd.OpPut(path, data))
@@ -2160,8 +2160,8 @@ func EtcdSetResources(obj *EmbdEtcd, hostname string, resourceList []resources.R
if res.Kind() == "" { if res.Kind() == "" {
log.Fatalf("Etcd: SetResources: Error: Empty kind: %v", res.GetName()) log.Fatalf("Etcd: SetResources: Error: Empty kind: %v", res.GetName())
} }
uuid := fmt.Sprintf("%s/%s", res.Kind(), res.GetName()) uid := fmt.Sprintf("%s/%s", res.Kind(), res.GetName())
path := fmt.Sprintf("/%s/exported/%s/resources/%s", NS, hostname, uuid) path := fmt.Sprintf("/%s/exported/%s/resources/%s", NS, hostname, uid)
if match(res, resourceList) { // if we match, no need to delete! if match(res, resourceList) { // if we match, no need to delete!
continue continue
@@ -2187,9 +2187,9 @@ func EtcdSetResources(obj *EmbdEtcd, hostname string, resourceList []resources.R
// If the kindfilter or hostnameFilter is empty, then it assumes no filtering... // If the kindfilter or hostnameFilter is empty, then it assumes no filtering...
// TODO: Expand this with a more powerful filter based on what we eventually // TODO: Expand this with a more powerful filter based on what we eventually
// support in our collect DSL. Ideally a server side filter like WithFilter() // support in our collect DSL. Ideally a server side filter like WithFilter()
// We could do this if the pattern was /$NS/exported/$kind/$hostname/$uuid = $data // We could do this if the pattern was /$NS/exported/$kind/$hostname/$uid = $data
func EtcdGetResources(obj *EmbdEtcd, hostnameFilter, kindFilter []string) ([]resources.Res, error) { func EtcdGetResources(obj *EmbdEtcd, hostnameFilter, kindFilter []string) ([]resources.Res, error) {
// key structure is /$NS/exported/$hostname/resources/$uuid = $data // key structure is /$NS/exported/$hostname/resources/$uid = $data
path := fmt.Sprintf("/%s/exported/", NS) path := fmt.Sprintf("/%s/exported/", NS)
resourceList := []resources.Res{} resourceList := []resources.Res{}
keyMap, err := obj.Get(path, etcd.WithPrefix(), etcd.WithSort(etcd.SortByKey, etcd.SortAscend)) keyMap, err := obj.Get(path, etcd.WithPrefix(), etcd.WithSort(etcd.SortByKey, etcd.SortAscend))

View File

@@ -26,29 +26,29 @@ import (
"github.com/purpleidea/mgmt/resources" "github.com/purpleidea/mgmt/resources"
) )
// add edges to the vertex in a graph based on if it matches a uuid list // add edges to the vertex in a graph based on if it matches a uid list
func (g *Graph) addEdgesByMatchingUUIDS(v *Vertex, uuids []resources.ResUUID) []bool { func (g *Graph) addEdgesByMatchingUIDS(v *Vertex, uids []resources.ResUID) []bool {
// search for edges and see what matches! // search for edges and see what matches!
var result []bool var result []bool
// loop through each uuid, and see if it matches any vertex // loop through each uid, and see if it matches any vertex
for _, uuid := range uuids { for _, uid := range uids {
var found = false var found = false
// uuid is a ResUUID object // uid is a ResUID object
for _, vv := range g.GetVertices() { // search for _, vv := range g.GetVertices() { // search
if v == vv { // skip self if v == vv { // skip self
continue continue
} }
if global.DEBUG { if global.DEBUG {
log.Printf("Compile: AutoEdge: Match: %v[%v] with UUID: %v[%v]", vv.Kind(), vv.GetName(), uuid.Kind(), uuid.GetName()) log.Printf("Compile: AutoEdge: Match: %v[%v] with UID: %v[%v]", vv.Kind(), vv.GetName(), uid.Kind(), uid.GetName())
} }
// we must match to an effective UUID 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
// handle, but it is not necessarily a unique identity! // handle, but it is not necessarily a unique identity!
// remember, resources can return multiple UUID's each! // remember, resources can return multiple UID's each!
if resources.UUIDExistsInUUIDs(uuid, vv.GetUUIDs()) { if resources.UIDExistsInUIDs(uid, vv.GetUIDs()) {
// add edge from: vv -> v // add edge from: vv -> v
if uuid.Reversed() { if uid.Reversed() {
txt := fmt.Sprintf("AutoEdge: %v[%v] -> %v[%v]", vv.Kind(), vv.GetName(), v.Kind(), v.GetName()) txt := fmt.Sprintf("AutoEdge: %v[%v] -> %v[%v]", vv.Kind(), vv.GetName(), v.Kind(), v.GetName())
log.Printf("Compile: Adding %v", txt) log.Printf("Compile: Adding %v", txt)
g.AddEdge(vv, v, NewEdge(txt)) g.AddEdge(vv, v, NewEdge(txt))
@@ -79,21 +79,21 @@ func (g *Graph) AutoEdges() {
continue // next vertex continue // next vertex
} }
for { // while the autoEdgeObj has more uuids to add... for { // while the autoEdgeObj has more uids to add...
uuids := autoEdgeObj.Next() // get some! uids := autoEdgeObj.Next() // get some!
if uuids == nil { if uids == nil {
log.Printf("%v[%v]: Config: The auto edge list is empty!", v.Kind(), v.GetName()) log.Printf("%v[%v]: Config: The auto edge list is empty!", v.Kind(), v.GetName())
break // inner loop break // inner loop
} }
if global.DEBUG { if global.DEBUG {
log.Println("Compile: AutoEdge: UUIDS:") log.Println("Compile: AutoEdge: UIDS:")
for i, u := range uuids { for i, u := range uids {
log.Printf("Compile: AutoEdge: UUID%d: %v", i, u) log.Printf("Compile: AutoEdge: UID%d: %v", i, u)
} }
} }
// match and add edges // match and add edges
result := g.addEdgesByMatchingUUIDS(v, uuids) result := g.addEdgesByMatchingUIDS(v, uids)
// report back, and find out if we should continue // report back, and find out if we should continue
if !autoEdgeObj.Test(result) { if !autoEdgeObj.Test(result) {

View File

@@ -792,7 +792,7 @@ func (g *Graph) Worker(v *Vertex) error {
// TODO: resources could have a separate exit channel to avoid this complexity!? // TODO: resources could have a separate exit channel to avoid this complexity!?
case event := <-obj.Events(): case event := <-obj.Events():
// NOTE: this code should match the similar Res code! // NOTE: this code should match the similar Res code!
//cuuid.SetConverged(false) // TODO: ? //cuid.SetConverged(false) // TODO: ?
if exit, send := obj.ReadEvent(&event); exit { if exit, send := obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} else if send { } else if send {

View File

@@ -171,7 +171,7 @@ func (obj *SSH) Sftp() error {
// TODO: make the path configurable to deal with /tmp/ mounted noexec? // TODO: make the path configurable to deal with /tmp/ mounted noexec?
tmpdir := func() string { tmpdir := func() string {
return fmt.Sprintf(formatPattern, fmtUUID(10)) // eg: /tmp/mgmt.abcdefghij/ return fmt.Sprintf(formatPattern, fmtUID(10)) // eg: /tmp/mgmt.abcdefghij/
} }
var ready bool var ready bool
obj.remotewd = "" obj.remotewd = ""
@@ -189,7 +189,7 @@ func (obj *SSH) Sftp() error {
} }
for i := 0; true; { for i := 0; true; {
// NOTE: since fmtUUID is deterministic, if we don't clean up // NOTE: since fmtUID is deterministic, if we don't clean up
// previous runs, we may get the same paths generated, and here // previous runs, we may get the same paths generated, and here
// they will conflict. // they will conflict.
if err := obj.sftp.Mkdir(obj.remotewd); err != nil { if err := obj.sftp.Mkdir(obj.remotewd); err != nil {
@@ -691,16 +691,16 @@ type Remotes struct {
converger cv.Converger converger cv.Converger
convergerCb func(func(map[string]bool) error) (func(), error) convergerCb func(func(map[string]bool) error) (func(), error)
wg sync.WaitGroup // keep track of each running SSH connection wg sync.WaitGroup // keep track of each running SSH connection
lock sync.Mutex // mutex for access to sshmap lock sync.Mutex // mutex for access to sshmap
sshmap map[string]*SSH // map to each SSH struct with the remote as the key sshmap map[string]*SSH // map to each SSH struct with the remote as the key
exiting bool // flag to let us know if we're exiting exiting bool // flag to let us know if we're exiting
exitChan chan struct{} // closes when we should exit exitChan chan struct{} // closes when we should exit
semaphore Semaphore // counting semaphore to limit concurrent connections semaphore Semaphore // counting semaphore to limit concurrent connections
hostnames []string // list of hostnames we've seen so far hostnames []string // list of hostnames we've seen so far
cuuid cv.ConvergerUUID // convergerUUID for the remote itself cuid cv.ConvergerUID // convergerUID for the remote itself
cuuids map[string]cv.ConvergerUUID // map to each SSH struct with the remote as the key cuids map[string]cv.ConvergerUID // map to each SSH struct with the remote as the key
callbackCancelFunc func() // stored callback function cancel function callbackCancelFunc func() // stored callback function cancel function
program string // name of the program program string // name of the program
} }
@@ -725,7 +725,7 @@ func NewRemotes(clientURLs, remoteURLs []string, noop bool, remotes []string, fi
exitChan: make(chan struct{}), exitChan: make(chan struct{}),
semaphore: NewSemaphore(int(cConns)), semaphore: NewSemaphore(int(cConns)),
hostnames: make([]string, len(remotes)), hostnames: make([]string, len(remotes)),
cuuids: make(map[string]cv.ConvergerUUID), cuids: make(map[string]cv.ConvergerUID),
program: program, program: program,
} }
} }
@@ -894,12 +894,12 @@ func (obj *Remotes) passwordCallback(user, host string) func() (string, error) {
func (obj *Remotes) Run() { func (obj *Remotes) Run() {
// TODO: we can disable a lot of this if we're not using --converged-timeout // TODO: we can disable a lot of this if we're not using --converged-timeout
// link in all the converged timeout checking and callbacks... // link in all the converged timeout checking and callbacks...
obj.cuuid = obj.converger.Register() // one for me! obj.cuid = obj.converger.Register() // one for me!
obj.cuuid.SetName("Remote: Run") obj.cuid.SetName("Remote: Run")
for _, f := range obj.remotes { // one for each remote... for _, f := range obj.remotes { // one for each remote...
obj.cuuids[f] = obj.converger.Register() // save a reference obj.cuids[f] = obj.converger.Register() // save a reference
obj.cuuids[f].SetName(fmt.Sprintf("Remote: %s", f)) obj.cuids[f].SetName(fmt.Sprintf("Remote: %s", f))
//obj.cuuids[f].SetConverged(false) // everyone starts off false //obj.cuids[f].SetConverged(false) // everyone starts off false
} }
// watch for converged state in the group of remotes... // watch for converged state in the group of remotes...
@@ -926,7 +926,7 @@ func (obj *Remotes) Run() {
} }
// if exiting, don't update, it will be unregistered... // if exiting, don't update, it will be unregistered...
if !sshobj.exiting { // this is actually racy, but safe if !sshobj.exiting { // this is actually racy, but safe
obj.cuuids[f].SetConverged(b) // ignore errors! obj.cuids[f].SetConverged(b) // ignore errors!
} }
} }
@@ -953,10 +953,10 @@ func (obj *Remotes) Run() {
if !more { if !more {
return return
} }
obj.cuuid.SetConverged(false) // activity! obj.cuid.SetConverged(false) // activity!
case <-obj.cuuid.ConvergedTimer(): case <-obj.cuid.ConvergedTimer():
obj.cuuid.SetConverged(true) // converged! obj.cuid.SetConverged(true) // converged!
continue continue
} }
obj.lock.Lock() obj.lock.Lock()
@@ -975,7 +975,7 @@ func (obj *Remotes) Run() {
} }
}() }()
} else { } else {
obj.cuuid.SetConverged(true) // if no watches, we're converged! obj.cuid.SetConverged(true) // if no watches, we're converged!
} }
// the semaphore provides the max simultaneous connection limit // the semaphore provides the max simultaneous connection limit
@@ -993,7 +993,7 @@ func (obj *Remotes) Run() {
if obj.cConns != 0 { if obj.cConns != 0 {
obj.semaphore.V(1) // don't lock the loop obj.semaphore.V(1) // don't lock the loop
} }
obj.cuuids[f].Unregister() // don't stall the converge! obj.cuids[f].Unregister() // don't stall the converge!
continue continue
} }
obj.sshmap[f] = sshobj // save a reference obj.sshmap[f] = sshobj // save a reference
@@ -1004,7 +1004,7 @@ func (obj *Remotes) Run() {
defer obj.semaphore.V(1) defer obj.semaphore.V(1)
} }
defer obj.wg.Done() defer obj.wg.Done()
defer obj.cuuids[f].Unregister() defer obj.cuids[f].Unregister()
if err := sshobj.Go(); err != nil { if err := sshobj.Go(); err != nil {
log.Printf("Remote: Error: %s", err) log.Printf("Remote: Error: %s", err)
@@ -1038,14 +1038,14 @@ func (obj *Remotes) Exit() {
obj.callbackCancelFunc() // cancel our callback obj.callbackCancelFunc() // cancel our callback
} }
defer obj.cuuid.Unregister() defer obj.cuid.Unregister()
obj.wg.Wait() // wait for everyone to exit obj.wg.Wait() // wait for everyone to exit
} }
// fmtUUID makes a random string of length n, it is not cryptographically safe. // fmtUID makes a random string of length n, it is not cryptographically safe.
// This function actually usually generates the same sequence of random strings // This function actually usually generates the same sequence of random strings
// each time the program is run, which makes repeatability of this code easier. // each time the program is run, which makes repeatability of this code easier.
func fmtUUID(n int) string { func fmtUID(n int) string {
b := make([]byte, n) b := make([]byte, n)
for i := range b { for i := range b {
b[i] = formatChars[rand.Intn(len(formatChars))] b[i] = formatChars[rand.Intn(len(formatChars))]

View File

@@ -116,8 +116,8 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -173,7 +173,7 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
obj.SetState(ResStateWatching) // reset obj.SetState(ResStateWatching) // reset
select { select {
case text := <-bufioch: case text := <-bufioch:
cuuid.SetConverged(false) cuid.SetConverged(false)
// each time we get a line of output, we loop! // each time we get a line of output, we loop!
log.Printf("%v[%v]: Watch output: %s", obj.Kind(), obj.GetName(), text) log.Printf("%v[%v]: Watch output: %s", obj.Kind(), obj.GetName(), text)
if text != "" { if text != "" {
@@ -181,7 +181,7 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
} }
case err := <-errch: case err := <-errch:
cuuid.SetConverged(false) cuid.SetConverged(false)
if err == nil { // EOF if err == nil { // EOF
// FIXME: add an "if watch command ends/crashes" // FIXME: add an "if watch command ends/crashes"
// restart or generate error option // restart or generate error option
@@ -191,17 +191,17 @@ func (obj *ExecRes) Watch(processChan chan event.Event) error {
return fmt.Errorf("Unknown %s[%s] error: %v", obj.Kind(), obj.GetName(), err) return fmt.Errorf("Unknown %s[%s] error: %v", obj.Kind(), obj.GetName(), err)
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
} }
@@ -340,17 +340,17 @@ func (obj *ExecRes) CheckApply(apply bool) (checkok bool, err error) {
return false, nil // success return false, nil // success
} }
// ExecUUID is the UUID struct for ExecRes. // ExecUID is the UID struct for ExecRes.
type ExecUUID struct { type ExecUID struct {
BaseUUID BaseUID
Cmd string Cmd string
IfCmd string IfCmd string
// TODO: add more elements here // TODO: add more elements here
} }
// IFF aka if and only if they are equivalent, return true. If not, false. // IFF aka if and only if they are equivalent, return true. If not, false.
func (obj *ExecUUID) IFF(uuid ResUUID) bool { func (obj *ExecUID) IFF(uid ResUID) bool {
res, ok := uuid.(*ExecUUID) res, ok := uid.(*ExecUID)
if !ok { if !ok {
return false return false
} }
@@ -389,16 +389,16 @@ func (obj *ExecRes) AutoEdges() AutoEdge {
return nil return nil
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *ExecRes) GetUUIDs() []ResUUID { func (obj *ExecRes) GetUIDs() []ResUID {
x := &ExecUUID{ x := &ExecUID{
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}, BaseUID: BaseUID{name: obj.GetName(), kind: obj.Kind()},
Cmd: obj.Cmd, Cmd: obj.Cmd,
IfCmd: obj.IfCmd, IfCmd: obj.IfCmd,
// TODO: add more params here // TODO: add more params here
} }
return []ResUUID{x} return []ResUID{x}
} }
// GroupCmp returns whether two resources can be grouped together or not. // GroupCmp returns whether two resources can be grouped together or not.

View File

@@ -147,8 +147,8 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -181,7 +181,7 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
if !ok { // channel shutdown if !ok { // channel shutdown
return nil return nil
} }
cuuid.SetConverged(false) cuid.SetConverged(false)
if err := event.Error; err != nil { if err := event.Error; err != nil {
return fmt.Errorf("Unknown %s[%s] watcher error: %v", obj.Kind(), obj.GetName(), err) return fmt.Errorf("Unknown %s[%s] watcher error: %v", obj.Kind(), obj.GetName(), err)
} }
@@ -192,18 +192,18 @@ func (obj *FileRes) Watch(processChan chan event.Event) error {
dirty = true dirty = true
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
//dirty = false // these events don't invalidate state //dirty = false // these events don't invalidate state
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
dirty = true dirty = true
} }
@@ -674,15 +674,15 @@ func (obj *FileRes) CheckApply(apply bool) (checkOK bool, _ error) {
return checkOK, nil // w00t return checkOK, nil // w00t
} }
// FileUUID is the UUID struct for FileRes. // FileUID is the UID struct for FileRes.
type FileUUID struct { type FileUID struct {
BaseUUID BaseUID
path string path string
} }
// IFF aka if and only if they are equivalent, return true. If not, false. // IFF aka if and only if they are equivalent, return true. If not, false.
func (obj *FileUUID) IFF(uuid ResUUID) bool { func (obj *FileUID) IFF(uid ResUID) bool {
res, ok := uuid.(*FileUUID) res, ok := uid.(*FileUID)
if !ok { if !ok {
return false return false
} }
@@ -691,13 +691,13 @@ func (obj *FileUUID) IFF(uuid ResUUID) bool {
// FileResAutoEdges holds the state of the auto edge generator. // FileResAutoEdges holds the state of the auto edge generator.
type FileResAutoEdges struct { type FileResAutoEdges struct {
data []ResUUID data []ResUID
pointer int pointer int
found bool found bool
} }
// Next returns the next automatic edge. // Next returns the next automatic edge.
func (obj *FileResAutoEdges) Next() []ResUUID { func (obj *FileResAutoEdges) Next() []ResUID {
if obj.found { if obj.found {
log.Fatal("Shouldn't be called anymore!") log.Fatal("Shouldn't be called anymore!")
} }
@@ -706,7 +706,7 @@ func (obj *FileResAutoEdges) Next() []ResUUID {
} }
value := obj.data[obj.pointer] value := obj.data[obj.pointer]
obj.pointer++ obj.pointer++
return []ResUUID{value} // we return one, even though api supports N return []ResUID{value} // we return one, even though api supports N
} }
// Test gets results of the earlier Next() call, & returns if we should continue! // Test gets results of the earlier Next() call, & returns if we should continue!
@@ -731,13 +731,13 @@ 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 {
var data []ResUUID // store linear result chain here... var data []ResUID // store linear result chain here...
values := util.PathSplitFullReversed(obj.path) // build it values := util.PathSplitFullReversed(obj.path) // build it
_, values = values[0], values[1:] // get rid of first value which is me! _, 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, &FileUUID{ data = append(data, &FileUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.GetName(), name: obj.GetName(),
kind: obj.Kind(), kind: obj.Kind(),
reversed: &reversed, reversed: &reversed,
@@ -752,14 +752,14 @@ func (obj *FileRes) AutoEdges() AutoEdge {
} }
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *FileRes) GetUUIDs() []ResUUID { func (obj *FileRes) GetUIDs() []ResUID {
x := &FileUUID{ x := &FileUID{
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}, BaseUID: BaseUID{name: obj.GetName(), kind: obj.Kind()},
path: obj.path, path: obj.path,
} }
return []ResUUID{x} return []ResUID{x}
} }
// GroupCmp returns whether two resources can be grouped together or not. // GroupCmp returns whether two resources can be grouped together or not.

View File

@@ -47,9 +47,9 @@ type MsgRes struct {
syslogStateOK bool syslogStateOK bool
} }
// MsgUUID is a unique representation for a MsgRes object. // MsgUID is a unique representation for a MsgRes object.
type MsgUUID struct { type MsgUID struct {
BaseUUID BaseUID
body string body string
} }
@@ -102,8 +102,8 @@ func (obj *MsgRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -120,7 +120,7 @@ func (obj *MsgRes) Watch(processChan chan event.Event) error {
obj.SetState(ResStateWatching) // reset obj.SetState(ResStateWatching) // reset
select { select {
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
// we avoid sending events on unpause // we avoid sending events on unpause
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
@@ -138,12 +138,12 @@ func (obj *MsgRes) Watch(processChan chan event.Event) error {
*/ */
send = true send = true
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
} }
@@ -160,17 +160,17 @@ func (obj *MsgRes) Watch(processChan chan event.Event) error {
} }
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *MsgRes) GetUUIDs() []ResUUID { func (obj *MsgRes) GetUIDs() []ResUID {
x := &MsgUUID{ x := &MsgUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.GetName(), name: obj.GetName(),
kind: obj.Kind(), kind: obj.Kind(),
}, },
body: obj.Body, body: obj.Body,
} }
return []ResUUID{x} return []ResUID{x}
} }
// AutoEdges returns the AutoEdges. In this case none are used. // AutoEdges returns the AutoEdges. In this case none are used.

View File

@@ -66,8 +66,8 @@ func (obj *NoopRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -84,18 +84,18 @@ func (obj *NoopRes) Watch(processChan chan event.Event) error {
obj.SetState(ResStateWatching) // reset obj.SetState(ResStateWatching) // reset
select { select {
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
// we avoid sending events on unpause // we avoid sending events on unpause
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
} }
@@ -118,9 +118,9 @@ func (obj *NoopRes) CheckApply(apply bool) (checkok bool, err error) {
return true, nil // state is always okay return true, nil // state is always okay
} }
// NoopUUID is the UUID struct for NoopRes. // NoopUID is the UID struct for NoopRes.
type NoopUUID struct { type NoopUID struct {
BaseUUID BaseUID
name string name string
} }
@@ -129,14 +129,14 @@ func (obj *NoopRes) AutoEdges() AutoEdge {
return nil return nil
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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) GetUUIDs() []ResUUID { func (obj *NoopRes) GetUIDs() []ResUID {
x := &NoopUUID{ x := &NoopUID{
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}, BaseUID: BaseUID{name: obj.GetName(), kind: obj.Kind()},
name: obj.Name, name: obj.Name,
} }
return []ResUUID{x} return []ResUID{x}
} }
// GroupCmp returns whether two resources can be grouped together or not. // GroupCmp returns whether two resources can be grouped together or not.

View File

@@ -116,8 +116,8 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -151,7 +151,7 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
obj.SetState(ResStateWatching) // reset obj.SetState(ResStateWatching) // reset
select { select {
case event := <-ch: case event := <-ch:
cuuid.SetConverged(false) cuid.SetConverged(false)
// FIXME: ask packagekit for info on what packages changed // FIXME: ask packagekit for info on what packages changed
if global.DEBUG { if global.DEBUG {
@@ -168,18 +168,18 @@ func (obj *PkgRes) Watch(processChan chan event.Event) error {
dirty = true dirty = true
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
dirty = false // these events don't invalidate state dirty = false // these events don't invalidate state
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
dirty = true dirty = true
} }
@@ -362,16 +362,16 @@ func (obj *PkgRes) CheckApply(apply bool) (checkok bool, err error) {
return false, nil // success return false, nil // success
} }
// PkgUUID is the UUID struct for PkgRes. // PkgUID is the UID struct for PkgRes.
type PkgUUID struct { type PkgUID struct {
BaseUUID BaseUID
name string // pkg name name string // pkg name
state string // pkg state or "version" state string // pkg state or "version"
} }
// IFF aka if and only if they are equivalent, return true. If not, false. // IFF aka if and only if they are equivalent, return true. If not, false.
func (obj *PkgUUID) IFF(uuid ResUUID) bool { func (obj *PkgUID) IFF(uid ResUID) bool {
res, ok := uuid.(*PkgUUID) res, ok := uid.(*PkgUID)
if !ok { if !ok {
return false return false
} }
@@ -382,30 +382,30 @@ func (obj *PkgUUID) IFF(uuid ResUUID) bool {
// PkgResAutoEdges holds the state of the auto edge generator. // PkgResAutoEdges holds the state of the auto edge generator.
type PkgResAutoEdges struct { type PkgResAutoEdges struct {
fileList []string fileList []string
svcUUIDs []ResUUID svcUIDs []ResUID
testIsNext bool // safety testIsNext bool // safety
name string // saved data from PkgRes obj name string // saved data from PkgRes obj
kind string kind string
} }
// Next returns the next automatic edge. // Next returns the next automatic edge.
func (obj *PkgResAutoEdges) Next() []ResUUID { func (obj *PkgResAutoEdges) Next() []ResUID {
if obj.testIsNext { if obj.testIsNext {
log.Fatal("Expecting a call to Test()") log.Fatal("Expecting a call to Test()")
} }
obj.testIsNext = true // set after all the errors paths are past obj.testIsNext = true // set after all the errors paths are past
// first return any matching svcUUIDs // first return any matching svcUIDs
if x := obj.svcUUIDs; len(x) > 0 { if x := obj.svcUIDs; len(x) > 0 {
return x return x
} }
var result []ResUUID var result []ResUID
// return UUID's for whatever is in obj.fileList // return UID's for whatever is in obj.fileList
for _, x := range obj.fileList { for _, x := range obj.fileList {
var reversed = false // cheat by passing a pointer var reversed = false // cheat by passing a pointer
result = append(result, &FileUUID{ result = append(result, &FileUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.name, name: obj.name,
kind: obj.kind, kind: obj.kind,
reversed: &reversed, reversed: &reversed,
@@ -422,12 +422,12 @@ func (obj *PkgResAutoEdges) Test(input []bool) bool {
log.Fatal("Expecting a call to Next()") log.Fatal("Expecting a call to Next()")
} }
// ack the svcUUID's... // ack the svcUID's...
if x := obj.svcUUIDs; len(x) > 0 { if x := obj.svcUIDs; len(x) > 0 {
if y := len(x); y != len(input) { if y := len(x); y != len(input) {
log.Fatalf("Expecting %d value(s)!", y) log.Fatalf("Expecting %d value(s)!", y)
} }
obj.svcUUIDs = []ResUUID{} // empty obj.svcUIDs = []ResUID{} // empty
obj.testIsNext = false obj.testIsNext = false
return true return true
} }
@@ -475,37 +475,37 @@ func (obj *PkgRes) AutoEdges() AutoEdge {
// is contained in the Test() method! This design is completely okay! // is contained in the Test() method! This design is completely okay!
// add matches for any svc resources found in pkg definition! // add matches for any svc resources found in pkg definition!
var svcUUIDs []ResUUID var svcUIDs []ResUID
for _, x := range ReturnSvcInFileList(obj.fileList) { for _, x := range ReturnSvcInFileList(obj.fileList) {
var reversed = false var reversed = false
svcUUIDs = append(svcUUIDs, &SvcUUID{ svcUIDs = append(svcUIDs, &SvcUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.GetName(), name: obj.GetName(),
kind: obj.Kind(), kind: obj.Kind(),
reversed: &reversed, reversed: &reversed,
}, },
name: x, // the svc name itself in the SvcUUID object! name: x, // the svc name itself in the SvcUID object!
}) // build list }) // build list
} }
return &PkgResAutoEdges{ return &PkgResAutoEdges{
fileList: util.RemoveCommonFilePrefixes(obj.fileList), // clean start! fileList: util.RemoveCommonFilePrefixes(obj.fileList), // clean start!
svcUUIDs: svcUUIDs, svcUIDs: svcUIDs,
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.Kind(), kind: obj.Kind(),
} }
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *PkgRes) GetUUIDs() []ResUUID { func (obj *PkgRes) GetUIDs() []ResUID {
x := &PkgUUID{ x := &PkgUID{
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}, BaseUID: BaseUID{name: obj.GetName(), kind: obj.Kind()},
name: obj.Name, name: obj.Name,
state: obj.State, state: obj.State,
} }
result := []ResUUID{x} result := []ResUID{x}
return result return result
} }

View File

@@ -45,17 +45,17 @@ const (
ResStatePoking ResStatePoking
) )
// ResUUID is a unique identifier for a resource, namely it's name, and the kind ("type"). // ResUID is a unique identifier for a resource, namely it's name, and the kind ("type").
type ResUUID interface { type ResUID interface {
GetName() string GetName() string
Kind() string Kind() string
IFF(ResUUID) bool IFF(ResUID) bool
Reversed() bool // true means this resource happens before the generator Reversed() bool // true means this resource happens before the generator
} }
// The BaseUUID struct is used to provide a unique resource identifier. // The BaseUID struct is used to provide a unique resource identifier.
type BaseUUID struct { type BaseUID struct {
name string // name and kind are the values of where this is coming from name string // name and kind are the values of where this is coming from
kind string kind string
@@ -64,7 +64,7 @@ type BaseUUID struct {
// The AutoEdge interface is used to implement the autoedges feature. // The AutoEdge interface is used to implement the autoedges feature.
type AutoEdge interface { type AutoEdge interface {
Next() []ResUUID // call to get list of edges to add Next() []ResUID // call to get list of edges to add
Test([]bool) bool // call until false Test([]bool) bool // call until false
} }
@@ -110,7 +110,7 @@ type Res interface {
Base // include everything from the Base interface Base // include everything from the Base interface
Init() error Init() error
//Validate() error // TODO: this might one day be added //Validate() error // TODO: this might one day be added
GetUUIDs() []ResUUID // most resources only return one GetUIDs() []ResUID // most resources only return one
Watch(chan event.Event) error // send on channel to signal process() events Watch(chan event.Event) 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
@@ -132,10 +132,10 @@ type BaseRes struct {
grouped []Res // list of any grouped resources grouped []Res // list of any grouped resources
} }
// UUIDExistsInUUIDs wraps the IFF method when used with a list of UUID's. // UIDExistsInUIDs wraps the IFF method when used with a list of UID's.
func UUIDExistsInUUIDs(uuid ResUUID, uuids []ResUUID) bool { func UIDExistsInUIDs(uid ResUID, uids []ResUID) bool {
for _, u := range uuids { for _, u := range uids {
if uuid.IFF(u) { if uid.IFF(u) {
return true return true
} }
} }
@@ -143,30 +143,30 @@ func UUIDExistsInUUIDs(uuid ResUUID, uuids []ResUUID) bool {
} }
// GetName returns the name of the resource. // GetName returns the name of the resource.
func (obj *BaseUUID) GetName() string { func (obj *BaseUID) GetName() string {
return obj.name return obj.name
} }
// Kind returns the kind of resource. // Kind returns the kind of resource.
func (obj *BaseUUID) Kind() string { func (obj *BaseUID) Kind() string {
return obj.kind return obj.kind
} }
// IFF looks at two UUID's and if and only if they are equivalent, returns true. // IFF looks at two UID's and if and only if they are equivalent, returns true.
// If they are not equivalent, it returns false. // If they are not equivalent, it returns false.
// Most resources will want to override this method, since it does the important // Most resources will want to override this method, since it does the important
// work of actually discerning if two resources are identical in function. // work of actually discerning if two resources are identical in function.
func (obj *BaseUUID) IFF(uuid ResUUID) bool { func (obj *BaseUID) IFF(uid ResUID) bool {
res, ok := uuid.(*BaseUUID) res, ok := uid.(*BaseUID)
if !ok { if !ok {
return false return false
} }
return obj.name == res.name return obj.name == res.name
} }
// Reversed is part of the ResUUID interface, and true means this resource // Reversed is part of the ResUID interface, and true means this resource
// happens before the generator. // happens before the generator.
func (obj *BaseUUID) Reversed() bool { func (obj *BaseUID) Reversed() bool {
if obj.reversed == nil { if obj.reversed == nil {
log.Fatal("Programming error!") log.Fatal("Programming error!")
} }
@@ -256,7 +256,7 @@ func (obj *BaseRes) DoSend(processChan chan event.Event, comment string) (bool,
// } // }
//case event := <-obj.events: //case event := <-obj.events:
// // NOTE: this code should match the similar code below! // // NOTE: this code should match the similar code below!
// //cuuid.SetConverged(false) // TODO: ? // //cuid.SetConverged(false) // TODO: ?
// if exit, send := obj.ReadEvent(&event); exit { // if exit, send := obj.ReadEvent(&event); exit {
// return true, nil // exit, without error // return true, nil // exit, without error
// } else if send { // } else if send {

View File

@@ -105,16 +105,16 @@ func TestMiscEncodeDecode2(t *testing.T) {
} }
func TestIFF(t *testing.T) { func TestIFF(t *testing.T) {
uuid := &BaseUUID{name: "/tmp/unit-test"} uid := &BaseUID{name: "/tmp/unit-test"}
same := &BaseUUID{name: "/tmp/unit-test"} same := &BaseUID{name: "/tmp/unit-test"}
diff := &BaseUUID{name: "/tmp/other-file"} diff := &BaseUID{name: "/tmp/other-file"}
if !uuid.IFF(same) { if !uid.IFF(same) {
t.Error("basic resource UUIDs with the same name should satisfy each other's IFF condition.") t.Error("basic resource UIDs with the same name should satisfy each other's IFF condition.")
} }
if uuid.IFF(diff) { if uid.IFF(diff) {
t.Error("basic resource UUIDs with different names should NOT satisfy each other's IFF condition.") t.Error("basic resource UIDs with different names should NOT satisfy each other's IFF condition.")
} }
} }

View File

@@ -82,8 +82,8 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -164,12 +164,12 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
obj.SetState(ResStateWatching) // reset obj.SetState(ResStateWatching) // reset
select { select {
case <-buschan: // XXX: wait for new units event to unstick case <-buschan: // XXX: wait for new units event to unstick
cuuid.SetConverged(false) cuid.SetConverged(false)
// loop so that we can see the changed invalid signal // loop so that we can see the changed invalid signal
log.Printf("Svc[%v]->DaemonReload()", svc) log.Printf("Svc[%v]->DaemonReload()", svc)
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
@@ -177,12 +177,12 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
dirty = true dirty = true
} }
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
dirty = true dirty = true
} }
@@ -220,11 +220,11 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
dirty = true dirty = true
case err := <-subErrors: case err := <-subErrors:
cuuid.SetConverged(false) cuid.SetConverged(false)
return fmt.Errorf("Unknown %s[%s] error: %v", obj.Kind(), obj.GetName(), err) return fmt.Errorf("Unknown %s[%s] error: %v", obj.Kind(), obj.GetName(), err)
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, send = obj.ReadEvent(&event); exit { if exit, send = obj.ReadEvent(&event); exit {
return nil // exit return nil // exit
} }
@@ -232,12 +232,12 @@ func (obj *SvcRes) Watch(processChan chan event.Event) error {
dirty = true dirty = true
} }
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) // converged! cuid.SetConverged(true) // converged!
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
dirty = true dirty = true
} }
@@ -352,19 +352,19 @@ func (obj *SvcRes) CheckApply(apply bool) (checkok bool, err error) {
return false, nil // success return false, nil // success
} }
// SvcUUID is the UUID struct for SvcRes. // SvcUID is the UID struct for SvcRes.
type SvcUUID struct { type SvcUID struct {
// NOTE: there is also a name variable in the BaseUUID struct, this is // NOTE: there is also a name variable in the BaseUID struct, this is
// information about where this UUID came from, and is unrelated to the // information about where this UID came from, and is unrelated to the
// information about the resource we're matching. That data which is // information about the resource we're matching. That data which is
// used in the IFF function, is what you see in the struct fields here. // used in the IFF function, is what you see in the struct fields here.
BaseUUID BaseUID
name string // the svc name name string // the svc name
} }
// IFF aka if and only if they are equivalent, return true. If not, false. // IFF aka if and only if they are equivalent, return true. If not, false.
func (obj *SvcUUID) IFF(uuid ResUUID) bool { func (obj *SvcUID) IFF(uid ResUID) bool {
res, ok := uuid.(*SvcUUID) res, ok := uid.(*SvcUID)
if !ok { if !ok {
return false return false
} }
@@ -373,13 +373,13 @@ func (obj *SvcUUID) IFF(uuid ResUUID) bool {
// SvcResAutoEdges holds the state of the auto edge generator. // SvcResAutoEdges holds the state of the auto edge generator.
type SvcResAutoEdges struct { type SvcResAutoEdges struct {
data []ResUUID data []ResUID
pointer int pointer int
found bool found bool
} }
// Next returns the next automatic edge. // Next returns the next automatic edge.
func (obj *SvcResAutoEdges) Next() []ResUUID { func (obj *SvcResAutoEdges) Next() []ResUID {
if obj.found { if obj.found {
log.Fatal("Shouldn't be called anymore!") log.Fatal("Shouldn't be called anymore!")
} }
@@ -388,7 +388,7 @@ func (obj *SvcResAutoEdges) Next() []ResUUID {
} }
value := obj.data[obj.pointer] value := obj.data[obj.pointer]
obj.pointer++ obj.pointer++
return []ResUUID{value} // we return one, even though api supports N return []ResUID{value} // we return one, even though api supports N
} }
// Test gets results of the earlier Next() call, & returns if we should continue! // Test gets results of the earlier Next() call, & returns if we should continue!
@@ -412,15 +412,15 @@ 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 {
var data []ResUUID 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
fmt.Sprintf("/usr/lib/systemd/system/%s.service", obj.Name), // pkg default fmt.Sprintf("/usr/lib/systemd/system/%s.service", obj.Name), // pkg default
} }
for _, x := range svcFiles { for _, x := range svcFiles {
var reversed = true var reversed = true
data = append(data, &FileUUID{ data = append(data, &FileUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.GetName(), name: obj.GetName(),
kind: obj.Kind(), kind: obj.Kind(),
reversed: &reversed, reversed: &reversed,
@@ -435,14 +435,14 @@ func (obj *SvcRes) AutoEdges() AutoEdge {
} }
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *SvcRes) GetUUIDs() []ResUUID { func (obj *SvcRes) GetUIDs() []ResUID {
x := &SvcUUID{ x := &SvcUID{
BaseUUID: BaseUUID{name: obj.GetName(), kind: obj.Kind()}, BaseUID: BaseUID{name: obj.GetName(), kind: obj.Kind()},
name: obj.Name, // svc name name: obj.Name, // svc name
} }
return []ResUUID{x} return []ResUID{x}
} }
// GroupCmp returns whether two resources can be grouped together or not. // GroupCmp returns whether two resources can be grouped together or not.

View File

@@ -35,9 +35,9 @@ type TimerRes struct {
Interval int `yaml:"interval"` // Interval : Interval between runs Interval int `yaml:"interval"` // Interval : Interval between runs
} }
// TimerUUID is the UUID struct for TimerRes. // TimerUID is the UID struct for TimerRes.
type TimerUUID struct { type TimerUID struct {
BaseUUID BaseUID
name string name string
} }
@@ -73,8 +73,8 @@ func (obj *TimerRes) Watch(processChan chan event.Event) error {
} }
obj.SetWatching(true) obj.SetWatching(true)
defer obj.SetWatching(false) defer obj.SetWatching(false)
cuuid := obj.converger.Register() cuid := obj.converger.Register()
defer cuuid.Unregister() defer cuid.Unregister()
var startup bool var startup bool
Startup := func(block bool) <-chan time.Time { Startup := func(block bool) <-chan time.Time {
@@ -98,16 +98,16 @@ func (obj *TimerRes) Watch(processChan chan event.Event) error {
send = true send = true
log.Printf("%v[%v]: received tick", obj.Kind(), obj.GetName()) log.Printf("%v[%v]: received tick", obj.Kind(), obj.GetName())
case event := <-obj.events: case event := <-obj.events:
cuuid.SetConverged(false) cuid.SetConverged(false)
if exit, _ := obj.ReadEvent(&event); exit { if exit, _ := obj.ReadEvent(&event); exit {
return nil return nil
} }
case <-cuuid.ConvergedTimer(): case <-cuid.ConvergedTimer():
cuuid.SetConverged(true) cuid.SetConverged(true)
continue continue
case <-Startup(startup): case <-Startup(startup):
cuuid.SetConverged(false) cuid.SetConverged(false)
send = true send = true
} }
if send { if send {
@@ -121,17 +121,17 @@ func (obj *TimerRes) Watch(processChan chan event.Event) error {
} }
} }
// GetUUIDs includes all params to make a unique identification of this object. // GetUIDs 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 *TimerRes) GetUUIDs() []ResUUID { func (obj *TimerRes) GetUIDs() []ResUID {
x := &TimerUUID{ x := &TimerUID{
BaseUUID: BaseUUID{ BaseUID: BaseUID{
name: obj.GetName(), name: obj.GetName(),
kind: obj.Kind(), kind: obj.Kind(),
}, },
name: obj.Name, name: obj.Name,
} }
return []ResUUID{x} return []ResUID{x}
} }
// AutoEdges returns the AutoEdge interface. In this case no autoedges are used. // AutoEdges returns the AutoEdge interface. In this case no autoedges are used.