github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/install/explain/updating.go (about)

     1  package explain
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/apprenda/kismatic/pkg/ansible"
     9  	"github.com/apprenda/kismatic/pkg/util"
    10  	"github.com/gosuri/uilive"
    11  )
    12  
    13  // DefaultExplainer returns the default ansible explainer
    14  func DefaultExplainer(verbose bool, out io.Writer) AnsibleEventExplainer {
    15  	if verbose || !isTerminal(out) {
    16  		return &verboseExplainer{out: out}
    17  	}
    18  	// otherwise, return the updating explainer
    19  	w := uilive.New()
    20  	w.Out = out
    21  	w.Start()
    22  	return &updatingExplainer{
    23  		out: w,
    24  	}
    25  }
    26  
    27  type updatingExplainer struct {
    28  	out             *uilive.Writer
    29  	currentPlayName string
    30  	currentTask     string
    31  	failureOccurred bool
    32  	taskRan         bool
    33  }
    34  
    35  func (e *updatingExplainer) ExplainEvent(ansibleEvent ansible.Event) {
    36  	switch event := ansibleEvent.(type) {
    37  	case *ansible.PlaybookStartEvent:
    38  
    39  	case *ansible.PlayStartEvent:
    40  		if e.currentPlayName != "" {
    41  			// If tasks ran, print OK. Otherwise, print SKIPPED
    42  			if e.taskRan {
    43  				util.PrettyPrintOk(e.out.Bypass(), "%s", e.currentPlayName)
    44  			} else {
    45  				util.PrettyPrintSkipped(e.out.Bypass(), "%s", e.currentPlayName)
    46  			}
    47  		}
    48  		e.taskRan = false
    49  		e.currentPlayName = event.Name
    50  		fmt.Fprintln(e.out, e.currentPlayName)
    51  
    52  	case *ansible.PlaybookEndEvent:
    53  		// Assuming no failure detected: playbook end => previous play success
    54  		if !e.failureOccurred {
    55  			util.PrettyPrintOk(e.out.Bypass(), "%s", e.currentPlayName)
    56  		}
    57  
    58  	case *ansible.TaskStartEvent:
    59  		e.currentTask = event.Name
    60  		buf := &bytes.Buffer{}
    61  		fmt.Fprintln(buf, e.currentPlayName)
    62  		fmt.Fprintln(buf, "- Task:", e.currentTask)
    63  		e.out.Write(buf.Bytes())
    64  
    65  	case *ansible.HandlerTaskStartEvent:
    66  		// Ansible echoes events for handlers even if the previous handler
    67  		// did not run successfully. We write handler information only if
    68  		// no failure has occurred.
    69  		if !e.failureOccurred {
    70  			buf := &bytes.Buffer{}
    71  			fmt.Fprintln(buf, e.currentPlayName)
    72  			fmt.Fprintln(buf, "- Task: ", event.Name)
    73  			e.out.Write(buf.Bytes())
    74  		}
    75  
    76  	case *ansible.RunnerOKEvent:
    77  		e.taskRan = true
    78  		buf := &bytes.Buffer{}
    79  		fmt.Fprintln(buf, e.currentPlayName)
    80  		util.PrettyPrintOk(buf, "- %s %s", event.Host, e.currentTask)
    81  		e.out.Write(buf.Bytes())
    82  
    83  	case *ansible.RunnerItemOKEvent:
    84  		buf := &bytes.Buffer{}
    85  		fmt.Fprintln(buf, e.currentPlayName)
    86  		msg := fmt.Sprintf("  %s", event.Host)
    87  		if event.Result.Item != "" {
    88  			msg = msg + fmt.Sprintf(" with %q", event.Result.Item)
    89  		}
    90  		util.PrettyPrintOk(buf, msg)
    91  		e.out.Write(buf.Bytes())
    92  
    93  	case *ansible.RunnerFailedEvent:
    94  		buf := &bytes.Buffer{}
    95  		// Only print this header if this is the first failure we get
    96  		if !e.failureOccurred {
    97  			util.PrettyPrintErr(buf, "%s", e.currentPlayName)
    98  			fmt.Fprintln(buf, "- Task: "+e.currentTask)
    99  		}
   100  		if event.IgnoreErrors {
   101  			util.PrettyPrintErrorIgnored(buf, "  %s", event.Host)
   102  		} else {
   103  			util.PrettyPrintErr(buf, "  %s: %s", event.Host, event.Result.Message)
   104  		}
   105  		if event.Result.Stdout != "" {
   106  			util.PrintColor(buf, util.Red, "---- STDOUT ----\n%s\n", event.Result.Stdout)
   107  		}
   108  		if event.Result.Stderr != "" {
   109  			util.PrintColor(buf, util.Red, "---- STDERR ----\n%s\n", event.Result.Stderr)
   110  		}
   111  		if event.Result.Stderr != "" || event.Result.Stdout != "" {
   112  			util.PrintColor(buf, util.Red, "---------------\n")
   113  		}
   114  		fmt.Fprintf(e.out.Bypass(), buf.String())
   115  		e.failureOccurred = true
   116  	case *ansible.RunnerUnreachableEvent:
   117  		fmt.Fprintln(e.out.Bypass(), e.currentPlayName)
   118  		util.PrettyPrintUnreachable(e.out.Bypass(), "  %s", event.Host)
   119  
   120  	case *ansible.RunnerSkippedEvent:
   121  		buf := &bytes.Buffer{}
   122  		fmt.Fprintln(buf, e.currentPlayName)
   123  		util.PrettyPrintSkipped(buf, "- %s %s", event.Host, e.currentTask)
   124  		e.out.Write(buf.Bytes())
   125  
   126  	case *ansible.RunnerItemFailedEvent:
   127  		buf := &bytes.Buffer{}
   128  		// Only print this header if this is the first failure we get
   129  		if !e.failureOccurred {
   130  			util.PrettyPrintErr(buf, "%s %s", e.currentPlayName)
   131  			fmt.Fprintln(buf, "- Task: "+e.currentTask)
   132  		}
   133  		msg := fmt.Sprintf("  %s", event.Host)
   134  		if event.Result.Item != "" {
   135  			msg = msg + fmt.Sprintf(" with %q", event.Result.Item)
   136  		}
   137  		if event.IgnoreErrors {
   138  			util.PrettyPrintErrorIgnored(buf, msg)
   139  		} else {
   140  			util.PrettyPrintErr(buf, "  %s: %s", msg, event.Result.Message)
   141  		}
   142  		if event.Result.Stdout != "" {
   143  			util.PrintColor(buf, util.Red, "---- STDOUT ----\n%s\n", event.Result.Stdout)
   144  		}
   145  		if event.Result.Stderr != "" {
   146  			util.PrintColor(buf, util.Red, "---- STDERR ----\n%s\n", event.Result.Stderr)
   147  		}
   148  		if event.Result.Stderr != "" || event.Result.Stdout != "" {
   149  			util.PrintColor(buf, util.Red, "---------------\n")
   150  		}
   151  		fmt.Fprintf(e.out.Bypass(), buf.String())
   152  		e.failureOccurred = true
   153  
   154  	case *ansible.RunnerItemRetryEvent:
   155  		buf := &bytes.Buffer{}
   156  		fmt.Fprintln(buf, e.currentPlayName)
   157  		fmt.Fprintf(buf, "- [%s] Retrying: %s (%d/%d attempts)\n", event.Host, e.currentTask, event.Result.Attempts, event.Result.MaxRetries-1)
   158  		e.out.Write(buf.Bytes())
   159  
   160  	default:
   161  		util.PrintColor(e.out.Bypass(), util.Orange, "Unhandled event: %T\n", event)
   162  	}
   163  }