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 }