-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/run: detect simulation errors and exit with appropriate rc #53
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package run | |
|
||
import ( | ||
"context" | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"net" | ||
|
@@ -358,6 +359,22 @@ func getDefaultDNSIntf() (string, error) { | |
return dnsIntfIP, nil | ||
} | ||
|
||
// failedSimulationNames returns a sorted slice of failed simulation names extracted from | ||
// them sims map. | ||
func failedSimulationNames(sims map[string]bool) []string { | ||
if len(sims) == 0 { | ||
return nil | ||
} | ||
failedSims := make([]string, len(sims)) | ||
i := 0 | ||
for sim := range sims { | ||
failedSims[i] = sim | ||
i++ | ||
} | ||
sort.Strings(failedSims) | ||
return failedSims | ||
} | ||
|
||
func run(sims []*Simulation, bind simulator.BindAddr, size int) error { | ||
// If user override on iface, both IP and DNS traffic will flow through bind.Addr. | ||
// NOTE: not passing the DNS server to printWelcome(), as it may be confusing in cases | ||
|
@@ -374,12 +391,15 @@ func run(sims []*Simulation, bind simulator.BindAddr, size int) error { | |
} | ||
printHeader() | ||
|
||
// Log failed simulations. | ||
failedSims := make(map[string]bool) | ||
for simN, sim := range sims { | ||
fmt.Print("\n") | ||
|
||
okHosts := 0 | ||
err := sim.Init(bind) | ||
if err != nil { | ||
failedSims[sim.Name()] = true | ||
printMsg(sim, msgPrefixErrorInit+fmt.Sprint(err)) | ||
} else { | ||
printMsg(sim, sim.HeaderMsg) | ||
|
@@ -391,6 +411,7 @@ func run(sims []*Simulation, bind simulator.BindAddr, size int) error { | |
|
||
hosts, err := sim.Module.Hosts(sim.Scope, numOfHosts) | ||
if err != nil { | ||
failedSims[sim.Name()] = true | ||
printMsg(sim, msgPrefixErrorInit+err.Error()) | ||
continue | ||
} | ||
|
@@ -412,6 +433,7 @@ func run(sims []*Simulation, bind simulator.BindAddr, size int) error { | |
// TODO: some module can return custom messages (e.g. hijack) | ||
// and "ERROR" prefix shouldn't be printed then | ||
printMsg(sim, fmt.Sprintf("ERROR: %s: %s", host, err.Error())) | ||
failedSims[sim.Name()] = true | ||
} else { | ||
okHosts++ | ||
} | ||
|
@@ -436,7 +458,14 @@ func run(sims []*Simulation, bind simulator.BindAddr, size int) error { | |
} | ||
sim.Cleanup() | ||
} | ||
|
||
printGoodbye() | ||
// Extract list of failed simulations and return as an error. | ||
failedSimNames := failedSimulationNames(failedSims) | ||
printGoodbye(failedSimNames != nil) | ||
if failedSimNames != nil { | ||
msg := fmt.Sprintf( | ||
"The following simulations experienced errors: %v", | ||
strings.Join(failedSimNames, ", ")) | ||
return errors.New(msg) | ||
} | ||
Comment on lines
+463
to
+469
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this won't be misleading in some scenarios. What if we run the simulation against 10 hosts and one of them fails? Should we report the whole module as failed?
I don't have an answer here, but we need to define what it means for the module to fail. Maybe simple boolean flag is not enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also most probably we should extract this for loop body into a separate function/structure so we don't repeat the errors handling (printMsg+failedSims). But we before we do so we should address what we really want to report at the end and how to handle partial failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK... I was a little concerned that a single host failure was a bit too coarse. I'll mark this as a draft PR until we discuss further.
Thanks for the review.