engine: graph, resources: Change Watch to use ctx
This is a general port. There are many optimizations and cleanups we can do now that we have a proper context passed in. That's for a future patch.
This commit is contained in:
@@ -277,7 +277,7 @@ will likely find the state to now be correct.
|
|||||||
### Watch
|
### Watch
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
Watch() error
|
Watch(ctx context.Context) error
|
||||||
```
|
```
|
||||||
|
|
||||||
`Watch` is a main loop that runs and sends messages when it detects that the
|
`Watch` is a main loop that runs and sends messages when it detects that the
|
||||||
@@ -304,23 +304,25 @@ If the resource is activated in `polling` mode, the `Watch` method will not get
|
|||||||
executed. As a result, the resource must still work even if the main loop is not
|
executed. As a result, the resource must still work even if the main loop is not
|
||||||
running.
|
running.
|
||||||
|
|
||||||
|
You must make sure to cleanup any running code or goroutines before Watch exits.
|
||||||
|
|
||||||
#### Select
|
#### Select
|
||||||
|
|
||||||
The lifetime of most resources `Watch` method should be spent in an infinite
|
The lifetime of most resources `Watch` method should be spent in an infinite
|
||||||
loop that is bounded by a `select` call. The `select` call is the point where
|
loop that is bounded by a `select` call. The `select` call is the point where
|
||||||
our method hands back control to the engine (and the kernel) so that we can
|
our method hands back control to the engine (and the kernel) so that we can
|
||||||
sleep until something of interest wakes us up. In this loop we must wait until
|
sleep until something of interest wakes us up. In this loop we must wait until
|
||||||
we get a shutdown event from the engine via the `<-obj.init.Done` channel, which
|
we get a shutdown event from the engine via the `<-ctx.Done()` channel, which
|
||||||
closes when we'd like to shut everything down. At this point you should cleanup,
|
closes when we'd like to shut everything down. At this point you should cleanup,
|
||||||
and let `Watch` close.
|
and let `Watch` close.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
If the `<-obj.init.Done` channel closes, we should shutdown our resource. When
|
If the `<-ctx.Done()` channel closes, we should shutdown our resource. When we
|
||||||
When we want to send an event, we use the `Event` helper function. This
|
want to send an event, we use the `Event` helper function. This automatically
|
||||||
automatically marks the resource state as `dirty`. If you're unsure, it's not
|
marks the resource state as `dirty`. If you're unsure, it's not harmful to send
|
||||||
harmful to send the event. This will ultimately cause `CheckApply` to run. This
|
the event. This will ultimately cause `CheckApply` to run. This method can block
|
||||||
method can block if the resource is being paused.
|
if the resource is being paused.
|
||||||
|
|
||||||
#### Startup
|
#### Startup
|
||||||
|
|
||||||
@@ -347,7 +349,7 @@ sending out erroneous `Event` messages to keep things alive until it finishes.
|
|||||||
|
|
||||||
```golang
|
```golang
|
||||||
// Watch is the listener and main loop for this resource.
|
// Watch is the listener and main loop for this resource.
|
||||||
func (obj *FooRes) Watch() error {
|
func (obj *FooRes) Watch(ctx context.Context) error {
|
||||||
// setup the Foo resource
|
// setup the Foo resource
|
||||||
var err error
|
var err error
|
||||||
if err, obj.foo = OpenFoo(); err != nil {
|
if err, obj.foo = OpenFoo(); err != nil {
|
||||||
@@ -371,7 +373,7 @@ func (obj *FooRes) Watch() error {
|
|||||||
case err := <-obj.foo.Errors:
|
case err := <-obj.foo.Errors:
|
||||||
return err // will cause a retry or permanent failure
|
return err // will cause a retry or permanent failure
|
||||||
|
|
||||||
case <-obj.init.Done: // signal for shutdown request
|
case <-ctx.Done(): // signal for shutdown request
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,11 +555,6 @@ ready to detect changes.
|
|||||||
Event sends an event notifying the engine of a possible state change. It is
|
Event sends an event notifying the engine of a possible state change. It is
|
||||||
only called from within `Watch`.
|
only called from within `Watch`.
|
||||||
|
|
||||||
### Done
|
|
||||||
|
|
||||||
Done is a channel that closes when the engine wants us to shutdown. It is only
|
|
||||||
called from within `Watch`.
|
|
||||||
|
|
||||||
### Refresh
|
### Refresh
|
||||||
|
|
||||||
Refresh returns whether the resource received a notification. This flag can be
|
Refresh returns whether the resource received a notification. This flag can be
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ func (obj *Engine) Worker(vertex pgraph.Vertex) error {
|
|||||||
case <-timer.C: // the wait is over
|
case <-timer.C: // the wait is over
|
||||||
return errDelayExpired // special
|
return errDelayExpired // special
|
||||||
|
|
||||||
case <-obj.state[vertex].init.DoneCtx.Done():
|
case <-obj.state[vertex].doneCtx.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,12 +319,12 @@ func (obj *Engine) Worker(vertex pgraph.Vertex) error {
|
|||||||
}
|
}
|
||||||
} else if interval := res.MetaParams().Poll; interval > 0 { // poll instead of watching :(
|
} else if interval := res.MetaParams().Poll; interval > 0 { // poll instead of watching :(
|
||||||
obj.state[vertex].cuid.StartTimer()
|
obj.state[vertex].cuid.StartTimer()
|
||||||
err = obj.state[vertex].poll(interval)
|
err = obj.state[vertex].poll(obj.state[vertex].doneCtx, interval)
|
||||||
obj.state[vertex].cuid.StopTimer() // clean up nicely
|
obj.state[vertex].cuid.StopTimer() // clean up nicely
|
||||||
} else {
|
} else {
|
||||||
obj.state[vertex].cuid.StartTimer()
|
obj.state[vertex].cuid.StartTimer()
|
||||||
obj.Logf("Watch(%s)", vertex)
|
obj.Logf("Watch(%s)", vertex)
|
||||||
err = res.Watch() // run the watch normally
|
err = res.Watch(obj.state[vertex].doneCtx) // run the watch normally
|
||||||
obj.Logf("Watch(%s): Exited(%+v)", vertex, err)
|
obj.Logf("Watch(%s): Exited(%+v)", vertex, err)
|
||||||
obj.state[vertex].cuid.StopTimer() // clean up nicely
|
obj.state[vertex].cuid.StopTimer() // clean up nicely
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package autogroup
|
package autogroup
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -66,7 +67,7 @@ func (obj *NoopResTest) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *NoopResTest) Watch() error {
|
func (obj *NoopResTest) Watch(context.Context) error {
|
||||||
return nil // not needed
|
return nil // not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ func (obj *State) Init() error {
|
|||||||
// Watch:
|
// Watch:
|
||||||
Running: obj.event,
|
Running: obj.event,
|
||||||
Event: obj.event,
|
Event: obj.event,
|
||||||
DoneCtx: obj.doneCtx,
|
|
||||||
|
|
||||||
// CheckApply:
|
// CheckApply:
|
||||||
Refresh: func() bool {
|
Refresh: func() bool {
|
||||||
@@ -393,7 +392,7 @@ func (obj *State) setDirty() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// poll is a replacement for Watch when the Poll metaparameter is used.
|
// poll is a replacement for Watch when the Poll metaparameter is used.
|
||||||
func (obj *State) poll(interval uint32) error {
|
func (obj *State) poll(ctx context.Context, interval uint32) error {
|
||||||
// create a time.Ticker for the given interval
|
// create a time.Ticker for the given interval
|
||||||
ticker := time.NewTicker(time.Duration(interval) * time.Second)
|
ticker := time.NewTicker(time.Duration(interval) * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
@@ -405,7 +404,7 @@ func (obj *State) poll(interval uint32) error {
|
|||||||
case <-ticker.C: // received the timer event
|
case <-ticker.C: // received the timer event
|
||||||
obj.init.Logf("polling...")
|
obj.init.Logf("polling...")
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // signal for shutdown request
|
case <-ctx.Done(): // signal for shutdown request
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,11 +102,6 @@ type Init struct {
|
|||||||
// Event sends an event notifying the engine of a possible state change.
|
// Event sends an event notifying the engine of a possible state change.
|
||||||
Event func()
|
Event func()
|
||||||
|
|
||||||
// DoneCtx returns a context that will cancel to signal to us that it's
|
|
||||||
// time for us to shutdown.
|
|
||||||
// TODO: this is temporary until Watch supports context directly.
|
|
||||||
DoneCtx context.Context
|
|
||||||
|
|
||||||
// Called from within CheckApply:
|
// Called from within CheckApply:
|
||||||
|
|
||||||
// Refresh returns whether the resource received a notification. This
|
// Refresh returns whether the resource received a notification. This
|
||||||
@@ -200,8 +195,8 @@ type Res interface {
|
|||||||
|
|
||||||
// Watch is run by the engine to monitor for state changes. If it
|
// Watch is run by the engine to monitor for state changes. If it
|
||||||
// detects any, it notifies the engine which will usually run CheckApply
|
// detects any, it notifies the engine which will usually run CheckApply
|
||||||
// in response.
|
// in response. If the input context cancels, we must shutdown.
|
||||||
Watch() error
|
Watch(context.Context) error
|
||||||
|
|
||||||
// CheckApply determines if the state of the resource is correct and if
|
// CheckApply determines if the state of the resource is correct and if
|
||||||
// asked to with the `apply` variable, applies the requested state.
|
// asked to with the `apply` variable, applies the requested state.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -125,7 +126,7 @@ func (obj *AugeasRes) Close() error {
|
|||||||
// Watch is the primary listener for this resource and it outputs events. This
|
// Watch is the primary listener for this resource and it outputs events. This
|
||||||
// was taken from the File resource.
|
// was taken from the File resource.
|
||||||
// FIXME: DRY - This is taken from the file resource
|
// FIXME: DRY - This is taken from the file resource
|
||||||
func (obj *AugeasRes) Watch() error {
|
func (obj *AugeasRes) Watch(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
obj.recWatcher, err = recwatch.NewRecWatcher(obj.File, false)
|
obj.recWatcher, err = recwatch.NewRecWatcher(obj.File, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -154,7 +155,7 @@ func (obj *AugeasRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -409,16 +409,16 @@ func (obj *AwsEc2Res) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *AwsEc2Res) Watch() error {
|
func (obj *AwsEc2Res) Watch(ctx context.Context) error {
|
||||||
if obj.WatchListenAddr != "" {
|
if obj.WatchListenAddr != "" {
|
||||||
return obj.snsWatch()
|
return obj.snsWatch(ctx)
|
||||||
}
|
}
|
||||||
return obj.longpollWatch()
|
return obj.longpollWatch(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// longpollWatch uses the ec2 api's built in methods to watch ec2 resource
|
// longpollWatch uses the ec2 api's built in methods to watch ec2 resource
|
||||||
// state.
|
// state.
|
||||||
func (obj *AwsEc2Res) longpollWatch() error {
|
func (obj *AwsEc2Res) longpollWatch(ctx context.Context) error {
|
||||||
send := false
|
send := false
|
||||||
|
|
||||||
// We tell the engine that we're running right away. This is not correct,
|
// We tell the engine that we're running right away. This is not correct,
|
||||||
@@ -426,7 +426,7 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
// cancellable context used for exiting cleanly
|
// cancellable context used for exiting cleanly
|
||||||
ctx, cancel := context.WithCancel(context.TODO())
|
innerCtx, cancel := context.WithCancel(context.TODO())
|
||||||
|
|
||||||
// clean up when we're done
|
// clean up when we're done
|
||||||
defer obj.wg.Wait()
|
defer obj.wg.Wait()
|
||||||
@@ -461,7 +461,7 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait for the instance state to change
|
// wait for the instance state to change
|
||||||
state, err := stateWaiter(ctx, instance, obj.client)
|
state, err := stateWaiter(innerCtx, instance, obj.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
select {
|
select {
|
||||||
case obj.awsChan <- &chanStruct{
|
case obj.awsChan <- &chanStruct{
|
||||||
@@ -502,7 +502,7 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +518,7 @@ func (obj *AwsEc2Res) longpollWatch() error {
|
|||||||
// Init() a CloudWatch rule is created along with a corresponding SNS topic that
|
// Init() a CloudWatch rule is created along with a corresponding SNS topic that
|
||||||
// it can publish to. snsWatch creates an http server which listens for messages
|
// it can publish to. snsWatch creates an http server which listens for messages
|
||||||
// published to the topic and processes them accordingly.
|
// published to the topic and processes them accordingly.
|
||||||
func (obj *AwsEc2Res) snsWatch() error {
|
func (obj *AwsEc2Res) snsWatch(ctx context.Context) error {
|
||||||
send := false
|
send := false
|
||||||
defer obj.wg.Wait()
|
defer obj.wg.Wait()
|
||||||
// create the sns listener
|
// create the sns listener
|
||||||
@@ -533,9 +533,9 @@ func (obj *AwsEc2Res) snsWatch() error {
|
|||||||
}
|
}
|
||||||
// close the listener and shutdown the sns server when we're done
|
// close the listener and shutdown the sns server when we're done
|
||||||
defer func() {
|
defer func() {
|
||||||
ctx, cancel := context.WithTimeout(context.TODO(), SnsServerShutdownTimeout*time.Second)
|
innerCtx, cancel := context.WithTimeout(context.TODO(), SnsServerShutdownTimeout*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := snsServer.Shutdown(ctx); err != nil {
|
if err := snsServer.Shutdown(innerCtx); err != nil {
|
||||||
if err != context.Canceled {
|
if err != context.Canceled {
|
||||||
obj.init.Logf("error stopping sns endpoint: %s", err)
|
obj.init.Logf("error stopping sns endpoint: %s", err)
|
||||||
return
|
return
|
||||||
@@ -596,7 +596,7 @@ func (obj *AwsEc2Res) snsWatch() error {
|
|||||||
obj.init.Logf("State: %v", msg.event)
|
obj.init.Logf("State: %v", msg.event)
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,7 +718,7 @@ func (obj *AwsEc2Res) CheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// context to cancel the waiter if it takes too long
|
// context to cancel the waiter if it takes too long
|
||||||
ctx, cancel := context.WithTimeout(context.TODO(), waitTimeout*time.Second)
|
innerCtx, cancel := context.WithTimeout(context.TODO(), waitTimeout*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// wait until the state converges
|
// wait until the state converges
|
||||||
@@ -727,11 +727,11 @@ func (obj *AwsEc2Res) CheckApply(apply bool) (bool, error) {
|
|||||||
}
|
}
|
||||||
switch obj.State {
|
switch obj.State {
|
||||||
case ec2.InstanceStateNameRunning:
|
case ec2.InstanceStateNameRunning:
|
||||||
err = obj.client.WaitUntilInstanceRunningWithContext(ctx, waitInput)
|
err = obj.client.WaitUntilInstanceRunningWithContext(innerCtx, waitInput)
|
||||||
case ec2.InstanceStateNameStopped:
|
case ec2.InstanceStateNameStopped:
|
||||||
err = obj.client.WaitUntilInstanceStoppedWithContext(ctx, waitInput)
|
err = obj.client.WaitUntilInstanceStoppedWithContext(innerCtx, waitInput)
|
||||||
case ec2.InstanceStateNameTerminated:
|
case ec2.InstanceStateNameTerminated:
|
||||||
err = obj.client.WaitUntilInstanceTerminatedWithContext(ctx, waitInput)
|
err = obj.client.WaitUntilInstanceTerminatedWithContext(innerCtx, waitInput)
|
||||||
default:
|
default:
|
||||||
return false, errwrap.Wrapf(err, "unrecognized instance state")
|
return false, errwrap.Wrapf(err, "unrecognized instance state")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,11 +95,11 @@ func (obj *ConfigEtcdRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *ConfigEtcdRes) Watch() error {
|
func (obj *ConfigEtcdRes) Watch(ctx context.Context) error {
|
||||||
obj.wg.Add(1)
|
obj.wg.Add(1)
|
||||||
defer obj.wg.Done()
|
defer obj.wg.Done()
|
||||||
// FIXME: add timeout to context
|
// FIXME: add timeout to context
|
||||||
ctx, cancel := context.WithCancel(obj.init.DoneCtx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
ch, err := obj.init.World.IdealClusterSizeWatch(util.CtxWithWg(ctx, obj.wg))
|
ch, err := obj.init.World.IdealClusterSizeWatch(util.CtxWithWg(ctx, obj.wg))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -120,7 +120,7 @@ Loop:
|
|||||||
}
|
}
|
||||||
// pass through and send an event
|
// pass through and send an event
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.init.Event() // notify engine of an event (this can block)
|
obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func (obj *ConsulKVRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the listener and main loop for this resource and it outputs events.
|
// Watch is the listener and main loop for this resource and it outputs events.
|
||||||
func (obj *ConsulKVRes) Watch() error {
|
func (obj *ConsulKVRes) Watch(ctx context.Context) error {
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
defer wg.Wait()
|
defer wg.Wait()
|
||||||
|
|
||||||
@@ -132,9 +132,9 @@ func (obj *ConsulKVRes) Watch() error {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
opts := &api.QueryOptions{RequireConsistent: true}
|
opts := &api.QueryOptions{RequireConsistent: true}
|
||||||
ctx, cancel := util.ContextWithCloser(context.Background(), exit)
|
innerCtx, cancel := util.ContextWithCloser(context.Background(), exit)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
opts = opts.WithContext(ctx)
|
opts = opts.WithContext(innerCtx)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_, meta, err := kv.Get(obj.key, opts)
|
_, meta, err := kv.Get(obj.key, opts)
|
||||||
@@ -162,10 +162,10 @@ func (obj *ConsulKVRes) Watch() error {
|
|||||||
// Unexpected situation, bug in consul API...
|
// Unexpected situation, bug in consul API...
|
||||||
select {
|
select {
|
||||||
case ch <- fmt.Errorf("unexpected behaviour in Consul API"):
|
case ch <- fmt.Errorf("unexpected behaviour in Consul API"):
|
||||||
case <-obj.init.DoneCtx.Done(): // signal for shutdown request
|
case <-ctx.Done(): // signal for shutdown request
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // signal for shutdown request
|
case <-ctx.Done(): // signal for shutdown request
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ func (obj *ConsulKVRes) Watch() error {
|
|||||||
}
|
}
|
||||||
obj.init.Event()
|
obj.init.Event()
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // signal for shutdown request
|
case <-ctx.Done(): // signal for shutdown request
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ func (obj *CronRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch for state changes and sends a message to the bus if there is a change.
|
// Watch for state changes and sends a message to the bus if there is a change.
|
||||||
func (obj *CronRes) Watch() error {
|
func (obj *CronRes) Watch(ctx context.Context) error {
|
||||||
var bus *dbus.Conn
|
var bus *dbus.Conn
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ func (obj *CronRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// do all our event sending all together to avoid duplicate msgs
|
// do all our event sending all together to avoid duplicate msgs
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -385,7 +386,7 @@ func (obj *DHCPServerRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *DHCPServerRes) Watch() error {
|
func (obj *DHCPServerRes) Watch(ctx context.Context) error {
|
||||||
addr, err := net.ResolveUDPAddr("udp", obj.getAddress()) // *net.UDPAddr
|
addr, err := net.ResolveUDPAddr("udp", obj.getAddress()) // *net.UDPAddr
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf(err, "could not resolve address")
|
return errwrap.Wrapf(err, "could not resolve address")
|
||||||
@@ -461,7 +462,7 @@ func (obj *DHCPServerRes) Watch() error {
|
|||||||
case <-closeSignal: // something shut us down early
|
case <-closeSignal: // something shut us down early
|
||||||
return closeError
|
return closeError
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,11 +1053,11 @@ func (obj *DHCPHostRes) Close() error {
|
|||||||
// Watch is the primary listener for this resource and it outputs events. This
|
// Watch is the primary listener for this resource and it outputs events. This
|
||||||
// particular one does absolutely nothing but block until we've received a done
|
// particular one does absolutely nothing but block until we've received a done
|
||||||
// signal.
|
// signal.
|
||||||
func (obj *DHCPHostRes) Watch() error {
|
func (obj *DHCPHostRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -170,11 +170,11 @@ func (obj *DockerContainerRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *DockerContainerRes) Watch() error {
|
func (obj *DockerContainerRes) Watch(ctx context.Context) error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
innerCtx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
eventChan, errChan := obj.client.Events(ctx, types.EventsOptions{})
|
eventChan, errChan := obj.client.Events(innerCtx, types.EventsOptions{})
|
||||||
|
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ func (obj *DockerContainerRes) Watch() error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,11 +131,11 @@ func (obj *DockerImageRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *DockerImageRes) Watch() error {
|
func (obj *DockerImageRes) Watch(ctx context.Context) error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
innerCtx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
eventChan, errChan := obj.client.Events(ctx, types.EventsOptions{})
|
eventChan, errChan := obj.client.Events(innerCtx, types.EventsOptions{})
|
||||||
|
|
||||||
// notify engine that we're running
|
// notify engine that we're running
|
||||||
obj.init.Running()
|
obj.init.Running()
|
||||||
@@ -158,7 +158,7 @@ func (obj *DockerImageRes) Watch() error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ func (obj *ExecRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *ExecRes) Watch() error {
|
func (obj *ExecRes) Watch(ctx context.Context) error {
|
||||||
ioChan := make(chan *cmdOutput)
|
ioChan := make(chan *cmdOutput)
|
||||||
defer obj.wg.Wait()
|
defer obj.wg.Wait()
|
||||||
|
|
||||||
@@ -187,9 +187,9 @@ func (obj *ExecRes) Watch() error {
|
|||||||
cmdArgs = []string{"-c", obj.WatchCmd}
|
cmdArgs = []string{"-c", obj.WatchCmd}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
innerCtx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cmd := exec.CommandContext(ctx, cmdName, cmdArgs...)
|
cmd := exec.CommandContext(innerCtx, cmdName, cmdArgs...)
|
||||||
cmd.Dir = obj.WatchCwd // run program in pwd if ""
|
cmd.Dir = obj.WatchCwd // run program in pwd if ""
|
||||||
// ignore signals sent to parent process (we're in our own group)
|
// ignore signals sent to parent process (we're in our own group)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
@@ -203,7 +203,7 @@ func (obj *ExecRes) Watch() error {
|
|||||||
return errwrap.Wrapf(err, "error while setting credential")
|
return errwrap.Wrapf(err, "error while setting credential")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ioChan, err = obj.cmdOutputRunner(ctx, cmd); err != nil {
|
if ioChan, err = obj.cmdOutputRunner(innerCtx, cmd); err != nil {
|
||||||
return errwrap.Wrapf(err, "error starting WatchCmd")
|
return errwrap.Wrapf(err, "error starting WatchCmd")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,7 +252,7 @@ func (obj *ExecRes) Watch() error {
|
|||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package resources
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -359,7 +360,7 @@ func (obj *FileRes) Close() error {
|
|||||||
// probably important to write some test cases first! If the Watch returns an
|
// probably important to write some test cases first! If the Watch returns an
|
||||||
// error, it means that something has gone wrong, and it must be restarted. On a
|
// error, it means that something has gone wrong, and it must be restarted. On a
|
||||||
// clean exit it returns nil.
|
// clean exit it returns nil.
|
||||||
func (obj *FileRes) Watch() error {
|
func (obj *FileRes) Watch(ctx context.Context) error {
|
||||||
// TODO: chan *recwatch.Event instead?
|
// TODO: chan *recwatch.Event instead?
|
||||||
inputEvents := make(chan recwatch.Event)
|
inputEvents := make(chan recwatch.Event)
|
||||||
defer close(inputEvents)
|
defer close(inputEvents)
|
||||||
@@ -497,7 +498,7 @@ func (obj *FileRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -76,7 +77,7 @@ func (obj *GroupRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *GroupRes) Watch() error {
|
func (obj *GroupRes) Watch(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
obj.recWatcher, err = recwatch.NewRecWatcher(groupFile, false)
|
obj.recWatcher, err = recwatch.NewRecWatcher(groupFile, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -105,7 +106,7 @@ func (obj *GroupRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ func (obj *HetznerVMRes) Close() error {
|
|||||||
// Watch is not implemented for this resource, since the Hetzner API does not
|
// Watch is not implemented for this resource, since the Hetzner API does not
|
||||||
// provide any event streams. Instead, always use polling.
|
// provide any event streams. Instead, always use polling.
|
||||||
// NOTE: HetznerPollLimit sets an explicit minimum on the polling interval.
|
// NOTE: HetznerPollLimit sets an explicit minimum on the polling interval.
|
||||||
func (obj *HetznerVMRes) Watch() error {
|
func (obj *HetznerVMRes) Watch(context.Context) error {
|
||||||
return fmt.Errorf("invalid Watch call: requires poll metaparam")
|
return fmt.Errorf("invalid Watch call: requires poll metaparam")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ func (obj *HostnameRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *HostnameRes) Watch() error {
|
func (obj *HostnameRes) Watch(ctx context.Context) error {
|
||||||
// if we share the bus with others, we will get each others messages!!
|
// if we share the bus with others, we will get each others messages!!
|
||||||
bus, err := util.SystemBusPrivateUsable() // don't share the bus connection!
|
bus, err := util.SystemBusPrivateUsable() // don't share the bus connection!
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -135,7 +136,7 @@ func (obj *HostnameRes) Watch() error {
|
|||||||
case <-signals:
|
case <-signals:
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ func (obj *HTTPServerRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *HTTPServerRes) Watch() error {
|
func (obj *HTTPServerRes) Watch(ctx context.Context) error {
|
||||||
// TODO: I think we could replace all this with:
|
// TODO: I think we could replace all this with:
|
||||||
//obj.conn, err := net.Listen("tcp", obj.getAddress())
|
//obj.conn, err := net.Listen("tcp", obj.getAddress())
|
||||||
// ...but what is the advantage?
|
// ...but what is the advantage?
|
||||||
@@ -304,13 +304,13 @@ func (obj *HTTPServerRes) Watch() error {
|
|||||||
// exit and waits instead for Shutdown to return.
|
// exit and waits instead for Shutdown to return.
|
||||||
defer func() {
|
defer func() {
|
||||||
defer close(shutdownChan) // signal that shutdown is finished
|
defer close(shutdownChan) // signal that shutdown is finished
|
||||||
ctx := context.Background()
|
innerCtx := context.Background()
|
||||||
if i := obj.getShutdownTimeout(); i != nil && *i > 0 {
|
if i := obj.getShutdownTimeout(); i != nil && *i > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(*i)*time.Second)
|
innerCtx, cancel = context.WithTimeout(innerCtx, time.Duration(*i)*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
}
|
}
|
||||||
err := obj.server.Shutdown(ctx) // shutdown gracefully
|
err := obj.server.Shutdown(innerCtx) // shutdown gracefully
|
||||||
if err == context.DeadlineExceeded {
|
if err == context.DeadlineExceeded {
|
||||||
// TODO: should we bubble up the error from Close?
|
// TODO: should we bubble up the error from Close?
|
||||||
// TODO: do we need a mutex around this Close?
|
// TODO: do we need a mutex around this Close?
|
||||||
@@ -335,7 +335,7 @@ func (obj *HTTPServerRes) Watch() error {
|
|||||||
case <-closeSignal: // something shut us down early
|
case <-closeSignal: // something shut us down early
|
||||||
return closeError
|
return closeError
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,11 +721,11 @@ func (obj *HTTPFileRes) Close() error {
|
|||||||
// Watch is the primary listener for this resource and it outputs events. This
|
// Watch is the primary listener for this resource and it outputs events. This
|
||||||
// particular one does absolutely nothing but block until we've received a done
|
// particular one does absolutely nothing but block until we've received a done
|
||||||
// signal.
|
// signal.
|
||||||
func (obj *HTTPFileRes) Watch() error {
|
func (obj *HTTPFileRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -129,10 +129,8 @@ func (obj *KVRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *KVRes) Watch() error {
|
func (obj *KVRes) Watch(ctx context.Context) error {
|
||||||
// FIXME: add timeout to context
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
// The obj.init.DoneCtx context is closed by the engine to signal shutdown.
|
|
||||||
ctx, cancel := context.WithCancel(obj.init.DoneCtx)
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
ch, err := obj.init.World.StrMapWatch(ctx, obj.getKey()) // get possible events!
|
ch, err := obj.init.World.StrMapWatch(ctx, obj.getKey()) // get possible events!
|
||||||
@@ -158,7 +156,7 @@ func (obj *KVRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ func (obj *MountRes) Close() error {
|
|||||||
|
|
||||||
// Watch listens for signals from the mount unit associated with the resource.
|
// Watch listens for signals from the mount unit associated with the resource.
|
||||||
// It also watch for changes to /etc/fstab, where mounts are defined.
|
// It also watch for changes to /etc/fstab, where mounts are defined.
|
||||||
func (obj *MountRes) Watch() error {
|
func (obj *MountRes) Watch(ctx context.Context) error {
|
||||||
// make sure systemd is running
|
// make sure systemd is running
|
||||||
if !systemdUtil.IsRunningSystemd() {
|
if !systemdUtil.IsRunningSystemd() {
|
||||||
return fmt.Errorf("systemd is not running")
|
return fmt.Errorf("systemd is not running")
|
||||||
@@ -266,7 +266,7 @@ func (obj *MountRes) Watch() error {
|
|||||||
|
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -93,13 +94,13 @@ func (obj *MsgRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *MsgRes) Watch() error {
|
func (obj *MsgRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
//var send = false // send event?
|
//var send = false // send event?
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package resources
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
@@ -202,7 +203,7 @@ func (obj *NetRes) Close() error {
|
|||||||
// Watch listens for events from the specified interface via a netlink socket.
|
// Watch listens for events from the specified interface via a netlink socket.
|
||||||
// TODO: currently gets events from ALL interfaces, would be nice to reject
|
// TODO: currently gets events from ALL interfaces, would be nice to reject
|
||||||
// events from other interfaces.
|
// events from other interfaces.
|
||||||
func (obj *NetRes) Watch() error {
|
func (obj *NetRes) Watch(ctx context.Context) error {
|
||||||
// create a netlink socket for receiving network interface events
|
// create a netlink socket for receiving network interface events
|
||||||
conn, err := socketset.NewSocketSet(rtmGrps, obj.socketFile, unix.NETLINK_ROUTE)
|
conn, err := socketset.NewSocketSet(rtmGrps, obj.socketFile, unix.NETLINK_ROUTE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -299,7 +300,7 @@ func (obj *NetRes) Watch() error {
|
|||||||
|
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/purpleidea/mgmt/engine"
|
"github.com/purpleidea/mgmt/engine"
|
||||||
@@ -62,11 +63,11 @@ func (obj *NoopRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *NoopRes) Watch() error {
|
func (obj *NoopRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -140,7 +141,7 @@ func (obj *NspawnRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch for state changes and sends a message to the bus if there is a change.
|
// Watch for state changes and sends a message to the bus if there is a change.
|
||||||
func (obj *NspawnRes) Watch() error {
|
func (obj *NspawnRes) Watch(ctx context.Context) error {
|
||||||
// this resource depends on systemd to ensure that it's running
|
// this resource depends on systemd to ensure that it's running
|
||||||
if !systemdUtil.IsRunningSystemd() {
|
if !systemdUtil.IsRunningSystemd() {
|
||||||
return fmt.Errorf("systemd is not running")
|
return fmt.Errorf("systemd is not running")
|
||||||
@@ -184,7 +185,7 @@ func (obj *NspawnRes) Watch() error {
|
|||||||
send = true
|
send = true
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -173,7 +174,7 @@ Loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *PasswordRes) Watch() error {
|
func (obj *PasswordRes) Watch(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
obj.recWatcher, err = recwatch.NewRecWatcher(obj.path, false)
|
obj.recWatcher, err = recwatch.NewRecWatcher(obj.path, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -196,7 +197,7 @@ func (obj *PasswordRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -92,11 +93,11 @@ func (obj *PippetRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *PippetRes) Watch() error {
|
func (obj *PippetRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -104,7 +105,7 @@ func (obj *PkgRes) Close() error {
|
|||||||
// uses the PackageKit UpdatesChanged signal to watch for changes.
|
// uses the PackageKit UpdatesChanged signal to watch for changes.
|
||||||
// TODO: https://github.com/hughsie/PackageKit/issues/109
|
// TODO: https://github.com/hughsie/PackageKit/issues/109
|
||||||
// TODO: https://github.com/hughsie/PackageKit/issues/110
|
// TODO: https://github.com/hughsie/PackageKit/issues/110
|
||||||
func (obj *PkgRes) Watch() error {
|
func (obj *PkgRes) Watch(ctx context.Context) error {
|
||||||
bus := packagekit.NewBus()
|
bus := packagekit.NewBus()
|
||||||
if bus == nil {
|
if bus == nil {
|
||||||
return fmt.Errorf("can't connect to PackageKit bus")
|
return fmt.Errorf("can't connect to PackageKit bus")
|
||||||
@@ -143,7 +144,7 @@ func (obj *PkgRes) Watch() error {
|
|||||||
|
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/purpleidea/mgmt/engine"
|
"github.com/purpleidea/mgmt/engine"
|
||||||
@@ -69,11 +70,11 @@ func (obj *PrintRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *PrintRes) Watch() error {
|
func (obj *PrintRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -510,7 +510,6 @@ func TestResources1(t *testing.T) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Watch listens on this for close/pause events.
|
// Watch listens on this for close/pause events.
|
||||||
DoneCtx: doneCtx,
|
|
||||||
Debug: debug,
|
Debug: debug,
|
||||||
Logf: logf,
|
Logf: logf,
|
||||||
|
|
||||||
@@ -591,7 +590,7 @@ func TestResources1(t *testing.T) {
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
t.Logf("test #%d: running Watch", index)
|
t.Logf("test #%d: running Watch", index)
|
||||||
if err := res.Watch(); err != nil {
|
if err := res.Watch(doneCtx); err != nil {
|
||||||
t.Errorf("test #%d: FAIL", index)
|
t.Errorf("test #%d: FAIL", index)
|
||||||
t.Errorf("test #%d: Watch failed: %s", index, err.Error())
|
t.Errorf("test #%d: Watch failed: %s", index, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
@@ -81,7 +82,7 @@ func (obj *SvcRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *SvcRes) Watch() error {
|
func (obj *SvcRes) Watch(ctx context.Context) error {
|
||||||
// obj.Name: svc name
|
// obj.Name: svc name
|
||||||
if !systemdUtil.IsRunningSystemd() {
|
if !systemdUtil.IsRunningSystemd() {
|
||||||
return fmt.Errorf("systemd is not running")
|
return fmt.Errorf("systemd is not running")
|
||||||
@@ -172,7 +173,7 @@ func (obj *SvcRes) Watch() error {
|
|||||||
// loop so that we can see the changed invalid signal
|
// loop so that we can see the changed invalid signal
|
||||||
obj.init.Logf("daemon reload")
|
obj.init.Logf("daemon reload")
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -215,7 +216,7 @@ func (obj *SvcRes) Watch() error {
|
|||||||
case err := <-subErrors:
|
case err := <-subErrors:
|
||||||
return errwrap.Wrapf(err, "unknown %s error", obj)
|
return errwrap.Wrapf(err, "unknown %s error", obj)
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
@@ -124,11 +125,11 @@ func (obj *TestRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *TestRes) Watch() error {
|
func (obj *TestRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package resources
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@@ -139,7 +140,7 @@ func (obj *TFTPServerRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *TFTPServerRes) Watch() error {
|
func (obj *TFTPServerRes) Watch(ctx context.Context) error {
|
||||||
addr, err := net.ResolveUDPAddr("udp", obj.getAddress())
|
addr, err := net.ResolveUDPAddr("udp", obj.getAddress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrapf(err, "could not resolve address")
|
return errwrap.Wrapf(err, "could not resolve address")
|
||||||
@@ -200,7 +201,7 @@ func (obj *TFTPServerRes) Watch() error {
|
|||||||
case <-closeSignal: // something shut us down early
|
case <-closeSignal: // something shut us down early
|
||||||
return closeError
|
return closeError
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,11 +548,11 @@ func (obj *TFTPFileRes) Close() error {
|
|||||||
// Watch is the primary listener for this resource and it outputs events. This
|
// Watch is the primary listener for this resource and it outputs events. This
|
||||||
// particular one does absolutely nothing but block until we've received a done
|
// particular one does absolutely nothing but block until we've received a done
|
||||||
// signal.
|
// signal.
|
||||||
func (obj *TFTPFileRes) Watch() error {
|
func (obj *TFTPFileRes) Watch(ctx context.Context) error {
|
||||||
obj.init.Running() // when started, notify engine that we're running
|
obj.init.Running() // when started, notify engine that we're running
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
//obj.init.Event() // notify engine of an event (this can block)
|
//obj.init.Event() // notify engine of an event (this can block)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ func (obj *TimerRes) newTicker() *time.Ticker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *TimerRes) Watch() error {
|
func (obj *TimerRes) Watch(ctx context.Context) error {
|
||||||
// create a time.Ticker for the given interval
|
// create a time.Ticker for the given interval
|
||||||
obj.ticker = obj.newTicker()
|
obj.ticker = obj.newTicker()
|
||||||
defer obj.ticker.Stop()
|
defer obj.ticker.Stop()
|
||||||
@@ -84,7 +85,7 @@ func (obj *TimerRes) Watch() error {
|
|||||||
send = true
|
send = true
|
||||||
obj.init.Logf("received tick")
|
obj.init.Logf("received tick")
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -110,7 +111,7 @@ func (obj *UserRes) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *UserRes) Watch() error {
|
func (obj *UserRes) Watch(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
obj.recWatcher, err = recwatch.NewRecWatcher(passwdFile, false)
|
obj.recWatcher, err = recwatch.NewRecWatcher(passwdFile, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -139,7 +140,7 @@ func (obj *UserRes) Watch() error {
|
|||||||
}
|
}
|
||||||
send = true
|
send = true
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -294,7 +295,7 @@ func (obj *VirtRes) connect() (conn *libvirt.Connect, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch is the primary listener for this resource and it outputs events.
|
// Watch is the primary listener for this resource and it outputs events.
|
||||||
func (obj *VirtRes) Watch() error {
|
func (obj *VirtRes) Watch(ctx context.Context) error {
|
||||||
// FIXME: how will this work if we're polling?
|
// FIXME: how will this work if we're polling?
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
defer wg.Wait() // wait until everyone has exited before we exit!
|
defer wg.Wait() // wait until everyone has exited before we exit!
|
||||||
@@ -441,7 +442,7 @@ func (obj *VirtRes) Watch() error {
|
|||||||
case err := <-errorChan:
|
case err := <-errorChan:
|
||||||
return errwrap.Wrapf(err, "unknown libvirt error")
|
return errwrap.Wrapf(err, "unknown libvirt error")
|
||||||
|
|
||||||
case <-obj.init.DoneCtx.Done(): // closed by the engine to signal shutdown
|
case <-ctx.Done(): // closed by the engine to signal shutdown
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os/user"
|
"os/user"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -201,7 +202,7 @@ func (t *testEngineRes) String() string { return "test-string" }
|
|||||||
|
|
||||||
func (t *testEngineRes) Validate() error { return nil }
|
func (t *testEngineRes) Validate() error { return nil }
|
||||||
|
|
||||||
func (t *testEngineRes) Watch() error { return nil }
|
func (t *testEngineRes) Watch(context.Context) error { return nil }
|
||||||
|
|
||||||
func TestStructKindToFieldNameTypeMap(t *testing.T) {
|
func TestStructKindToFieldNameTypeMap(t *testing.T) {
|
||||||
k := "test-kind"
|
k := "test-kind"
|
||||||
|
|||||||
Reference in New Issue
Block a user