type Config struct {
DryRun bool `yaml:"-"` // set via command line
+ Quiet bool `yaml:"-"` // set via command line
LogLevel safcm.LogLevel `yaml:"-"` // set via command line
DetectGroups []string `yaml:"detect_groups"`
optionDryRun := flag.Bool("n", false,
"dry-run, show diff but don't perform any changes")
+ optionQuiet := flag.Bool("q", false,
+ "hide successful, non-trigger commands with no output from host changes listing")
optionLog := flag.String("log", "info", "set log `level`; "+
"levels: error, info, verbose, debug, debug2, debug3")
return err
}
cfg.DryRun = *optionDryRun
+ cfg.Quiet = *optionQuiet
cfg.LogLevel = level
toSync, err := hostsToSync(names, allHosts, allGroups)
func (s *Sync) formatCommandChanges(changes []safcm.CommandChange) string {
const indent = " > "
+ // Quiet hides all successful, non-trigger commands which produce no
+ // output. This is useful as many commands will be used to enforce a
+ // certain state (e.g. file not-present, `ainsl`, etc.) and are run on
+ // each sync. Displaying them provides not much useful information.
+ // Instead, quiet shows them only when they produce output (e.g.
+ // `ainsl`, `rm -v`) and thus modify the host's state.
+ var noOutput int
+ if s.config.Quiet && !s.config.DryRun {
+ for _, x := range changes {
+ if x.Trigger == "" &&
+ x.Error == "" &&
+ x.Output == "" {
+ noOutput++
+ }
+ }
+ }
+
var buf strings.Builder
- fmt.Fprintf(&buf, "executed %d command(s):", len(changes))
+ fmt.Fprintf(&buf, "executed %d command(s)", len(changes))
+ if noOutput > 0 {
+ fmt.Fprintf(&buf, ", %d with no output", noOutput)
+ }
+ if noOutput != len(changes) {
+ fmt.Fprintf(&buf, ":")
+ }
if s.config.DryRun {
fmt.Fprintf(&buf, " (dry-run)")
}
fmt.Fprintf(&buf, "\n")
for _, x := range changes {
+ if noOutput > 0 &&
+ x.Trigger == "" && x.Error == "" && x.Output == "" {
+ continue
+ }
+
fmt.Fprintf(&buf, "%s", s.formatTarget(x.Command))
if x.Trigger != "" {
fmt.Fprintf(&buf, ", trigger for %q", x.Trigger)
tests := []struct {
name string
dryRun bool
+ quiet bool
changes []safcm.CommandChange
exp string
}{
{
"regular",
false,
+ false,
[]safcm.CommandChange{
{
Command: "fake command",
{
"dry-run",
true,
+ false,
[]safcm.CommandChange{
{
Command: "fake command",
`,
},
+ {
+ "quiet",
+ false,
+ true,
+ []safcm.CommandChange{
+ {
+ Command: "fake command",
+ Output: "fake output",
+ },
+ {
+ Command: "fake command with no output",
+ },
+ {
+ Command: "fake command with newline",
+ Output: "fake output\n",
+ },
+ {
+ Command: "fake command with more output",
+ Output: "fake out\nfake put\nfake\n",
+ },
+ {
+ Command: "fake failed command",
+ Output: "fake output",
+ Error: "fake error",
+ },
+ },
+ `executed 5 command(s), 1 with no output:
+"fake command":
+ > fake output
+ > \ No newline at end of file
+"fake command with newline":
+ > fake output
+"fake command with more output":
+ > fake out
+ > fake put
+ > fake
+"fake failed command", failed: "fake error":
+ > fake output
+ > \ No newline at end of file
+`,
+ },
+
+ {
+ "quiet (only quiet commands)",
+ false,
+ true,
+ []safcm.CommandChange{
+ {
+ Command: "fake command with no output",
+ },
+ {
+ Command: "fake command with no output",
+ },
+ },
+ `executed 2 command(s), 2 with no output
+`,
+ },
+
+ {
+ "quiet (quiet with errors)",
+ false,
+ true,
+ []safcm.CommandChange{
+ {
+ Command: "fake command with no output but error",
+ Error: "fake error",
+ },
+ {
+ Command: "fake command with no output",
+ },
+ },
+ `executed 2 command(s), 1 with no output:
+"fake command with no output but error", failed: "fake error"
+`,
+ },
+
+ {
+ "quiet & dry-run",
+ true,
+ true,
+ []safcm.CommandChange{
+ {
+ Command: "fake command",
+ },
+ {
+ Command: "fake command with no output",
+ },
+ {
+ Command: "fake command with newline",
+ },
+ {
+ Command: "fake command with more output",
+ },
+ {
+ Command: "fake failed command",
+ },
+ },
+ `executed 5 command(s): (dry-run)
+"fake command"
+"fake command with no output"
+"fake command with newline"
+"fake command with more output"
+"fake failed command"
+`,
+ },
+
{
"escaping",
false,
+ false,
[]safcm.CommandChange{
{
Command: "\x00",
s := &Sync{
config: &config.Config{
DryRun: tc.dryRun,
+ Quiet: tc.quiet,
},
}