Skip to content

Commit

Permalink
Add Gornir.WithRunner (#27)
Browse files Browse the repository at this point in the history
* test examples

* fix

* fix

* fix

* fix

* fix

* fix

* test linter as well

* fix linter

* fix build status badge

* added WithRunner and removed from RunSync and RunAsync

* fix example

* fix doc.go and README
  • Loading branch information
dbarrosop authored and nleiva committed Jun 16, 2019
1 parent 6dda124 commit a27105f
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 39 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
coverage.txt

# following file is a leftover of calling make test-example without the proper argument
examples/output.txt

vendor/
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ func main() {
log.Fatal(err)
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(runner.Parallel())

results, err := gr.RunSync(
"What's my ip?",
runner.Parallel(),
&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@
// log.Fatal(err)
// }
//
// gr := gornir.New().WithInventory(inv).WithLogger(log)
// gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(runner.Parallel())
//
// results, err := gr.RunSync(
// "What's my ip?",
// runner.Parallel(),
// &task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
// )
// if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions examples/1_simple/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ func main() {
log.Fatal(err)
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
rnr := runner.Sorted()

gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(rnr)

// Following call is going to execute the task over all the hosts using the runner.Parallel runner.
// Said runner is going to handle the parallelization for us. Gornir.RunS is also going to block
// until the runner has completed executing the task over all the hosts
results, err := gr.RunSync(
"What's my ip?",
runner.Sorted(),
&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
)
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions examples/2_simple_with_filter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ func main() {
return h.Hostname == "dev1.group_1" || h.Hostname == "dev4.group_2"
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
rnr := runner.Sorted()

gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(rnr)

// Before calling Gornir.RunS we call Gornir.Filter and pass the function defined
// above. This will narrow down the inventor to the hosts matching the filter
results, err := gr.Filter(filter).RunSync(
"What's my ip?",
runner.Sorted(),
&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions examples/2_simple_with_filter_bis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ func main() {
// this time our filter is composed from various FilterFunc
filter := f.Or(f.WithHostname("dev1.group_1"), f.WithHostname("dev4.group_2"))

gr := gornir.New().WithInventory(inv).WithLogger(log)
gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(runner.Sorted())

// Before calling Gornir.RunS we call Gornir.Filter and pass the function defined
// above. This will narrow down the inventor to the hosts matching the filter
results, err := gr.Filter(filter).RunSync(
"What's my ip?",
runner.Sorted(),
&task.RemoteCommand{Command: "ip addr | grep \\/24 | awk '{ print $2 }'"},
)
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions examples/3_grouped_simple/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ func main() {
log.Fatal(err)
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
rnr := runner.Sorted()

gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(rnr)

results, err := gr.RunSync(
"Let's run a couple of commands",
runner.Sorted(),
&getHostnameAndIP{},
)
if err != nil {
Expand Down
9 changes: 3 additions & 6 deletions examples/4_advanced_1/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,16 @@ func main() {
log.Fatal(err)
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
rnr := runner.Sorted()

results := make(chan *gornir.JobResult, len(gr.Inventory.Hosts))
gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(rnr)

// We need to store the runner as we will need to check its completion later on
// by calling rnr.Wait()
rnr := runner.Sorted()
results := make(chan *gornir.JobResult, len(gr.Inventory.Hosts))

// Gornir.RunAsync doesn't block so it's up to the user to check the runner is done
err = gr.RunAsync(
context.Background(),
"What's my hostname?",
rnr,
&task.RemoteCommand{Command: "hostname"},
results,
)
Expand Down
7 changes: 3 additions & 4 deletions examples/5_advanced_2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,16 @@ func main() {
log.Fatal(err)
}

gr := gornir.New().WithInventory(inv).WithLogger(log)
rnr := runner.Sorted()

results := make(chan *gornir.JobResult, len(gr.Inventory.Hosts))
gr := gornir.New().WithInventory(inv).WithLogger(log).WithRunner(rnr)

rnr := runner.Sorted()
results := make(chan *gornir.JobResult, len(gr.Inventory.Hosts))

// The following call will not block
err = gr.RunAsync(
context.Background(),
"What's my hostname?",
rnr,
&task.RemoteCommand{Command: "hostname"},
results,
)
Expand Down
48 changes: 31 additions & 17 deletions pkg/gornir/gornir.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type Gornir struct {
Inventory *Inventory // Inventory for the object
Logger Logger // Logger for the object
Runner Runner // Runner that will be used to run the task
}

// New is a Gornir constructor. It is currently no different that new,
Expand All @@ -23,39 +24,52 @@ func New() *Gornir {
return new(Gornir)
}

// WithInventory creates a new Gornir with an Inventory.
func (gr *Gornir) WithInventory(inv Inventory) *Gornir {
// Clone returns a new instance of Gornir with the same attributes as the receiver
func (gr *Gornir) Clone() *Gornir {
return &Gornir{
Inventory: &inv,
Inventory: gr.Inventory,
Logger: gr.Logger,
Runner: gr.Runner,
}
}

// WithRunner returns a clone of the current Gornir but with the given runner
func (gr *Gornir) WithRunner(rnr Runner) *Gornir {
c := gr.Clone()
c.Runner = rnr
return c
}

// WithInventory returns a clone of the current Gornir but with the given inventory
func (gr *Gornir) WithInventory(inv Inventory) *Gornir {
c := gr.Clone()
c.Inventory = &inv
return c
}

// Filter creates a new Gornir with a filtered Inventory.
// It filters the hosts in the inventory returning a copy of the current
// Gornir instance but with only the hosts that passed the filter.
func (gr *Gornir) Filter(f FilterFunc) *Gornir {
return &Gornir{
Inventory: gr.Inventory.Filter(f),
Logger: gr.Logger,
}
c := gr.Clone()
c.Inventory = c.Inventory.Filter(f)
return c
}

// WithLogger creates a new Gornir with a Logger.
// WithLogger returns a clone of the current Gornir but with the given logger
func (gr *Gornir) WithLogger(l Logger) *Gornir {
return &Gornir{
Inventory: gr.Inventory,
Logger: l,
}
c := gr.Clone()
c.Logger = l
return c
}

// RunSync will execute the task over the hosts in the inventory using the given runner.
// This function will block until all the tasks are completed.
func (gr *Gornir) RunSync(title string, runner Runner, task Task) (chan *JobResult, error) {
func (gr *Gornir) RunSync(title string, task Task) (chan *JobResult, error) {
logger := gr.Logger.WithField("ID", uuid.New().String()).WithField("runFunc", getFunctionName(task))
results := make(chan *JobResult, len(gr.Inventory.Hosts))
defer close(results)
err := runner.Run(
err := gr.Runner.Run(
context.Background(),
task,
gr.Inventory.Hosts,
Expand All @@ -65,7 +79,7 @@ func (gr *Gornir) RunSync(title string, runner Runner, task Task) (chan *JobResu
if err != nil {
return results, errors.Wrap(err, "problem calling runner")
}
if err := runner.Wait(); err != nil {
if err := gr.Runner.Wait(); err != nil {
return results, errors.Wrap(err, "problem waiting for runner")
}
return results, nil
Expand All @@ -74,9 +88,9 @@ func (gr *Gornir) RunSync(title string, runner Runner, task Task) (chan *JobResu
// RunAsync will execute the task over the hosts in the inventory using the given runner.
// This function doesn't block, the user can use the method Runnner.Wait instead.
// It's also up to the user to ennsure the channel is closed
func (gr *Gornir) RunAsync(ctx context.Context, title string, runner Runner, task Task, results chan *JobResult) error {
func (gr *Gornir) RunAsync(ctx context.Context, title string, task Task, results chan *JobResult) error {
logger := gr.Logger.WithField("ID", uuid.New().String()).WithField("runFunc", getFunctionName(task))
err := runner.Run(
err := gr.Runner.Run(
ctx,
task,
gr.Inventory.Hosts,
Expand Down

0 comments on commit a27105f

Please sign in to comment.